Customize attributes when inserting img tags with Vue quill rich text editor

Posted by djopie on Wed, 08 Dec 2021 10:04:56 +0100

Recently, I was tortured by quill.js, a rich text editor, for several days, and finally completed the requirements. Now describe the requirements encountered this time: the product says that it needs to add a graphic mixing function in the rich text editor (the picture needs to support zooming, and the picture and text need to be centered). Before, it was just text, and there was no function of uploading pictures. After getting the requirements, I think it is very simple to add a picture upload function in the rich text editor. After that, many problems were encountered in the development process. Let's explain it in detail. I hope I can help you.
1. The first thing to be solved is the image upload and zoom function. Implementation steps.

      editorOption: {
        theme: "snow", // theme
        placeholder: this.isStem
          ? "Since the question number is automatically generated when generating the test paper, it is recommended that the question stem be entered without the question number"
          : "",
        modules: {
          imageDrop: true, // Drag to load the picture component.
          imageResize: {
            //Resize component.
            displayStyles: {
              backgroundColor: "black",
              border: "none",
              color: "white"
            },
            modules: ["Resize", "DisplaySize", "Toolbar"]
          },
          toolbar: {
            container: [
              ["bold", "italic", "underline", "strike"], // toggled buttons
              [{ script: "sub" }, { script: "super" }],
              [{ align: [] }],
              ["image"]
            ],
            handlers: {
              image: value => {
                if (value) {
                  this.$refs[this.uploadId].$refs["commonUpload"].$refs[
                    "uploadFile"
                  ].$children[0].$refs.input.click();
                } else {
                  this.quill.format("image", false);
                }
              }
            }
          }
        }
      }

This object is the object of the rich text configuration. When toolbar.container joins [[image]], the button for uploading pictures can be transferred in the toolbar. If you use the default upload image, you will eventually return a particularly long string of base64, which is not conducive to back-end storage. Therefore, at this time, we should use the company's upload interface to obtain the returned image access address, and then insert it into rich text.

Define an image key in handlers, and its corresponding function is the function we respond to after clicking the toolbar. In this, I asked him to click the hidden upload button. In the callback function for successful upload, we need to insert the url of the image into the rich text. The code is as follows:

 // Gets the position of the cursor
        let length = this.editor.selection.savedRange.index; //Get cursor position
        if (length == 0) {
          length = this.editor.getLength();
        }
        // Insert a picture, and res is the picture link address returned by the server
        this.editor.insertEmbed(
          length,
          "image",
          "https://kz-teaching-test.oss-cn-beijing.aliyuncs.com/" + e[0].url
        );
        // Adjust cursor to last
        this.editor.setSelection(length + 1);

this.editor here is the quill object, and you can change the name according to your own definition. If there are multiple rich text in the page, it needs to be distinguished according to the unique ID, otherwise the scope will be confused.

2. How to zoom a picture:

import { ImageDrop } from "quill-image-drop-module";
import ImageResize from "quill-image-resize-module";
Quill.register("modules/imageDrop", ImageDrop);
Quill.register("modules/imageResize", ImageResize);
// The following contents can be placed under options.modules, and the overall options definition is above
imageDrop: true, // Drag to load the picture component.
 imageResize: {
   //Resize component.
   displayStyles: {
     backgroundColor: "black",
     border: "none",
     color: "white"
   },
   modules: ["Resize", "DisplaySize", "Toolbar"]
 },

If it is a version after vue-cli3, we need to import it in vue.config.js after introducing these

  plugins: [
        new webpack.ProvidePlugin({
            // Add the following two lines here
            'window.Quill': 'quill/dist/quill.js',
            'Quill': 'quill/dist/quill.js'
    })
    ]

3. After solving the problem of uploading pictures, there is also a function of displaying pictures and text in the middle. If the default text and picture are together, they are relatively flush with the bottom of the picture and text. A property is designed here, which is vertical align. Let's take a look at the default situation and the situation after changing this property:

The default is bottom alignment. After we change it to vertical align: middle

We can see that he is centered. However, how to add the css attribute to the img tag when inserting the tag? After research, it is found that the insertembebd api does not support adding attributes. If necessary, you need to customize this class. The code is as follows:

var BlockEmbed = Quill.import('blots/block/embed')
         class ImageBlot extends BlockEmbed {
          static create(value) {
            let node = super.create();
            node.setAttribute('src', value.url);
            node.setAttribute('controls', value.controls)
            node.setAttribute('width', value.width)
            node.setAttribute('height', value.height)
            return node;
        }

        static value(node) {
            return{
                url:node.getAttribute('src'),
                controls:node.getAttribute('controls'),
                width: node.getAttribute('width'),
                height:node.getAttribute('height')
            }
         }
      }
      ImageBlot.blotName = 'image';
      ImageBlot.tagName = 'img';

   // Mode of use
  quill.insertEmbed(range.index, 'image',{     
  url:url,heigth:'',widht:''  })                                                                                                  
 // In this way, we can define the properties when adding rich text, but it will wrap lines. This problem is not solved. If it is solved, let me know.

Reference link:
quill.js.com
https://quilljs.com/guides/cloning-medium-with-parchment/#dividers

Topics: Javascript Front-end Vue.js