Skip to content
Advertisement

Adding a custom drop down tool to the Quill Editor with JavaScript

Please note this is a self-answered question.

The Quill Editor’s toolbar module doesn’t appear to offer a way to add custom tools to it using the JavaScript API. You can merely choose from a list of predefined tools or you have to completely rewrite the entire HTML of the toolbar which seems very hacky and often is not an option. Because of that mechanism, tools can’t just be added or removed during runtime and are always static, meaning that (for example) you can’t have a dynamic drop down list that loads or changes it’s entries during runtime.

The Quill Editor itself only offers an API to add another module. So you could write another toolbar module that supports the above mentioned features the original one is lacking, but it would be much nicer to be able to continue using the original one because of the amount of work that would be required to effectively rewrite it.

The question is: How to add a potentially dynamic tool like a drop down menu to an existing Quill Editor instance’s toolbar.

Answer

I wrote a library called DynamicQuillTools which can do the job.

It can be used like this:

const dropDownItems = {
    'Mike Smith': 'mike.smith@gmail.com',
    'Jonathan Dyke': 'jonathan.dyke@yahoo.com',
    'Max Anderson': 'max.anderson@gmail.com'
}

const myDropDown = new QuillToolbarDropDown({
    label: "Email Addresses",
    rememberSelection: false
})

myDropDown.setItems(dropDownItems)

myDropDown.onSelect = function(label, value, quill) {
    // Do whatever you want with the new dropdown selection here

    // For example, insert the value of the dropdown selection:
    const { index, length } = quill.selection.savedRange
    quill.deleteText(index, length)
    quill.insertText(index, value)
    quill.setSelection(index + value.length)
}

myDropDown.attach(quill)

Here is a full demo adding a custom drop down tool and a custom button to a Quill Editor instance:

// Create a Quill Editor instance with some built-in toolbar tools
const quill = new Quill('#editor', {
    theme: 'snow',
    modules: {
        toolbar: {
            container: [
                ['bold', 'italic', 'underline', 'strike'],
                ['blockquote', 'code-block'],

                [{ 'header': 1 }, { 'header': 2 }],
                [{ 'list': 'ordered' }, { 'list': 'bullet' }],
                [{ 'script': 'sub' }, { 'script': 'super' }],
                [{ 'indent': '-1' }, { 'indent': '+1' }],
                [{ 'direction': 'rtl' }],

                [{ 'size': ['small', false, 'large', 'huge'] }],
                [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

                [{ 'color': [] }, { 'background': [] }],
                [{ 'font': [] }],
                [{ 'align': [] }],

                ['clean'],
            ]
        }
    }
})


// Add a custom DropDown Menu to the Quill Editor's toolbar:

const dropDownItems = {
    'Mike Smith': 'mike.smith@gmail.com',
    'Jonathan Dyke': 'jonathan.dyke@yahoo.com',
    'Max Anderson': 'max.anderson@gmail.com'
}

const myDropDown = new QuillToolbarDropDown({
    label: "Email Addresses",
    rememberSelection: false
})

myDropDown.setItems(dropDownItems)

myDropDown.onSelect = function(label, value, quill) {
    // Do whatever you want with the new dropdown selection here

    // For example, insert the value of the dropdown selection:
    const { index, length } = quill.selection.savedRange
    quill.deleteText(index, length)
    quill.insertText(index, value)
    quill.setSelection(index + value.length)
}

myDropDown.attach(quill)


// Add a custom Button to the Quill Editor's toolbar:

const myButton = new QuillToolbarButton({
    icon: `<svg viewBox="0 0 18 18"> <path class="ql-stroke" d="M5,3V9a4.012,4.012,0,0,0,4,4H9a4.012,4.012,0,0,0,4-4V3"></path></svg>`
})
myButton.onClick = function(quill) {
    // Do whatever you want here. You could use this.getValue() or this.setValue() if you wanted.

    // For example, get the selected text and convert it to uppercase:
    const { index, length } = quill.selection.savedRange
    const selectedText = quill.getText(index, length)
    const newText = selectedText.toUpperCase()
    quill.deleteText(index, length)
    quill.insertText(index, newText)
    quill.setSelection(index, newText.length)
}
myButton.attach(quill)
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.quilljs.com/1.3.7/quill.bubble.css"></link>
<link rel="stylesheet" type="text/css" href="https://cdn.quilljs.com/1.3.7/quill.snow.css"></link>
<script src="https://cdn.jsdelivr.net/gh/T-vK/DynamicQuillTools@master/DynamicQuillTools.js"></script>

<div id="editor">The last two elements in the toolbar are our custom tools. The first one (<b>Email Addresses</b>) is a simple drop down menu that inserts the email address of the person selected and the second one (<b>U</b>) is a simple button that makes the selected text uppercase.</div>
Advertisement