Quill Editor script to read from database

I was afraid of that.

As a thought if you have time, open the full.asp page that I sent you and see what happens on your cell phone. Thanks!

The uploader does work, with the Android phone, you have to click on Documents and then use the side menu to bring up the photo album. My mistake for not seeing that! Thanks again.

1 Like

I am having problems trying to incorporate table code to the existing editor that works just fine. The table code is located at https://codepen.io/quill/pen/QxypzX. Any assistance in this would be greatly appreciated. Thank you.

<html lang="en">
  <head>
    <title>Full Editor - Quill Rich Text Editor</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css" />
    <link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" />


  </head>
  <body>
<div id="standalone-container">
      <div id="toolbar-container">
        <span class="ql-formats">
          <select class="ql-font"></select>
          <select class="ql-size"></select>
        </span>
        <span class="ql-formats">
          <button class="ql-bold"></button>
          <button class="ql-italic"></button>
          <button class="ql-underline"></button>
          <button class="ql-strike"></button>
        </span>
        <span class="ql-formats">
          <select class="ql-color"></select>
          <select class="ql-background"></select>
        </span>
        <span class="ql-formats">
          <button class="ql-script" value="sub"></button>
          <button class="ql-script" value="super"></button>
        </span>
        <span class="ql-formats">
          <button class="ql-header" value="1"></button>
          <button class="ql-header" value="2"></button>
          <button class="ql-blockquote"></button>
          <button class="ql-code-block"></button>
        </span>
        <span class="ql-formats">
          <button class="ql-list" value="ordered"></button>
          <button class="ql-list" value="bullet"></button>
          <button class="ql-indent" value="-1"></button>
          <button class="ql-indent" value="+1"></button>
        </span>
        <span class="ql-formats">
          <button class="ql-direction" value="rtl"></button>
          <select class="ql-align"></select>
        </span>
        <span class="ql-formats">
          <button class="ql-link"></button>
          <button class="ql-image"></button>
          <button class="ql-video"></button>
          <button class="ql-formula"></button>
        </span>
        <span class="ql-formats">
          <button class="ql-clean"></button>
        </span>
      </div>
      <div id="editor-container"></div>
    </div>

    <center>
    <form method="POST" action="post.asp" name="mainform">
      <input type="hidden" id="myHtml" name= "myHtml">
      <input type="hidden" value="45" name= "id">
      <input type="submit" value="Submit">
    </form>
    </center>
 

<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
    <script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>

    <script>
        // Fetch content from database here
        var editorContent = '<%=rs("myHtml")%>';
        var editor = document.getElementById('editor-container');
        var hiddenInput = document.getElementById('myHtml');
        var form = document.forms.mainform;

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

        editor.firstChild.innerHTML = editorContent;

        form.addEventListener('submit', function (e) {
            e.preventDefault();
            hiddenInput.value = editor.firstChild.innerHTML;
            this.submit();
        });

        function selectLocalImage() {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.click(); // Listen upload local image and save to server

            input.onchange = function () {
                var file = input.files[0]; // file type is only image.

                if (/^image\//.test(file.type)) {
                    saveToServer(file);
                } else {
                    console.warn('You could only upload images.');
                }
            };
        }

        function saveToServer(file) {
            var fd = new FormData();
            fd.append('image', file);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://localhost/post.asp', true);

            xhr.onload = function () {
                if (xhr.status === 200) {
                    var url = xhr.responseText;
                    insertToEditor(url);
                }
            };

            xhr.send(fd);
        }

        function insertToEditor(url) {
            // push image url to rich editor.
            var range = quill.getSelection();
            quill.insertEmbed(range.index, 'image', "https://mydomain".concat(url));
        }

        quill.getModule('toolbar').addHandler('image', function () {
            selectLocalImage();
        });


    </script>
  </body>
</html>

Hi,

I just looked at that Pen. It seems a bit clunky with the buttons for table actions below the actual editor.

Wouldn’t something like this be more what you are after?

Demo: http://quilljstable.timepress.cz/quilljs-extended-toolbar/index.html

