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