hi-mention
Version:
纯JS聊天框,兼容原生HTML/React/Vue等各种框架;支持@提及功能、插入富文本等多功能编辑器;内置H5和PC的交互样式
289 lines (288 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = wordDelete;
var const_1 = require("../const");
var _1 = require(".");
var range_1 = require("./range");
function onDelete(range, _a) {
var _b, _c, _d, _e, _f, _g, _h, _j, _k;
var rowEl = _a.rowEl, textEl = _a.textEl;
var rangeNode = range.commonAncestorContainer;
// 删除文本内容
var isText = rangeNode.nodeName === "#text";
var textLength = ((_b = rangeNode.textContent) === null || _b === void 0 ? void 0 : _b.length) || 0;
var isEmpty = rangeNode.textContent === const_1.PLACEHOLDER_TEXT;
if (isText && !isEmpty && range.endOffset < textLength) {
// 如果只有一个字符,则将节点内容设置为0宽占位符
if (textLength === 1) {
rangeNode.textContent = const_1.PLACEHOLDER_TEXT;
return true;
}
// 否则删除光标位置之后的第一个文本内容
var index = range.endOffset;
// 找到要删除的内容
var text = (_c = rangeNode.textContent) === null || _c === void 0 ? void 0 : _c[index];
var sIndex = index;
var eIndex = index + 1;
if (text === const_1.PLACEHOLDER_TEXT) {
index += 1;
sIndex = index;
eIndex = index + 1;
text = (_d = rangeNode.textContent) === null || _d === void 0 ? void 0 : _d[index + 1];
}
// 如果要删除的是\r,则将连续的\r都删除
if (text === "\r" && index < Number((_e = rangeNode.textContent) === null || _e === void 0 ? void 0 : _e.length)) {
for (var i = index; i < Number((_f = rangeNode.textContent) === null || _f === void 0 ? void 0 : _f.length); i++) {
if (((_g = rangeNode.textContent) === null || _g === void 0 ? void 0 : _g[i]) === "\r") {
index += 1;
eIndex = index + 1;
}
else
break;
}
}
var text1 = ((_h = rangeNode.textContent) === null || _h === void 0 ? void 0 : _h.slice(0, sIndex)) || "";
var text2 = ((_j = rangeNode.textContent) === null || _j === void 0 ? void 0 : _j.slice(eIndex)) || "";
rangeNode.textContent = text1 + text2;
index = Math.min(index, rangeNode.textContent.length);
range.setStart(rangeNode, index);
range.collapse(true);
return true;
}
// 获取当前所在行的下一个兄弟节点
var nextRow = rowEl.nextElementSibling;
// 如果当前节点是空标签
if ((0, _1.isEmptyElement)(rowEl)) {
// 如果存在下一个兄弟节点
if (nextRow) {
rowEl.remove();
// 将光标移动到下一个兄弟的起点
(0, range_1.moveRangeAtRowStart)(range, nextRow);
}
return true;
}
// 没有下一个节点并且在当前行的末尾
if (!nextRow && (0, range_1.isRangeAtRowEnd)(range, rowEl)) {
return true;
}
// 如果光标在当前行的末尾并且有下一个兄弟节点
if ((0, range_1.isRangeAtRowEnd)(range, rowEl) && nextRow) {
// 如果下一个节点是空标签
if ((0, _1.isEmptyElement)(nextRow)) {
nextRow.remove();
return true;
}
// 将下一个兄弟节点的内容转移到当前节点
(0, _1.transferElement)(nextRow, rowEl);
return true;
}
var delEl = textEl; // 要删除的内容
// 如果当前是空节点或者光标在当前文本的末尾
if ((0, _1.isEmptyElement)(textEl) || (0, range_1.isRangeAtTextEnd)(range)) {
var index = Array.from(rowEl.childNodes).indexOf(textEl);
// 往后删除所有空节点
var delIndexs = [];
// 如果当前节点为空,则删除当前节点
if ((0, _1.isEmptyElement)(delEl))
delIndexs.push(delEl);
for (var i = index + 1; i < rowEl.childNodes.length; i++) {
var node = rowEl.childNodes[i];
if ((0, _1.isEmptyElement)(node)) {
delIndexs.push(node);
}
else {
delEl = node;
break;
}
}
// 删除所有空节点
delIndexs.forEach(function (node) {
var _a;
(_a = node.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(node);
});
}
// 如果是文本节点,则删除第一个字符并将光标移动到节点开头
if (delEl.className === const_1.TEXT_TAG_CLASS) {
delEl.textContent = ((_k = delEl.textContent) === null || _k === void 0 ? void 0 : _k.slice(1)) || "";
// 如果还有剩余内容,将光标移动到节点开头
if (!(0, _1.isEmptyElement)(delEl)) {
var textNode = delEl.lastChild;
range.setStart(textNode ? textNode : delEl, 0);
range.collapse(true);
return true;
}
}
// 获取下一个节点
var nextNode = delEl.nextElementSibling;
delEl.remove();
if ((0, _1.isEmptyElement)(rowEl)) {
rowEl.innerHTML = (0, _1.createTextTag)(const_1.NEW_LINE).outerHTML;
(0, range_1.moveRangeAtRowEnd)(range, rowEl);
}
else if (nextNode) {
// 下一个节点的第一个子节点
var textNode = nextNode.firstChild;
range.setStart(textNode ? textNode : nextNode, 0);
range.collapse(true);
}
return true;
}
function onBackspace(range, _a) {
var _b, _c, _d, _e, _f, _g, _h, _j, _k;
var rowEl = _a.rowEl, textEl = _a.textEl;
var rangeNode = range.commonAncestorContainer;
// 删除文本内容
var isText = rangeNode.nodeName === "#text";
var isEmpty = rangeNode.textContent === const_1.PLACEHOLDER_TEXT;
if (isText && !isEmpty && range.startOffset > 0) {
// 如果只有一个字符,则将节点内容设置为0宽占位符
if (((_b = range.startContainer.textContent) === null || _b === void 0 ? void 0 : _b.length) === 1) {
rangeNode.textContent = const_1.PLACEHOLDER_TEXT;
return true;
}
// 否则删除光标位置之前的第一个文本内容
var index = range.startOffset;
// 找到要删除的内容
var text = (_c = rangeNode.textContent) === null || _c === void 0 ? void 0 : _c[index - 1];
var sIndex = index - 1;
var eIndex = index;
if (text === const_1.PLACEHOLDER_TEXT) {
index -= 1;
sIndex = index - 1;
eIndex = index;
text = (_d = rangeNode.textContent) === null || _d === void 0 ? void 0 : _d[index - 1];
}
// 如果要删除的是\r,则将连续的\r都删除
if (text === "\r" && index > 1) {
for (var i = index - 1; i >= 0; i--) {
if (((_e = rangeNode.textContent) === null || _e === void 0 ? void 0 : _e[i]) === "\r") {
index -= 1;
sIndex = index - 1;
}
else
break;
}
}
var text1 = ((_f = rangeNode.textContent) === null || _f === void 0 ? void 0 : _f.slice(0, sIndex)) || "";
var text2 = ((_g = rangeNode.textContent) === null || _g === void 0 ? void 0 : _g.slice(eIndex)) || "";
rangeNode.textContent = text1 + text2;
index = Math.max(0, index - 1);
index = Math.min(index, rangeNode.textContent.length);
range.setStart(rangeNode, index);
range.collapse(true);
return true;
}
// 获取当前光标所在P标签的上一个兄弟节点
var upRow = rowEl.previousElementSibling;
// 如果当前节点是空标签
if ((0, _1.isEmptyElement)(rowEl)) {
// 如果有上一个兄弟节点
if (upRow) {
rowEl.remove();
// 将光标移动到上一个P标签的末尾
(0, range_1.moveRangeAtRowEnd)(range, upRow);
}
// 如果没有兄弟不执行操作
return true;
}
// 如果没有上级兄弟,并且光标在当前行开头,不执行操作
if (!upRow && (0, range_1.isRangeAtRowStart)(range, rowEl)) {
return true;
}
// 如果光标在当前行开头,并且有上一个兄弟节点
if ((0, range_1.isRangeAtRowStart)(range, rowEl) && upRow) {
// 如果上一个标签是空节点,直接删除上一个标签
if ((0, _1.isEmptyElement)(upRow)) {
upRow.remove();
return true;
}
// 将光标移动到上一个P标签的末尾
(0, range_1.moveRangeAtRowEnd)(range, upRow);
rowEl.remove();
// 将当前行的内容添加到上一行中
(0, _1.transferElement)(rowEl, upRow);
return true;
}
var delEl = textEl; // 要删除的内容
// 如果当前是空节点或者光标在当前文本的开头
if ((0, _1.isEmptyElement)(textEl) || (0, range_1.isRangeAtTextStart)(range)) {
var index = Array.from(rowEl.childNodes).indexOf(textEl);
// 如果为空,删除当前节点
if ((0, _1.isEmptyElement)(textEl))
textEl.remove();
// 往前删除所有空节点
for (var i = index - 1; i >= 0; i--) {
var node = rowEl.childNodes[i];
if (!(0, _1.isEmptyElement)(node)) {
delEl = node;
break;
}
node.remove();
}
}
// 如果是文本节点,则删除最后一个文字
if (delEl.className === const_1.TEXT_TAG_CLASS) {
delEl.textContent = ((_h = delEl.textContent) === null || _h === void 0 ? void 0 : _h.slice(0, -1)) || "";
// 如果还有内容,将光标移动到文本末尾
if (!(0, _1.isEmptyElement)(delEl)) {
var textNode = delEl.lastChild;
var textLength = ((_j = delEl.textContent) === null || _j === void 0 ? void 0 : _j.length) || 0;
range.setStart(textNode ? textNode : delEl, textNode ? textLength : delEl.childNodes.length);
range.collapse(true);
return true;
}
}
// 获取上一个节点
var upNode = delEl.previousElementSibling;
delEl.remove();
// 修正光标位置
if ((0, _1.isEmptyElement)(rowEl)) {
rowEl.innerHTML = (0, _1.createTextTag)(const_1.NEW_LINE).outerHTML;
(0, range_1.moveRangeAtRowEnd)(range, rowEl);
}
else if (upNode) {
var childLength = upNode.childNodes.length;
var nextChild = upNode.childNodes[childLength - 1];
var index = (0, _1.isEmptyElement)(upNode) ? 0 : ((_k = nextChild.textContent) === null || _k === void 0 ? void 0 : _k.length) || 0;
range.setStart(nextChild, index);
range.collapse(true);
}
return true;
}
function wordDelete(e, editorEl) {
var range = (0, range_1.getRangeAt)();
if (!range)
return false;
if ((0, _1.fixEditorContent)(editorEl)) {
// 将光标移动到编辑器末尾
(0, range_1.moveRangeAtEditorEnd)(range, editorEl);
return true;
}
// 如果有选中内容
if (!range.collapsed) {
// 获取光标开始和结束的P标签
var sEls = (0, range_1.rangeEls)(range, "start");
var eEls = (0, range_1.rangeEls)(range, "end");
if (!(sEls === null || sEls === void 0 ? void 0 : sEls.rowEl) || !(eEls === null || eEls === void 0 ? void 0 : eEls.rowEl))
return false;
(0, range_1.removeRangeContent)(range, { startEls: sEls, endEls: eEls, mergeRow: true });
return true;
}
// 获取当前光标所在的P标签
var els = (0, range_1.rangeEls)(range);
if (!els)
return true;
var bool = false;
(0, range_1.fixTextContent)(range, els);
if (e.code === "Backspace") {
bool = onBackspace(range, els);
}
if (e.code === "Delete") {
bool = onDelete(range, els);
}
if (bool) {
// 修正当前行标签
(0, _1.fixRowContent)(els.rowEl);
}
return bool;
}