1 Like

Yes, that’s the only one that I able to find.

Agree - this is much better.

So if that one isn’t too difficult to add to the existing one, I would appreciate it.

Thank you.

I’m afraid I don’t have the time to write everything for you, but here is a quick demo that incorporates the table functionality into the editor you have.

To keep it on point, I’ve removed all of the upload functionality, as well as the tooltips, so you’ll need to add them back in. But hopefully this gives you a good starting point.

<html lang="en">
  <head>
    <title>Full Editor - Quill Rich Text Editor</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" />
    <link href="http://quilljstable.timepress.cz/quilljs-extended-toolbar/css/quill.toolbar.extended.css" rel="stylesheet">
  </head>
  <body>
    <div id="editor"></div>

    <script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>
    <script src="http://quilljstable.timepress.cz/quilljs-extended-toolbar/js/contain.js"></script>
    <script>
      const maxRows = 10;
      const maxCols = 5;
      const tableOptions = [];
      for (let r = 1; r <= maxRows; r++) {
        for (let c = 1; c <= maxCols; c++) {
          tableOptions.push('newtable_' + r + '_' + c);
        }
      }

      const toolbarOptions = [
        [{ 'font': [] }],
        [{ 'size': ['small', false, 'large', 'huge'] }], 
        ['bold', 'italic', 'underline', 'strike'],
        [{ 'color': [] }, { 'background': [] }],
        [{ 'script': 'sub'}, { 'script': 'super' }],
        [{ 'header': 1 }, { 'header': 2 }],
        ['blockquote', 'code-block'],
        [{ 'list': 'ordered'}, { 'list': 'bullet' }],
        [{ 'indent': '-1'}, { 'indent': '+1' }],
        [{ 'direction': 'rtl' }],
        [{ 'align': [] }],
        ['link', 'image', 'video', 'formula'],
        ['clean'],
        [{ 'table': tableOptions }],
        [{ 'table': 'append-row' }],
        [{ 'table': 'append-col' }]
      ];

      const quill = new Quill('#editor', {
        modules: {
          toolbar: {
            container: toolbarOptions,
          }
        },
        theme: 'snow'
      });
    </script>
  </body>
</html>

A couple of pointers:

  • The toolbar is now being initialized in the JavaScript (using a simple array of format names) instead of the custom HTML container.
  • Please don’t link to http://quilljstable.timepress.cz — download the files to your machine and link to those instead.
1 Like

Thanks, for that I will work on it. Regarding this point, is it a good practice to download the other files to my server? Not just this one.

Nah, the other files are on CDNs and are meant to be linked to. This one however, is on some agency’s website and it would be bad form to steal their bandwidth.

1 Like

Had a chance to use this on my own server and the table properties have issues. When inserting a photo into the left cell and then typing a description of photo in the right cell, the text runs together with no spacing of words.

Even though the look is much better, as it is nicely laid out on the top menu, the first “clunky” looking menus at the bottom seem to function better. Probably the best way to make it less clunky would be to have fewer option buttons and then you can do a CSS for form buttons which look much better, and that I know how to do!

Even though my choice would be the second one, I will continue to mess around with the first one to see if I can code it properly to make it functional.

Something here I am not getting. Have the table button on the bottom of the editor but I am still missing a concept to get the JS to work (tables not working - the rest does). I have some of the JS in place and have experimented with placement of the remaining per below, but no results.

<html lang="en">
  <head>
    <title>Full Editor - Quill Rich Text Editor</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css" />
    <link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" />

    <style>
      body > #standalone-container {
        margin: 50px auto;
        max-width: 720px;
      }
      #editor-container {
        height: 350px;
      }
    </style>

    <style>
.tooltip {
    position: relative;
    display: inline-block;
    border-bottom: 0px dotted black;
}

.tooltip .tooltiptext {
    visibility: hidden;
    width: 120px;
    background-color: black;
    color: #fff;
    text-align: center;
    border-radius: 6px;
    padding: 5px 0;
	font-family: consolas,monospace;
    position: absolute;
    bottom: 25px;
    z-index: 1;
}

