This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0

优化meditor

old
宇天 2021-04-02 19:44:48 +08:00
parent 4ddffd2585
commit 2457e14a86
1 changed files with 195 additions and 63 deletions

View File

@ -60,7 +60,8 @@
min-width: 200px;
min-height: 100px;
// max-height: 360px;
border-radius: 2px;
border-radius: 3px;
transition: box-shadow 0.15s linear;
}
.meditor {
@ -135,6 +136,7 @@
background: none;
outline: none;
resize: none;
cursor: inherit;
}
.preview {
@ -336,6 +338,10 @@
width: 100%;
height: 100%;
}
:host(:focus-within) {
box-shadow: 0 0 0 2px var(--color-plain-a);
}
</style>
<script>
@ -360,6 +366,10 @@ export default class Meditor {
preview: window.innerWidth > 768
}
state = {
toolbar: []
}
__init__() {
/* render */
@ -625,27 +635,24 @@ export default class Meditor {
)
}
// 往文本框中插入内容
insert(val, isSelect) {
/**
* 往文本框中插入内容
* @param {String} val [要插入的文本]
* @param {Boolean} isSelect [插入之后是否要选中文本]
* @param {Boolean} offset [选中文本时的偏移量]
*/
insert(val = '', isSelect = false, offset = 0) {
var dom = this.__EDITOR__
if (document.selection) {
dom.focus()
let range = document.selection.createRange()
range.text = val
dom.focus()
range.moveStart('character', -1)
} else if (dom.selectionStart || dom.selectionStart === 0) {
let startPos = dom.selectionStart
let endPos = dom.selectionEnd
let scrollTop = dom.scrollTop
var start = dom.selectionStart
var end = dom.selectionEnd
var scrollTop = dom.scrollTop
if (start || start === 0) {
dom.value =
dom.value.slice(0, startPos) +
val +
dom.value.slice(endPos, dom.value.length)
dom.value.slice(0, start) + val + dom.value.slice(end, dom.value.length)
dom.selectionStart = isSelect ? startPos : startPos + val.length
dom.selectionEnd = startPos + val.length
dom.selectionStart = (isSelect ? start : start + val.length) + offset
dom.selectionEnd = start + val.length - offset
dom.scrollTop = scrollTop
dom.focus()
} else {
@ -659,39 +666,70 @@ export default class Meditor {
* @param {[type]} dom [要操作的元素]
* @param {[type]} forceHoleLine [是否强制光标所在的整行文本]
*/
selection(forceHoleLine) {
selection(forceHoleLine = false) {
var dom = this.__EDITOR__
if (document.selection) {
return document.selection.createRange().text
} else {
let startPos = dom.selectionStart
let endPos = dom.selectionEnd
var start = dom.selectionStart
var end = dom.selectionEnd
if (endPos) {
if (end) {
//强制选择整行
if (forceHoleLine) {
startPos = dom.value.slice(0, startPos).lastIndexOf('\n')
start = dom.value.slice(0, start).lastIndexOf('\n')
let tmpEnd = dom.value.slice(endPos).indexOf('\n')
tmpEnd = tmpEnd < 0 ? dom.value.slice(endPos).length : tmpEnd
let tmpEnd = dom.value.slice(end).indexOf('\n')
tmpEnd = tmpEnd < 0 ? dom.value.slice(end).length : tmpEnd
startPos += 1 // 把\n加上
endPos += tmpEnd
start += 1 // 把\n加上
end += tmpEnd
dom.selectionStart = startPos
dom.selectionEnd = endPos
dom.selectionStart = start
dom.selectionEnd = end
}
} else {
//强制选择整行
if (forceHoleLine) {
endPos = dom.value.indexOf('\n')
endPos = endPos < 0 ? dom.value.length : endPos
dom.selectionEnd = endPos
end = dom.value.indexOf('\n')
end = end < 0 ? dom.value.length : end
dom.selectionEnd = end
}
}
dom.focus()
return dom.value.slice(startPos, endPos)
return dom.value.slice(start, end)
}
select(start = 0, end = 0) {
var dom = this.__EDITOR__
dom.selectionStart = start
dom.selectionEnd = end
}
cursor(step) {
var pos = this.__EDITOR__.selectionStart || 0
pos += step
if (step === 0) {
return
}
if (pos < 0) {
pos = 0
}
this.select(pos, pos)
}
_getCursorText(n) {
var dom = this.__EDITOR__
var start = dom.selectionStart
var end = dom.selectionEnd
var pos = end
if (n < 0) {
pos = start - 1
if (pos < 0) {
pos = 0
}
}
return this.value[pos] || ''
}
get value() {
@ -701,7 +739,28 @@ export default class Meditor {
set value(val) {
this.__EDITOR__.value = val
if (this.props.preview) {
this.__VIEW__.textContent = val
this.__VIEW__.value = val
}
}
get disabled() {
return this.props.disabled
}
set disabled(val) {
var type = typeof val
if (val === this.props.disabled) {
return
}
if ((type === 'boolean' && val) || type !== 'boolean') {
this.props.disabled = true
this.__EDITOR__.disabled = true
this.setAttribute('disabled', '')
} else {
this.props.disabled = false
this.__EDITOR__.disabled = false
this.removeAttribute('disabled')
}
}
@ -717,7 +776,7 @@ export default class Meditor {
if (this.props.preview) {
var txt = this.__EDITOR__.value.trim()
if (txt) {
this.__VIEW__.textContent = txt
this.__VIEW__.value = txt
} else {
this.__VIEW__.clear()
}
@ -727,8 +786,10 @@ export default class Meditor {
$.bind(this.__EDITOR__, 'keydown', ev => {
let wrap = this.selection() || ''
let select = !!wrap
switch (ev.keyCode) {
//tab键改为插入2个空格,阻止默认事件,防止焦点失去
if (ev.keyCode === 9) {
case 9:
ev.preventDefault()
wrap = wrap
.split('\n')
@ -737,14 +798,77 @@ export default class Meditor {
})
.join('\n')
this.insert(wrap, select)
}
break
//修复按退格键删除选中文本时,选中的状态不更新的bug
if (ev.keyCode === 8) {
if (select) {
ev.preventDefault()
this.insert('', select)
case 8:
if (!select) {
let pos = this.__EDITOR__.selectionStart
let prev = this._getCursorText(-1)
let next = this._getCursorText(1)
if (
(prev === next && (prev === '"' || prev === "'")) ||
(prev === '[' && next === ']') ||
(prev === '{' && next === '}') ||
(prev === '(' && next === ')')
) {
this.select(pos - 1, pos + 1)
}
}
break
// (
case 57:
if (ev.shiftKey) {
ev.preventDefault()
this.insert('(' + wrap + ')', select, (select && 1) || 0)
this.cursor(select ? 0 : -1)
}
break
case 219: // [ & {
ev.preventDefault()
this.insert(
ev.shiftKey ? `{${wrap}}` : `[${wrap}]`,
select,
(select && 1) || 0
)
this.cursor(select ? 0 : -1)
break
// ' & "
case 222:
{
ev.preventDefault()
let val = "'"
let prev = this._getCursorText(-1)
let next = this._getCursorText(1)
if (select) {
this.insert(val + wrap + val, true, 1)
} else {
if (ev.shiftKey) {
val = '"'
}
if (prev === next && prev === val) {
this.cursor(1)
} else {
if (prev === val || next === val) {
this.insert(val)
} else {
this.insert(val.repeat(2))
this.cursor(-1)
}
}
}
}
break
}
})
$.bind(this.__EDITOR__, 'paste', ev => {
@ -807,13 +931,21 @@ export default class Meditor {
this.value = val
break
case 'preview':
if (val === 'false') {
this.props.preview = false
} else {
this.props.preview = window.innerWidth > 768
}
break
case 'readonly':
case 'disabled':
var k = name
if (k === 'readonly') {
k = 'readOnly'
}
this[k] = true
this[k] = val !== null
break
default: