Search code examples
javascripthtmlquill

How can I add a new format (<hr> tag) to Quill.js?


I want to add a button which would add a <hr> tag to the quill.js (beta) editor.

Here the fiddle.

<!-- Initialize Quill editor -->
    <div id="toolbar-container">
        <span class="ql-formats">
          <button class="ql-hr"></button>  //here my hr-button
        </span>
        <span class="ql-formats">
          <button class="ql-bold"></button>
          <button class="ql-italic"></button>
        </span>
    </div>

    <div id="editor">

      <p>Hello World!</p>
      <hr> // this gets replaced by <p> tag automatically *strange*
      <p>Some initial <strong>bold</strong> text</p>
    </div>

I initialize my editor:

 var quill = new Quill('#editor', {
        modules: {
          toolbar: '#toolbar-container'
        },
        placeholder: 'Compose an epic...',
        theme: 'snow'
      });

Here I add a <h1> tag functionality to my editor and it works very well:

  $('.ql-hr').on("click",function(){

      var range = quill.getSelection();      
      var text = quill.getText(range.index, range.length);
      quill.deleteText(range.index, range.length);
      quill.pasteHTML(range.index, '<h1>'+text+'</h1>');
  })

Now I try the same for a <hr> tag, which doesn't work at all:

  $('.ql-hr').on("click",function(){

      var range = quill.getSelection();      
      quill.pasteHTML(range.index, '<hr>');
  })

the <hr> tag in the initial div#editor gets replaced with a <p> tag. And the button functionality I added doensn't work for <hr> tags, but for other tags it works. I know the <hr> tag is not implemented to Quill.js, that's also why I get this console output:

quill:toolbar ignoring attaching to nonexistent format hr select.ql-hr

Is there any way to fix this?


Solution

  • I have still no idea why the question has downvotes, but however here is the solution:

    Import the embed blot - important: not "block", not "embed", "block/embed"!

    var Embed = Quill.import('blots/block/embed');
    

    Define a new class that extends that Embed

    class Hr extends Embed {
        static create(value) {
            let node = super.create(value);
            // give it some margin
            node.setAttribute('style', "height:0px; margin-top:10px; margin-bottom:10px;");
            return node;
        }
    }
    

    Define your tag

    Hr.blotName = 'hr'; //now you can use .ql-hr classname in your toolbar
    Hr.className = 'my-hr';
    Hr.tagName = 'hr';
    

    Write a custom handler for the <hr> button

    var customHrHandler = function(){
        // get the position of the cursor
        var range = quill.getSelection();
        if (range) {
            // insert the <hr> where the cursor is
            quill.insertEmbed(range.index,"hr","null")
        }
    }
    

    Register your new format

    Quill.register({
        'formats/hr': Hr
    });
    

    Instantiate your Editor with the right selectors in your HTML

    var quill = new Quill('#editor', {
        modules: {
            toolbar: { container: '#toolbar-container',
                handlers: {
                    'hr': customHrHandler
                }
            }
        },
        theme: 'snow'
    });
    

    The HTML part remains the same. The whole <hr> functionality can be done similar to the <img> format.

    Thank you, you helpful community.