.tooltip:hover .tooltiptext {
    visibility: visible;
}
</style>

<style>
    img{
    max-height:250px;
    max-width:250px;
    height:auto;
    width:auto;
}</style>

<style>
button[name="snow-container"] {
    font-family: Arial, Helvetica, sans-serif;
    border: 1px solid transparent;
    width: 200px;
    height: 25px;
    font-size: 18px;
    background-color: #4c659b;
    border-radius: 10px;
    color: white;

}
</style>

  </head>
  <body>
           <div id="standalone-container">
       <div id="Div1">
        <div id="Div2">
        <div id="toolbar-container">

        <span class="ql-formats">
            <select class="ql-size"></select>
        <span class="ql-formats">

        <div class="tooltip">
          <span class="tooltiptext">Bold</span>
        <button class="ql-bold"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Italic</span>
        <button class="ql-italic"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Underline</span>
        <button class="ql-underline"></button>
        </div>
        </span>

        <span class="ql-formats">

        <div class="tooltip">
        <span class="tooltiptext">Text color</span>
            <select class="ql-color"></select>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Text color background</span>
        <select class="ql-background"></select>
        </div>

        </span>
      
        <span class="ql-formats">

        <div class="tooltip">
            <span class="tooltiptext">Intent Order by Number</span>
        <button class="ql-list" value="ordered"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Intent Order by Bullets</span>
        <button class="ql-list" value="bullet"></button>
        </div>

        </span>

        <span class="ql-formats">

        <div class="tooltip">
          <span class="tooltiptext">Alignment Left, Center, Right</span>
        <select class="ql-align">
        <option value=""></option>
        <option value="center"></option>
        <option value="right"></option>
        </select>
        </div>

        </span>

        <span class="ql-formats">

        <div class="tooltip">
            <span class="tooltiptext">Hyperlink</span>
        <button class="ql-link"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Image Upload</span>
        <button class="ql-image"></button>
        </div>


        <div class="tooltip">
            <span class="tooltiptext">Youtube Link</span>
        <button class="ql-video"></button>
        </div>
        </span>

      </div>
      <div id="editor-container"></div>
      <br />

      <div class="container">
  <div class="panel">
    <div id="snow-container"></div>
    <div>
      <button id="insert-table">Insert Table</button>
      <button id="insert-row-above">Insert Row Above</button>
      <button id="insert-row-below">Insert Row Below</button>
      <button id="insert-column-left">Insert Column Left</button>
      <button id="insert-column-right">Insert Column Right</button>
      <button id="delete-row">Delete Row</button>
      <button id="delete-column">Delete Column</button>
      <button id="delete-table">Delete Table</button>
    </div>
  </div>
 
  <div class="panel">
    <div id="output-container"></div>
  </div>
</div>

    <center>
    <form method="POST" action="post.asp" name="mainform">
      <input type="hidden" id="myHtml" name= "myHtml">
      <input type="hidden" value="47" name= "id">
      <input type="submit" value="Submit">
    </form>
    </center>
 

