UNPKG

quill-image-super-solution-module

Version:

The ultimate solution. Image upload server. Copy, drag and drop to upload server.

322 lines (305 loc) 9.92 kB
/** *@description 观察者模式 全局监听富文本编辑器 */ export const QuillWatch = { watcher: {}, // 登记编辑器信息 active: null, // 当前触发的编辑器 on: function(imageExtendId, ImageExtend) { // 登记注册使用了ImageEXtend的编辑器 if (!this.watcher[imageExtendId]) { this.watcher[imageExtendId] = ImageExtend; } }, emit: function(activeId, type = 1) { // 事件发射触发 this.active = this.watcher[activeId]; if (type === 1) { imgHandler(); } }, }; /** * @description 图片功能拓展: 增加上传 拖动 复制 */ export class ImageExtend { /** * @param quill {Quill}富文本实例 * @param config {Object} options * config keys: action, headers, editForm start end error size response */ constructor(quill, config = {}) { this.id = Math.random(); this.quill = quill; this.quill.id = this.id; this.config = config; this.file = ""; // 要上传的图片 this.imgURL = ""; // 图片地址 quill.root.addEventListener("paste", this.pasteHandle.bind(this), false); quill.root.addEventListener("drop", this.dropHandle.bind(this), false); quill.root.addEventListener( "dropover", function(e) { e.preventDefault(); }, false ); this.cursorIndex = 0; QuillWatch.on(this.id, this); } /** * @description 检验图片大小是否超出限制 */ checkPicSize() { let self = this; if (self.config.size && self.file.size >= self.config.size * 1024 * 1024) { if (self.config.sizeError) { self.config.sizeError(); } return false; } return true; } /** * @description 粘贴 * @param e */ pasteHandle(e) { e.preventDefault(); QuillWatch.emit(this.quill.id, 0); let clipboardData = e.clipboardData; let i = 0; let items, item, types; if (clipboardData) { items = clipboardData.items; if (!items) { return; } item = items[0]; types = clipboardData.types || []; for (; i < types.length; i++) { if (types[i] === "Files") { item = items[i]; break; } } if (item && item.kind === "file" && item.type.match(/^image\//i)) { this.file = item.getAsFile(); let self = this; // 如果图片限制大小 if (!this.checkPicSize()) { return; } if (this.config.action) { this.uploadImg(); } else { this.toBase64(); } } if (item && item.kind === "string" && ["text/plain", "text/html"].indexOf(item.types)) { //将粘贴的文本内容插入到编辑器中 item.getAsString(function(s) { const self = QuillWatch.active; let length = self.quill.getSelection(true).index; self.cursorIndex = length; self.quill.insertText(QuillWatch.active.cursorIndex, s.replace(/\s{2,}/g, "\n")); self.quill.update(); setTimeout(() => self.quill.setSelection(self.cursorIndex + s.length, 0), 0); }); } } } /** * 拖拽 * @param e */ dropHandle(e) { QuillWatch.emit(this.quill.id, 0); const self = this; e.preventDefault(); // 如果图片限制大小 if (!self.checkPicSize()) { return; } self.file = e.dataTransfer.files[0]; // 获取到第一个上传的文件对象 if (this.config.action) { self.uploadImg(); } else { self.toBase64(); } } /** * @description 将图片转为base4 */ toBase64() { const self = this; const reader = new FileReader(); reader.onload = (e) => { // 返回base64 self.imgURL = e.target.result; self.insertImg(); }; reader.readAsDataURL(self.file); } /** * @description 上传图片到服务器 */ uploadImg() { const self = this; let quillLoading = self.quillLoading; let config = self.config; // 构造表单 let formData = new FormData(); formData.append(config.name, self.file); // 自定义修改表单 if (config.editForm) { config.editForm(formData); } // 创建ajax请求 let xhr = new XMLHttpRequest(); xhr.open("post", config.action, true); // 如果有设置请求头 if (config.headers) { config.headers(xhr); } if (config.change) { config.change(xhr, formData); } xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { //success let res = JSON.parse(xhr.responseText); self.imgURL = config.response(res); QuillWatch.active.uploadSuccess(); self.insertImg(); if (self.config.success) { self.config.success(); } } else { //error if (self.config.error) { self.config.error(); } QuillWatch.active.uploadError(); } } }; // 开始上传数据 xhr.upload.onloadstart = function(e) { QuillWatch.active.uploading(); // let length = (self.quill.getSelection() || {}).index || self.quill.getLength() // self.quill.insertText(length, '[uploading...]', { 'color': 'red'}, true) if (config.start) { config.start(); } }; // 上传过程 xhr.upload.onprogress = function(e) { let complete = (((e.loaded / e.total) * 100) | 0) + "%"; QuillWatch.active.progress(complete); }; // 当发生网络异常的时候会触发,如果上传数据的过程还未结束 xhr.upload.onerror = function(e) { QuillWatch.active.uploadError(); if (config.error) { config.error(); } }; // 上传数据完成(成功或者失败)时会触发 xhr.upload.onloadend = function(e) { if (config.end) { config.end(); } }; xhr.send(formData); } /** * @description 往富文本编辑器插入图片 */ insertImg() { const self = QuillWatch.active; self.quill.insertEmbed(QuillWatch.active.cursorIndex, "image", self.imgURL); self.quill.update(); self.quill.setSelection(self.cursorIndex + 1); } /** * @description 显示上传的进度 */ progress(pro) { pro = "[" + "uploading" + pro + "]"; QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace( /\[uploading.*?\]/, pro ); } /** * 开始上传 */ uploading() { let length = QuillWatch.active.quill.getSelection(true).index; QuillWatch.active.cursorIndex = length; QuillWatch.active.quill.insertText(QuillWatch.active.cursorIndex, "[uploading...]", { color: "red" }, true); } /** * 上传失败 */ uploadError() { QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace( /\[uploading.*?\]/, "[upload error]" ); } uploadSuccess() { QuillWatch.active.quill.root.innerHTML = QuillWatch.active.quill.root.innerHTML.replace(/\[uploading.*?\]/, ""); } } /** * @description 点击图片上传 */ export function imgHandler() { let fileInput = document.querySelector(".quill-image-input"); if (fileInput === null) { fileInput = document.createElement("input"); fileInput.setAttribute("type", "file"); fileInput.classList.add("quill-image-input"); fileInput.style.display = "none"; // 监听选择文件 fileInput.addEventListener("change", function() { let self = QuillWatch.active; self.file = fileInput.files[0]; fileInput.value = ""; // 可设置上传图片的格式 fileInput.setAttribute("accept", self.config.accept); // 如果图片限制大小 if (!self.checkPicSize()) { return; } if (self.config.action) { self.uploadImg(); } else { self.toBase64(); } }); document.body.appendChild(fileInput); } fileInput.click(); } /** *@description 全部工具栏 */ export const 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"], ["link", "image", "video"], ];