javascript|javascript 实现富文本框选中对齐

需求: 一个可编辑(contenteditable=true)的div,对齐选中内容,左、中,右 ,其实质是:对选中的末梢节点,找到块属性的父元素,设置text-algin:center:

MDN:text-align CSS属性定义行内内容(例如文字)如何相对它的块父元素对齐。text-align 并不控制块元素自己的对齐,只控制它的行内内容的对齐。
分析需求: 我们来分解一下这个需求的三个关键问题: ”选中部分“,”块元素“,"末梢元素"
1如何获取选中的部分 *
这里涉及到的Web API Document.getSelection().getRangeAt(0) 这里只处理一个选取的情况
注意:光标所在位置,光标所在节点 视为选中区域
2什么是块元素
MDN:
display:block
这个值会生成一个块级元素盒子,同时在该元素之前和之后打断(换行)。简单来说就是,这个值会将该元素变成块级元素。
除非特殊指定,诸如标题(等)和段落()默认情况下都是块级的盒子。
用做链接的 元素、 以及 都是默认处于 inline 状态的。
3末梢元素(没有子节点的元素)
? 我们操作对齐,实质是操作盒模型中的内容的对齐方式,也就是对:图片,文字 等设置对齐样式,在这里我称其为末梢节点
实现思路: 1、获取选区内的所有末梢元素(递归)
2、找到这些末梢元素的父块元素,设置其text-align:'left|center|right'
代码实现: 前端页面:一个div contenteditable="true"; 三个按钮:触发对齐(左,中,右)
javascript|javascript 实现富文本框选中对齐
文章图片

javascript|javascript 实现富文本框选中对齐
文章图片

document.querySelector("#btn_alignl").addEventListener("click", () => { Align.call(this, 'left') }) document.querySelector("#btn_alignc").addEventListener("click", () => { Align.call(this, 'center') }) document.querySelector("#btn_alignr").addEventListener("click", () => { Align('right') })

js 代码:
1、一个公共的Align方法,参数为:left|center|right
/** * 1 通过getEndNodes(PNode,startNode,endNode, ResultNodes)获取PNode中在startNode和ResultNodes之间的所有末梢元素 * 2 遍历EndNodes,通过getBlockParent获取每一个endNode的父级block元素 * 3 设置endnode 的 blockparent.style.textAlign=left|center|right * @param alignStr left|center|right **/ function Align(alignStr) { const rng = document.getSelection().getRangeAt(0) const commonAncestor = rng.commonAncestorContainer isStarted = false, isEnded = false const startEndNode=getEndNodes(rng.startContainer,rng.startContainer,rng.startContainer,[])[0] isStarted = false, isEnded = false const endEndNode=getEndNodes(rng.endContainer,rng.endContainer,rng.endContainer,[])[0] isStarted = false, isEnded = false const EndNodes = getEndNodes(commonAncestor,startEndNode,endEndNode,[]) EndNodes.forEach(node => { const blockparent = getBlockParent(node) if (!!blockparent && blockparent.style.textAlign != alignStr) { blockparent.style.textAlign = alignStr } }) }

获取选中元素的末梢节点的方法
let isStarted = false, isEnded = false function getEndNodes(PNode,startNode,endNode, ResultNodes) { if (PNode == startNode) { isStarted = true } if (PNode == endNode) { isEnded = true ResultNodes.push(PNode) console.log(PNode) } if (isStarted == true && isEnded == false && PNode.hasChildNodes()==false) { ResultNodes.push(PNode) ; console.log(PNode)}if (PNode.hasChildNodes() && isEnded==false) { PNode.childNodes.forEach(node => { getEndNodes(node, startNode,endNode, ResultNodes) }); } // debugger return ResultNodes }

【javascript|javascript 实现富文本框选中对齐】getBlockParent的实现--获取选中末梢节点的块父节点的实现
let blockTags = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'ul', 'ol', 'li', 'div', 'body', 'td', 'th'] // let inlineTags = ['img', 'font', 'b', 'strong', 'span', 'a'] let blockTagSet = new Map() blockTags.forEach((v) => { blockTagSet.set(v, true) }); const source = document.querySelector('div.source'); function getBlockParent(ele) { let result = undefined if (ele === source) { console.log('已找到editor的根,并没有找父级block元素'); result = undefined } else { switch (ele.nodeType) { //element: 判断ele是否是块级元素,判断依据1 display:block 2 默认的块级元素 case 1: { const disPro = ele.style.display; if (disPro && disPro.toLowerCase().indexOf('block') > -1) { result = ele; } else if (blockTagSet.get(ele.tagName.toLowerCase())) { result = ele } else { result = getBlockParent(ele.parentElement) } break; } case 3: {//textNode if (!!ele.nodeValue.trim()) result = getBlockParent(ele.parentElement) else result = undefined break; } default: { break; } } //end switch }//end ifreturn result }

    推荐阅读