/** * 样式 */ (function (utils) { function inputHandle(e) { if (!utils.inCompositionEvent) { updateText(e) } } function compositionstartHandle(e) { // console.log("compositionstart") utils.inCompositionEvent = true } function compositionendHandle(e) { // console.log("compositionend") updateText(e) utils.inCompositionEvent = false } /** * 鼠标按下事件 */ function windowsCtrZHandle(e) { const event = e || window.event //标准化事件处理 const keyCode = event.keyCode || event.which || event.charCode const metaKey = event.metaKey // console.log("windows键盘事件 ", event, keyCombination, metaKey, keyCode) //撤销 if (metaKey && keyCode === 90) { console.log('触发ctrl + Z 事件', e.target) if (utils.latestOpDoc !== undefined && utils.latestOpDoc !== null) { // // // let cNo = parseInt(utils.latestOpDoc.getAttribute("data-order")) // console.log("恢复", utils.latestOpDoc, cNo) // if (cNo > 1) { // let qq = "#noteshare p[data-order='" + (cNo - 1) + "']" // // console.log("qq: ", qq) // utils.insertAfter(utils.latestOpDoc, document.querySelector(qq)) // } else { // //添加元素到首位 // yanxuelu.insertBefore(utils.latestOpDoc, utils.MyRoot.children[0]) // } // utils.MyDocMap.get(cNo).setHidden(false) //恢复 utils.latestOpDoc.recovery(); // utils.MyDocMap.get(cNo).setSource(latestOpDoc.innerText) // showTestText() event.preventDefault() event.returnValue = false } utils.latestOpDoc = null } } /** * 鼠标按下事件 & 键盘组合事件 * @param {*} e */ function onkeydownHandle(e) { const event = e || window.event //标准化事件处理 // window.event 等价于 event参数 // 有些浏览器除了通过keyCode获取输入键code,还可以通过which,charCode获取,这么写是出于浏览器兼容性考虑 const keyCode = event.keyCode || event.which || event.charCode const keyCombination = event.ctrlKey const metaKey = event.metaKey // console.log("键盘事件 ", event, keyCombination, metaKey, keyCode) // ctrl + c 复制 if (keyCombination && keyCode === 67) { // 阻止默认事件 event.preventDefault() event.returnValue = false console.log('触发ctrl + c 事件', e.target) } //撤销 if (metaKey && keyCode === 90) { // console.log('触发ctrl + Z 事件', e.target) if (utils.latestOpDoc !== undefined && utils.latestOpDoc !== null) { // console.log(utils.latestOpDoc) //恢复 utils.latestOpDoc.recovery(); // // console.log(MyDocMap.get(cNo)) let cNo = parseInt(utils.latestOpDoc.getData().getAttribute("data-order")) utils.MyDocMap.get(cNo).setHidden(false) // utils.MyDocMap.get(cNo).setSource(latestOpDoc.innerText) // showTestText() //阻止事件 event.preventDefault() event.returnValue = false } utils.latestOpDoc = null } //删除 if (keyCode === 46 || keyCode === 8) { let curP = event.target let cNo = parseInt(curP.getAttribute("data-order")) //维护最近一次编辑的内容 if (utils.latestOpDoc === undefined || utils.latestOpDoc === null || utils.latestOpDoc.getData().getAttribute("data-id") !== curP.getAttribute("data-id")) { utils.latestOpDoc = new utils.MyRecovery(curP.cloneNode(true), function () { let cNo = parseInt(this.data.getAttribute("data-order")) console.log("恢复", this.data, cNo) if (cNo > 1) { utils.insertAfter(this.data, document.querySelector("#noteshare p[data-order='" + (cNo - 1) + "']")) } else { //添加元素到首位 utils.MyRoot.insertBefore(this.data, utils.MyRoot.children[0]) } // 恢复该元素展示 utils.MyDocMap.get(cNo).setHidden(false) }) } //如果是第一行 let previousSibling = curP.previousSibling // console.log(curP, previousSibling == undefined ,previousSibling.id == undefined) if (previousSibling === undefined || previousSibling.id === undefined) { //显示用户的输入内容 showTestText() return } // console.log('触发删除', curP.innerHTML, cNo, utils.num, utils.MyDocMap.get(cNo + 1)) let curS = window.getSelection() // console.log("当前内容: ", curP.innerHTML, " 当前选区 :", curS) //处理前面没有内容,后面还有内容需要拼接到上层的场景 if ((curS.isCollapsed && curS.anchorOffset === 0) || curP.innerHTML === '
') { let curNodeRetainHtml = curP.innerHTML //异步修正顺序(第一行删除不掉) // if (curP.innerHTML === '
' ) { // console.log("删除当前行。选取信息: ", curS) //阻止事件传递 event.preventDefault() event.returnValue = false //设置该元素隐藏 utils.MyDocMap.get(cNo).setHidden(true) //删除当前元素 curP.remove() //拼接 if (curNodeRetainHtml !== '
') { previousSibling.innerHTML = previousSibling.innerHTML + curNodeRetainHtml } //收起选区到一个点,光标落在一个可编辑元素上 window.getSelection().setPosition(previousSibling, 1); } //显示用户的输入内容 showTestText(); } //回车事件 if (keyCode === 13 /* && currentNode === key.lastElementChild */) { event.preventDefault() let uuid = utils.uuid() let curOrder = ++(utils.num) var newParagraph = document.createElement("p") newParagraph.setAttribute("contenteditable", "true") newParagraph.setAttribute("data-id", uuid) newParagraph.setAttribute("id", uuid) newParagraph.setAttribute("data-order", curOrder) newParagraph.onkeydown = onkeydownHandle newParagraph.focus() newParagraph.innerHTML = "
" utils.MyRoot.appendChild(newParagraph) utils.MyDocMap.set(curOrder, new utils.MyNode(uuid)) //收起选区到一个点,光标落在一个可编辑元素上 window.getSelection().setPosition(newParagraph, 0) } } /** * */ function showTestText() { //显示用户的输入内容 const obj = {}; for ([k, v] of utils.MyDocMap.entries()) { if (v.getHidden() && v.getHidden() === true) { continue } obj[k] = v } // console.log("当前文档结构数: ",obj); // var userInput = document.getElementById("testInput") // userInput.value = JSON.stringify(obj) } /** * 更新文档 * @param {*} e */ function updateText(e) { let curP = e.target //是否需要变更元素类型 utils.firstCmd(curP, onkeydownHandle) let cNo = parseInt(curP.getAttribute("data-order")) let cp = utils.MyDocMap.get(cNo) //内容不变则不处理 let h5CurLen = curP.innerText.length let myDocNodeLen = (cp && cp.getSource()) ? cp.getSource().length : 0 if (h5CurLen === myDocNodeLen) { return } cp.setSource(curP.innerText) // console.log("curPTx: ", curP.innerText, "MyDocMap : ", utils.MyDocMap) //显示用户的输入内容 showTestText() } function surroundContentsByStyle() { let curS = utils.getSelection() let curSec = curS.getRangeAt(0) let styleName = this.getAttribute("data-value"); let className = utils.parseStyleName2ClassName(styleName) //todo 只对 nodeType = p 执行 // console.log("当前光标信息: ", curS, " 当前选区信息 : ", curSec) for (let i = 0; i < curS.rangeCount; i++) { let curSec = curS.getRangeAt(i) let curEleSize = curSec.commonAncestorContainer.childNodes.length let curStartP = curSec.startContainer.parentElement //todo 先支持 一行。 let start = curSec.startOffset; let end = curSec.endOffset; // console.log(curStartP.cloneNode(true), styleName, start, end, " curEleSize: ", curEleSize) let curPEle = null; //第一次选择的时候将整行转换成

if (curEleSize === 0) { //没选择,则退出 if (start === end) { return } // console.log("debug1: ", curSec.commonAncestorContainer) //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑) utils.latestOpDoc = new utils.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 utils.syncOnePInfo(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; } else { // console.log("debug2: ", curSec.commonAncestorContainer) //维护最近一次编辑的内容(暂时只支持恢复最近一次编辑) utils.latestOpDoc = new utils.MyRecovery(curSec.commonAncestorContainer.cloneNode(true), function () { console.log("恢复上一步样式1", this.data) let curEl = document.getElementById(this.data.getAttribute("id")); curEl.innerHTML = this.data.innerHTML; //文本映射 直接覆盖 map 中的 childrenStyle utils.syncOnePInfo(this.data); }) let myChildren = curSec.commonAncestorContainer.children for (let j = 0; j < curEleSize; j++) { let curEle = myChildren[j] if (curS.containsNode(curEle, true)) { curEle.classList.remove(className); curEle.classList.add(className); } } curPEle = curSec.commonAncestorContainer; } //文本映射 直接覆盖 map 中的 childrenStyle utils.syncOnePInfo(curPEle) } } window.styleCmd = { inputHandle, compositionstartHandle, compositionendHandle, onkeydownHandle, windowsCtrZHandle, surroundContentsByStyle, showTestText, updateText, } })(utils)