Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quill link handler not working

I'm trying to write a custom handler for the link input value. In case the user inputs a link that does not have a custom protocol, I wish to prepend a http: before the input value. That's because if link value lacks http:, link is not interpreted and about:blank is shown intead. (https://github.com/quilljs/quill/issues/1268#issuecomment-272959998)

Here's what I've written (similar to the official example here):

toolbar.addHandler("link", function sanitizeLinkInput(linkValueInput) {
    console.log(linkValueInput); // debugging

    if (linkValueInput === "")
        this.quill.format(false);

    // do nothing, since it implies user has just clicked the icon
    // for link, hasn't entered url yet
    else if (linkValueInput == true);

    // do nothing, since this implies user's already using a custom protocol
    else if (/^\w+:/.test(linkValueInput));

    else if (!/^https?:/.test(linkValueInput)) {
        linkValueInput = "http:" + linkValueInput;
        this.quill.format("link", linkValueInput);
    }
});

Every time the user clicks the link icon, nothing happens and true is logged to the console. I actually wished this handler to be executed when person clicks "save" on the tooltip that's shown after pressing the link icon.

Any idea how to do this? Hints or suggestions are also appreciated.

Thanks!

like image 424
Gaurang Tandon Avatar asked Jan 17 '17 11:01

Gaurang Tandon


2 Answers

congregating all the information

The snow theme itself uses the toolbar's addHandler to show a tooltip and so it is impossible to use the addHandler method to achieve what we wish to.

So, instead we can do the following:

var Link = Quill.import('formats/link');
var builtInFunc = Link.sanitize;
Link.sanitize = function customSanitizeLinkInput(linkValueInput) {
    var val = linkValueInput;

    // do nothing, since this implies user's already using a custom protocol
    if (/^\w+:/.test(val));
    else if (!/^https?:/.test(val))
        val = "http:" + val;

    return builtInFunc.call(this, val); // retain the built-in logic
};

this method doesn't hook onto handlers but instead modifies the built-in sanitisation logic itself. We have also retained the original behavior of the sanitisation so that doesn't modify the editor's original behavior.

Alternatively, we could actually hook onto the save button of the tooltip, using this code. But it is too long a method compared to the one above.

like image 116
Gaurang Tandon Avatar answered Oct 18 '22 02:10

Gaurang Tandon


As far as I can tell, the handling of creating and updating links is a bit distributed in Quill's sources. The default Snow theme handles editing links to some extent: it tracks the user selection and last selected link internally. Because of this I do not think that it is possible to achieve what you want currently in Quill using only a custom handler.

You may want to open an issue to report this, the authors might be willing to add such a handler.

In the meantime I came up with a way to update the link by simply listening for events causing the edit tooltip to close. There are some complications, because a link can be edited and the theme then relies on its internal tracking to update it. However, all in all I think that this solution is not too bad. You might want to add some error checking here and there, but overall it seems to work nicely and do what you want it do to. I have created a Fiddle demonstrating this. For completeness, I have included it here as a code snippet too.

var quill = new Quill('#editor', {
    modules: {
      toolbar: true
    },
    theme: 'snow'
  }),
  editor = document.getElementById('editor'),
  lastLinkRange = null;

/**
 * Add protocol to link if it is missing. Considers the current selection in Quill.
 */
function updateLink() {
  var selection = quill.getSelection(),
    selectionChanged = false;
  if (selection === null) {
    var tooltip = quill.theme.tooltip;
    if (tooltip.hasOwnProperty('linkRange')) {
      // user started to edit a link
      lastLinkRange = tooltip.linkRange;
      return;
    } else {
      // user finished editing a link
      var format = quill.getFormat(lastLinkRange),
        link = format.link;
      quill.setSelection(lastLinkRange.index, lastLinkRange.length, 'silent');
      selectionChanged = true;
    }
  } else {
    var format = quill.getFormat();
    if (!format.hasOwnProperty('link')) {
      return; // not a link after all
    }
    var link = format.link;
  }
  // add protocol if not there yet
  if (!/^https?:/.test(link)) {
    link = 'http:' + link;
    quill.format('link', link);
    // reset selection if we changed it
    if (selectionChanged) {
      if (selection === null) {
        quill.setSelection(selection, 0, 'silent');
      } else {
        quill.setSelection(selection.index, selection.length, 'silent');
      }
    }
  }
}

// listen for clicking 'save' button
editor.addEventListener('click', function(event) {
  // only respond to clicks on link save action
  if (event.target === editor.querySelector('.ql-tooltip[data-mode="link"] .ql-action')) {
    updateLink();
  }
});

// listen for 'enter' button to save URL
editor.addEventListener('keydown', function(event) {
  // only respond to clicks on link save action
  var key = (event.which || event.keyCode);
  if (key === 13 && event.target === editor.querySelector('.ql-tooltip[data-mode="link"] input')) {
    updateLink();
  }
});
<link href="https://cdn.quilljs.com/1.1.10/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.quilljs.com/1.1.10/quill.min.js"></script>
<div id="editor"></div>

Let me know if you have any questions.

like image 41
Just a student Avatar answered Oct 18 '22 01:10

Just a student