最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

javascript實(shí)現(xiàn)富文本框選中對(duì)齊的思路與代碼

 更新時(shí)間:2022年03月24日 09:59:41   作者:jiayouliucui  
最近在項(xiàng)目中經(jīng)常遇到使用富文本框的情況,下面這篇文章主要給大家介紹了關(guān)于javascript實(shí)現(xiàn)富文本框選中對(duì)齊的思路與代碼,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

需求:

一個(gè)可編輯(contenteditable=true)的div,對(duì)齊選中內(nèi)容,左、中,右 ,其實(shí)質(zhì)是:對(duì)選中的末梢節(jié)點(diǎn),找到塊屬性的父元素,設(shè)置text-algin:center:

MDN:text-align CSS屬性定義行內(nèi)內(nèi)容(例如文字)如何相對(duì)它的塊父元素對(duì)齊。text-align 并不控制塊元素自己的對(duì)齊,只控制它的行內(nèi)內(nèi)容的對(duì)齊。

分析需求:

我們來(lái)分解一下這個(gè)需求的三個(gè)關(guān)鍵問(wèn)題: ”選中部分“,”塊元素“,"末梢元素"

1如何獲取選中的部分 *

這里涉及到的Web API Document.getSelection().getRangeAt(0) 這里只處理一個(gè)選取的情況

注意:光標(biāo)所在位置,光標(biāo)所在節(jié)點(diǎn) 視為選中區(qū)域

2什么是塊元素

MDN:

display:block

這個(gè)值會(huì)生成一個(gè)塊級(jí)元素盒子,同時(shí)在該元素之前和之后打斷(換行)。簡(jiǎn)單來(lái)說(shuō)就是,這個(gè)值會(huì)將該元素變成塊級(jí)元素

除非特殊指定,諸如標(biāo)題(<h1>等)和段落(<p>)默認(rèn)情況下都是塊級(jí)的盒子。

用做鏈接的 <a> 元素、 <span>、 <em> 以及 <strong> 都是默認(rèn)處于 inline 狀態(tài)的。

3末梢元素(沒(méi)有子節(jié)點(diǎn)的元素)

我們操作對(duì)齊,實(shí)質(zhì)是操作盒模型中的內(nèi)容的對(duì)齊方式,也就是對(duì):圖片,文字 等設(shè)置對(duì)齊樣式,在這里我稱其為末梢節(jié)點(diǎn)

實(shí)現(xiàn)思路:

1、獲取選區(qū)內(nèi)的所有末梢元素(遞歸)

2、找到這些末梢元素的父塊元素,設(shè)置其text-align:'left|center|right'

代碼實(shí)現(xiàn):

前端頁(yè)面:一個(gè)div contenteditable="true";三個(gè)按鈕:觸發(fā)對(duì)齊(左,中,右)

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、一個(gè)公共的Align方法,參數(shù)為:left|center|right

