vue-editify 0.0.51 → 0.1.0
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 +20 -5594
- package/lib/editify.es.js +6873 -7843
- package/lib/editify.umd.js +1 -1
- package/lib/style.css +1 -1
- package/package.json +2 -2
- package/src/Editify.vue +258 -1241
- 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} +60 -296
- 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,67 @@ 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
|
+
],
|
314
|
+
allowCopy: this.allowCopy,
|
315
|
+
allowPaste: this.allowPaste,
|
316
|
+
allowCut: this.allowCut,
|
317
|
+
allowPasteHtml: this.allowPasteHtml,
|
318
|
+
allowPasteHtml: this.allowPasteHtml,
|
319
|
+
customImagePaste: this.handleCustomImagePaste,
|
320
|
+
customVideoPaste: this.handleCustomVideoPaste,
|
321
|
+
customMerge: this.handleCustomMerge,
|
322
|
+
customParseNode: this.handleCustomParseNode
|
323
|
+
})
|
324
|
+
//编辑器渲染后会有一个渲染过程,会改变内容,因此重新获取内容的值来设置value
|
325
|
+
this.internalModify(this.editor.value)
|
326
|
+
//设置监听事件
|
327
|
+
this.editor.on('change', this.handleEditorChange)
|
328
|
+
this.editor.on('focus', this.handleEditorFocus)
|
329
|
+
this.editor.on('blur', this.handleEditorBlur)
|
330
|
+
this.editor.on('insertParagraph', this.handleInsertParagraph)
|
331
|
+
this.editor.on('rangeUpdate', this.handleRangeUpdate)
|
332
|
+
this.editor.on('pasteHtml', this.handlePasteHtml)
|
333
|
+
this.editor.on('deleteInStart', this.handleDeleteInStart)
|
334
|
+
this.editor.on('deleteComplete', this.handleDeleteComplete)
|
335
|
+
this.editor.on('afterRender', this.handleAfterRender)
|
336
|
+
//格式化和dom渲染
|
337
|
+
this.editor.formatElementStack()
|
338
|
+
this.editor.domRender()
|
339
|
+
//自动获取焦点
|
340
|
+
if (this.autofocus && !this.isSourceView && !this.disabled) {
|
341
|
+
this.collapseToEnd()
|
369
342
|
}
|
370
|
-
return ele
|
371
|
-
},
|
372
|
-
//隐藏工具条
|
373
|
-
hideToolbar() {
|
374
|
-
this.toolbarOptions.show = false
|
375
|
-
this.toolbarOptions.node = null
|
376
343
|
},
|
377
344
|
//鼠标在页面按下:处理表格拖拽改变列宽和菜单栏是否使用判断
|
378
345
|
documentMouseDown(e) {
|
@@ -380,9 +347,9 @@ export default {
|
|
380
347
|
return
|
381
348
|
}
|
382
349
|
//鼠标在编辑器内按下
|
383
|
-
if (
|
350
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
384
351
|
const elm = e.target
|
385
|
-
const key =
|
352
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
386
353
|
if (key) {
|
387
354
|
const element = this.editor.getElementByKey(key)
|
388
355
|
if (element && element.parsedom == 'td') {
|
@@ -391,7 +358,7 @@ export default {
|
|
391
358
|
if (element.parent.children[length - 1].isEqual(element)) {
|
392
359
|
return
|
393
360
|
}
|
394
|
-
const rect =
|
361
|
+
const rect = DapElement.getElementBounding(elm)
|
395
362
|
//在可拖拽范围内
|
396
363
|
if (e.pageX >= Math.abs(rect.left + elm.offsetWidth - 5) && e.pageX <= Math.abs(rect.left + elm.offsetWidth + 5)) {
|
397
364
|
this.tableColumnResizeParams.element = element
|
@@ -401,7 +368,7 @@ export default {
|
|
401
368
|
}
|
402
369
|
}
|
403
370
|
//如果点击了除编辑器外的地方,菜单栏不可使用
|
404
|
-
if (!
|
371
|
+
if (!DapElement.isContains(this.$el, e.target) && !this.isSourceView) {
|
405
372
|
this.canUseMenu = false
|
406
373
|
}
|
407
374
|
},
|
@@ -413,7 +380,7 @@ export default {
|
|
413
380
|
if (!this.tableColumnResizeParams.element) {
|
414
381
|
return
|
415
382
|
}
|
416
|
-
const table =
|
383
|
+
const table = getCurrentParsedomElement(this, 'table')
|
417
384
|
if (!table) {
|
418
385
|
return
|
419
386
|
}
|
@@ -429,14 +396,14 @@ export default {
|
|
429
396
|
this.tableColumnResizeParams.start = e.pageX
|
430
397
|
},
|
431
398
|
//鼠标在页面松开:处理表格拖拽改变列宽
|
432
|
-
documentMouseUp(
|
399
|
+
documentMouseUp() {
|
433
400
|
if (this.disabled) {
|
434
401
|
return
|
435
402
|
}
|
436
403
|
if (!this.tableColumnResizeParams.element) {
|
437
404
|
return
|
438
405
|
}
|
439
|
-
const table =
|
406
|
+
const table = getCurrentParsedomElement(this, 'table')
|
440
407
|
if (!table) {
|
441
408
|
return
|
442
409
|
}
|
@@ -461,17 +428,17 @@ export default {
|
|
461
428
|
if (this.disabled) {
|
462
429
|
return
|
463
430
|
}
|
464
|
-
|
465
|
-
if (
|
431
|
+
//鼠标在编辑器内点击
|
432
|
+
if (DapElement.isContains(this.$refs.content, e.target)) {
|
466
433
|
const elm = e.target
|
467
|
-
const key =
|
434
|
+
const key = DapData.get(elm, 'data-alex-editor-key')
|
468
435
|
if (key) {
|
469
436
|
const element = this.editor.getElementByKey(key)
|
470
437
|
//如果是任务列表元素
|
471
|
-
if (
|
472
|
-
const rect =
|
438
|
+
if (isTask(element)) {
|
439
|
+
const rect = DapElement.getElementBounding(elm)
|
473
440
|
//在复选框范围内
|
474
|
-
if (e.pageX >= Math.abs(rect.left) && e.pageX <= Math.abs(rect.left + 16) && e.pageY >= Math.abs(rect.top +
|
441
|
+
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
442
|
//取消勾选
|
476
443
|
if (element.marks['data-editify-task'] == 'checked') {
|
477
444
|
element.marks['data-editify-task'] = 'uncheck'
|
@@ -493,6 +460,99 @@ export default {
|
|
493
460
|
}
|
494
461
|
}
|
495
462
|
},
|
463
|
+
//自定义图片粘贴
|
464
|
+
async handleCustomImagePaste(url) {
|
465
|
+
const newUrl = await this.customImagePaste.apply(this, [url])
|
466
|
+
if (newUrl) {
|
467
|
+
insertImage(this, newUrl)
|
468
|
+
}
|
469
|
+
},
|
470
|
+
//自定义视频粘贴
|
471
|
+
async handleCustomVideoPaste(url) {
|
472
|
+
const newUrl = await this.customVideoPaste.apply(this, [url])
|
473
|
+
if (newUrl) {
|
474
|
+
insertVideo(this, newUrl)
|
475
|
+
}
|
476
|
+
},
|
477
|
+
//重新定义编辑器合并元素的逻辑
|
478
|
+
handleCustomMerge(ele, preEle) {
|
479
|
+
const uneditable = preEle.getUneditableElement()
|
480
|
+
if (uneditable) {
|
481
|
+
uneditable.toEmpty()
|
482
|
+
} else {
|
483
|
+
preEle.children.push(...ele.children)
|
484
|
+
preEle.children.forEach(item => {
|
485
|
+
item.parent = preEle
|
486
|
+
})
|
487
|
+
ele.children = null
|
488
|
+
}
|
489
|
+
},
|
490
|
+
//针对node转为元素进行额外的处理
|
491
|
+
handleCustomParseNode(ele) {
|
492
|
+
if (ele.parsedom == 'code') {
|
493
|
+
ele.parsedom = 'span'
|
494
|
+
const marks = {
|
495
|
+
'data-editify-code': true
|
496
|
+
}
|
497
|
+
if (ele.hasMarks()) {
|
498
|
+
Object.assign(ele.marks, marks)
|
499
|
+
} else {
|
500
|
+
ele.marks = marks
|
501
|
+
}
|
502
|
+
}
|
503
|
+
if (typeof this.customParseNoe == 'function') {
|
504
|
+
ele = this.customParseNoe.apply(this, [ele])
|
505
|
+
}
|
506
|
+
return ele
|
507
|
+
},
|
508
|
+
//编辑区域键盘按下:设置缩进快捷键
|
509
|
+
handleEditorKeydown(e) {
|
510
|
+
if (this.disabled) {
|
511
|
+
return
|
512
|
+
}
|
513
|
+
//增加缩进
|
514
|
+
if (e.keyCode == 9 && !e.metaKey && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
515
|
+
e.preventDefault()
|
516
|
+
if (!hasTableInRange(this)) {
|
517
|
+
setIndentIncrease(this)
|
518
|
+
this.editor.formatElementStack()
|
519
|
+
this.editor.domRender()
|
520
|
+
this.editor.rangeRender()
|
521
|
+
}
|
522
|
+
}
|
523
|
+
//减少缩进
|
524
|
+
else if (e.keyCode == 9 && !e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey) {
|
525
|
+
e.preventDefault()
|
526
|
+
if (!hasTableInRange(this)) {
|
527
|
+
setIndentDecrease(this)
|
528
|
+
this.editor.formatElementStack()
|
529
|
+
this.editor.domRender()
|
530
|
+
this.editor.rangeRender()
|
531
|
+
}
|
532
|
+
}
|
533
|
+
//自定义键盘按下操作
|
534
|
+
this.$emit('keydown', e)
|
535
|
+
},
|
536
|
+
//点击编辑器:处理图片和视频的光标聚集
|
537
|
+
handleEditorClick(e) {
|
538
|
+
if (this.disabled || this.isSourceView) {
|
539
|
+
return
|
540
|
+
}
|
541
|
+
const node = e.target
|
542
|
+
//点击的是图片或者视频
|
543
|
+
if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
|
544
|
+
const key = Number(node.getAttribute('data-editify-element'))
|
545
|
+
if (DapNumber.isNumber(key)) {
|
546
|
+
const element = this.editor.getElementByKey(key)
|
547
|
+
if (!this.editor.range) {
|
548
|
+
this.editor.initRange()
|
549
|
+
}
|
550
|
+
this.editor.range.anchor.moveToStart(element)
|
551
|
+
this.editor.range.focus.moveToEnd(element)
|
552
|
+
this.editor.rangeRender()
|
553
|
+
}
|
554
|
+
}
|
555
|
+
},
|
496
556
|
//编辑器的值更新
|
497
557
|
handleEditorChange(newVal, oldVal) {
|
498
558
|
if (this.disabled) {
|
@@ -530,7 +590,7 @@ export default {
|
|
530
590
|
//编辑区域边框颜色
|
531
591
|
this.$refs.body.style.borderColor = this.color
|
532
592
|
//转换颜色值
|
533
|
-
const rgb =
|
593
|
+
const rgb = DapColor.hex2rgb(this.color)
|
534
594
|
//菜单栏模式为inner
|
535
595
|
if (this.menuConfig.use && this.menuConfig.mode == 'inner') {
|
536
596
|
//编辑区域除顶部边框的阴影
|
@@ -554,56 +614,15 @@ export default {
|
|
554
614
|
//获取焦点时可以使用菜单栏
|
555
615
|
setTimeout(() => {
|
556
616
|
this.canUseMenu = true
|
617
|
+
this.$emit('focus', val)
|
557
618
|
}, 0)
|
558
|
-
this.$emit('focus', val)
|
559
|
-
},
|
560
|
-
//编辑区域键盘按下
|
561
|
-
handleEditorKeydown(e) {
|
562
|
-
if (this.disabled) {
|
563
|
-
return
|
564
|
-
}
|
565
|
-
//增加缩进
|
566
|
-
if (e.keyCode == 9 && !e.metaKey && !e.shiftKey && !e.ctrlKey && !e.altKey) {
|
567
|
-
e.preventDefault()
|
568
|
-
this.setIndentIncrease()
|
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) {
|
581
|
-
return
|
582
|
-
}
|
583
|
-
const node = e.target
|
584
|
-
//点击的是图片或者视频
|
585
|
-
if (node.nodeName.toLocaleLowerCase() == 'img' || node.nodeName.toLocaleLowerCase() == 'video') {
|
586
|
-
const key = node.getAttribute('data-editify-element')
|
587
|
-
if (key) {
|
588
|
-
const element = this.editor.getElementByKey(key)
|
589
|
-
if (!this.editor.range) {
|
590
|
-
this.editor.initRange()
|
591
|
-
}
|
592
|
-
this.editor.range.anchor.moveToStart(element)
|
593
|
-
this.editor.range.focus.moveToEnd(element)
|
594
|
-
this.editor.rangeRender()
|
595
|
-
}
|
596
|
-
}
|
597
619
|
},
|
598
620
|
//编辑器换行
|
599
621
|
handleInsertParagraph(element, previousElement) {
|
600
622
|
//前一个块元素如果是只包含换行符的元素,并且当前块元素也是包含换行符的元素,则当前块元素转为段落
|
601
623
|
if (previousElement.isOnlyHasBreak() && element.isOnlyHasBreak()) {
|
602
|
-
if (!previousElement.isBlock()) {
|
603
|
-
previousElement.convertToBlock()
|
604
|
-
}
|
605
624
|
if (previousElement.parsedom != AlexElement.BLOCK_NODE) {
|
606
|
-
|
625
|
+
elementToParagraph(previousElement)
|
607
626
|
this.editor.range.anchor.moveToStart(previousElement)
|
608
627
|
this.editor.range.focus.moveToStart(previousElement)
|
609
628
|
element.toEmpty()
|
@@ -616,41 +635,31 @@ export default {
|
|
616
635
|
if (this.disabled) {
|
617
636
|
return
|
618
637
|
}
|
638
|
+
|
639
|
+
//如果没有range禁用菜单栏
|
619
640
|
this.canUseMenu = !!this.editor.range
|
641
|
+
|
642
|
+
//没有range直接返回
|
620
643
|
if (!this.editor.range) {
|
621
644
|
return
|
622
645
|
}
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
if (this.toolbarConfig.use) {
|
633
|
-
this.handleToolbar(true)
|
634
|
-
}
|
635
|
-
//如果使用菜单栏
|
636
|
-
if (this.menuConfig.use) {
|
637
|
-
this.$refs.menu.handleRangeUpdate(true)
|
638
|
-
}
|
646
|
+
|
647
|
+
//获取光标选取范围内的元素数据,并且进行缓存
|
648
|
+
this.dataRangeCaches = this.editor.getElementsByRange()
|
649
|
+
|
650
|
+
//如果使用工具条或者菜单栏
|
651
|
+
if (this.toolbarConfig.use || this.menuConfig.use) {
|
652
|
+
//如果使用工具条
|
653
|
+
if (this.toolbarConfig.use) {
|
654
|
+
this.handleToolbar()
|
639
655
|
}
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
//编辑器剪切
|
648
|
-
handleCut(text, html) {
|
649
|
-
this.$emit('cut', text, html)
|
650
|
-
},
|
651
|
-
//编辑器粘贴纯文本
|
652
|
-
handlePasteText(data) {
|
653
|
-
this.$emit('paste-text', data)
|
656
|
+
//如果使用菜单栏
|
657
|
+
if (this.menuConfig.use) {
|
658
|
+
this.$refs.menu.handleRangeUpdate()
|
659
|
+
}
|
660
|
+
}
|
661
|
+
|
662
|
+
this.$emit('rangeupdate')
|
654
663
|
},
|
655
664
|
//编辑器粘贴html
|
656
665
|
handlePasteHtml(elements) {
|
@@ -677,20 +686,11 @@ export default {
|
|
677
686
|
el.styles = styles
|
678
687
|
}
|
679
688
|
})
|
680
|
-
this.$emit('paste-html', elements)
|
681
689
|
},
|
682
|
-
|
683
|
-
handlePasteImage(url) {
|
684
|
-
this.$emit('paste-image', url)
|
685
|
-
},
|
686
|
-
//编辑器粘贴视频
|
687
|
-
handlePasteVideo(url) {
|
688
|
-
this.$emit('paste-video', url)
|
689
|
-
},
|
690
|
-
//编辑器部分删除情景
|
690
|
+
//编辑器部分删除情景(在编辑器起始处)
|
691
691
|
handleDeleteInStart(element) {
|
692
692
|
if (element.isBlock()) {
|
693
|
-
|
693
|
+
elementToParagraph(element)
|
694
694
|
}
|
695
695
|
},
|
696
696
|
//编辑器删除完成后事件
|
@@ -700,39 +700,12 @@ export default {
|
|
700
700
|
uneditable.toEmpty()
|
701
701
|
}
|
702
702
|
},
|
703
|
-
//编辑器dom渲染之前
|
704
|
-
handleBeforeRender() {
|
705
|
-
this.$emit('before-render')
|
706
|
-
},
|
707
703
|
//编辑器dom渲染
|
708
704
|
handleAfterRender() {
|
709
705
|
//设定视频高度
|
710
706
|
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
|
-
}
|
707
|
+
|
708
|
+
this.$emit('updateview')
|
736
709
|
},
|
737
710
|
|
738
711
|
//api:光标设置到文档底部
|
@@ -742,7 +715,7 @@ export default {
|
|
742
715
|
}
|
743
716
|
this.editor.collapseToEnd()
|
744
717
|
this.editor.rangeRender()
|
745
|
-
|
718
|
+
DapElement.setScrollTop({
|
746
719
|
el: this.$refs.content,
|
747
720
|
number: 1000000,
|
748
721
|
time: 0
|
@@ -756,364 +729,13 @@ export default {
|
|
756
729
|
this.editor.collapseToStart()
|
757
730
|
this.editor.rangeRender()
|
758
731
|
this.$nextTick(() => {
|
759
|
-
|
732
|
+
DapElement.setScrollTop({
|
760
733
|
el: this.$refs.content,
|
761
734
|
number: 0,
|
762
735
|
time: 0
|
763
736
|
})
|
764
737
|
})
|
765
738
|
},
|
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
739
|
//api:撤销
|
1118
740
|
undo() {
|
1119
741
|
if (this.disabled) {
|
@@ -1143,621 +765,15 @@ export default {
|
|
1143
765
|
this.editor.domRender(true)
|
1144
766
|
this.editor.rangeRender()
|
1145
767
|
}
|
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
768
|
}
|
1753
769
|
},
|
1754
770
|
beforeUnmount() {
|
1755
771
|
//卸载绑定在滚动元素上的事件
|
1756
772
|
this.removeScrollHandle()
|
1757
773
|
//卸载绑定在document.documentElement上的事件
|
1758
|
-
|
774
|
+
DapEvent.off(document.documentElement, `mousedown.editify_${this.uid} mousemove.editify_${this.uid} mouseup.editify_${this.uid} click.editify_${this.uid}`)
|
1759
775
|
//卸载绑定在window上的事件
|
1760
|
-
|
776
|
+
DapEvent.off(window, `resize.editify_${this.uid}`)
|
1761
777
|
//销毁编辑器
|
1762
778
|
this.editor.destroy()
|
1763
779
|
}
|
@@ -1765,8 +781,11 @@ export default {
|
|
1765
781
|
</script>
|
1766
782
|
<style lang="less" scoped>
|
1767
783
|
.editify {
|
1768
|
-
display:
|
784
|
+
display: flex;
|
785
|
+
justify-content: flex-start;
|
786
|
+
flex-direction: column;
|
1769
787
|
width: 100%;
|
788
|
+
height: 100%;
|
1770
789
|
position: relative;
|
1771
790
|
box-sizing: border-box;
|
1772
791
|
-webkit-tap-highlight-color: transparent;
|
@@ -1781,18 +800,14 @@ export default {
|
|
1781
800
|
-webkit-tap-highlight-color: transparent;
|
1782
801
|
outline: none;
|
1783
802
|
}
|
1784
|
-
|
1785
|
-
&.fullheight {
|
1786
|
-
height: 100%;
|
1787
|
-
}
|
1788
|
-
|
1789
803
|
&.fullscreen {
|
1790
804
|
position: fixed;
|
1791
805
|
z-index: 1000;
|
1792
806
|
left: 0;
|
1793
807
|
top: 0;
|
1794
|
-
width: 100vw;
|
1795
|
-
height: 100vh;
|
808
|
+
width: 100vw !important;
|
809
|
+
height: 100vh !important;
|
810
|
+
background: @background;
|
1796
811
|
|
1797
812
|
.editify-body {
|
1798
813
|
border-radius: 0;
|
@@ -1803,6 +818,8 @@ export default {
|
|
1803
818
|
.editify-body {
|
1804
819
|
display: block;
|
1805
820
|
width: 100%;
|
821
|
+
height: 0;
|
822
|
+
flex: 1;
|
1806
823
|
position: relative;
|
1807
824
|
background-color: @background;
|
1808
825
|
padding: 1px;
|
@@ -1834,6 +851,7 @@ export default {
|
|
1834
851
|
overflow-x: hidden;
|
1835
852
|
overflow-y: auto;
|
1836
853
|
width: 100%;
|
854
|
+
height: 100%;
|
1837
855
|
border-radius: inherit;
|
1838
856
|
padding: 6px 10px;
|
1839
857
|
line-height: 1.5;
|
@@ -2061,8 +1079,7 @@ export default {
|
|
2061
1079
|
content: '';
|
2062
1080
|
position: absolute;
|
2063
1081
|
left: 0;
|
2064
|
-
top:
|
2065
|
-
transform: translateY(-50%);
|
1082
|
+
top: 2px;
|
2066
1083
|
z-index: 1;
|
2067
1084
|
cursor: pointer;
|
2068
1085
|
}
|