javascript实现富文本框选中对齐的思路与代码

 更新时间:2022年03月24日 09:59:41   作者:jiayouliucui  
最近在项目中经常遇到使用富文本框的情况,下面这篇文章主要给大家介绍了关于javascript实现富文本框选中对齐的思路与代码,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

需求:

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

MDN:text-align CSS属性定义行内内容(例如文字)如何相对它的块父元素对齐。text-align 并不控制块元素自己的对齐,只控制它的行内内容的对齐。

分析需求:

我们来分解一下这个需求的三个关键问题: ”选中部分“,”块元素“,"末梢元素"

1如何获取选中的部分 *

这里涉及到的Web API Document.getSelection().getRangeAt(0) 这里只处理一个选取的情况

注意:光标所在位置,光标所在节点 视为选中区域

2什么是块元素

MDN:

display:block

这个值会生成一个块级元素盒子,同时在该元素之前和之后打断(换行)。简单来说就是,这个值会将该元素变成块级元素

除非特殊指定,诸如标题(<h1>等)和段落(<p>)默认情况下都是块级的盒子。

用做链接的 <a> 元素、 <span>、 <em> 以及 <strong> 都是默认处于 inline 状态的。

3末梢元素(没有子节点的元素)

我们操作对齐,实质是操作盒模型中的内容的对齐方式,也就是对:图片,文字 等设置对齐样式,在这里我称其为末梢节点

实现思路:

1、获取选区内的所有末梢元素(递归)

2、找到这些末梢元素的父块元素,设置其text-align:'left|center|right'

代码实现:

前端页面:一个div contenteditable="true";三个按钮:触发对齐(左,中,右)

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 通过getBoundaryEndNodes获取所有末梢元素
     * 2 遍历末梢节点,通过getBlockParent获取每一个末梢节点的父级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
        //获取开始节点,到结尾节点之间的所有末梢节点
        let getBoundaryEndNodes = function (pNode) {
            if (pNode == boundaries.start) { boundaries.isStart = true }
            if (pNode == boundaries.end) {
                boundaries.isEnd = true
                resultNodes.push(pNode)
                console.log(pNode)
            }
            if (boundaries.isStart == true && boundaries.isEnd == false && pNode.hasChildNodes() == false) { resultNodes.push(pNode); console.log(pNode) }

            if (pNode.hasChildNodes() && boundaries.isEnd == false) {
                pNode.childNodes.forEach(node => {
                    getBoundaryEndNodes(node)
                });
            }
        }
        //获取所有末梢节点
        let getEndNodes = function (node, nodes=[]) {
            if (node.hasChildNodes()) {
                node.childNodes.forEach(node => {
                    getEndNodes(node, nodes)
                });
            } else {
                nodes.push(node)
            }
            return nodes
        }

        const startBoundaryNode = getEndNodes(rng.startContainer)[0]
        const endBoundaryNode = getEndNodes(rng.endContainer).pop()
        let resultNodes = [] //存放开始节点,到结尾节点之间的所有末梢节点
        let boundaries = { start: startBoundaryNode, end: endBoundaryNode, isStart: false, isEnd: false }
        getBoundaryEndNodes.call(this, commonAncestor)
        //遍历所有末梢节点,找到其块父元素 设置对齐样式
        resultNodes.forEach(node => {
            const blockparent = getBlockParent(node)
            if (!!blockparent && blockparent.style.textAlign != alignStr) {
                blockparent.style.textAlign = alignStr
            }
        })
    }

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 if
        return result
    }

总结 

到此这篇关于javascript实现富文本框选中对齐的思路与代码的文章就介绍到这了,更多相关js富文本框选中对齐内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中判断网络状态的几种方法

    JavaScript中判断网络状态的几种方法

    这篇文章主要介绍了如何使用JavaScript的`navigator.onLine`属性和`ononline`、`onoffline`事件来检测浏览器的在线状态,并提供了兼容性代码示例,需要的朋友可以参考下
    2025-02-02
  • 优雅处理前端异常的几种方式推荐

    优雅处理前端异常的几种方式推荐

    前端一直是距离用户最近的一层,随着产品的日益完善,我们会更加注重用户体验,而前端异常却如鲠在喉,甚是烦人,下面这篇文章主要给大家推荐介绍了关于优雅处理前端异常的几种方式,需要的朋友可以参考下
    2022-08-08
  • javascript中基本类型和引用类型的区别分析

    javascript中基本类型和引用类型的区别分析

    大多数人系统学习过的程序设计语言,在这些语言的学习过程中最早学到的几个要点之一就是值类型和引用类型的区别。下面我们来看一下在 JavaScript 中基本数据类型(Primitive Types)和引用类型(Reference Types)的区别。
    2015-05-05
  • BootStrapValidator初使用教程详解

    BootStrapValidator初使用教程详解

    bootstrap能够增加兼容性的强大框架,在项目中用到了数据验证功能,今天小编就抽空给大家介绍下BootStrapValidator初使用教程详解,一起看看吧
    2017-02-02
  • 微博@符号的用户名提示效果。(想@到谁?)

    微博@符号的用户名提示效果。(想@到谁?)

    相信你老早就在腾讯或者新浪的微博上体验到了,@符号在微博时代的便捷呼叫。
    2010-11-11
  • 原生JS查找元素的方法(推荐)

    原生JS查找元素的方法(推荐)

    下面小编就为大家带来一篇原生JS查找元素的方法(推荐)。小编觉得挺不错的,希望对大家有所帮助。一起跟随小编过来看看吧,祝大家游戏愉快哦
    2016-11-11
  • javascript工厂模式和构造函数模式创建对象方法解析

    javascript工厂模式和构造函数模式创建对象方法解析

    本文主要对javascript工厂模式和构造函数模式创建对象方法进行解析,具有一定的参考价值,下面跟着小编一起来看下吧
    2016-12-12
  • ES10的13个新特性示例(小结)

    ES10的13个新特性示例(小结)

    这篇文章主要介绍了ES10的13个新特性示例(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • ES6 async、await的基本使用方法示例

    ES6 async、await的基本使用方法示例

    这篇文章主要介绍了ES6 async、await的基本使用方法,结合实例形式分析了ES6 async、await的基本功能、使用方法与相关注意事项,需要的朋友可以参考下
    2020-06-06
  • JS技巧Canvas性能优化脏矩形渲染实例详解

    JS技巧Canvas性能优化脏矩形渲染实例详解

    这篇文章主要为大家介绍了JS技巧Canvas 性能优化脏矩形渲染实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01

最新评论