/**
     * 1 通過(guò)getBoundaryEndNodes獲取所有末梢元素
     * 2 遍歷末梢節(jié)點(diǎn),通過(guò)getBlockParent獲取每一個(gè)末梢節(jié)點(diǎn)的父級(jí)block元素
     * 3 設(shè)置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
        //獲取開(kāi)始節(jié)點(diǎn),到結(jié)尾節(jié)點(diǎn)之間的所有末梢節(jié)點(diǎn)
        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)
                });
            }
        }
        //獲取所有末梢節(jié)點(diǎn)
        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 = [] //存放開(kāi)始節(jié)點(diǎn),到結(jié)尾節(jié)點(diǎn)之間的所有末梢節(jié)點(diǎn)
        let boundaries = { start: startBoundaryNode, end: endBoundaryNode, isStart: false, isEnd: false }
        getBoundaryEndNodes.call(this, commonAncestor)
        //遍歷所有末梢節(jié)點(diǎn),找到其塊父元素 設(shè)置對(duì)齊樣式
        resultNodes.forEach(node => {
            const blockparent = getBlockParent(node)
            if (!!blockparent && blockparent.style.textAlign != alignStr) {
                blockparent.style.textAlign = alignStr
            }
        })
    }

getBlockParent的實(shí)現(xiàn)--獲取選中末梢節(jié)點(diǎn)的塊父節(jié)點(diǎn)的實(shí)現(xiàn)

	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的根,并沒(méi)有找父級(jí)block元素');
            result = undefined
        } else {
            switch (ele.nodeType) {
                //element: 判斷ele是否是塊級(jí)元素,判斷依據(jù)1 display:block 2 默認(rèn)的塊級(jí)元素
                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
    }

總結(jié) 

到此這篇關(guān)于javascript實(shí)現(xiàn)富文本框選中對(duì)齊的思路與代碼的文章就介紹到這了,更多相關(guān)js富文本框選中對(duì)齊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript中判斷網(wǎng)絡(luò)狀態(tài)的幾種方法

    JavaScript中判斷網(wǎng)絡(luò)狀態(tài)的幾種方法

    這篇文章主要介紹了如何使用JavaScript的`navigator.onLine`屬性和`ononline`、`onoffline`事件來(lái)檢測(cè)瀏覽器的在線狀態(tài),并提供了兼容性代碼示例,需要的朋友可以參考下
    2025-02-02
  • 優(yōu)雅處理前端異常的幾種方式推薦

    優(yōu)雅處理前端異常的幾種方式推薦

    前端一直是距離用戶最近的一層,隨著產(chǎn)品的日益完善,我們會(huì)更加注重用戶體驗(yàn),而前端異常卻如鯁在喉,甚是煩人,下面這篇文章主要給大家推薦介紹了關(guān)于優(yōu)雅處理前端異常的幾種方式,需要的朋友可以參考下
    2022-08-08
  • javascript中基本類型和引用類型的區(qū)別分析

    javascript中基本類型和引用類型的區(qū)別分析

    大多數(shù)人系統(tǒng)學(xué)習(xí)過(guò)的程序設(shè)計(jì)語(yǔ)言,在這些語(yǔ)言的學(xué)習(xí)過(guò)程中最早學(xué)到的幾個(gè)要點(diǎn)之一就是值類型和引用類型的區(qū)別。下面我們來(lái)看一下在 JavaScript 中基本數(shù)據(jù)類型(Primitive Types)和引用類型(Reference Types)的區(qū)別。
    2015-05-05
  • BootStrapValidator初使用教程詳解

    BootStrapValidator初使用教程詳解

    bootstrap能夠增加兼容性的強(qiáng)大框架,在項(xiàng)目中用到了數(shù)據(jù)驗(yàn)證功能,今天小編就抽空給大家介紹下BootStrapValidator初使用教程詳解,一起看看吧
    2017-02-02
  • 微博@符號(hào)的用戶名提示效果。(想@到誰(shuí)?)

    微博@符號(hào)的用戶名提示效果。(想@到誰(shuí)?)

    相信你老早就在騰訊或者新浪的微博上體驗(yàn)到了,@符號(hào)在微博時(shí)代的便捷呼叫。
    2010-11-11
  • 原生JS查找元素的方法(推薦)

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

    下面小編就為大家?guī)?lái)一篇原生JS查找元素的方法(推薦)。小編覺(jué)得挺不錯(cuò)的,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧,祝大家游戲愉快哦
    2016-11-11
  • javascript工廠模式和構(gòu)造函數(shù)模式創(chuàng)建對(duì)象方法解析

    javascript工廠模式和構(gòu)造函數(shù)模式創(chuàng)建對(duì)象方法解析

    本文主要對(duì)javascript工廠模式和構(gòu)造函數(shù)模式創(chuàng)建對(duì)象方法進(jìn)行解析,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2016-12-12
  • ES10的13個(gè)新特性示例(小結(jié))

    ES10的13個(gè)新特性示例(小結(jié))

    這篇文章主要介紹了ES10的13個(gè)新特性示例(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • ES6 async、await的基本使用方法示例

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

    這篇文章主要介紹了ES6 async、await的基本使用方法,結(jié)合實(shí)例形式分析了ES6 async、await的基本功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2020-06-06
  • JS技巧Canvas性能優(yōu)化臟矩形渲染實(shí)例詳解

    JS技巧Canvas性能優(yōu)化臟矩形渲染實(shí)例詳解

    這篇文章主要為大家介紹了JS技巧Canvas?性能優(yōu)化臟矩形渲染實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論

苍山县| 绵竹市| 楚雄市| 塔河县| 利辛县| 古交市| 容城县| 光泽县| 濉溪县| 抚宁县| 宣武区| 梓潼县| 武清区| 德阳市| 四会市| 拜泉县| 宜章县| 辰溪县| 正宁县| 东丰县| 惠东县| 惠安县| 铜梁县| 延川县| 高阳县| 肇源县| 淮南市| 大港区| 宜兰市| 黎城县| 葵青区| 贺兰县| 军事| 渭源县| 万源市| 柳州市| 昂仁县| 永川市| 汾西县| 望江县| 贵港市|