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!
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With