<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
    <script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>

    <script>
        // Fetch content from database here
        var editorContent = '<%=rs("myHtml")%>';
        var editor = document.getElementById('editor-container');
        var hiddenInput = document.getElementById('myHtml');
        var form = document.forms.mainform;

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


        document.querySelector('#insert-table').addEventListener('click', function () {
            table.insertTable(2, 2);
        });
        document.querySelector('#insert-row-above').addEventListener('click', function () {
            table.insertRowAbove();
        });
        document.querySelector('#insert-row-below').addEventListener('click', function () {
            table.insertRowBelow();
        });
        document.querySelector('#insert-column-left').addEventListener('click', function () {
            table.insertColumnLeft();
        });
        document.querySelector('#insert-column-right').addEventListener('click', function () {
            table.insertColumnRight();
        });
        document.querySelector('#delete-row').addEventListener('click', function () {
            table.deleteRow();
        });
        document.querySelector('#delete-column').addEventListener('click', function () {
            table.deleteColumn();
        });
        document.querySelector('#delete-table').addEventListener('click', function () {
            table.deleteTable();
        });

        editor.firstChild.innerHTML = editorContent;

        form.addEventListener('submit', function (e) {
            e.preventDefault();
            hiddenInput.value = editor.firstChild.innerHTML;
            this.submit();
        });

        function selectLocalImage() {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.click(); // Listen upload local image and save to server

            input.onchange = function () {
                var file = input.files[0]; // file type is only image.

                if (/^image\//.test(file.type)) {
                    saveToServer(file);
                } else {
                    console.warn('You could only upload images.');
                }
            };
        }

        function saveToServer(file) {
            var fd = new FormData();
            fd.append('image', file);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'https://localhost.post.asp', true);

            xhr.onload = function () {
                if (xhr.status === 200) {
                    var url = xhr.responseText;
                    insertToEditor(url);
                }
            };

            xhr.send(fd);
        }

        function insertToEditor(url) {
            // push image url to rich editor.
            var range = quill.getSelection();
            quill.insertEmbed(range.index, 'image', "https:// 				mydomain.com".concat(url));
        }

        quill.getModule('toolbar').addHandler('image', function () {
            selectLocalImage();
        });


    </script>

 
  </body>
</html>

The rest of JS that I am not getting. I realize that some of it refers to “bubble” but I was trying to piece together the “snow” theme.

<script>
var bubble = new Quill('#bubble-container', {
  theme: 'bubble',
  modules: {
    table: true,
  }
});
var snow = new Quill('#snow-container', {
  theme: 'snow',
  modules: {
    table: true,
  }
});
var output = new Quill('#output-container', {
  theme: 'bubble',
  modules: { table: true },
  readOnly: true,
})
bubble.on('text-change', function(delta, old, source) {
  if (source === 'user') {
    snow.updateContents(delta, 'api');
    updateOutput();
  }
});
const table = snow.getModule('table');
snow.on('text-change', function(delta, old, source) {
  if (source === 'user') {
    bubble.updateContents(delta, 'api');
    updateOutput();
  }
});

function updateOutput() {
  const bubbleContent = bubble.getContents();
  const snowContent = snow.getContents();
  // TODO compare
  output.setContents(bubbleContent);
  const outputContent = output.getContents();
  // TODO compare outputContent
}
</script>

If an easy fix, whenever you have time - appreciated.

If you click one of the table buttons, then look in your browser’s console , you see the error message:

ReferenceError: table is not defined

This is because you have commented it out in your code:

modules: {
  //table: true,

Uncomment that. Then, to add the table module we need to update to Quill version 2.x

<script src="https://cdn.quilljs.com/2.0.0-dev.2/quill.js"></script>

Now you need to define the variable:

const table = quill.getModule('table');

and you’ll be able to insert tables into the editor.

Please note that you’ll need to add some CSS so that you can see the table elements. They’re in the DOM, but need some styling.

1 Like

Yes, forgot to mention that - that was commented out before because when I use that, the editor doesn’t display the rs(“myHtml”)

If I use:

… do I replace it with and take this out?

<script src="https://cdn.quilljs.com/1.3.6/quill.min.js"></script>

Is there a particular place where that is defined?

Thank you!

Yup. The newer version replaces the older version.

Like so:

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

var table = quill.getModule('table');
1 Like

I am doing this:

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

        var table = quill.getModule('table');

        document.querySelector('#insert-table').addEventListener('click', function () {
            table.insertTable(2, 2);
        });
        document.querySelector('#insert-row-above').addEventListener('click', function () {
            table.insertRowAbove();
        });
        document.querySelector('#insert-row-below').addEventListener('click', function () {
            table.insertRowBelow();
        });
        document.querySelector('#insert-column-left').addEventListener('click', function () {
            table.insertColumnLeft();
        });
        document.querySelector('#insert-column-right').addEventListener('click', function () {
            table.insertColumnRight();
        });
        document.querySelector('#delete-row').addEventListener('click', function () {
            table.deleteRow();
        });
        document.querySelector('#delete-column').addEventListener('click', function () {
            table.deleteColumn();
        });
        document.querySelector('#delete-table').addEventListener('click', function () {
            table.deleteTable();
        });

        editor.firstChild.innerHTML = editorContent;

        etc...

The rs(“myHtml”) is working. Put tables don’t work.

Using this for css and that table buttons move many breaks down the page.

<style>
body {
  padding: 25px;
}
#bubble-container, #snow-container {
  height: 300px;
  margin-bottom: 10px;
}
.container {
  display: flex;
}
.panel {
  flex: 1;
  margin-left: 25px;
  margin-right: 25px;
}
</style>

