primevue-mirror/components/lib/editor/Editor.vue

178 lines
6.8 KiB
Vue
Raw Normal View History

2022-09-06 12:03:37 +00:00
<template>
<div :class="cx('root')" v-bind="ptm('root')">
2023-05-25 14:18:27 +00:00
<div ref="toolbarElement" :class="cx('toolbar')" v-bind="ptm('toolbar')">
2022-09-06 12:03:37 +00:00
<slot name="toolbar">
2023-08-04 10:02:52 +00:00
<span class="ql-formats" v-bind="ptm('formats')">
<select class="ql-header" defaultValue="0" v-bind="ptm('header')">
2023-05-05 10:15:25 +00:00
<option value="1" v-bind="ptm('option')">Heading</option>
<option value="2" v-bind="ptm('option')">Subheading</option>
<option value="0" v-bind="ptm('option')">Normal</option>
2022-09-06 12:03:37 +00:00
</select>
2023-08-04 10:02:52 +00:00
<select class="ql-font" v-bind="ptm('font')">
2023-05-05 10:15:25 +00:00
<option v-bind="ptm('option')"></option>
<option value="serif" v-bind="ptm('option')"></option>
<option value="monospace" v-bind="ptm('option')"></option>
2022-09-06 12:03:37 +00:00
</select>
</span>
2023-08-04 10:02:52 +00:00
<span class="ql-formats" v-bind="ptm('formats')">
<button class="ql-bold" type="button" v-bind="ptm('bold')"></button>
<button class="ql-italic" type="button" v-bind="ptm('italic')"></button>
<button class="ql-underline" type="button" v-bind="ptm('underline')"></button>
2022-09-06 12:03:37 +00:00
</span>
2023-08-04 10:02:52 +00:00
<span :key="reRenderColorKey" class="ql-formats" v-bind="ptm('formats')">
<select class="ql-color" v-bind="ptm('color')"></select>
<select class="ql-background" v-bind="ptm('background')"></select>
2022-09-06 12:03:37 +00:00
</span>
2023-08-04 10:02:52 +00:00
<span class="ql-formats" v-bind="ptm('formats')">
<button class="ql-list" value="ordered" type="button" v-bind="ptm('list')"></button>
<button class="ql-list" value="bullet" type="button" v-bind="ptm('list')"></button>
<select class="ql-align" v-bind="ptm('select')">
2023-05-05 10:15:25 +00:00
<option defaultValue v-bind="ptm('option')"></option>
<option value="center" v-bind="ptm('option')"></option>
<option value="right" v-bind="ptm('option')"></option>
<option value="justify" v-bind="ptm('option')"></option>
2022-09-06 12:03:37 +00:00
</select>
</span>
2023-08-04 10:02:52 +00:00
<span class="ql-formats" v-bind="ptm('formats')">
<button class="ql-link" type="button" v-bind="ptm('link')"></button>
<button class="ql-image" type="button" v-bind="ptm('image')"></button>
<button class="ql-code-block" type="button" v-bind="ptm('codeBlock')"></button>
2022-09-06 12:03:37 +00:00
</span>
2023-08-04 10:02:52 +00:00
<span class="ql-formats" v-bind="ptm('formats')">
<button class="ql-clean" type="button" v-bind="ptm('clean')"></button>
2022-09-06 12:03:37 +00:00
</span>
</slot>
</div>
2023-05-25 14:18:27 +00:00
<div ref="editorElement" :class="cx('content')" :style="editorStyle" v-bind="ptm('content')"></div>
2022-09-06 12:03:37 +00:00
</div>
</template>
<script>
2022-09-14 11:26:01 +00:00
import { DomHandler } from 'primevue/utils';
2023-05-25 14:18:27 +00:00
import BaseEditor from './BaseEditor.vue';
2022-09-14 11:26:01 +00:00
const QuillJS = (function () {
try {
return window.Quill;
} catch {
return null;
}
})();
2022-09-06 12:03:37 +00:00
export default {
name: 'Editor',
2023-05-25 14:18:27 +00:00
extends: BaseEditor,
2022-09-14 11:26:01 +00:00
emits: ['update:modelValue', 'text-change', 'selection-change', 'load'],
data() {
return {
reRenderColorKey: 0
};
},
2022-09-06 12:03:37 +00:00
quill: null,
watch: {
modelValue(newValue, oldValue) {
if (newValue !== oldValue && this.quill && !this.quill.hasFocus()) {
this.reRenderColorKey++;
2022-09-06 12:03:37 +00:00
this.renderValue(newValue);
}
},
readonly() {
this.handleReadOnlyChange();
2022-09-06 12:03:37 +00:00
}
},
mounted() {
2022-09-14 11:26:01 +00:00
const configuration = {
2022-09-06 12:03:37 +00:00
modules: {
2022-09-14 11:26:01 +00:00
toolbar: this.$refs.toolbarElement,
...this.modules
2022-09-06 12:03:37 +00:00
},
readOnly: this.readonly,
theme: 'snow',
formats: this.formats,
placeholder: this.placeholder
2022-09-14 11:26:01 +00:00
};
if (QuillJS) {
// Loaded by script only
this.quill = new QuillJS(this.$refs.editorElement, configuration);
this.initQuill();
this.handleLoad();
} else {
import('quill')
.then((module) => {
if (module && DomHandler.isExist(this.$refs.editorElement)) {
if (module.default) {
// webpack
this.quill = new module.default(this.$refs.editorElement, configuration);
} else {
// parceljs
this.quill = new module(this.$refs.editorElement, configuration);
}
this.initQuill();
}
})
.then(() => {
this.handleLoad();
});
}
},
beforeUnmount() {
this.quill = null;
},
methods: {
renderValue(value) {
if (this.quill) {
if (value) this.quill.setContents(this.quill.clipboard.convert(value));
else this.quill.setText('');
}
},
initQuill() {
this.renderValue(this.modelValue);
this.quill.on('text-change', (delta, oldContents, source) => {
if (source === 'user') {
let html = this.$refs.editorElement.children[0].innerHTML;
let text = this.quill.getText().trim();
2022-09-06 12:03:37 +00:00
2022-09-14 11:26:01 +00:00
if (html === '<p><br></p>') {
html = '';
}
2022-09-06 12:03:37 +00:00
2022-09-14 11:26:01 +00:00
this.$emit('update:modelValue', html);
this.$emit('text-change', {
htmlValue: html,
textValue: text,
delta: delta,
source: source,
instance: this.quill
});
}
});
this.quill.on('selection-change', (range, oldRange, source) => {
2022-09-06 12:03:37 +00:00
let html = this.$refs.editorElement.children[0].innerHTML;
let text = this.quill.getText().trim();
2022-09-14 11:26:01 +00:00
this.$emit('selection-change', {
2022-09-06 12:03:37 +00:00
htmlValue: html,
textValue: text,
2022-09-14 11:26:01 +00:00
range: range,
oldRange: oldRange,
2022-09-06 12:03:37 +00:00
source: source,
instance: this.quill
});
2022-09-14 11:26:01 +00:00
});
},
handleLoad() {
if (this.quill && this.quill.getModule('toolbar')) {
this.$emit('load', { instance: this.quill });
2022-09-06 12:03:37 +00:00
}
},
handleReadOnlyChange() {
if (this.quill) this.quill.enable(!this.readonly);
2022-09-06 12:03:37 +00:00
}
}
2022-09-14 11:26:01 +00:00
};
2022-09-06 12:03:37 +00:00
</script>