vue-editify 0.0.51 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/examples/App.vue +25 -5594
- package/lib/editify.es.js +6859 -7821
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/Editify.vue +273 -1255
- package/src/components/{bussiness/Menu.vue → Menu.vue} +235 -142
- package/src/components/{bussiness/Toolbar.vue → Toolbar.vue} +227 -141
- package/src/components/base/Button.vue +6 -6
- package/src/components/base/Checkbox.vue +4 -4
- package/src/components/base/Layer.vue +12 -12
- package/src/components/{bussiness → common}/InsertImage.vue +7 -7
- package/src/components/{bussiness → common}/InsertVideo.vue +7 -7
- package/src/core/function.js +1044 -0
- package/src/core/rule.js +239 -0
- package/src/core/{index.js → tool.js} +62 -291
- package/src/index.js +1 -1
- /package/src/components/{bussiness → common}/Colors.vue +0 -0
- /package/src/components/{bussiness → common}/InsertLink.vue +0 -0
- /package/src/components/{bussiness → common}/InsertTable.vue +0 -0
package/src/Editify.vue
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
<template>
|
2
|
-
<div class="editify" :class="{
|
2
|
+
<div class="editify" :class="{ fullscreen: isFullScreen }">
|
3
3
|
<!-- 菜单区域 -->
|
4
|
-
<Menu v-if="menuConfig.use" :config="menuConfig" :
|
4
|
+
<Menu v-if="menuConfig.use" :config="menuConfig" :color="color" ref="menu"></Menu>
|
5
5
|
<!-- 编辑层,与编辑区域宽高相同必须适配 -->
|
6
6
|
<div ref="body" class="editify-body" :class="{ border: showBorder, menu_inner: menuConfig.use && menuConfig.mode == 'inner' }" :data-editify-uid="uid">
|
7
7
|
<!-- 编辑器 -->
|
8
|
-
<div ref="content" class="editify-content" :class="{ placeholder: showPlaceholder, disabled: disabled }"
|
8
|
+
<div ref="content" class="editify-content" :class="{ placeholder: showPlaceholder, disabled: disabled }" @keydown="handleEditorKeydown" @click="handleEditorClick" @compositionstart="isInputChinese = true" @compositionend="isInputChinese = false" :data-editify-placeholder="placeholder"></div>
|
9
9
|
<!-- 代码视图 -->
|
10
10
|
<textarea v-if="isSourceView" :value="value" readonly class="editify-source" />
|
11
11
|
<!-- 工具条 -->
|
@@ -21,16 +21,18 @@
|
|
21
21
|
<script>
|
22
22
|
import { getCurrentInstance } from 'vue'
|
23
23
|
import { AlexEditor, AlexElement } from 'alex-editor'
|
24
|
-
import
|
25
|
-
import { pasteKeepData, editorProps,
|
26
|
-
import
|
24
|
+
import { element as DapElement, event as DapEvent, data as DapData, number as DapNumber, color as DapColor } from 'dap-util'
|
25
|
+
import { pasteKeepData, editorProps, mergeObject, getToolbarConfig, getMenuConfig } from './core/tool'
|
26
|
+
import { parseList, orderdListHandle, mediaHandle, tableHandle, preHandle, specialInblockHandle } from './core/rule'
|
27
|
+
import { isTask, elementToParagraph, getCurrentParsedomElement, hasTableInRange, hasLinkInRange, hasPreInRange, hasImageInRange, hasVideoInRange, setIndentIncrease, setIndentDecrease, insertImage, insertVideo } from './core/function'
|
27
28
|
import Tooltip from './components/base/Tooltip'
|
28
|
-
import
|
29
|
+
import Toolbar from './components/Toolbar'
|
30
|
+
import Menu from './components/Menu'
|
29
31
|
|
30
32
|
export default {
|
31
33
|
name: 'editify',
|
32
34
|
props: { ...editorProps },
|
33
|
-
emits: ['update:modelValue', 'focus', 'blur', 'change', 'keydown', 'insertparagraph', 'rangeupdate', '
|
35
|
+
emits: ['update:modelValue', 'focus', 'blur', 'change', 'keydown', 'insertparagraph', 'rangeupdate', 'updateview'],
|
34
36
|
setup() {
|
35
37
|
const instance = getCurrentInstance()
|
36
38
|
return {
|
@@ -39,14 +41,8 @@ export default {
|
|
39
41
|
},
|
40
42
|
data() {
|
41
43
|
return {
|
42
|
-
//编辑器对象
|
43
|
-
editor: null,
|
44
44
|
//是否编辑器内部修改值
|
45
45
|
isModelChange: false,
|
46
|
-
//是否代码视图
|
47
|
-
isSourceView: false,
|
48
|
-
//是否全屏
|
49
|
-
isFullScreen: false,
|
50
46
|
//是否正在输入中文
|
51
47
|
isInputChinese: false,
|
52
48
|
//表格列宽拖拽记录数据
|
@@ -63,12 +59,22 @@ export default {
|
|
63
59
|
//类型
|
64
60
|
type: 'text'
|
65
61
|
},
|
66
|
-
|
67
|
-
|
62
|
+
|
63
|
+
/** 以下是可对外使用的属性 */
|
64
|
+
|
65
|
+
//编辑器对象
|
66
|
+
editor: null,
|
67
|
+
//是否代码视图
|
68
|
+
isSourceView: false,
|
69
|
+
//是否全屏
|
70
|
+
isFullScreen: false,
|
68
71
|
//菜单栏是否可以使用标识
|
69
72
|
canUseMenu: false,
|
70
|
-
|
71
|
-
|
73
|
+
//光标选取范围内的元素数组
|
74
|
+
dataRangeCaches: {
|
75
|
+
flatList: [],
|
76
|
+
list: []
|
77
|
+
}
|
72
78
|
}
|
73
79
|
},
|
74
80
|
computed: {
|
@@ -83,7 +89,7 @@ export default {
|
|
83
89
|
},
|
84
90
|
//编辑器的纯文本值
|
85
91
|
textValue() {
|
86
|
-
return
|
92
|
+
return DapElement.string2dom(`<div>${this.value}</div>`).innerText
|
87
93
|
},
|
88
94
|
//是否显示占位符
|
89
95
|
showPlaceholder() {
|
@@ -103,15 +109,6 @@ export default {
|
|
103
109
|
}
|
104
110
|
return this.border
|
105
111
|
},
|
106
|
-
//编辑器样式设置
|
107
|
-
contentStyle() {
|
108
|
-
if (this.height === true || this.isFullScreen) {
|
109
|
-
return {
|
110
|
-
height: this.contentHeight + 'px'
|
111
|
-
}
|
112
|
-
}
|
113
|
-
return this.autoheight ? { minHeight: this.height } : { height: this.height }
|
114
|
-
},
|
115
112
|
//最终生效的工具栏配置
|
116
113
|
toolbarConfig() {
|
117
114
|
return mergeObject(getToolbarConfig(this.$editTrans, this.$editLocale), this.toolbar || {})
|
@@ -152,19 +149,12 @@ export default {
|
|
152
149
|
}
|
153
150
|
}
|
154
151
|
},
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
this.
|
159
|
-
}
|
160
|
-
|
161
|
-
//监听height为true
|
162
|
-
height: {
|
163
|
-
immediate: true,
|
164
|
-
handler: function () {
|
165
|
-
this.$nextTick(() => {
|
166
|
-
this.setContentHeight()
|
167
|
-
})
|
152
|
+
//监听disabled
|
153
|
+
disabled(newValue) {
|
154
|
+
if (newValue) {
|
155
|
+
this.editor.setDisabled()
|
156
|
+
} else {
|
157
|
+
this.editor.setEnabled()
|
168
158
|
}
|
169
159
|
}
|
170
160
|
},
|
@@ -174,71 +164,17 @@ export default {
|
|
174
164
|
//监听滚动隐藏工具条
|
175
165
|
this.handleScroll()
|
176
166
|
//鼠标按下监听
|
177
|
-
|
167
|
+
DapEvent.on(document.documentElement, `mousedown.editify_${this.uid}`, this.documentMouseDown)
|
178
168
|
//鼠标移动监听
|
179
|
-
|
169
|
+
DapEvent.on(document.documentElement, `mousemove.editify_${this.uid}`, this.documentMouseMove)
|
180
170
|
//鼠标松开监听
|
181
|
-
|
171
|
+
DapEvent.on(document.documentElement, `mouseup.editify_${this.uid}`, this.documentMouseUp)
|
182
172
|
//鼠标点击箭头
|
183
|
-
|
173
|
+
DapEvent.on(document.documentElement, `click.editify_${this.uid}`, this.documentClick)
|
184
174
|
//监听窗口改变
|
185
|
-
|
186
|
-
this.setVideoHeight()
|
187
|
-
this.setContentHeight()
|
188
|
-
})
|
175
|
+
DapEvent.on(window, `resize.editify_${this.uid}`, this.setVideoHeight)
|
189
176
|
},
|
190
177
|
methods: {
|
191
|
-
//初始创建编辑器
|
192
|
-
createEditor() {
|
193
|
-
//创建编辑器
|
194
|
-
this.editor = new AlexEditor(this.$refs.content, {
|
195
|
-
value: this.value,
|
196
|
-
disabled: this.disabled,
|
197
|
-
renderRules: [
|
198
|
-
parseList,
|
199
|
-
mediaHandle,
|
200
|
-
tableHandle,
|
201
|
-
el => {
|
202
|
-
preHandle.apply(this.editor, [el, this.toolbarConfig?.use && this.toolbarConfig?.codeBlock?.languages?.show, this.toolbarConfig?.codeBlock?.languages.options])
|
203
|
-
},
|
204
|
-
...this.renderRules
|
205
|
-
],
|
206
|
-
allowCopy: this.allowCopy,
|
207
|
-
allowPaste: this.allowPaste,
|
208
|
-
allowCut: this.allowCut,
|
209
|
-
allowPasteHtml: this.allowPasteHtml,
|
210
|
-
allowPasteHtml: this.allowPasteHtml,
|
211
|
-
customImagePaste: this.customImagePaste,
|
212
|
-
customVideoPaste: this.customVideoPaste,
|
213
|
-
customMerge: this.handleCustomMerge,
|
214
|
-
customParseNode: this.handleCustomParseNode
|
215
|
-
})
|
216
|
-
//编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
|
217
|
-
this.internalModify(this.editor.value)
|
218
|
-
//设置监听事件
|
219
|
-
this.editor.on('change', this.handleEditorChange)
|
220
|
-
this.editor.on('focus', this.handleEditorFocus)
|
221
|
-
this.editor.on('blur', this.handleEditorBlur)
|
222
|
-
this.editor.on('insertParagraph', this.handleInsertParagraph)
|
223
|
-
this.editor.on('rangeUpdate', this.handleRangeUpdate)
|
224
|
-
this.editor.on('copy', this.handleCopy)
|
225
|
-
this.editor.on('cut', this.handleCut)
|
226
|
-
this.editor.on('pasteText', this.handlePasteText)
|
227
|
-
this.editor.on('pasteHtml', this.handlePasteHtml)
|
228
|
-
this.editor.on('pasteImage', this.handlePasteImage)
|
229
|
-
this.editor.on('pasteVideo', this.handlePasteVideo)
|
230
|
-
this.editor.on('deleteInStart', this.handleDeleteInStart)
|
231
|
-
this.editor.on('deleteComplete', this.handleDeleteComplete)
|
232
|
-
this.editor.on('beforeRender', this.handleBeforeRender)
|
233
|
-
this.editor.on('afterRender', this.handleAfterRender)
|
234
|
-
//格式化和dom渲染
|
235
|
-
this.editor.formatElementStack()
|
236
|
-
this.editor.domRender()
|
237
|
-
//自动获取焦点
|
238
|
-
if (this.autofocus && !this.isSourceView && !this.disabled) {
|
239
|
-
this.collapseToEnd()
|
240
|
-
}
|
241
|
-
},
|
242
178
|
//编辑器内部修改值的方法
|
243
179
|
internalModify(val) {
|
244
180
|
this.isModelChange = true
|
@@ -247,10 +183,15 @@ export default {
|
|
247
183
|
this.isModelChange = false
|
248
184
|
})
|
249
185
|
},
|
186
|
+
//隐藏工具条
|
187
|
+
hideToolbar() {
|
188
|
+
this.toolbarOptions.show = false
|
189
|
+
this.toolbarOptions.node = null
|
190
|
+
},
|
250
191
|
//监听滚动隐藏工具条
|
251
192
|
handleScroll() {
|
252
193
|
const setScroll = el => {
|
253
|
-
|
194
|
+
DapEvent.on(el, `scroll.editify_${this.uid}`, () => {
|
254
195
|
if (this.toolbarConfig.use && this.toolbarOptions.show) {
|
255
196
|
this.hideToolbar()
|
256
197
|
}
|
@@ -264,7 +205,7 @@ export default {
|
|
264
205
|
//移除上述滚动事件的监听
|
265
206
|
removeScrollHandle() {
|
266
207
|
const removeScroll = el => {
|
267
|
-
|
208
|
+
DapEvent.off(el, `scroll.editify_${this.uid}`)
|
268
209
|
if (el.parentNode) {
|
269
210
|
removeScroll(el.parentNode)
|
270
211
|
}
|
@@ -272,17 +213,17 @@ export default {
|
|
272
213
|
removeScroll(this.$refs.content)
|
273
214
|
},
|
274
215
|
//工具条显示判断
|
275
|
-
handleToolbar(
|
216
|
+
handleToolbar() {
|
276
217
|
if (this.disabled || this.isSourceView) {
|
277
218
|
return
|
278
219
|
}
|
279
220
|
this.hideToolbar()
|
280
221
|
this.$nextTick(() => {
|
281
|
-
const table =
|
282
|
-
const pre =
|
283
|
-
const link =
|
284
|
-
const image =
|
285
|
-
const video =
|
222
|
+
const table = getCurrentParsedomElement(this, 'table')
|
223
|
+
const pre = getCurrentParsedomElement(this, 'pre')
|
224
|
+
const link = getCurrentParsedomElement(this, 'a')
|
225
|
+
const image = getCurrentParsedomElement(this, 'img')
|
226
|
+
const video = getCurrentParsedomElement(this, 'video')
|
286
227
|
if (link) {
|
287
228
|
this.toolbarOptions.type = 'link'
|
288
229
|
this.toolbarOptions.node = `[data-editify-uid="${this.uid}"] [data-editify-element="${link.key}"]`
|
@@ -324,10 +265,10 @@ export default {
|
|
324
265
|
this.toolbarOptions.show = true
|
325
266
|
}
|
326
267
|
} else {
|
327
|
-
const result = this.
|
268
|
+
const result = this.dataRangeCaches.flatList.filter(item => {
|
328
269
|
return item.element.isText()
|
329
270
|
})
|
330
|
-
if (result.length && !this
|
271
|
+
if (result.length && !hasTableInRange(this) && !hasPreInRange(this) && !hasLinkInRange(this) && !hasImageInRange(this) && !hasVideoInRange(this)) {
|
331
272
|
this.toolbarOptions.type = 'text'
|
332
273
|
if (this.toolbarOptions.show) {
|
333
274
|
this.$refs.toolbar.$refs.layer.setPosition()
|
@@ -338,41 +279,68 @@ export default {
|
|
338
279
|
}
|
339
280
|
})
|
340
281
|
},
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
} else {
|
347
|
-
preEle.children.push(...ele.children)
|
348
|
-
preEle.children.forEach(item => {
|
349
|
-
item.parent = preEle
|
350
|
-
})
|
351
|
-
ele.children = null
|
352
|
-
}
|
282
|
+
//设定编辑器内的视频高度
|
283
|
+
setVideoHeight() {
|
284
|
+
this.$refs.content.querySelectorAll('video').forEach(video => {
|
285
|
+
video.style.height = video.offsetWidth / this.videoRatio + 'px'
|
286
|
+
})
|
353
287
|
},
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
288
|
+
//初始创建编辑器
|
289
|
+
createEditor() {
|
290
|
+
//创建编辑器
|
291
|
+
this.editor = new AlexEditor(this.$refs.content, {
|
292
|
+
value: this.value,
|
293
|
+
disabled: this.disabled,
|
294
|
+
renderRules: [
|
295
|
+
el => {
|
296
|
+
parseList(this.editor, el)
|
297
|
+
},
|
298
|
+
el => {
|
299
|
+
orderdListHandle(this.editor, el)
|
300
|
+
},
|
301
|
+
el => {
|
302
|
+
mediaHandle(this.editor, el)
|
303
|
+
},
|
304
|
+
el => {
|
305
|
+
tableHandle(this.editor, el)
|
306
|
+
},
|
307
|
+
el => {
|
308
|
+
preHandle(this.editor, el, this.toolbarConfig?.use && this.toolbarConfig?.codeBlock?.languages?.show, this.toolbarConfig?.codeBlock?.languages.options)
|
309
|
+
},
|
310
|
+
el => {
|
311
|
+
specialInblockHandle(this.editor, el)
|
312
|
+
},
|
313
|
+
...this.renderRules
|
314
|
+
],
|
315
|
+
allowCopy: this.allowCopy,
|
316
|
+
allowPaste: this.allowPaste,
|
317
|
+
allowCut: this.allowCut,
|
318
|
+
allowPasteHtml: this.allowPasteHtml,
|
319
|
+
allowPasteHtml: this.allowPasteHtml,
|
320
|
+
customImagePaste: this.handleCustomImagePaste,
|
321
|
+
customVideoPaste: this.handleCustomVideoPaste,
|
322
|
+
customMerge: this.handleCustomMerge,
|
323
|
+
customParseNode: this.handleCustomParseNode
|
324
|
+
})
|
325
|
+
//编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
|
326
|
+
this.internalModify(this.editor.value)
|
327
|
+
//设置监听事件
|
328
|
+
this.editor.on('change', this.handleEditorChange)
|
329
|
+
this.editor.on('focus', this.handleEditorFocus)
|
330
|
+
this.editor.on('blur', this.handleEditorBlur)
|
331
|
+
this.editor.on('insertParagraph', this.handleInsertParagraph)
|
332
|
+
this.editor.on('rangeUpdate', this.handleRangeUpdate)
|
333
|
+
this.editor.on('pasteHtml', this.handlePasteHtml)
|
334
|
+
this.editor.on('deleteInStart', this.handleDeleteInStart)
|
335
|
+
this.editor.on('deleteComplete', this.handleDeleteComplete)
|
336
|
+
this.editor.on('afterRender', this.handleAfterRender)
|
337
|
+
//格式化和dom渲染
|
338
|
+
this.editor.formatElementStack()
|
339
|
+
this.editor.domRender()
|
340
|
+
//自动获取焦点
|
341
|
+
if (this.autofocus && !this.isSourceView && !this.disabled) {
|
342
|
+
this.collapseToEnd()
|
369
343
|
}
|
370
|
-
return ele
|
371
|
-
},
|
372
|
-
//隐藏工具条
|
373
|
-
hideToolbar() {
|
374
|
-
this.toolbarOptions.show = false
|
375
|
-
this.toolbarOptions.node = null
|
376
344
|
},
|
377
345
|
//鼠标在页面按下:处理表格拖拽改变列宽和菜单栏是否使用判断
|
378
346
|
documentMouseDown(e) {
|
@@ -380,9 +348,9 @@ export default {
|
|
380
348
|
return
|
381
349
|
}
|
382
350
|
//鼠标在编辑器内按下
|
383
|
-
if (
|
351
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
384
352
|
const elm = e.target
|
385
|
-
const key =
|
353
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
386
354
|
if (key) {
|
387
355
|
const element = this.editor.getElementByKey(key)
|
388
356
|
if (element && element.parsedom == 'td') {
|
@@ -391,7 +359,7 @@ export default {
|
|
391
359
|
if (element.parent.children[length - 1].isEqual(element)) {
|
392
360
|
return
|
393
361
|
}
|
394
|
-
const rect =
|
362
|
+
const rect = DapElement.getElementBounding(elm)
|
395
363
|
//在可拖拽范围内
|
396
364
|
if (e.pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && e.pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
|
397
365
|
this.tableColumnResizeParams.element = element
|
@@ -401,7 +369,7 @@ export default {
|
|
401
369
|
}
|
402
370
|
}
|
403
371
|
//如果点击了除编辑器外的地方,菜单栏不可使用
|
404
|
-
if (!
|
372
|
+
if (!DapElement.isContains(this.$el, e.target) && !this.isSourceView) {
|
405
373
|
this.canUseMenu = false
|
406
374
|
}
|
407
375
|
},
|
@@ -413,7 +381,7 @@ export default {
|
|
413
381
|
if (!this.tableColumnResizeParams.element) {
|
414
382
|
return
|
415
383
|
}
|
416
|
-
const table =
|
384
|
+
const table = getCurrentParsedomElement(this, 'table')
|
417
385
|
if (!table) {
|
418
386
|
return
|
419
387
|
}
|
@@ -429,14 +397,14 @@ export default {
|
|
429
397
|
this.tableColumnResizeParams.start = e.pageX
|
430
398
|
},
|
431
399
|
//鼠标在页面松开:处理表格拖拽改变列宽
|
432
|
-
documentMouseUp(
|
400
|
+
documentMouseUp() {
|
433
401
|
if (this.disabled) {
|
434
402
|
return
|
435
403
|
}
|
436
404
|
if (!this.tableColumnResizeParams.element) {
|
437
405
|
return
|
438
406
|
}
|
439
|
-
const table =
|
407
|
+
const table = getCurrentParsedomElement(this, 'table')
|
440
408
|
if (!table) {
|
441
409
|
return
|
442
410
|
}
|
@@ -461,17 +429,17 @@ export default {
|
|
461
429
|
if (this.disabled) {
|
462
430
|
return
|
463
431
|
}
|
464
|
-
|
465
|
-
if (
|
432
|
+
//鼠标在编辑器内点击
|
433
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
466
434
|
const elm = e.target
|
467
|
-
const key =
|
435
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
468
436
|
if (key) {
|
469
437
|
const element = this.editor.getElementByKey(key)
|
470
438
|
//如果是任务列表元素
|
471
|
-
if (
|
472
|
-
const rect =
|
439
|
+
if (isTask(element)) {
|
440
|
+
const rect = DapElement.getElementBounding(elm)
|
473
441
|
//在复选框范围内
|
474
|
-
if (e.pageX >= Math.abs(rect.left) && e.pageX <= Math.abs(rect.left + 16) && e.pageY >= Math.abs(rect.top +
|
442
|
+
if (e.pageX >= Math.abs(rect.left) && e.pageX <= Math.abs(rect.left + 16) && e.pageY >= Math.abs(rect.top + 2) && e.pageY <= Math.abs(rect.top + 18)) {
|
475
443
|
//取消勾选
|
476
444
|
if (element.marks['data-editify-task'] == 'checked') {
|
477
445
|
element.marks['data-editify-task'] = 'uncheck'
|
@@ -493,6 +461,99 @@ export default {
|
|
493
461
|
}
|
494
462
|
}
|
495
463
|
},
|
464
|
+
//自定义图片粘贴
|
465
|
+
async handleCustomImagePaste(url) {
|
466
|
+
const newUrl = await this.customImagePaste.apply(this, [url])
|
467
|
+
if (newUrl) {
|
468
|
+
insertImage(this, newUrl)
|
469
|
+
}
|
470
|
+
},
|
471
|
+
//自定义视频粘贴
|
472
|
+
async handleCustomVideoPaste(url) {
|
473
|
+
const newUrl = await this.customVideoPaste.apply(this, [url])
|
474
|
+
if (newUrl) {
|
475
|
+
insertVideo(this, newUrl)
|
476
|
+
}
|
477
|
+
},
|
478
|
+
//重新定义编辑器合并元素的逻辑
|
479
|
+
handleCustomMerge(ele, preEle) {
|
480
|
+
const uneditable = preEle.getUneditableElement()
|
481
|
+
if (uneditable) {
|
482
|
+
uneditable.toEmpty()
|
483
|
+
} else {
|
484
|
+
preEle.children.push(...ele.children)
|
485
|
+
preEle.children.forEach(item => {
|
486
|
+
item.parent = preEle
|
487
|
+
})
|
488
|
+
ele.children = null
|
489
|
+
}
|
490
|
+
},
|
491
|
+
//针对node转为元素进行额外的处理
|
492
|
+
handleCustomParseNode(ele) {
|
493
|
+
if (ele.parsedom == 'code') {
|
494
|
+
ele.parsedom = 'span'
|
495
|
+
const marks = {
|
496
|
+
'data-editify-code': true
|
497
|
+
}
|
498
|
+
if (ele.hasMarks()) {
|
499
|
+
Object.assign(ele.marks, marks)
|
500
|
+
} else {
|
501
|
+
ele.marks = marks
|
502
|
+
}
|
503
|
+
}
|
504
|
+
if (typeof this.customParseNoe == 'function') {
|
505
|
+
ele = this.customParseNoe.apply(this, [ele])
|
506
|
+
}
|
507
|
+
return ele
|
508
|
+
},
|
509
|
+
//编辑区域键盘按下:设置缩进快捷键
|
510
|
+
handleEditorKeydown(e) {
|
511
|
+
if (this.disabled) {
|
512
|
+
return
|
513
|
+
}
|
514
|
+
//增加缩进
|
515
|
+
if (e.keyCode == 9 && !e.metaKey && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
516
|
+
e.preventDefault()
|
517
|
+
if (!hasTableInRange(this)) {
|
518
|
+
setIndentIncrease(this)
|
519
|
+
this.editor.formatElementStack()
|
520
|
+
this.editor.domRender()
|
521
|
+
this.editor.rangeRender()
|
522
|
+
}
|
523
|
+
}
|
524
|
+
//减少缩进
|
525
|
+
else if (e.keyCode == 9 && !e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
526
|
+
e.preventDefault()
|
527
|
+
if (!hasTableInRange(this)) {
|
528
|
+
setIndentDecrease(this)
|
529
|
+
this.editor.formatElementStack()
|
530
|
+
this.editor.domRender()
|
531
|
+
this.editor.rangeRender()
|
532
|
+
}
|
533
|
+
}
|
534
|
+
//自定义键盘按下操作
|
535
|
+
this.$emit('keydown', e)
|
536
|
+
},
|
537
|
+
//点击编辑器:处理图片和视频的光标聚集
|
538
|
+
handleEditorClick(e) {
|
539
|
+
if (this.disabled || this.isSourceView) {
|
540
|
+
return
|
541
|
+
}
|
542
|
+
const node = e.target
|
543
|
+
//点击的是图片或者视频
|
544
|
+
if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
|
545
|
+
const key = Number(node.getAttribute('data-editify-element'))
|
546
|
+
if (DapNumber.isNumber(key)) {
|
547
|
+
const element = this.editor.getElementByKey(key)
|
548
|
+
if (!this.editor.range) {
|
549
|
+
this.editor.initRange()
|
550
|
+
}
|
551
|
+
this.editor.range.anchor.moveToStart(element)
|
552
|
+
this.editor.range.focus.moveToEnd(element)
|
553
|
+
this.editor.rangeRender()
|
554
|
+
}
|
555
|
+
}
|
556
|
+
},
|
496
557
|
//编辑器的值更新
|
497
558
|
handleEditorChange(newVal, oldVal) {
|
498
559
|
if (this.disabled) {
|
@@ -530,7 +591,7 @@ export default {
|
|
530
591
|
//编辑区域边框颜色
|
531
592
|
this.$refs.body.style.borderColor = this.color
|
532
593
|
//转换颜色值
|
533
|
-
const rgb =
|
594
|
+
const rgb = DapColor.hex2rgb(this.color)
|
534
595
|
//菜单栏模式为inner
|
535
596
|
if (this.menuConfig.use && this.menuConfig.mode == 'inner') {
|
536
597
|
//编辑区域除顶部边框的阴影
|
@@ -554,103 +615,52 @@ export default {
|
|
554
615
|
//获取焦点时可以使用菜单栏
|
555
616
|
setTimeout(() => {
|
556
617
|
this.canUseMenu = true
|
618
|
+
this.$emit('focus', val)
|
557
619
|
}, 0)
|
558
|
-
this.$emit('focus', val)
|
559
620
|
},
|
560
|
-
|
561
|
-
|
621
|
+
//编辑器换行
|
622
|
+
handleInsertParagraph(element, previousElement) {
|
623
|
+
//前一个块元素如果是只包含换行符的元素,并且当前块元素也是包含换行符的元素,则当前块元素转为段落
|
624
|
+
if (previousElement.isOnlyHasBreak() && element.isOnlyHasBreak()) {
|
625
|
+
if (previousElement.parsedom != AlexElement.BLOCK_NODE) {
|
626
|
+
elementToParagraph(previousElement)
|
627
|
+
this.editor.range.anchor.moveToStart(previousElement)
|
628
|
+
this.editor.range.focus.moveToStart(previousElement)
|
629
|
+
element.toEmpty()
|
630
|
+
}
|
631
|
+
}
|
632
|
+
this.$emit('insertparagraph', this.value)
|
633
|
+
},
|
634
|
+
//编辑器焦点更新
|
635
|
+
handleRangeUpdate() {
|
562
636
|
if (this.disabled) {
|
563
637
|
return
|
564
638
|
}
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
else if (e.keyCode == 9 && !e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
572
|
-
e.preventDefault()
|
573
|
-
this.setIndentDecrease()
|
574
|
-
}
|
575
|
-
//自定义键盘按下操作
|
576
|
-
this.$emit('keydown', e)
|
577
|
-
},
|
578
|
-
//点击编辑器
|
579
|
-
handleEditorClick(e) {
|
580
|
-
if (this.disabled || this.isSourceView) {
|
639
|
+
|
640
|
+
//如果没有range禁用菜单栏
|
641
|
+
this.canUseMenu = !!this.editor.range
|
642
|
+
|
643
|
+
//没有range直接返回
|
644
|
+
if (!this.editor.range) {
|
581
645
|
return
|
582
646
|
}
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
this.editor.range.anchor.moveToStart(element)
|
593
|
-
this.editor.range.focus.moveToEnd(element)
|
594
|
-
this.editor.rangeRender()
|
595
|
-
}
|
596
|
-
}
|
597
|
-
},
|
598
|
-
//编辑器换行
|
599
|
-
handleInsertParagraph(element, previousElement) {
|
600
|
-
//前一个块元素如果是只包含换行符的元素,并且当前块元素也是包含换行符的元素,则当前块元素转为段落
|
601
|
-
if (previousElement.isOnlyHasBreak() && element.isOnlyHasBreak()) {
|
602
|
-
if (!previousElement.isBlock()) {
|
603
|
-
previousElement.convertToBlock()
|
647
|
+
|
648
|
+
//获取光标选取范围内的元素数据,并且进行缓存
|
649
|
+
this.dataRangeCaches = this.editor.getElementsByRange()
|
650
|
+
|
651
|
+
//如果使用工具条或者菜单栏
|
652
|
+
if (this.toolbarConfig.use || this.menuConfig.use) {
|
653
|
+
//如果使用工具条
|
654
|
+
if (this.toolbarConfig.use) {
|
655
|
+
this.handleToolbar()
|
604
656
|
}
|
605
|
-
|
606
|
-
|
607
|
-
this.
|
608
|
-
this.editor.range.focus.moveToStart(previousElement)
|
609
|
-
element.toEmpty()
|
657
|
+
//如果使用菜单栏
|
658
|
+
if (this.menuConfig.use) {
|
659
|
+
this.$refs.menu.handleRangeUpdate()
|
610
660
|
}
|
611
661
|
}
|
612
|
-
|
613
|
-
|
614
|
-
//编辑器焦点更新
|
615
|
-
handleRangeUpdate() {
|
616
|
-
if (this.disabled) {
|
617
|
-
return
|
618
|
-
}
|
619
|
-
this.canUseMenu = !!this.editor.range
|
620
|
-
if (!this.editor.range) {
|
621
|
-
return
|
622
|
-
}
|
623
|
-
if (this.updateTimer) {
|
624
|
-
clearTimeout(this.updateTimer)
|
625
|
-
}
|
626
|
-
this.updateTimer = setTimeout(() => {
|
627
|
-
//如果使用工具条或者菜单栏
|
628
|
-
if (this.toolbarConfig.use || this.menuConfig.use) {
|
629
|
-
//先获取选区内的元素设置内部缓存
|
630
|
-
this.editor.getElementsByRange()
|
631
|
-
//如果使用工具条
|
632
|
-
if (this.toolbarConfig.use) {
|
633
|
-
this.handleToolbar(true)
|
634
|
-
}
|
635
|
-
//如果使用菜单栏
|
636
|
-
if (this.menuConfig.use) {
|
637
|
-
this.$refs.menu.handleRangeUpdate(true)
|
638
|
-
}
|
639
|
-
}
|
640
|
-
}, 200)
|
641
|
-
this.$emit('rangeupdate', this.value)
|
642
|
-
},
|
643
|
-
//编辑器复制
|
644
|
-
handleCopy(text, html) {
|
645
|
-
this.$emit('copy', text, html)
|
646
|
-
},
|
647
|
-
//编辑器剪切
|
648
|
-
handleCut(text, html) {
|
649
|
-
this.$emit('cut', text, html)
|
650
|
-
},
|
651
|
-
//编辑器粘贴纯文本
|
652
|
-
handlePasteText(data) {
|
653
|
-
this.$emit('paste-text', data)
|
662
|
+
|
663
|
+
this.$emit('rangeupdate')
|
654
664
|
},
|
655
665
|
//编辑器粘贴html
|
656
666
|
handlePasteHtml(elements) {
|
@@ -677,20 +687,11 @@ export default {
|
|
677
687
|
el.styles = styles
|
678
688
|
}
|
679
689
|
})
|
680
|
-
this.$emit('paste-html', elements)
|
681
|
-
},
|
682
|
-
//编辑器粘贴图片
|
683
|
-
handlePasteImage(url) {
|
684
|
-
this.$emit('paste-image', url)
|
685
690
|
},
|
686
|
-
|
687
|
-
handlePasteVideo(url) {
|
688
|
-
this.$emit('paste-video', url)
|
689
|
-
},
|
690
|
-
//编辑器部分删除情景
|
691
|
+
//编辑器部分删除情景(在编辑器起始处)
|
691
692
|
handleDeleteInStart(element) {
|
692
693
|
if (element.isBlock()) {
|
693
|
-
|
694
|
+
elementToParagraph(element)
|
694
695
|
}
|
695
696
|
},
|
696
697
|
//编辑器删除完成后事件
|
@@ -700,39 +701,12 @@ export default {
|
|
700
701
|
uneditable.toEmpty()
|
701
702
|
}
|
702
703
|
},
|
703
|
-
//编辑器dom渲染之前
|
704
|
-
handleBeforeRender() {
|
705
|
-
this.$emit('before-render')
|
706
|
-
},
|
707
704
|
//编辑器dom渲染
|
708
705
|
handleAfterRender() {
|
709
706
|
//设定视频高度
|
710
707
|
this.setVideoHeight()
|
711
|
-
|
712
|
-
this.$emit('
|
713
|
-
},
|
714
|
-
//设定视频高度
|
715
|
-
setVideoHeight() {
|
716
|
-
this.$refs.content.querySelectorAll('video').forEach(video => {
|
717
|
-
video.style.height = video.offsetWidth / this.videoRatio + 'px'
|
718
|
-
})
|
719
|
-
},
|
720
|
-
//设置编辑器主体高度
|
721
|
-
setContentHeight() {
|
722
|
-
if (this.height === true || this.isFullScreen) {
|
723
|
-
let height = this.$el.offsetHeight
|
724
|
-
if (this.menuConfig.use) {
|
725
|
-
height -= this.$refs.menu.$el.offsetHeight
|
726
|
-
}
|
727
|
-
if (this.showWordLength) {
|
728
|
-
height -= this.$refs.footer.offsetHeight
|
729
|
-
}
|
730
|
-
if (this.$refs.menu.menuMode == 'default') {
|
731
|
-
height -= 10
|
732
|
-
}
|
733
|
-
//这里减去2px是因为body设了padding:1px
|
734
|
-
this.contentHeight = height - 2
|
735
|
-
}
|
708
|
+
|
709
|
+
this.$emit('updateview')
|
736
710
|
},
|
737
711
|
|
738
712
|
//api:光标设置到文档底部
|
@@ -742,7 +716,7 @@ export default {
|
|
742
716
|
}
|
743
717
|
this.editor.collapseToEnd()
|
744
718
|
this.editor.rangeRender()
|
745
|
-
|
719
|
+
DapElement.setScrollTop({
|
746
720
|
el: this.$refs.content,
|
747
721
|
number: 1000000,
|
748
722
|
time: 0
|
@@ -756,364 +730,13 @@ export default {
|
|
756
730
|
this.editor.collapseToStart()
|
757
731
|
this.editor.rangeRender()
|
758
732
|
this.$nextTick(() => {
|
759
|
-
|
733
|
+
DapElement.setScrollTop({
|
760
734
|
el: this.$refs.content,
|
761
735
|
number: 0,
|
762
736
|
time: 0
|
763
737
|
})
|
764
738
|
})
|
765
739
|
},
|
766
|
-
//api:获取某个元素是否在某个标签元素下,如果是返回该标签元素,否则返回null
|
767
|
-
getParsedomElementByElement(element, parsedom) {
|
768
|
-
if (element.isBlock()) {
|
769
|
-
return element.parsedom == parsedom ? element : null
|
770
|
-
}
|
771
|
-
if (!element.isText() && element.parsedom == parsedom) {
|
772
|
-
return element
|
773
|
-
}
|
774
|
-
return this.getParsedomElementByElement(element.parent, parsedom)
|
775
|
-
},
|
776
|
-
//api:获取光标是否在指定标签元素下,如果是返回该标签元素,否则返回null
|
777
|
-
getCurrentParsedomElement(parsedom, useCache = false) {
|
778
|
-
if (this.disabled) {
|
779
|
-
return null
|
780
|
-
}
|
781
|
-
if (!this.editor.range) {
|
782
|
-
return null
|
783
|
-
}
|
784
|
-
if (this.editor.range.anchor.element.isEqual(this.editor.range.focus.element)) {
|
785
|
-
return this.getParsedomElementByElement(this.editor.range.anchor.element, parsedom)
|
786
|
-
}
|
787
|
-
const arr = this.editor.getElementsByRange(useCache).includes.map(item => {
|
788
|
-
return this.getParsedomElementByElement(item.element, parsedom)
|
789
|
-
})
|
790
|
-
let hasNull = arr.some(el => {
|
791
|
-
return el == null
|
792
|
-
})
|
793
|
-
//如果存在null,则表示有的选区元素不在指定标签下,返回null
|
794
|
-
if (hasNull) {
|
795
|
-
return null
|
796
|
-
}
|
797
|
-
//如果只有一个元素,则返回该元素
|
798
|
-
if (arr.length == 1) {
|
799
|
-
return arr[0]
|
800
|
-
}
|
801
|
-
//默认数组中的元素都相等
|
802
|
-
let flag = true
|
803
|
-
for (let i = 1; i < arr.length; i++) {
|
804
|
-
if (!arr[i].isEqual(arr[0])) {
|
805
|
-
flag = false
|
806
|
-
break
|
807
|
-
}
|
808
|
-
}
|
809
|
-
//如果相等,则返回该元素
|
810
|
-
if (flag) {
|
811
|
-
return arr[0]
|
812
|
-
}
|
813
|
-
return null
|
814
|
-
},
|
815
|
-
//api:删除光标所在的指定标签元素
|
816
|
-
deleteByParsedom(parsedom, isRender = true, useCache = false) {
|
817
|
-
if (this.disabled) {
|
818
|
-
return
|
819
|
-
}
|
820
|
-
if (!this.editor.range) {
|
821
|
-
return
|
822
|
-
}
|
823
|
-
const element = this.getCurrentParsedomElement(parsedom, useCache)
|
824
|
-
if (element) {
|
825
|
-
element.toEmpty()
|
826
|
-
if (isRender) {
|
827
|
-
this.editor.formatElementStack()
|
828
|
-
this.editor.domRender()
|
829
|
-
this.editor.rangeRender()
|
830
|
-
}
|
831
|
-
}
|
832
|
-
},
|
833
|
-
//api:当光标在链接上时可以移除链接
|
834
|
-
removeLink(isRender = true, useCache = false) {
|
835
|
-
if (this.disabled) {
|
836
|
-
return
|
837
|
-
}
|
838
|
-
if (!this.editor.range) {
|
839
|
-
return
|
840
|
-
}
|
841
|
-
const link = this.getCurrentParsedomElement('a', useCache)
|
842
|
-
if (link) {
|
843
|
-
link.parsedom = AlexElement.TEXT_NODE
|
844
|
-
delete link.marks.target
|
845
|
-
delete link.marks.href
|
846
|
-
if (isRender) {
|
847
|
-
this.editor.formatElementStack()
|
848
|
-
this.editor.domRender()
|
849
|
-
this.editor.rangeRender()
|
850
|
-
}
|
851
|
-
}
|
852
|
-
},
|
853
|
-
//api:设置标题
|
854
|
-
setHeading(parsedom, isRender = true, useCache = false) {
|
855
|
-
if (this.disabled) {
|
856
|
-
return
|
857
|
-
}
|
858
|
-
if (!this.editor.range) {
|
859
|
-
return
|
860
|
-
}
|
861
|
-
const values = getButtonOptionsConfig(this.$editTrans, this.$editLocale).heading.map(item => {
|
862
|
-
return item.value
|
863
|
-
})
|
864
|
-
if (!values.includes(parsedom)) {
|
865
|
-
throw new Error('The parameter supports only h1-h6 and p')
|
866
|
-
}
|
867
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
868
|
-
const block = this.editor.range.anchor.element.getBlock()
|
869
|
-
//先转为段落
|
870
|
-
blockToParagraph(block)
|
871
|
-
//设置标题
|
872
|
-
block.parsedom = parsedom
|
873
|
-
} else {
|
874
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
875
|
-
result.forEach(el => {
|
876
|
-
if (el.element.isBlock()) {
|
877
|
-
blockToParagraph(el.element)
|
878
|
-
el.element.parsedom = parsedom
|
879
|
-
} else {
|
880
|
-
const block = el.element.getBlock()
|
881
|
-
blockToParagraph(block)
|
882
|
-
block.parsedom = parsedom
|
883
|
-
}
|
884
|
-
})
|
885
|
-
}
|
886
|
-
if (isRender) {
|
887
|
-
this.editor.formatElementStack()
|
888
|
-
this.editor.domRender()
|
889
|
-
this.editor.rangeRender()
|
890
|
-
}
|
891
|
-
},
|
892
|
-
//api:插入有序列表 ordered为true表示有序列表
|
893
|
-
setList(ordered, isRender = true, useCache = false) {
|
894
|
-
if (this.disabled) {
|
895
|
-
return
|
896
|
-
}
|
897
|
-
if (!this.editor.range) {
|
898
|
-
return
|
899
|
-
}
|
900
|
-
//起点和终点在一起
|
901
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
902
|
-
const block = this.editor.range.anchor.element.getBlock()
|
903
|
-
const isList = blockIsList(block, ordered)
|
904
|
-
if (isList) {
|
905
|
-
blockToParagraph(block)
|
906
|
-
} else {
|
907
|
-
blockToList(block, ordered)
|
908
|
-
}
|
909
|
-
}
|
910
|
-
//起点和终点不在一起
|
911
|
-
else {
|
912
|
-
let blocks = []
|
913
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
914
|
-
result.forEach(item => {
|
915
|
-
const block = item.element.getBlock()
|
916
|
-
const exist = blocks.some(el => block.isEqual(el))
|
917
|
-
if (!exist) {
|
918
|
-
blocks.push(block)
|
919
|
-
}
|
920
|
-
})
|
921
|
-
blocks.forEach(block => {
|
922
|
-
const isList = blockIsList(block, ordered)
|
923
|
-
if (isList) {
|
924
|
-
blockToParagraph(block)
|
925
|
-
} else {
|
926
|
-
blockToList(block, ordered)
|
927
|
-
}
|
928
|
-
})
|
929
|
-
}
|
930
|
-
if (isRender) {
|
931
|
-
this.editor.formatElementStack()
|
932
|
-
this.editor.domRender()
|
933
|
-
this.editor.rangeRender()
|
934
|
-
}
|
935
|
-
},
|
936
|
-
//api:插入任务列表
|
937
|
-
setTask(isRender = true, useCache = false) {
|
938
|
-
if (this.disabled) {
|
939
|
-
return
|
940
|
-
}
|
941
|
-
if (!this.editor.range) {
|
942
|
-
return
|
943
|
-
}
|
944
|
-
//起点和终点在一起
|
945
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
946
|
-
const block = this.editor.range.anchor.element.getBlock()
|
947
|
-
const isTask = blockIsTask(block)
|
948
|
-
if (isTask) {
|
949
|
-
blockToParagraph(block)
|
950
|
-
} else {
|
951
|
-
blockToTask(block)
|
952
|
-
}
|
953
|
-
}
|
954
|
-
//起点和终点不在一起
|
955
|
-
else {
|
956
|
-
let blocks = []
|
957
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
958
|
-
result.forEach(item => {
|
959
|
-
const block = item.element.getBlock()
|
960
|
-
const exist = blocks.some(el => block.isEqual(el))
|
961
|
-
if (!exist) {
|
962
|
-
blocks.push(block)
|
963
|
-
}
|
964
|
-
})
|
965
|
-
blocks.forEach(block => {
|
966
|
-
const isTask = blockIsTask(block)
|
967
|
-
if (isTask) {
|
968
|
-
blockToParagraph(block)
|
969
|
-
} else {
|
970
|
-
blockToTask(block)
|
971
|
-
}
|
972
|
-
})
|
973
|
-
}
|
974
|
-
if (isRender) {
|
975
|
-
this.editor.formatElementStack()
|
976
|
-
this.editor.domRender()
|
977
|
-
this.editor.rangeRender()
|
978
|
-
}
|
979
|
-
},
|
980
|
-
//api:设置样式
|
981
|
-
setTextStyle(name, value, isRender = true, useCache = false) {
|
982
|
-
if (this.disabled) {
|
983
|
-
return
|
984
|
-
}
|
985
|
-
if (!this.editor.range) {
|
986
|
-
return
|
987
|
-
}
|
988
|
-
const active = this.queryTextStyle(name, value, useCache)
|
989
|
-
if (active) {
|
990
|
-
this.editor.removeTextStyle([name], true)
|
991
|
-
} else {
|
992
|
-
let styles = {}
|
993
|
-
styles[name] = value
|
994
|
-
this.editor.setTextStyle(styles, true)
|
995
|
-
}
|
996
|
-
if (isRender) {
|
997
|
-
this.editor.formatElementStack()
|
998
|
-
this.editor.domRender()
|
999
|
-
this.editor.rangeRender()
|
1000
|
-
}
|
1001
|
-
},
|
1002
|
-
//api:查询是否具有某个样式
|
1003
|
-
queryTextStyle(name, value, useCache = false) {
|
1004
|
-
return this.editor.queryTextStyle(name, value, useCache)
|
1005
|
-
},
|
1006
|
-
//api:设置标记
|
1007
|
-
setTextMark(name, value, isRender = true, useCache = false) {
|
1008
|
-
if (this.disabled) {
|
1009
|
-
return
|
1010
|
-
}
|
1011
|
-
if (!this.editor.range) {
|
1012
|
-
return
|
1013
|
-
}
|
1014
|
-
const active = this.queryTextMark(name, value, useCache)
|
1015
|
-
if (active) {
|
1016
|
-
this.editor.removeTextMark([name], true)
|
1017
|
-
} else {
|
1018
|
-
let marks = {}
|
1019
|
-
marks[name] = value
|
1020
|
-
this.editor.setTextMark(marks, true)
|
1021
|
-
}
|
1022
|
-
if (isRender) {
|
1023
|
-
this.editor.formatElementStack()
|
1024
|
-
this.editor.domRender()
|
1025
|
-
this.editor.rangeRender()
|
1026
|
-
}
|
1027
|
-
},
|
1028
|
-
//api:查询是否具有某个标记
|
1029
|
-
queryTextMark(name, value, useCache = false) {
|
1030
|
-
return this.editor.queryTextMark(name, value, useCache)
|
1031
|
-
},
|
1032
|
-
//api:清除文本样式和标记
|
1033
|
-
formatText(isRender = true, useCache = false) {
|
1034
|
-
if (this.disabled) {
|
1035
|
-
return
|
1036
|
-
}
|
1037
|
-
if (!this.editor.range) {
|
1038
|
-
return
|
1039
|
-
}
|
1040
|
-
this.editor.removeTextStyle(null, useCache)
|
1041
|
-
//这里不能使用缓存,因为removeTextStyle会更新光标位置
|
1042
|
-
this.editor.removeTextMark(null)
|
1043
|
-
if (isRender) {
|
1044
|
-
this.editor.formatElementStack()
|
1045
|
-
this.editor.domRender()
|
1046
|
-
this.editor.rangeRender()
|
1047
|
-
}
|
1048
|
-
},
|
1049
|
-
//api:设置对齐方式,参数取值justify/left/right/center
|
1050
|
-
setAlign(value, isRender = true, useCache = false) {
|
1051
|
-
if (this.disabled) {
|
1052
|
-
return
|
1053
|
-
}
|
1054
|
-
if (!this.editor.range) {
|
1055
|
-
return
|
1056
|
-
}
|
1057
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1058
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1059
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1060
|
-
if (inblock) {
|
1061
|
-
if (inblock.hasStyles()) {
|
1062
|
-
inblock.styles['text-align'] = value
|
1063
|
-
} else {
|
1064
|
-
inblock.styles = {
|
1065
|
-
'text-align': value
|
1066
|
-
}
|
1067
|
-
}
|
1068
|
-
} else {
|
1069
|
-
if (block.hasStyles()) {
|
1070
|
-
block.styles['text-align'] = value
|
1071
|
-
} else {
|
1072
|
-
block.styles = {
|
1073
|
-
'text-align': value
|
1074
|
-
}
|
1075
|
-
}
|
1076
|
-
}
|
1077
|
-
} else {
|
1078
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1079
|
-
result.forEach(el => {
|
1080
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
1081
|
-
if (el.element.hasStyles()) {
|
1082
|
-
el.element.styles['text-align'] = value
|
1083
|
-
} else {
|
1084
|
-
el.element.styles = {
|
1085
|
-
'text-align': value
|
1086
|
-
}
|
1087
|
-
}
|
1088
|
-
} else {
|
1089
|
-
const block = el.element.getBlock()
|
1090
|
-
const inblock = el.element.getInblock()
|
1091
|
-
if (inblock) {
|
1092
|
-
if (inblock.hasStyles()) {
|
1093
|
-
inblock.styles['text-align'] = value
|
1094
|
-
} else {
|
1095
|
-
inblock.styles = {
|
1096
|
-
'text-align': value
|
1097
|
-
}
|
1098
|
-
}
|
1099
|
-
} else {
|
1100
|
-
if (block.hasStyles()) {
|
1101
|
-
block.styles['text-align'] = value
|
1102
|
-
} else {
|
1103
|
-
block.styles = {
|
1104
|
-
'text-align': value
|
1105
|
-
}
|
1106
|
-
}
|
1107
|
-
}
|
1108
|
-
}
|
1109
|
-
})
|
1110
|
-
}
|
1111
|
-
if (isRender) {
|
1112
|
-
this.editor.formatElementStack()
|
1113
|
-
this.editor.domRender()
|
1114
|
-
this.editor.rangeRender()
|
1115
|
-
}
|
1116
|
-
},
|
1117
740
|
//api:撤销
|
1118
741
|
undo() {
|
1119
742
|
if (this.disabled) {
|
@@ -1143,621 +766,15 @@ export default {
|
|
1143
766
|
this.editor.domRender(true)
|
1144
767
|
this.editor.rangeRender()
|
1145
768
|
}
|
1146
|
-
},
|
1147
|
-
//api:插入引用
|
1148
|
-
setQuote(isRender = true, useCache = false) {
|
1149
|
-
if (this.disabled) {
|
1150
|
-
return
|
1151
|
-
}
|
1152
|
-
if (!this.editor.range) {
|
1153
|
-
return
|
1154
|
-
}
|
1155
|
-
//起点和终点在一起
|
1156
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1157
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1158
|
-
const oldParsedom = block.parsedom
|
1159
|
-
blockToParagraph(block)
|
1160
|
-
if (oldParsedom != 'blockquote') {
|
1161
|
-
block.parsedom = 'blockquote'
|
1162
|
-
}
|
1163
|
-
}
|
1164
|
-
//起点和终点不在一起
|
1165
|
-
else {
|
1166
|
-
let blocks = []
|
1167
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1168
|
-
result.forEach(item => {
|
1169
|
-
const block = item.element.getBlock()
|
1170
|
-
const exist = blocks.some(el => block.isEqual(el))
|
1171
|
-
if (!exist) {
|
1172
|
-
blocks.push(block)
|
1173
|
-
}
|
1174
|
-
})
|
1175
|
-
blocks.forEach(block => {
|
1176
|
-
const oldParsedom = block.parsedom
|
1177
|
-
blockToParagraph(block)
|
1178
|
-
if (oldParsedom != 'blockquote') {
|
1179
|
-
block.parsedom = 'blockquote'
|
1180
|
-
}
|
1181
|
-
})
|
1182
|
-
}
|
1183
|
-
if (isRender) {
|
1184
|
-
this.editor.formatElementStack()
|
1185
|
-
this.editor.domRender()
|
1186
|
-
this.editor.rangeRender()
|
1187
|
-
}
|
1188
|
-
},
|
1189
|
-
//api:设置行高
|
1190
|
-
setLineHeight(value, isRender = true, useCache = false) {
|
1191
|
-
if (this.disabled) {
|
1192
|
-
return
|
1193
|
-
}
|
1194
|
-
if (!this.editor.range) {
|
1195
|
-
return
|
1196
|
-
}
|
1197
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1198
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1199
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1200
|
-
if (inblock) {
|
1201
|
-
if (inblock.hasStyles()) {
|
1202
|
-
inblock.styles['line-height'] = value
|
1203
|
-
} else {
|
1204
|
-
inblock.styles = {
|
1205
|
-
'line-height': value
|
1206
|
-
}
|
1207
|
-
}
|
1208
|
-
} else {
|
1209
|
-
if (block.hasStyles()) {
|
1210
|
-
block.styles['line-height'] = value
|
1211
|
-
} else {
|
1212
|
-
block.styles = {
|
1213
|
-
'line-height': value
|
1214
|
-
}
|
1215
|
-
}
|
1216
|
-
}
|
1217
|
-
} else {
|
1218
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1219
|
-
result.forEach(el => {
|
1220
|
-
if (el.element.isBlock() || el.element.isInblock()) {
|
1221
|
-
if (el.element.hasStyles()) {
|
1222
|
-
el.element.styles['line-height'] = value
|
1223
|
-
} else {
|
1224
|
-
el.element.styles = {
|
1225
|
-
'line-height': value
|
1226
|
-
}
|
1227
|
-
}
|
1228
|
-
} else {
|
1229
|
-
const block = el.element.getBlock()
|
1230
|
-
const inblock = el.element.getInblock()
|
1231
|
-
if (inblock) {
|
1232
|
-
if (inblock.hasStyles()) {
|
1233
|
-
inblock.styles['line-height'] = value
|
1234
|
-
} else {
|
1235
|
-
inblock.styles = {
|
1236
|
-
'line-height': value
|
1237
|
-
}
|
1238
|
-
}
|
1239
|
-
} else {
|
1240
|
-
if (block.hasStyles()) {
|
1241
|
-
block.styles['line-height'] = value
|
1242
|
-
} else {
|
1243
|
-
block.styles = {
|
1244
|
-
'line-height': value
|
1245
|
-
}
|
1246
|
-
}
|
1247
|
-
}
|
1248
|
-
}
|
1249
|
-
})
|
1250
|
-
}
|
1251
|
-
if (isRender) {
|
1252
|
-
this.editor.formatElementStack()
|
1253
|
-
this.editor.domRender()
|
1254
|
-
this.editor.rangeRender()
|
1255
|
-
}
|
1256
|
-
},
|
1257
|
-
//api:增加缩进
|
1258
|
-
setIndentIncrease(isRender = true, useCache = false) {
|
1259
|
-
if (this.disabled) {
|
1260
|
-
return
|
1261
|
-
}
|
1262
|
-
if (!this.editor.range) {
|
1263
|
-
return
|
1264
|
-
}
|
1265
|
-
const fn = element => {
|
1266
|
-
if (element.hasStyles()) {
|
1267
|
-
if (element.styles.hasOwnProperty('text-indent')) {
|
1268
|
-
let val = element.styles['text-indent']
|
1269
|
-
if (val.endsWith('em')) {
|
1270
|
-
val = parseFloat(val)
|
1271
|
-
} else {
|
1272
|
-
val = 0
|
1273
|
-
}
|
1274
|
-
element.styles['text-indent'] = `${val + 2}em`
|
1275
|
-
} else {
|
1276
|
-
element.styles['text-indent'] = '2em'
|
1277
|
-
}
|
1278
|
-
} else {
|
1279
|
-
element.styles = {
|
1280
|
-
'text-indent': '2em'
|
1281
|
-
}
|
1282
|
-
}
|
1283
|
-
}
|
1284
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1285
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1286
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1287
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1288
|
-
fn(inblock)
|
1289
|
-
} else if (!block.isPreStyle()) {
|
1290
|
-
fn(block)
|
1291
|
-
}
|
1292
|
-
} else {
|
1293
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1294
|
-
result.forEach(item => {
|
1295
|
-
const block = item.element.getBlock()
|
1296
|
-
const inblock = item.element.getInblock()
|
1297
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1298
|
-
fn(inblock)
|
1299
|
-
} else if (!block.isPreStyle()) {
|
1300
|
-
fn(block)
|
1301
|
-
}
|
1302
|
-
})
|
1303
|
-
}
|
1304
|
-
if (isRender) {
|
1305
|
-
this.editor.formatElementStack()
|
1306
|
-
this.editor.domRender()
|
1307
|
-
this.editor.rangeRender()
|
1308
|
-
}
|
1309
|
-
},
|
1310
|
-
//api:减少缩进
|
1311
|
-
setIndentDecrease(isRender = true, useCache = false) {
|
1312
|
-
if (this.disabled) {
|
1313
|
-
return
|
1314
|
-
}
|
1315
|
-
if (!this.editor.range) {
|
1316
|
-
return
|
1317
|
-
}
|
1318
|
-
const fn = element => {
|
1319
|
-
if (element.hasStyles() && element.styles.hasOwnProperty('text-indent')) {
|
1320
|
-
let val = element.styles['text-indent']
|
1321
|
-
if (val.endsWith('em')) {
|
1322
|
-
val = parseFloat(val)
|
1323
|
-
} else {
|
1324
|
-
val = 0
|
1325
|
-
}
|
1326
|
-
element.styles['text-indent'] = `${val - 2 >= 0 ? val - 2 : 0}em`
|
1327
|
-
}
|
1328
|
-
}
|
1329
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1330
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1331
|
-
const inblock = this.editor.range.anchor.element.getInblock()
|
1332
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1333
|
-
fn(inblock)
|
1334
|
-
} else if (!block.isPreStyle()) {
|
1335
|
-
fn(block)
|
1336
|
-
}
|
1337
|
-
} else {
|
1338
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1339
|
-
result.forEach(item => {
|
1340
|
-
const block = item.element.getBlock()
|
1341
|
-
const inblock = item.element.getInblock()
|
1342
|
-
if (inblock && inblock.behavior == 'block' && !inblock.isPreStyle()) {
|
1343
|
-
fn(inblock)
|
1344
|
-
} else if (!block.isPreStyle()) {
|
1345
|
-
fn(block)
|
1346
|
-
}
|
1347
|
-
})
|
1348
|
-
}
|
1349
|
-
if (isRender) {
|
1350
|
-
this.editor.formatElementStack()
|
1351
|
-
this.editor.domRender()
|
1352
|
-
this.editor.rangeRender()
|
1353
|
-
}
|
1354
|
-
},
|
1355
|
-
//api:插入图片
|
1356
|
-
insertImage(url, isRender = true, useCache = false) {
|
1357
|
-
if (this.disabled) {
|
1358
|
-
return
|
1359
|
-
}
|
1360
|
-
if (!this.editor.range) {
|
1361
|
-
return
|
1362
|
-
}
|
1363
|
-
if (!url || typeof url != 'string') {
|
1364
|
-
throw new Error('An image address must be given')
|
1365
|
-
}
|
1366
|
-
const image = new AlexElement(
|
1367
|
-
'closed',
|
1368
|
-
'img',
|
1369
|
-
{
|
1370
|
-
src: url
|
1371
|
-
},
|
1372
|
-
null,
|
1373
|
-
null
|
1374
|
-
)
|
1375
|
-
this.editor.insertElement(image, true, useCache)
|
1376
|
-
if (isRender) {
|
1377
|
-
this.editor.formatElementStack()
|
1378
|
-
this.editor.domRender()
|
1379
|
-
this.editor.rangeRender()
|
1380
|
-
}
|
1381
|
-
},
|
1382
|
-
//api:插入视频
|
1383
|
-
insertVideo(url, isRender = true, useCache = false) {
|
1384
|
-
if (this.disabled) {
|
1385
|
-
return
|
1386
|
-
}
|
1387
|
-
if (!this.editor.range) {
|
1388
|
-
return
|
1389
|
-
}
|
1390
|
-
if (!url || typeof url != 'string') {
|
1391
|
-
throw new Error('A video address must be given')
|
1392
|
-
}
|
1393
|
-
const video = new AlexElement(
|
1394
|
-
'closed',
|
1395
|
-
'video',
|
1396
|
-
{
|
1397
|
-
src: url
|
1398
|
-
},
|
1399
|
-
null,
|
1400
|
-
null
|
1401
|
-
)
|
1402
|
-
this.editor.insertElement(video, true, useCache)
|
1403
|
-
const leftSpace = AlexElement.getSpaceElement()
|
1404
|
-
const rightSpace = AlexElement.getSpaceElement()
|
1405
|
-
this.editor.addElementAfter(rightSpace, video)
|
1406
|
-
this.editor.addElementBefore(leftSpace, video)
|
1407
|
-
this.editor.range.anchor.moveToEnd(rightSpace)
|
1408
|
-
this.editor.range.focus.moveToEnd(rightSpace)
|
1409
|
-
if (isRender) {
|
1410
|
-
this.editor.formatElementStack()
|
1411
|
-
this.editor.domRender()
|
1412
|
-
this.editor.rangeRender()
|
1413
|
-
}
|
1414
|
-
},
|
1415
|
-
//api:选区是否含有代码块样式
|
1416
|
-
hasPreStyle(useCache = false) {
|
1417
|
-
if (!this.editor.range) {
|
1418
|
-
return false
|
1419
|
-
}
|
1420
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1421
|
-
return this.editor.range.anchor.element.isPreStyle()
|
1422
|
-
}
|
1423
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1424
|
-
return result.some(item => {
|
1425
|
-
return item.element.isPreStyle()
|
1426
|
-
})
|
1427
|
-
},
|
1428
|
-
//api:选区是否含有引用
|
1429
|
-
hasQuote(useCache = false) {
|
1430
|
-
if (!this.editor.range) {
|
1431
|
-
return false
|
1432
|
-
}
|
1433
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1434
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1435
|
-
return block.parsedom == 'blockquote'
|
1436
|
-
}
|
1437
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1438
|
-
return result.some(item => {
|
1439
|
-
if (item.element.isBlock()) {
|
1440
|
-
return item.element.parsedom == 'blockquote'
|
1441
|
-
} else {
|
1442
|
-
const block = item.element.getBlock()
|
1443
|
-
return block.parsedom == 'blockquote'
|
1444
|
-
}
|
1445
|
-
})
|
1446
|
-
},
|
1447
|
-
//api:选区是否含有列表
|
1448
|
-
hasList(ordered = false, useCache = false) {
|
1449
|
-
if (!this.editor.range) {
|
1450
|
-
return false
|
1451
|
-
}
|
1452
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1453
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1454
|
-
return blockIsList(block, ordered)
|
1455
|
-
}
|
1456
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1457
|
-
return result.some(item => {
|
1458
|
-
if (item.element.isBlock()) {
|
1459
|
-
return blockIsList(item.element, ordered)
|
1460
|
-
} else {
|
1461
|
-
const block = item.element.getBlock()
|
1462
|
-
return blockIsList(block, ordered)
|
1463
|
-
}
|
1464
|
-
})
|
1465
|
-
},
|
1466
|
-
//api:选区是否含有链接
|
1467
|
-
hasLink(useCache = false) {
|
1468
|
-
if (!this.editor.range) {
|
1469
|
-
return false
|
1470
|
-
}
|
1471
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1472
|
-
return !!this.getParsedomElementByElement(this.editor.range.anchor.element, 'a')
|
1473
|
-
}
|
1474
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes.filter(item => {
|
1475
|
-
return item.element.isText()
|
1476
|
-
})
|
1477
|
-
return result.some(item => {
|
1478
|
-
return !!this.getParsedomElementByElement(item.element, 'a')
|
1479
|
-
})
|
1480
|
-
},
|
1481
|
-
//api:选区是否含有表格
|
1482
|
-
hasTable(useCache = false) {
|
1483
|
-
if (!this.editor.range) {
|
1484
|
-
return false
|
1485
|
-
}
|
1486
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1487
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1488
|
-
return block.parsedom == 'table'
|
1489
|
-
}
|
1490
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1491
|
-
return result.some(item => {
|
1492
|
-
if (item.element.isBlock()) {
|
1493
|
-
return item.element.parsedom == 'table'
|
1494
|
-
} else {
|
1495
|
-
const block = item.element.getBlock()
|
1496
|
-
return block.parsedom == 'table'
|
1497
|
-
}
|
1498
|
-
})
|
1499
|
-
},
|
1500
|
-
//api:选区是否含有任务列表
|
1501
|
-
hasTask(useCache = false) {
|
1502
|
-
if (!this.editor.range) {
|
1503
|
-
return false
|
1504
|
-
}
|
1505
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1506
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1507
|
-
return blockIsTask(block)
|
1508
|
-
}
|
1509
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1510
|
-
return result.some(item => {
|
1511
|
-
if (item.element.isBlock()) {
|
1512
|
-
return blockIsTask(item.element)
|
1513
|
-
} else {
|
1514
|
-
const block = item.element.getBlock()
|
1515
|
-
return blockIsTask(block)
|
1516
|
-
}
|
1517
|
-
})
|
1518
|
-
},
|
1519
|
-
//api:选区是否含有图片
|
1520
|
-
hasImage(useCache = false) {
|
1521
|
-
if (!this.editor.range) {
|
1522
|
-
return false
|
1523
|
-
}
|
1524
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1525
|
-
return this.editor.range.anchor.element.isClosed() && this.editor.range.anchor.element.parsedom == 'img'
|
1526
|
-
}
|
1527
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes
|
1528
|
-
return result.some(item => {
|
1529
|
-
return item.element.isClosed() && item.element.parsedom == 'img'
|
1530
|
-
})
|
1531
|
-
},
|
1532
|
-
//api:选区是否含有视频
|
1533
|
-
hasVideo(useCache = false) {
|
1534
|
-
if (!this.editor.range) {
|
1535
|
-
return false
|
1536
|
-
}
|
1537
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1538
|
-
return this.editor.range.anchor.element.isClosed() && this.editor.range.anchor.element.parsedom == 'video'
|
1539
|
-
}
|
1540
|
-
const result = this.editor.getElementsByRange(useCache).flatIncludes
|
1541
|
-
return result.some(item => {
|
1542
|
-
return item.element.isClosed() && item.element.parsedom == 'video'
|
1543
|
-
})
|
1544
|
-
},
|
1545
|
-
//api:选区是否全部在引用内
|
1546
|
-
inQuote(useCache = false) {
|
1547
|
-
if (!this.editor.range) {
|
1548
|
-
return false
|
1549
|
-
}
|
1550
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1551
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1552
|
-
return block.parsedom == 'blockquote'
|
1553
|
-
}
|
1554
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1555
|
-
return result.every(item => {
|
1556
|
-
if (item.element.isBlock()) {
|
1557
|
-
return item.element.parsedom == 'blockquote'
|
1558
|
-
} else {
|
1559
|
-
const block = item.element.getBlock()
|
1560
|
-
return block.parsedom == 'blockquote'
|
1561
|
-
}
|
1562
|
-
})
|
1563
|
-
},
|
1564
|
-
//api:选区是否全部在列表内
|
1565
|
-
inList(ordered = false, useCache = false) {
|
1566
|
-
if (!this.editor.range) {
|
1567
|
-
return false
|
1568
|
-
}
|
1569
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1570
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1571
|
-
return blockIsList(block, ordered)
|
1572
|
-
}
|
1573
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1574
|
-
return result.every(item => {
|
1575
|
-
if (item.element.isBlock()) {
|
1576
|
-
return blockIsList(item.element, ordered)
|
1577
|
-
} else {
|
1578
|
-
const block = item.element.getBlock()
|
1579
|
-
return blockIsList(block, ordered)
|
1580
|
-
}
|
1581
|
-
})
|
1582
|
-
},
|
1583
|
-
//api:选区是否全部在任务列表里
|
1584
|
-
inTask(useCache = false) {
|
1585
|
-
if (!this.editor.range) {
|
1586
|
-
return false
|
1587
|
-
}
|
1588
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1589
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1590
|
-
return blockIsTask(block)
|
1591
|
-
}
|
1592
|
-
const result = this.editor.getElementsByRange(useCache).includes
|
1593
|
-
return result.every(item => {
|
1594
|
-
if (item.element.isBlock()) {
|
1595
|
-
return blockIsTask(item.element)
|
1596
|
-
} else {
|
1597
|
-
const block = item.element.getBlock()
|
1598
|
-
return blockIsTask(block)
|
1599
|
-
}
|
1600
|
-
})
|
1601
|
-
},
|
1602
|
-
//api:创建一个空的表格
|
1603
|
-
insertTable(rowLength, colLength, isRender = true, useCache = false) {
|
1604
|
-
if (this.disabled) {
|
1605
|
-
return
|
1606
|
-
}
|
1607
|
-
if (!this.editor.range) {
|
1608
|
-
return
|
1609
|
-
}
|
1610
|
-
const table = new AlexElement('block', 'table', null, null, null)
|
1611
|
-
const tbody = new AlexElement('inblock', 'tbody', null, null, null)
|
1612
|
-
this.editor.addElementTo(tbody, table)
|
1613
|
-
for (let i = 0; i < rowLength; i++) {
|
1614
|
-
const row = new AlexElement('inblock', 'tr', null, null, null)
|
1615
|
-
for (let j = 0; j < colLength; j++) {
|
1616
|
-
const column = new AlexElement('inblock', 'td', null, null, null)
|
1617
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1618
|
-
this.editor.addElementTo(breakEl, column)
|
1619
|
-
this.editor.addElementTo(column, row)
|
1620
|
-
}
|
1621
|
-
this.editor.addElementTo(row, tbody)
|
1622
|
-
}
|
1623
|
-
this.editor.insertElement(table, true, useCache)
|
1624
|
-
//在表格后创建一个段落
|
1625
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1626
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1627
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1628
|
-
this.editor.addElementAfter(paragraph, table)
|
1629
|
-
this.editor.range.anchor.moveToStart(tbody)
|
1630
|
-
this.editor.range.focus.moveToStart(tbody)
|
1631
|
-
if (isRender) {
|
1632
|
-
this.editor.formatElementStack()
|
1633
|
-
this.editor.domRender()
|
1634
|
-
this.editor.rangeRender()
|
1635
|
-
}
|
1636
|
-
},
|
1637
|
-
//api:插入代码块
|
1638
|
-
insertCodeBlock(isRender = true, useCache = false) {
|
1639
|
-
if (this.disabled) {
|
1640
|
-
return
|
1641
|
-
}
|
1642
|
-
if (!this.editor.range) {
|
1643
|
-
return
|
1644
|
-
}
|
1645
|
-
const pre = this.getCurrentParsedomElement('pre', useCache)
|
1646
|
-
if (pre) {
|
1647
|
-
let content = ''
|
1648
|
-
AlexElement.flatElements(pre.children)
|
1649
|
-
.filter(item => {
|
1650
|
-
return item.isText()
|
1651
|
-
})
|
1652
|
-
.forEach(item => {
|
1653
|
-
content += item.textContent
|
1654
|
-
})
|
1655
|
-
const splits = content.split('\n')
|
1656
|
-
splits.forEach(item => {
|
1657
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1658
|
-
const text = new AlexElement('text', null, null, null, item)
|
1659
|
-
this.editor.addElementTo(text, paragraph)
|
1660
|
-
this.editor.addElementBefore(paragraph, pre)
|
1661
|
-
})
|
1662
|
-
pre.toEmpty()
|
1663
|
-
} else {
|
1664
|
-
//起点和终点在一起
|
1665
|
-
if (this.editor.range.anchor.isEqual(this.editor.range.focus)) {
|
1666
|
-
const block = this.editor.range.anchor.element.getBlock()
|
1667
|
-
blockToParagraph(block)
|
1668
|
-
block.parsedom = 'pre'
|
1669
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1670
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1671
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1672
|
-
this.editor.addElementAfter(paragraph, block)
|
1673
|
-
}
|
1674
|
-
//起点和终点不在一起
|
1675
|
-
else {
|
1676
|
-
let result = this.editor.getElementsByRange(true).includes
|
1677
|
-
this.editor.range.anchor.moveToStart(result[0].element.getBlock())
|
1678
|
-
this.editor.range.focus.moveToEnd(result[result.length - 1].element.getBlock())
|
1679
|
-
const res = this.editor.getElementsByRange(true).flatIncludes.filter(el => el.element.isText())
|
1680
|
-
const obj = {}
|
1681
|
-
res.forEach(el => {
|
1682
|
-
if (obj[el.element.getBlock().key]) {
|
1683
|
-
obj[el.element.getBlock().key].push(el.element.clone())
|
1684
|
-
} else {
|
1685
|
-
obj[el.element.getBlock().key] = [el.element.clone()]
|
1686
|
-
}
|
1687
|
-
})
|
1688
|
-
const pre = new AlexElement('block', 'pre', null, null, null)
|
1689
|
-
Object.keys(obj).forEach((key, index) => {
|
1690
|
-
if (index > 0) {
|
1691
|
-
const text = new AlexElement('text', null, null, null, '\n')
|
1692
|
-
if (pre.hasChildren()) {
|
1693
|
-
this.editor.addElementTo(text, pre, pre.children.length)
|
1694
|
-
} else {
|
1695
|
-
this.editor.addElementTo(text, pre)
|
1696
|
-
}
|
1697
|
-
}
|
1698
|
-
obj[key].forEach(el => {
|
1699
|
-
if (pre.hasChildren()) {
|
1700
|
-
this.editor.addElementTo(el, pre, pre.children.length)
|
1701
|
-
} else {
|
1702
|
-
this.editor.addElementTo(el, pre)
|
1703
|
-
}
|
1704
|
-
})
|
1705
|
-
})
|
1706
|
-
this.editor.delete()
|
1707
|
-
this.editor.insertElement(pre)
|
1708
|
-
const paragraph = new AlexElement('block', AlexElement.BLOCK_NODE, null, null, null)
|
1709
|
-
const breakEl = new AlexElement('closed', 'br', null, null, null)
|
1710
|
-
this.editor.addElementTo(breakEl, paragraph)
|
1711
|
-
this.editor.addElementAfter(paragraph, pre)
|
1712
|
-
}
|
1713
|
-
}
|
1714
|
-
if (isRender) {
|
1715
|
-
this.editor.formatElementStack()
|
1716
|
-
this.editor.domRender()
|
1717
|
-
this.editor.rangeRender()
|
1718
|
-
}
|
1719
|
-
},
|
1720
|
-
//api:插入文本
|
1721
|
-
insertText(text, isRender = true, useCache = false) {
|
1722
|
-
if (this.disabled) {
|
1723
|
-
return
|
1724
|
-
}
|
1725
|
-
if (!this.editor.range) {
|
1726
|
-
return
|
1727
|
-
}
|
1728
|
-
this.editor.insertText(text, useCache)
|
1729
|
-
if (isRender) {
|
1730
|
-
this.editor.formatElementStack()
|
1731
|
-
this.editor.domRender()
|
1732
|
-
this.editor.rangeRender()
|
1733
|
-
}
|
1734
|
-
},
|
1735
|
-
//api:插入html
|
1736
|
-
insertHtml(html, isRender = true, useCache = false) {
|
1737
|
-
if (this.disabled) {
|
1738
|
-
return
|
1739
|
-
}
|
1740
|
-
if (!this.editor.range) {
|
1741
|
-
return
|
1742
|
-
}
|
1743
|
-
const elements = this.editor.parseHtml(html)
|
1744
|
-
for (let i = 0; i < elements.length; i++) {
|
1745
|
-
this.editor.insertElement(elements[i], false, i == 0 ? useCache : false)
|
1746
|
-
}
|
1747
|
-
if (isRender) {
|
1748
|
-
this.editor.formatElementStack()
|
1749
|
-
this.editor.domRender()
|
1750
|
-
this.editor.rangeRender()
|
1751
|
-
}
|
1752
769
|
}
|
1753
770
|
},
|
1754
771
|
beforeUnmount() {
|
1755
772
|
//卸载绑定在滚动元素上的事件
|
1756
773
|
this.removeScrollHandle()
|
1757
774
|
//卸载绑定在document.documentElement上的事件
|
1758
|
-
|
775
|
+
DapEvent.off(document.documentElement, `mousedown.editify_${this.uid} mousemove.editify_${this.uid} mouseup.editify_${this.uid} click.editify_${this.uid}`)
|
1759
776
|
//卸载绑定在window上的事件
|
1760
|
-
|
777
|
+
DapEvent.off(window, `resize.editify_${this.uid}`)
|
1761
778
|
//销毁编辑器
|
1762
779
|
this.editor.destroy()
|
1763
780
|
}
|
@@ -1765,8 +782,11 @@ export default {
|
|
1765
782
|
</script>
|
1766
783
|
<style lang="less" scoped>
|
1767
784
|
.editify {
|
1768
|
-
display:
|
785
|
+
display: flex;
|
786
|
+
justify-content: flex-start;
|
787
|
+
flex-direction: column;
|
1769
788
|
width: 100%;
|
789
|
+
height: 100%;
|
1770
790
|
position: relative;
|
1771
791
|
box-sizing: border-box;
|
1772
792
|
-webkit-tap-highlight-color: transparent;
|
@@ -1781,18 +801,14 @@ export default {
|
|
1781
801
|
-webkit-tap-highlight-color: transparent;
|
1782
802
|
outline: none;
|
1783
803
|
}
|
1784
|
-
|
1785
|
-
&.fullheight {
|
1786
|
-
height: 100%;
|
1787
|
-
}
|
1788
|
-
|
1789
804
|
&.fullscreen {
|
1790
805
|
position: fixed;
|
1791
806
|
z-index: 1000;
|
1792
807
|
left: 0;
|
1793
808
|
top: 0;
|
1794
|
-
width: 100vw;
|
1795
|
-
height: 100vh;
|
809
|
+
width: 100vw !important;
|
810
|
+
height: 100vh !important;
|
811
|
+
background: @background;
|
1796
812
|
|
1797
813
|
.editify-body {
|
1798
814
|
border-radius: 0;
|
@@ -1803,6 +819,8 @@ export default {
|
|
1803
819
|
.editify-body {
|
1804
820
|
display: block;
|
1805
821
|
width: 100%;
|
822
|
+
height: 0;
|
823
|
+
flex: 1;
|
1806
824
|
position: relative;
|
1807
825
|
background-color: @background;
|
1808
826
|
padding: 1px;
|
@@ -1834,6 +852,7 @@ export default {
|
|
1834
852
|
overflow-x: hidden;
|
1835
853
|
overflow-y: auto;
|
1836
854
|
width: 100%;
|
855
|
+
height: 100%;
|
1837
856
|
border-radius: inherit;
|
1838
857
|
padding: 6px 10px;
|
1839
858
|
line-height: 1.5;
|
@@ -2061,8 +1080,7 @@ export default {
|
|
2061
1080
|
content: '';
|
2062
1081
|
position: absolute;
|
2063
1082
|
left: 0;
|
2064
|
-
top:
|
2065
|
-
transform: translateY(-50%);
|
1083
|
+
top: 2px;
|
2066
1084
|
z-index: 1;
|
2067
1085
|
cursor: pointer;
|
2068
1086
|
}
|