Can you post enough code that I can run on my PC and reproduce your problem, please.

1 Like

Would like to that the css is 1.3.6 if that makes any difference.

<html lang="en">
  <head>
    <title>Full Editor - Quill Rich Text Editor</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/monokai-sublime.min.css" />
    <link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" />

    <style>
      body > #standalone-container {
        margin: 50px auto;
        max-width: 720px;
      }
      #editor-container {
        height: 350px;
      }
    </style>

    <style>
.tooltip {
    position: relative;
    display: inline-block;
    border-bottom: 0px dotted black;
}

.tooltip .tooltiptext {
    visibility: hidden;
    width: 120px;
    background-color: black;
    color: #fff;
    text-align: center;
    border-radius: 6px;
    padding: 5px 0;
	font-family: consolas,monospace;
    position: absolute;
    bottom: 25px;
    z-index: 1;
}

.tooltip:hover .tooltiptext {
    visibility: visible;
}
</style>

<style>
    img{
    max-height:250px;
    max-width:250px;
    height:auto;
    width:auto;
}</style>

<style>
button[name="snow-container"] {
    font-family: Arial, Helvetica, sans-serif;
    border: 1px solid transparent;
    width: 200px;
    height: 25px;
    font-size: 18px;
    background-color: #4c659b;
    border-radius: 10px;
    color: white;

}
</style>

<style>
body {
  padding: 25px;
}
#bubble-container, #snow-container {
  height: 300px;
  margin-bottom: 10px;
}
.container {
  display: flex;
}
.panel {
  flex: 1;
  margin-left: 25px;
  margin-right: 25px;
}
</style>

  </head>
  <body>
           <div id="standalone-container">
       <div id="Div1">
        <div id="Div2">
        <div id="toolbar-container">

        <span class="ql-formats">
            <select class="ql-size"></select>
        <span class="ql-formats">

        <div class="tooltip">
          <span class="tooltiptext">Bold</span>
        <button class="ql-bold"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Italic</span>
        <button class="ql-italic"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Underline</span>
        <button class="ql-underline"></button>
        </div>
        </span>

        <span class="ql-formats">

        <div class="tooltip">
        <span class="tooltiptext">Text color</span>
            <select class="ql-color"></select>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Text color background</span>
        <select class="ql-background"></select>
        </div>

        </span>
      
        <span class="ql-formats">

        <div class="tooltip">
            <span class="tooltiptext">Intent Order by Number</span>
        <button class="ql-list" value="ordered"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Intent Order by Bullets</span>
        <button class="ql-list" value="bullet"></button>
        </div>

        </span>

        <span class="ql-formats">

        <div class="tooltip">
          <span class="tooltiptext">Alignment Left, Center, Right</span>
        <select class="ql-align">
        <option value=""></option>
        <option value="center"></option>
        <option value="right"></option>
        </select>
        </div>

        </span>

        <span class="ql-formats">

        <div class="tooltip">
            <span class="tooltiptext">Hyperlink</span>
        <button class="ql-link"></button>
        </div>

        <div class="tooltip">
            <span class="tooltiptext">Image Upload</span>
        <button class="ql-image"></button>
        </div>


        <div class="tooltip">
            <span class="tooltiptext">Youtube Link</span>
        <button class="ql-video"></button>
        </div>
        </span>

      </div>
      <div id="editor-container"></div>
      <br />

      <div class="container">
  <div class="panel">
    <div id="snow-container"></div>
    <div>
      <button id="insert-table">Insert Table</button>
      <button id="insert-row-above">Insert Row Above</button>
      <button id="insert-row-below">Insert Row Below</button>
      <button id="insert-column-left">Insert Column Left</button>
      <button id="insert-column-right">Insert Column Right</button>
      <button id="delete-row">Delete Row</button>
      <button id="delete-column">Delete Column</button>
      <button id="delete-table">Delete Table</button>
    </div>
  </div>
 
  <div class="panel">
    <div id="output-container"></div>
  </div>
