Quill: Allow images to be normal URLs not data URIs?

Created on 17 Aug 2016  路  11Comments  路  Source: quilljs/quill

Could we have a choice about the image behaviour, so that I can just enter a URL for the image source? Relates to Issue #844

I can't seem to find any options to choose how this works. It appears that the right way is to create a new theme, so if I can work that out I'll offer a pull request. It's a complicated feature and I imagine there's many opinions about how it should work. One size may not fit all.

Steps for Reproduction

  1. Using 1.0.0-beta.11
  2. Initialise withtoolbar: [['image']]
  3. Click the image button in the toolbar
  4. Observe that you must upload from your local computer

Expected behavior: I'd quite like to just have an image with src="/some/relative/path.jpg"
Actual behavior: It really wants to upload an image and insert a huge data URI.
Platforms: Any?
Version: Using 1.0.0-beta.11

Most helpful comment

I could upload images to server and insert URL to rich editor.
This is my code:

   const editor = new Quill('#quill-editor', {
      bounds: '#quill-editor',
      modules: {
        toolbar: this.toolbarOptions
      },
      placeholder: 'Free Write...',
      theme: 'snow'
    });

      /**
       * Step1. select local image
       *
       */
    function selectLocalImage() {
      const input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.click();

      // Listen upload local image and save to server
      input.onchange = () => {
        const file = input.files[0];

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

    /**
     * Step2. save to server
     *
     * @param {File} file
     */
    function saveToServer(file: File) {
      const fd = new FormData();
      fd.append('image', file);

      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://localhost:3000/upload/image', true);
      xhr.onload = () => {
        if (xhr.status === 200) {
          // this is callback data: url
          const url = JSON.parse(xhr.responseText).data;
          insertToEditor(url);
        }
      };
      xhr.send(fd);
    }

    /**
     * Step3. insert image url to rich editor.
     *
     * @param {string} url
     */
    function insertToEditor(url: string) {
      // push image url to rich editor.
      const range = editor.getSelection();
      editor.insertEmbed(range.index, 'image', `http://localhost:9000${url}`);
    }

    // quill editor add image handler
    editor.getModule('toolbar').addHandler('image', () => {
      selectLocalImage();
    });

Quill is awesome and easy to extensible.

All 11 comments

Related #822

If you just want to change the image UX the you could just configure its handler instead of implementing an entire theme.

var quill = new Quill('#editor-container', {
    theme: 'snow',
    modules: {
        toolbar: {
          container: [['image']],
          handlers: {
            image: imageHandler
          }
        }
    },
}); 

function imageHandler() {
  var range = this.quill.getSelection();
  var value = prompt('What is the image URL');
  this.quill.insertEmbed(range.index, 'image', value, Quill.sources.USER);
}

Of course there are better UIs than a prompt box but this quickly becomes a slippery slope and maintenance would be prohibitive. So Quill offers one good default and the ability to customize.

I could upload images to server and insert URL to rich editor.
This is my code:

   const editor = new Quill('#quill-editor', {
      bounds: '#quill-editor',
      modules: {
        toolbar: this.toolbarOptions
      },
      placeholder: 'Free Write...',
      theme: 'snow'
    });

      /**
       * Step1. select local image
       *
       */
    function selectLocalImage() {
      const input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.click();

      // Listen upload local image and save to server
      input.onchange = () => {
        const file = input.files[0];

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

    /**
     * Step2. save to server
     *
     * @param {File} file
     */
    function saveToServer(file: File) {
      const fd = new FormData();
      fd.append('image', file);

      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'http://localhost:3000/upload/image', true);
      xhr.onload = () => {
        if (xhr.status === 200) {
          // this is callback data: url
          const url = JSON.parse(xhr.responseText).data;
          insertToEditor(url);
        }
      };
      xhr.send(fd);
    }

    /**
     * Step3. insert image url to rich editor.
     *
     * @param {string} url
     */
    function insertToEditor(url: string) {
      // push image url to rich editor.
      const range = editor.getSelection();
      editor.insertEmbed(range.index, 'image', `http://localhost:9000${url}`);
    }

    // quill editor add image handler
    editor.getModule('toolbar').addHandler('image', () => {
      selectLocalImage();
    });

Quill is awesome and easy to extensible.

@jhchen is there a good example of how to add the same tooltip as video/formula for an image?

@rickhanlonii

Did you have any luck utilizing the existing quill tooltip structure for your custom image handler? I'm just now heading down that road, and am surprised by the lack of answers I am finding.

@Scheerc I had to write a custom Toolbar and Tooltip to support (basically just copied the one that's provided and added to it). I don't think the provided toolbar/tooltip is extendable.

How to solve drag and drop or ctrl+v pictures to send AJAX, but not base64

@TaylorPzreal The code is not working on iOS. But the rest is ok. Better use $(input).on('change', function() { });

@rickhanlonii any chance you could show how you did your custom toolbar/tooltip?

@JohEngstrom I forked the whole snow theme - the tooltip, the toolbar, the blots, the handlers -- everything. I don't remember everything I had to do, but here's how I started

First I extended the Snow theme:

import { Quill } from 'react-quill';

import MyTooltip from '../MyTooltip';

const SnowTheme = Quill.import('themes/snow');

class MyTheme extends SnowTheme {
  extendToolbar(toolbar) {
    super.extendToolbar(toolbar);
    this.tooltip = new MyTooltip(this.quill, this.options.bounds);
  }
}

export default MyTheme;

Then I copied over the tooltip that the Snow theme uses, and customized it:

import { Quill } from 'react-quill';

const Tooltip = Quill.import('ui/tooltip');

class MyTooltip extends Tooltip {
  // copy this for now, then customize
}

Then you can register the theme:

Quill.register('themes/mytheme', MyTheme);

And use it in the editor:

<ReactQuill
  theme={'mytheme'}
/>

That got me started and I worked to customize from there. You may need to go really deep and override some handlers and blots to do what you want

So far it seems like all of the comments with toolbar-base image handler functions only handle the case where an image is added via the button in the toolbar. Is there any way to handle pasted images from the clipboard? Those continue to be saved as base64 and bypass the custom toolbar image handler.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Yves-K picture Yves-K  路  3Comments

aletorrado picture aletorrado  路  3Comments

ouhman picture ouhman  路  3Comments

lustoykov picture lustoykov  路  3Comments

rsdrsd picture rsdrsd  路  3Comments