Quill: Catching blot clicks (on selection-change) in readonly editor?

Created on 23 Jan 2018  Â·  6Comments  Â·  Source: quilljs/quill

I've got a Blot where I catch clicks using on('selection-change') and offer to change that blot with a menu. I'd now like to make the editor readonly, apart from changes made by the clicks on those blots. But if it's readonly, on('selection-change') is never hit, since source === "user".

You can "reproduce" this by doing quill.disable() on quilljs.com and trying to edit a link, which also seems to use on('selection-change').

Is there a way to have a "readonly-light", where users can't modify text by typing, but they can by clicking on blots? I see there is this function

https://github.com/quilljs/quill/blob/131db2b98d1fcabf8586ecd1b493345ea2bb1002/core/quill.js#L431

which never emits anything if the editor is disabled and source is user, so I'm guessing there's nothing implemented to do what I want using selection-change. But maybe there's a different way I could get what I want?

Most helpful comment

If your goal is to find the blot would something like this work:

static create() {
  let node = super.create();
  node.addEventListener('click', function(e) {
    // e.target should always be node since it is attached to node
    let blot = Quill.find(node);
    // Do what you want with blot
  });
  // ...
}

All 6 comments

Can you just use normal DOM click events instead of selection-change?

Can I still get a hold of range.index from a DOM click event? I'm doing

onSelectionChange = function(range, _oldRange, source) { 
  let idx = range.index; 
  let blot_and_offset = this.quill.scroll.descendant(ErrorBlot, idx); 
  let beg = idx - blot_and_offset[1]; 
  let blot = blot_and_offset[0];
  …
 };

more or less, in order to get the Blot at that point, along with its beginning and length.

Is this a custom Blot? If so can you paste the constructor / create functions?

slightly simplified:

let Inline = Quill.import('blots/inline');
class ErrorBlot extends Inline {
  static create(err/*:err*/) {
    let node = super.create();
    if(typeof(err) != "object") {
      console.log("Error creating ErrorBlot, expected object, not "+typeof(err));
      return super.create();
    }
    $(node).data("error", err);
    return node;
  }
  static formats(node) {
    return $(node).data("error");
  }
}
ErrorBlot.blotName = 'error';
ErrorBlot.tagName = 'span';
ErrorBlot.className = 'divvun-error';
Quill.register(ErrorBlot);

If your goal is to find the blot would something like this work:

static create() {
  let node = super.create();
  node.addEventListener('click', function(e) {
    // e.target should always be node since it is attached to node
    let blot = Quill.find(node);
    // Do what you want with blot
  });
  // ...
}

I was unsure if just the blot element would have enough info to safely remove/unwrap the blot, or change the text contents in it, but after looking through https://github.com/quilljs/parchment/#blots I see I can use Quill.find(node).offset(quill.scroll) to get the the beginning/offset, and Quill.find(node).length()) to get the length, so I believe that gives me all the information I need :-)

Thanks! I'll close this then; using a normal DOM click event seems like a better solution than a "partial readonly" state.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aletorrado picture aletorrado  Â·  3Comments

kheraud picture kheraud  Â·  3Comments

benbro picture benbro  Â·  3Comments

scottfr picture scottfr  Â·  3Comments

markstewie picture markstewie  Â·  3Comments