</div>

    <center>
    <form method="POST" action="post.asp" name="mainform">
      <input type="hidden" id="myHtml" name= "myHtml">
      <input type="hidden" value="47" name= "id">
      <input type="submit" value="Submit">
    </form>
    </center>
 

<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
   
    <script src="https://cdn.quilljs.com/2.0.0-dev.2/quill.js"></script>

    <script>
        // Fetch content from database here
        var editorContent = '<%=rs("myHtml")%>';
        var editor = document.getElementById('editor-container');
        var hiddenInput = document.getElementById('myHtml');
        var form = document.forms.mainform;

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

        var table = quill.getModule('table');

        document.querySelector('#insert-table').addEventListener('click', function () {
            table.insertTable(2, 2);
        });
        document.querySelector('#insert-row-above').addEventListener('click', function () {
            table.insertRowAbove();
        });
        document.querySelector('#insert-row-below').addEventListener('click', function () {
            table.insertRowBelow();
        });
        document.querySelector('#insert-column-left').addEventListener('click', function () {
            table.insertColumnLeft();
        });
        document.querySelector('#insert-column-right').addEventListener('click', function () {
            table.insertColumnRight();
        });
        document.querySelector('#delete-row').addEventListener('click', function () {
            table.deleteRow();
        });
        document.querySelector('#delete-column').addEventListener('click', function () {
            table.deleteColumn();
        });
        document.querySelector('#delete-table').addEventListener('click', function () {
            table.deleteTable();
        });

        editor.firstChild.innerHTML = editorContent;

        form.addEventListener('submit', function (e) {
            e.preventDefault();
            hiddenInput.value = editor.firstChild.innerHTML;
            this.submit();
        });

        function selectLocalImage() {
            var input = document.createElement('input');
            input.setAttribute('type', 'file');
            input.click(); // Listen upload local image and save to server

            input.onchange = function () {
                var file = input.files[0]; // file type is only image.

                if (/^image\//.test(file.type)) {
                    saveToServer(file);
                } else {
                    console.warn('You could only upload images.');
                }
            };
        }

        function saveToServer(file) {
            var fd = new FormData();
            fd.append('image', file);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'https://local.com', true);

            xhr.onload = function () {
                if (xhr.status === 200) {
                    var url = xhr.responseText;
                    insertToEditor(url);
                }
            };

            xhr.send(fd);
        }

        function insertToEditor(url) {
            // push image url to rich editor.
            var range = quill.getSelection();
            quill.insertEmbed(range.index, 'image', "https://yourwebsite.com".concat(url));
        }

        quill.getModule('toolbar').addHandler('image', function () {
            selectLocalImage();
        });


    </script>

 
  </body>
</html>

Lol, yeah, that’s right. Good catch. Swap this:

<link rel="stylesheet" href="https://cdn.quilljs.com/1.3.6/quill.snow.css" />

for this:

<link rel="stylesheet" href="https://cdn.quilljs.com/2.0.0-dev.2/quill.snow.css" />

And your example will work.

1 Like

Yes, you are right!
And the nice thing is that on the output the table has no border!
When we began this thread tonight, the table icon buttons lined up nicely underneath the editor, not they look at this:

You can see how far under the table and partial photo that I am showing. Do you see in the css where I can bring them to align better to the bottom of the editor?

Thanks

You can use your browser’s dev tools for this.

The culprit is this line:

<div id="snow-container"></div>

Simply deleting it removes the space.

1 Like