UNPKG

@opentiny/vue-renderless

Version:

An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.

206 lines (205 loc) 6.69 kB
import "../chunk-G2ADBYYC.js"; import { extend } from "@opentiny/utils"; import { xss } from "@opentiny/utils"; import { getToolbarTips, defaultOptions } from "./options"; import registerTableModule from "./table-module"; import registerCustomClipboard from "./clipboard"; const initContent = ({ state, props, nextTick }) => () => { if (state.quill) { const flag = state.quill.selection.hasFocus(); if (state.content && state.content !== state.innerContent) { state.innerContent = state.content; state.quill.pasteHTML(xss.filterHtml(state.content)); } else { if (!state.content) { state.quill.setText(""); } } nextTick(() => { if (!props.disabled && !props.displayOnly) { state.quill.enable(true); } flag ? state.quill.selection.focus() : state.quill.blur(); }); } }; const initQuill = ({ api, emit, props, vm, service, state, Quill, ImageDrop, ImageUpload, FileUpload }) => () => { state.innerOptions = extend(true, {}, defaultOptions, props.globalOptions, props.options); if (document.caretRangeFromPoint) { if (props.imageDrop) { Quill.register("modules/imageDrop", ImageDrop, true); state.innerOptions.modules.imageDrop = props.imageDrop; } if (props.imageUpload) { Quill.register("modules/imageUpload", ImageUpload, true); state.innerOptions.modules.imageUpload = props.imageUpload; } if (props.fileUpload) { Quill.register("modules/fileUpload", FileUpload, true); state.innerOptions.modules.fileUpload = extend( true, {}, { httpRequest: service && service.network.request }, props.fileUpload, { url: state.fileUploadUrl } ); } } registerTableModule(Quill); if (state.innerOptions.modules) { state.innerOptions.modules.tableModule = props.tableModule === true; } registerCustomClipboard(Quill, props.keepClass); state.quill = Object.freeze(new Quill(vm.$refs.editor, state.innerOptions)); state.quill.enable(false); state.quill.on("selection-change", api.selectionChange); state.quill.on("text-change", api.textChange); state.quill.root.addEventListener("click", api.handleClick); if (state.content) { state.quill.pasteHTML(xss.filterHtml(state.content)); api.textChange(); } if (!props.disabled && !props.displayOnly) { state.quill.enable(true); } emit("ready", state.quill); api.setToolbarTips(); }; const handleClick = ({ state, Quill }) => (event) => { const el = event.target; if (!(el instanceof HTMLElement) || el.tagName !== "IMG") { return; } event.stopPropagation(); const imgBlot = Quill.find(el); const index = state.quill.getIndex(imgBlot); state.quill.setSelection(index + 1); }; const setToolbarTips = ({ t, vm }) => () => { let tip; const item = getToolbarTips(t); const length = item.length; const richTextEl = vm.$el; for (let i = 0; i < length; i++) { tip = richTextEl.querySelectorAll(".quill-editor " + item[i].Choice); if (tip.length) { Array.prototype.slice.call(tip).forEach((ite) => { ite.setAttribute("title", item[i].title); }); } } tip = richTextEl.querySelectorAll(".quill-editor .ql-file"); if (tip.length) { const iconEl = vm.$refs.iconFile.$el; Array.prototype.slice.call(tip).forEach((ite) => { ite.innerHTML = getOuterHTML(iconEl); }); } }; const setPlaceholder = ({ state, props }) => () => { if (state.quill) { state.quill.root.setAttribute("data-placeholder", props.options.placeholder); } }; const getFileUploadUrl = ({ service }) => () => { return service ? service.common.getFileUploadUrl() : Promise.resolve(""); }; const selectionChange = ({ emit, state }) => (range) => { if (!range) { emit("blur", state.quill); } else { emit("focus", state.quill); } }; const handlePaste = ({ state }) => (event) => { const rangeLength = state.quill.selection.savedRange.length || 0; const newLength = event.clipboardData.getData("text").length || 0; const currentLength = state.quill.getText().length || 0; const totalLength = currentLength - rangeLength + newLength; if (totalLength > state.maxLength) { event.preventDefault(); state.pasteCanceled = true; } else { state.pasteCanceled = false; } }; const maxLength = ({ props, constants }) => () => { return props.maxLength > 0 ? props.maxLength : constants.MAX_LENGTH; }; const isDisplayOnly = ({ state, props, parent, nextTick }) => () => { let displayOnly = props.displayOnly || (parent.auiForm || {}).displayOnly; nextTick(() => { if (state.quill && !props.disabled) { state.quill.root.setAttribute("contenteditable", !displayOnly); } }); return displayOnly; }; const textChange = ({ emit, vm, state, Modal, t }) => (delta, oldDelta) => { const quill = state.quill; if (state.pasteCanceled) { state.pasteCanceled = false; quill.setContents(oldDelta); Modal.message({ message: `${t("ui.richText.maxLength")}${state.maxLength}`, status: "warning" }); return; } const text = state.quill.getText(); const currentLength = text.length - 1; const maxLength2 = state.maxLength; if (currentLength > maxLength2) { quill.setContents(oldDelta); Modal.message({ message: `${t("ui.richText.maxLength")}${state.maxLength}`, status: "warning" }); return; } let html = xss.filterHtml(vm.$refs.editor.children[0].innerHTML); if (html === "<p><br></p>") html = ""; state.innerContent = html; emit("update:modelValue", html); emit("change", { html, text, quill }); }; const getOuterHTML = (el) => { if (!el.outerHTML) { const container = document.createElement("div"); container.appendChild(el); return xss.filterHtml(container.innerHTML); } else { return xss.filterHtml(el.outerHTML); } }; const mounted = ({ api, props, state, i18n, watch }) => () => { if (props.fileUpload && !props.fileUpload.url) { api.getFileUploadUrl().then((url) => { url = xss.filterUrl(url); state.fileUploadUrl = url; api.initQuill(); }); } else { api.initQuill(); } if (i18n) { watch(() => i18n.locale, api.setToolbarTips); } }; const beforeUnmount = ({ api, state }) => () => { state.quill.off("selection-change", api.selectionChange); state.quill.off("text-change", api.textChange); state.quill.root.removeEventListener("click", api.handleClick); state.quill = null; delete state.quill; }; export { beforeUnmount, getFileUploadUrl, handleClick, handlePaste, initContent, initQuill, isDisplayOnly, maxLength, mounted, selectionChange, setPlaceholder, setToolbarTips, textChange };