quill icon indicating copy to clipboard operation
quill copied to clipboard

How to insert an undeletable block-level element?

Open awpsawps12 opened this issue 7 years ago • 8 comments

Here I customize a block element by Quill.import('blots/block/embed') which I insert into the editor content. I would like to know that if there is any way to make it undeletable, therefore the user could not delete it or edit it? Thanks a lot.

awpsawps12 avatar Apr 12 '17 03:04 awpsawps12

Hi, I have the same issue, as well as a related one: If I initialise Quill with some HTML content, what is the easiest way to support "protected" regions, i.e. based on a particular pattern (such as CSS class name) such that Quill will not allow the editing of those elements.

With my limited understand of Quill's architecture, it seems that it should be fully possible to do this. However, I can't find any information about whether any of the standard modules can be configured to support this kind of functionality, or whether anybody has perhaps made some extensions that simply support "locked" regions.

Any insight would be much appreciated.

DawidLoubser avatar May 04 '17 10:05 DawidLoubser

It's easy to make a blot undeletable by overriding the base class deleteAt method with one that just returns false. To prevent editing I've been using a nested span with contenteditable="false" set on it. It's still a little buggy but seems to work better than just setting contenteditable directly on the blot element.

The hard part is preventing replacement when the blot's part of a selection. I've got some progress by listening to keypress and making a list of any of my blots in the selected range and just reinserting them. It sort of works when the selection is confined to one block element but fails when it spans multiple blocks.

Here's a pen to try it out

edit - fixed the spanning multiple paragraphs, it's still pretty buggy though

jspaine avatar Jun 13 '17 15:06 jspaine

@jspaine thank you for the deleteAt tip. If this helps anyone. I am attempting to overlay a template that is not editable and not deleteable. Embed blots are immutable but are deletable, but overriding deleteAt it looks like now I have an immutable and un-deletable blot

        #${this.id + 'Editor'} .template::before {
            content: 'This is an awesome template';
            font-style: italic;
            }</style>```

jonathanfishbein1 avatar Dec 19 '17 02:12 jonathanfishbein1

You can add an event listener for the backspace button to the keyboard module like that:

this.quill = new Quill(this.contentElement, {
  modules: {
    keyboard: {
      bindings: {
        video: {
          key: 'backspace',
          handler: function(range, keycontext) {
            let format = _this.quill.getFormat(range.index - 1);
            if (!format.video && !keycontext.format.video) {
              // propogate to Quill's default
              return true;
            } // else do nothing to prevent deleting video
          }
        }
      }
    }
  },
  theme: 'snow'
});

karim10 avatar May 30 '18 16:05 karim10

It's easy to make a blot undeletable by overriding the base class deleteAt method with one that just returns false. To prevent editing I've been using a nested span with contenteditable="false" set on it. It's still a little buggy but seems to work better than just setting contenteditable directly on the blot element.

The hard part is preventing replacement when the blot's part of a selection. I've got some progress by listening to keypress and making a list of any of my blots in the selected range and just reinserting them. It sort of works when the selection is confined to one block element but fails when it spans multiple blocks.

Here's a pen to try it out

edit - fixed the spanning multiple paragraphs, it's still pretty buggy though

thx, how can i define a user-undeletable blot, which means i can delete it by updateContents method?

hakonleung avatar Mar 08 '19 07:03 hakonleung

It's easy to make a blot undeletable by overriding the base class deleteAt method with one that just returns false. To prevent editing I've been using a nested span with contenteditable="false" set on it. It's still a little buggy but seems to work better than just setting contenteditable directly on the blot element.

The hard part is preventing replacement when the blot's part of a selection. I've got some progress by listening to keypress and making a list of any of my blots in the selected range and just reinserting them. It sort of works when the selection is confined to one block element but fails when it spans multiple blocks.

Here's a pen to try it out

edit - fixed the spanning multiple paragraphs, it's still pretty buggy though

Hey, any tips how to make the blot deletable via an event (and undeletable on selection/backspace)? I was thinking to call super.deleteAt once the event is catched, but this does not do the trick.

kosty4 avatar May 19 '20 18:05 kosty4

I have found a way to remove the blot via an event - it has nothing to do with quill, but more html-style access of DOM element:

` class MyBlot extends BlotEmbed { static create(value) { const node = super.create(); node.setAttribute("class", "ti-myblot myblot-success"); EventBus.$on("eventfromoutside", ()=> { node.parentNode.removeChild(node) }); return node; } length() { return 1; } //here i overwrite the possibility to delete the blot with backspace deleteAt() { console.log('try') return; }

  }`

kosty4 avatar May 19 '20 19:05 kosty4

Add:

    deleteAt() {
      return false
    }

to your custom blot class

yattias avatar Jul 07 '22 13:07 yattias

Quill 2.0 has been released (announcement post) with many changes and fixes. If this is still an issue please create a new issue after reviewing our updated Contributing guide :pray:

quill-bot avatar Apr 17 '24 10:04 quill-bot