"use strict"; import {MyRecovery} from "../model/MyRecovery.js"; import {MyDocItem} from "../model/MyDocItem.js"; import {MyMapItem} from "../model/MyMapItem.js"; export class MyBiz { constructor() { } /** * 根据类型名称解析 样式的 class 名称 * @param styleName * @returns {string} */ parseStyleName2ClassName(styleName) { switch (styleName) { case "b": return "childStyleStrong"; case "i": return "childStyleI"; case "u": return "childStyleU"; case "c_red": return "childStyleColor"; case "del": return "childStyleDel" } } /** * 输入事件 * @param e */ inputHandle(e) { let curP = window.myEdit.utils.GetEventTarget(e); this.updateText(curP) } /** * 中文输入开始事件 * @param e */ compositionstartHandle(e) { // console.log("compositionstart") window.myEdit.ctx.inCompositionEvent = true } /** * 中文输入结束事件 * @param e */ compositionendHandle(e) { // console.log("compositionend") let curP = window.myEdit.utils.GetEventTarget(e); this.updateText(curP) //中文输入结束 window.myEdit.ctx.inCompositionEvent = false } /** * 撤销事件 * @param event */ cancelHandle(event) { console.log('触发ctrl + Z 事件', event.target) if (window.myEdit.ctx.latestOpDoc !== undefined && window.myEdit.ctx.latestOpDoc !== null) { //恢复 window.myEdit.ctx.latestOpDoc.recovery(); //测试展示 window.myEdit.ctx.showTestText() //阻止事件 window.myEdit.utils.ProhibitDefaultEvent(event); } window.myEdit.ctx.latestOpDoc = null } /** * 删除事件 * @param event */ deleteHandle(event) { let curP = window.myEdit.utils.GetEventTarget(event); let cNo = parseInt(curP.getAttribute("data-order")) //维护最近一次编辑的内容 if (window.myEdit.ctx.latestOpDoc === undefined || window.myEdit.ctx.latestOpDoc === null || window.myEdit.ctx.latestOpDoc.getData().getAttribute("data-id") !== curP.getAttribute("data-id")) { window.myEdit.ctx.latestOpDoc = new MyRecovery(curP.cloneNode(true), function () { let cNo = parseInt(this.data.getAttribute("data-order")) console.log("恢复", this.data, cNo, " this: ", this) if (cNo > 1) { window.myEdit.utils.InsertAfter(this.data, document.querySelector("#noteshare p[data-order='" + (cNo - 1) + "']")) } else { //添加元素到首位 todo_xxx // window.myEdit.ctx.MyRoot.insertBefore(this.data, window.myEdit.ctx.MyRoot.children[0]) window.myEdit.ctx.MyRoot.insertBefore(this.data, window.myEdit.ctx.MyRoot.children[0]); } // 恢复该元素展示 window.myEdit.ctx.MyDocMap.get(cNo).setHidden(false); }) } //如果是第一行 let previousSibling = curP.previousSibling console.log(curP, previousSibling === undefined, previousSibling.id === undefined) if (previousSibling === undefined || previousSibling.id === undefined) { //显示用户的输入内容 window.myEdit.ctx.showTestText() return } console.log('触发删除', curP.innerHTML, cNo) let curS = window.myEdit.utils.GetSelection(); // console.log("当前内容: ", curP.innerHTML, " 当前选区 :", curS) //处理前面没有内容,后面还有内容需要拼接到上层的场景 if ((curS.isCollapsed && curS.anchorOffset === 0) || curP.innerHTML === '
') { let curNodeRetainHtml = curP.innerHTML //阻止事件传递 window.myEdit.utils.ProhibitDefaultEvent(event); //设置该元素隐藏 window.myEdit.ctx.MyDocMap.get(cNo).setHidden(true) //删除当前元素 // curP.remove() curP.innerHTML = "
" let emptyRowNoList = window.myEdit.ctx.MyDocMap.get("emptyRowNoList"); if (emptyRowNoList === undefined || emptyRowNoList === null) { emptyRowNoList = []; window.myEdit.ctx.MyDocMap.set("emptyRowNoList", emptyRowNoList); } emptyRowNoList.push(cNo); //拼接 if (curNodeRetainHtml !== '
') { previousSibling.innerHTML = previousSibling.innerHTML + curNodeRetainHtml } //收起选区到一个点,光标落在一个可编辑元素上 window.getSelection().setPosition(previousSibling, 1); } //显示用户的输入内容 window.myEdit.ctx.showTestText(); } /** * 回车事件 * @param event * @param onkeydownHandle */ enterHandler(event) { //阻止事件 window.myEdit.utils.ProhibitDefaultEvent(event); //uuid let uuid = window.myEdit.utils.Uuid(); //rowNo let rowNo = 0; let emptyRowNoList = window.myEdit.ctx.MyDocMap.get("emptyRowNoList"); console.log(emptyRowNoList); let empListIsEmpty = (emptyRowNoList === undefined || emptyRowNoList === null || emptyRowNoList.length <= 0); if (!empListIsEmpty) { let tmpArr = []; for (let i = 0; i < emptyRowNoList.length; i++) { let tmpNo = emptyRowNoList[i]; if (window.myEdit.ctx.getMapItem(tmpNo).getHidden()) { tmpArr.push(emptyRowNoList[i]); } } window.myEdit.ctx.MyDocMap.set("emptyRowNoList", tmpArr); empListIsEmpty = tmpArr.length <= 0; emptyRowNoList = tmpArr } if (empListIsEmpty) { rowNo = window.myEdit.ctx.incrementNumThenReturn(); //添加新元素 let newParagraph = document.createElement("p") newParagraph.setAttribute("contenteditable", "true") newParagraph.setAttribute("data-id", uuid) newParagraph.setAttribute("id", uuid) newParagraph.setAttribute("data-order", rowNo) newParagraph.onkeydown = window.myEdit.eventListener.KeydownListener // newParagraph.innerHTML = "
" window.myEdit.ctx.MyRoot.appendChild(newParagraph) window.myEdit.ctx.MyDocMap.set(rowNo, new MyMapItem(uuid)) //收起选区到一个点,光标落在一个可编辑元素上 window.getSelection().setPosition(newParagraph, 0); return } let sortArr = emptyRowNoList.sort((a, b) => a - b) console.log(sortArr); // 最小值 rowNo = sortArr[0]; let newParagraph = document.querySelector("#noteshare p[data-order='" + rowNo + "']"); newParagraph.innerHTML = "
"; window.myEdit.ctx.MyDocMap.get(rowNo).setHidden(false); //收起选区到一个点,光标落在一个可编辑元素上 window.getSelection().setPosition(newParagraph, 0) } /** * 更新文档 * @param {*} e */ updateText(curP) { if (window.myEdit.ctx.inCompositionEvent) { return; } let myP = new MyDocItem(curP); let cNo = myP.parseOrder(); let mapItem = window.myEdit.ctx.getMapItem(cNo) //内容不变则不处理 let h5CurLen = curP.innerText.length let myDocNodeLen = (mapItem && mapItem.getSource()) ? mapItem.getSource().length : 0 if (h5CurLen === myDocNodeLen) { return } mapItem.setSource(curP.innerText); mapItem.setHidden(false); // console.log("curPTx: ", curP.innerText, "MyDocMap : ", utils.MyDocMap) //显示用户的输入内容 window.myEdit.ctx.showTestText() } /** * 空格键处理 * @param {*} event */ emptyKeyWorkHandler(event) { let curP = window.myEdit.utils.GetEventTarget(event); let myDocItem = new MyDocItem(curP); let inputLength = curP.innerText.length console.log("emptyKeyWorkHandler :", curP, " _'", curP.innerHTML, "'_'", curP.innerText, "'_", "\neq00", curP.innerHTML.startsWith(" # "), "\neq01", curP.innerHTML.startsWith(" # "), "\neq1", curP.innerText.startsWith("# "), "\neq2", curP.innerText.startsWith("#"), "\neq3", curP.innerHTML.startsWith("# "), "\neq4", curP.innerHTML.startsWith("# ")) /** * h1 ~ h6 */ if (curP.innerText.startsWith("#")) { let curNo = myDocItem.parseOrder(); let mapNode = window.myEdit.ctx.MyDocMap.get(curNo); if (curP.innerHTML.startsWith("######")) { mapNode.getStyle().setNodeType("h6") curP.innerHTML = curP.innerHTML.replace("######", "") this.becomeAnotherElement(curP, "h6") } else if (curP.innerHTML.startsWith("#####")) { mapNode.getStyle().setNodeType("h5") curP.innerHTML = curP.innerHTML.replace("#####", "") this.becomeAnotherElement(curP, "h5") } else if (curP.innerHTML.startsWith("####")) { mapNode.getStyle().setNodeType("h4") curP.innerHTML = curP.innerHTML.replace("####", "") this.becomeAnotherElement(curP, "h4") } else if (curP.innerHTML.startsWith("###")) { mapNode.getStyle().setNodeType("h3") curP.innerHTML = curP.innerHTML.replace("###", "") this.becomeAnotherElement(curP, "h3") } else if (curP.innerHTML.startsWith("##")) { mapNode.getStyle().setNodeType("h2") curP.innerHTML = curP.innerHTML.replace("##", "") this.becomeAnotherElement(curP, "h2") } else { mapNode.getStyle().setNodeType("h1") curP.innerHTML = curP.innerHTML.replace("#", "") this.becomeAnotherElement(curP, "h1") } } /** * 无序列表效果 */ if (curP.innerText.startsWith("-")) { let curNo = myDocItem.parseOrder(); let mapNode = window.myEdit.ctx.MyDocMap.get(curNo); mapNode.getStyle().setPreStyle("ul", true) //clean let historyContent = curP.innerHTML.replace("-", ""); mapNode.setSource(curP.innerText) //根据上一层级元素动态选择 todo curP.setAttribute("style", "padding-left: 1rem;") //新增元素 let newParagraph = document.createElement("span"); newParagraph.setAttribute("contenteditable", "false") //∙ vs ∘ newParagraph.innerHTML = "∙  " curP.innerHTML = "" curP.append(newParagraph); curP.innerHTML = curP.innerHTML + historyContent //收起选区到一个点,光标落在一个可编辑元素上 window.myEdit.utils.GetSelection().collapse(curP, true) } /** * 有序列表效果 */ let preContent = curP.innerText.split("\.")[0] if (window.myEdit.utils.IsNum(preContent)) { let curNo = myDocItem.parseOrder(); let mapNode = window.myEdit.ctx.MyDocMap.get(curNo); mapNode.getStyle().setPreStyle("ol", preContent) //clean let historyContent = curP.innerHTML.replace(preContent + ".", ""); mapNode.setSource(curP.innerText) //todo curP.setAttribute("style", "padding-left: 1rem;") //新增元素 let newParagraph = document.createElement("span"); newParagraph.setAttribute("contenteditable", "false"); newParagraph.innerHTML = preContent + ". " curP.innerHTML = "" curP.append(newParagraph); curP.innerHTML = curP.innerHTML + historyContent //收起选区到一个点,光标落在一个可编辑元素上 window.myEdit.utils.GetSelection().collapse(curP, true) } } /** * 变成另一个元素 * @param {*} elementName */ becomeAnotherElement(curP, elementName) { let newParagraph = document.createElement(elementName) newParagraph.setAttribute("contenteditable", "true") newParagraph.setAttribute("data-id", curP.getAttribute("data-id")) newParagraph.setAttribute("id", curP.getAttribute("data-id")) newParagraph.setAttribute("data-order", curP.getAttribute("data-order")) newParagraph.onkeydown = window.myEdit.eventListener.KeydownListener //todo 支持 有数据的行 在行首输入 # // if() // switch (elementName){ // case "h1": // } newParagraph.innerHTML = curP.innerHTML window.myEdit.utils.InsertAfter(curP, newParagraph) curP.remove(); curP = newParagraph; //matData let myP = new MyDocItem(curP); let curNo = myP.parseOrder(); let mapNode = window.myEdit.ctx.getMapItem(curNo) mapNode.setSource(curP.innerText) //收起选区到一个点,光标落在一个可编辑元素上 window.myEdit.utils.GetSelection().setPosition(newParagraph, 0) } /** * 包围样式事件处理 * @param event */ surroundContentsByStyleHandler(event) { let curS = window.myEdit.utils.GetSelection(); let curP = window.myEdit.utils.GetEventTarget(event); let styleName = curP.getAttribute("data-value"); if (styleName === undefined || styleName === null) { styleName = curP.closest("span").getAttribute("data-value"); console.log("closest: ", curP, curP.closest("span")) } let className = this.parseStyleName2ClassName(styleName) //todo 只对 nodeType = p 执行 console.log("当前光标信息: ", curS, styleName, " className: ", className, curP) for (let i = 0; i < curS.rangeCount; i++) { let curSec = curS.getRangeAt(i); let curPe = curSec.commonAncestorContainer; //一个元素节点,例如

。 let curPeIsP = curPe.nodeType === 1 && curPe.nodeName === "P"; let curPeParentIsP = curPe.parentNode.nodeType === 1 && curPe.parentNode.nodeName === "P"; let curPeParentIsDIV = curPe.parentNode.nodeType === 1 && curPe.parentNode.nodeName === "DIV"; let curPeParentIsSpan = curPe.parentNode.nodeType === 1 && (curPe.parentNode.nodeName === 'SPAN"' || curPe.parentNode.nodeName === 'SPAN'); let start = curSec.startOffset; let end = curSec.endOffset; console.log(" 当前选区信息 : ", curSec, "\ncurPe: ", curPe, "\ncurPeP: ", curPe.parentNode, curPe.parentNode.nodeType, curPe.parentNode.nodeName, "\ncurPeIsP: ", curPeIsP, "\ncurPeParentIsP : ", curPeParentIsP, "\ncurPeParentIsDIV", curPeParentIsDIV, "\ncurPeParentIsSpan", curPeParentIsSpan, "\nclassName: ", className, "\ntart: ", start, "\nend: ", end) let curPEle = null; //第一次选择的时候将整行转换成

if (!curPeIsP && curPeParentIsP) { //没选择,则退出 if (start === end) { return } else { // div } let curStartP = curSec.startContainer.parentElement; console.log("debug1: ", curStartP, curStartP.nodeType, curStartP.nodeName) //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑) window.myEdit.ctx.latestOpDoc = new MyRecovery(curStartP.cloneNode(true), function () { console.log("恢复上一步样式1", this.innerHTML) let curEl = document.getElementById(this.data.getAttribute("id")); curEl.innerHTML = this.data.innerHTML; //文本映射 直接覆盖 map 中的 childrenStyle window.myEdit.utils.SyncMapItemChildrenStyle(this.data); }) let curHtml = "" for (let j = 0; j < curStartP.innerText.length; j++) { // console.log(curStartP.innerText.charAt(j)) if (j >= start && j < end) { curHtml += '' + curStartP.innerText.charAt(j) + ''; } else { curHtml += '' + curStartP.innerText.charAt(j) + ''; } } curStartP.innerHTML = curHtml; curPEle = curStartP; //光标保持 // curS.collapseToEnd(); // window.myEdit.utils.GetSelection().setPosition(newParagraph, 0); } else { let tmpPNode = curSec.commonAncestorContainer; if (!curPeIsP && curPeParentIsSpan) { tmpPNode = curSec.commonAncestorContainer.parentNode.parentNode; } console.log("debug2: ", curSec.commonAncestorContainer, tmpPNode, tmpPNode.children, tmpPNode.childNodes) //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑) window.myEdit.ctx.latestOpDoc = new MyRecovery(tmpPNode.cloneNode(true), function () { console.log("恢复上一步样式1", this.data) let curEl = document.getElementById(this.data.getAttribute("id")); curEl.innerHTML = this.data.innerHTML; //文本映射 直接覆盖 map 中的 childrenStyle window.myEdit.utils.SyncMapItemChildrenStyle(this.data); }) let myChildren = tmpPNode.childNodes // let curEleSize = tmpPNode.childNodes.length for (let j = 0; j < myChildren.length; j++) { let curEle = myChildren[j] if (curS.containsNode(curEle, true)) { curEle.classList.remove(className); curEle.classList.add(className); } } curPEle = curSec.commonAncestorContainer; } //文本映射 直接覆盖 map 中的 childrenStyle window.myEdit.utils.SyncMapItemChildrenStyle(curPEle); } } }