"use strict"; /** * 使用样式事件 */ define(function (require, exports, module) { function handle(mutationList) { for (let mutation of mutationList) { switch (mutation.type) { case "childList": addNewP(mutation); break; case "characterData": updateText(mutation); break; case "attributes": //暂时忽略属性变化 break default: { other(mutation); } } } } function other(mutation) { console.dir(mutation) // console.log("other -> mutation : ", mutation, // // 观察的变动类型(attributes、characterData或者childList)。 // "\ntype", mutation.type, // //发生变动的DOM节点。 // "\ntarget", mutation.target, mutation.target.nodeName, mutation.previousSibling, // "\ntargetParent", mutation.target.parentElement, mutation.target.parentNode, // //新增的DOM节点。 // "\naddedNodes", mutation.addedNodes, // //删除的DOM节点。 // "\nremovedNodes", mutation.removedNodes, // //前一个同级节点,如果没有则返回null。 // "\npreviousSibling", mutation.previousSibling, // //下一个同级节点,如果没有则返回null。 // "\nnextSibling", mutation.nextSibling, // //发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。 // "\nattributeName", mutation.attributeName, // //变动前的值。这个属性只对attribute和characterData变动有效,如果发生childList变动,则返回null。 // "\noldValue", mutation.oldValue); } function addNewP(mutation) { //div 下新增p元素 let target = mutation.target; // target.clone() if (target.nodeName === "DIV" && mutation.previousSibling !== null) { let utils = require("../../common/utils"); let ctx = require("../../common/ctx"); let newParagraph = mutation.previousSibling.nextSibling; console.log( "addNewP target: ", target, "\nnodeType: ", target.nodeType, "\nnodeName: ", target.nodeName, "\ndata: ", target.value, "\n next: ", newParagraph, "\ncurRowNo: ", ctx.getCurRowNo() ) if (newParagraph !== undefined && newParagraph !== null) { newParagraph.id = utils.Uuid(ctx.usn, ctx.docType); newParagraph.setAttribute("data-order", ctx.incrementNumThenReturn()); // let newParagraph = document.getElementById(targetP.id); //前置 span let preSpan = newParagraph.querySelector("span[data-flag='span_pre']"); if (preSpan === undefined || preSpan === null) { preSpan = document.createElement("span"); preSpan.setAttribute("contenteditable", "false") preSpan.setAttribute("data-flag", "span_pre") //额外处理无序和有序列表 let preP = newParagraph.previousElementSibling; if (preP !== undefined && preP !== null) { let preSpanTxtOfPreP = preP.querySelector("span[data-flag='span_pre']").textContent; if (preSpanTxtOfPreP === " • " || preSpanTxtOfPreP === " ◦ " || preSpanTxtOfPreP === " ▪ ") { preSpan.setAttribute("contenteditable", "true"); preSpan.innerHTML = "" + preSpanTxtOfPreP + ""; } } //添加到元素首位 newParagraph.insertBefore(preSpan, newParagraph.firstChild); } else { console.log("newParagraph preSpan exist ", newParagraph, " ", preSpan) } //内置span let spanContent = newParagraph.querySelector("span[data-flag='span_content']"); if (spanContent === undefined || spanContent === null) { spanContent = document.createElement("span"); spanContent.append(document.createElement("br")); spanContent.setAttribute("data-flag", "span_content") spanContent.setAttribute("placeholder", "请输入") newParagraph.appendChild(spanContent); } else { console.log("newParagraph spanContent exist", spanContent); spanContent.innerHTML = "
"; } utils.GetSelection().removeAllRanges(); utils.GetSelection().setPosition(spanContent, 0); spanContent.focus(); } return } //解决(flex 布局 for 无序列表 前面可以输入问题)回车不换行问题 if (target.nodeName === "P" && target.getAttribute("data-order") != null && mutation.previousSibling !== null && mutation.previousSibling.getAttribute("data-flag") === "span_content") { // let utils = require("../../common/utils"); let flagP = target; for (let i = 0; i < mutation.addedNodes.length; i++) { let tmpSpan = mutation.addedNodes[i]; let tmpP = document.createElement("p"); tmpP.appendChild(tmpSpan) utils.InsertAfter(flagP, tmpP); flagP = tmpP; } // console.log( // "addNewSpan target: ", target, // "\nmutation:", mutation, // "\naddedNodes:", mutation.addedNodes, // "\nnodeType: ", target.nodeType, // "\nnodeName: ", target.nodeName, // "\ndata: ", target.value, // "\n previousContentSpan: ", previousContentSpan, // "\ncurRowNo: ", ctx.getCurRowNo() // ) return; } //删除 for 无序列表 删除样式恢复正常行 if (mutation.removedNodes.length === 0 && mutation.addedNodes.length === 1 && target.nodeName === "P" && target.getAttribute("data-order") != null // && target.childNodes && mutation.addedNodes[0].nodeName === "BR" ) { console.log( "删除 br target: ", target, "\nmutation:", mutation, "\ntarget.childNodes:", target.childNodes, "\naddedNodes:", mutation.addedNodes, "\nremovedNodes:", mutation.removedNodes, "\nnodeType: ", mutation.addedNodes[0].nodeType, "\nnodeName: ", mutation.addedNodes[0].nodeName, "\ndata: ", mutation.addedNodes[0].value ) console.log("捕捉 ‘删除样式恢复正常行’ 成功") let spanContent = document.createElement("span"); spanContent.setAttribute("data-flag", "span_content") spanContent.innerHTML = "
"; target.innerHTML = null; target.append(spanContent); return; } other(mutation); } function updateText(mutation) { let target = mutation.target; if (target.nodeType === 3 && target.nodeName === "#text") { let utils = require("../../common/utils"); let ctx = require("../../common/ctx"); //测试内容填写 let testDiv = document.getElementById("testDevice"); testDiv.innerText = mutation.oldValue let grandfatherElement = target.parentNode?.parentElement; //处理添加了样式的 行 if (grandfatherElement != null && grandfatherElement.getAttribute("data-flag") === "span_content") { //正在输入中文直接忽略 if (ctx.Compositionstart) { return; } let select = utils.GetSelection(); let selectRange = select.getRangeAt(0); if (select.isCollapsed) { //输入场景 let tmpSpan = selectRange.startContainer.parentElement; console.log(utils.GetText(tmpSpan)) let curTxt = utils.GetText(tmpSpan); if (curTxt.trim().length <= 1) { return } // console.dir(select) // console.dir(mutation) // console.dir(grandfatherElement) // console.dir(tmpSpan) // console.log(tmpSpan) // console.log(curTxt.split('')) let curTxtArr = curTxt.split(''); //保留一个 tmpSpan.innerText = curTxtArr[0]; let lastSpan = tmpSpan; for (let i = 1; i < curTxtArr.length; i++) { let tmpSpan = document.createElement("span"); tmpSpan.innerText = curTxtArr[i]; utils.InsertAfter(lastSpan, tmpSpan); lastSpan = tmpSpan; } //选区调整 console.log("lastSpan : ", lastSpan) utils.GetSelection().setPosition(lastSpan, 1); } else { console.log("TODO 暂时不支持") } } else { // 处理没有添加样式的行 console.log("TODO 暂时不支持") } //处理无序列表和有序列表 探究 if (target.parentNode === undefined || target.parentNode?.parentElement === undefined) { return; } // console.log( // "updateText mutation: ", mutation, // "\ntarget: ", target, // "\nnodeType: ", target.nodeType, // "\nnodeName: ", target.nodeName, // "\ndata: ", target.value, // "\noldValue: ", target.oldValue, target.oldValue?.startsWith("- "), // "\nparentNode: ", target.parentNode, target.parentElement, // "\nparentNode_parentNode: ", target.parentNode?.parentElement, // ) let curP = target.parentElement?.closest("p"); let curSpanContent = curP.querySelector("span[data-flag='span_content']") // console.log("curSpanContent: ", curSpanContent) //无序列表 if (curSpanContent.innerHTML.startsWith("- ") || curSpanContent.innerHTML.startsWith("- ")) { let curPreSpan = curP.querySelector("span[data-flag='span_pre']"); let curPreSpanTxt = utils.GetText(curPreSpan); if (curPreSpanTxt === " • " || curPreSpanTxt === " ◦ " || curPreSpanTxt === " ▪ ") { return; } else { let previousSiblingP = curP.previousElementSibling; let preSpanTxtOfPreP = null if (previousSiblingP != null) { let tmpPre = previousSiblingP.querySelector("span[data-flag='span_pre']"); preSpanTxtOfPreP = utils.GetText(tmpPre); } //上一级是否也是无序列表。 如果是则 后移 if (preSpanTxtOfPreP != null && (preSpanTxtOfPreP === " • " || preSpanTxtOfPreP === " ◦ " || preSpanTxtOfPreP === " ▪ ")) { if (preSpanTxtOfPreP === " • ") { curPreSpan.setAttribute("contenteditable", "true"); curPreSpan.innerHTML = "" + " ◦ " + "" } else if (preSpanTxtOfPreP === " ◦ ") { curPreSpan.setAttribute("contenteditable", "true"); curPreSpan.innerHTML = "" + " ▪ " + "" } else { console.log("不支持继续下转") } } else { curPreSpan.innerHTML = "" + " • " + "" } curSpanContent.textContent = curSpanContent.textContent.substring(2, curSpanContent.textContent.length); //光标定位 utils.GetSelection().removeAllRanges(); utils.GetSelection().setPosition(curSpanContent, 0); curSpanContent.focus(); } } } else { other(mutation); } } //导出 exports.handle = handle; });