初试富文本编辑器
都说富文本编辑器是天坑,我也去坑边看一眼
为什么都说富文本编辑器是天坑?。早就听说过富文本编辑器,一般看到这种标题都会让人有一种想去试试的冲动,至少也要去溜达一圈,就像地牢围攻1的绝望洞一样。于是我去MDN上找了找教程。原来现成的代码都有。
要尝试点什么?
-
MDN的代码,无法实现光标位置变化之后,读取光标处的文本格式,并改变样式按钮状态的功能。比如word里面,光标处的文本是加粗的话,工具栏的加粗按钮就变成按下状态,离开这段区域之后又会变成未按下状态。要实现这个功能,基本思路就是利用点击和键盘事件加上queryCommandState,大致代码如下:
var editor = document.getElementById('editor');
editor.addEventListener('keyup', function() {
statusCheck(buttons);
});
editor.addEventListener('mouseup', function() {
statusCheck(buttons);
});function statusCheck(buttons) {
commands.forEach(function(command) {
var state = document.queryCommandState(command.cmd);
var className = buttons[command.cmd].className;
if (state) {
buttons[command.cmd].className = addClass(className, 'on');
} else {
buttons[command.cmd].className = removeClass(className, 'on');
}
});
} -
无法取得选中区域的文字。因为getSelection只返回选择的起始和结束的DOM元素及信息,如果想要取得所选文件,必须自己去遍历选中的DOM节点,取出其中的text节点。大致代码实现如下:
function getSelectedText() {
var selection = getSelection();// 取得开始的文字
var anchorNode = selection.anchorNode;
var anchorOffset = selection.anchorOffset;
var focusNode = selection.focusNode;
var focusOffset = selection.focusOffset;// 判断选择的方向
var isForward = isNodeBefore(anchorNode, focusNode);
var startNode;
var endNode;
var startOffset;
var endOffset;
if (isForward) {
startNode = anchorNode;
endNode = focusNode;
startOffset = anchorOffset;
endOffset = focusOffset;
} else {
startNode = focusNode;
endNode = anchorNode;
startOffset = focusOffset;
endOffset = anchorOffset;
}var text1 = '';
if (startNode !== null) {
var startText = startNode.data;
text1 = startText.substring(startOffset);
}// 取得结束的文字
var text2 = '';
if (endNode !== null) {
var endText = endNode.data;
text2 = endText.substring(0, endOffset);
}//取得中间的文字
var middleText = '';
if (startNode !== null && endNode !== null) {
middleText = getMiddleText(startNode, endNode);
}return text1 + middleText + text2;
}function getMiddleText(startNode, endNode) {
if (startNode === null && endNode === null) {
return;
}var pivot = startNode;
var middleText = '';
var text;
while(pivot !== endNode) {
text = '';
if (pivot.nextSibling === null) {
if (pivot.parentNode === null) {
break;
} else {
pivot = pivot.parentNode;
}
} else {
pivot = pivot.nextSibling;
text = traversal(pivot);
}
middleText += text;
}return middleText;
// 遍历节点选择文字
function traversal(root) {
if (pivot === endNode) {
return '';
}
if (root.nodeType === 3) {
return root.nodeValue;
} else {
var text = '';
var childNodes = root.childNodes;
for (var i = 0; i < childNodes.length; i++) {
if (childNodes[i] === endNode) {
pivot = endNode;
break;
}
text += traversal(childNodes[i]);
}
return text;
}
}
}function isNodeBefore(startNode, endNode) {
var startParents = getParents(startNode), endParents = getParents(endNode);
var count = Math.min(startParents.length, endParents.length);
var commonParent, startParent, endParent;
for (var i = 0; i < count; i++) {
startParent = startParents[startParents.length - i - 1];
endParent = endParents[endParents.length - i - 1];
if (startParent === endParent) {
commonParent = startParent;
} else {
var startPos = convertToArray(commonParent.childNodes).indexOf(startParent);
var endPos = convertToArray(commonParent.childNodes).indexOf(endParent);
return startPos < endPos;
}
}
return true;
}
难得能用上一点点数据结构的知识
完整代码
尽管惨不忍睹,我还是献丑放上来。不被婊怎么进步,虽然我觉得也不会有人觉得值得花功夫婊。(以后再也不贴大段代码了,调格式好累。这次就当充数了。结果调格式的过程中自己给自己增加了点击量)
浙公网安备 33010602011771号