日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java实现给选中文字添加样式,天坑之路:用js给选中文字添加样式

發(fā)布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java实现给选中文字添加样式,天坑之路:用js给选中文字添加样式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

本例基于react,但是實(shí)際上就是用原生js做的。兼容性做到了IE9,但是按照這個思路做是可以做到IE8甚至更低的。

需求與最初的思路

當(dāng)我拿到這個需求的時候以為很簡單,就是可以給頁面上的文章做記號,比如添加個下劃線,或者背景涂色做成熒光筆的樣子。

因?yàn)橹恍枰嫒軮E9,所以window.getSelection是支持的。(IE8及以下有其它的獲取選中的方法)

那么思路就是選中文本,點(diǎn)擊添加下劃線后,通過 window.getSelection.getRangeAt(0) 拿到選中的文本對象,獲取到文本后,通過文本對象的 surroundContents 方法來將文本替換為帶有class的元素。

初步的實(shí)現(xiàn)

思路很簡單,代碼同樣也很簡單。

CSS代碼:.custom-underline{??border-bottom:?1px?solid?#f00;??font-style:?normal;

}.nite-writer-pen{??background-color:?lightgreen;??border-radius:?5px;??box-shadow:?0?0?10px?lightgreen;??font-style:?normal;

}

JS代碼:/**

*?用元素替換被選中的文本

*/var?replaceSelectedStrByEle?=?function(className){??var?selecter?=?window.getSelection();??var?selectStr?=?selecter.toString();??if?(selectStr.trim?!=?"")?{????var?rang?=?selecter.getRangeAt(0);????var?ele?=?document.createElement("i");

ele.className?=?className;

ele.textContent?=?selectStr

rang.surroundContents(ele);

}

}

replaceSelectedStrByEle('nite-writer-pen');

天坑出現(xiàn)

上面的思路實(shí)在是過于簡單,如果是一個很簡單的元素,那么這種做法是沒有問題的。

但是我們的文章的html結(jié)構(gòu)一般都沒有這么簡單,比如對于以下情況:

道可道,非常道。

名可名,非常名

如果在頁面上我選中的操作如下:

那么上面的代碼實(shí)現(xiàn)就會出現(xiàn)BUG,對于這種跨元素選中的情況,想當(dāng)然的用元素去替換文本是沒用的。

如果你想得更多,比如跨多個元素選中,以及選中元素為更為復(fù)雜的html結(jié)構(gòu),你就會發(fā)現(xiàn)這是一個多大的坑。

html結(jié)構(gòu)有多復(fù)雜,這個坑就有多深。

思路的僵局與寫輪眼

其實(shí)天坑也不是完全沒有路走,在跨多個元素選中的過程中,我想給選中的內(nèi)容加樣式,那么就需要獲取到所有選中的文本節(jié)點(diǎn),并且批量替換成元素。

但是 window.getSelection.getRangeAt(0) 獲取到的range對象只能獲取到最開始選中的節(jié)點(diǎn)和最后選中的節(jié)點(diǎn)的。

那么接下來通過選中的最開始的節(jié)點(diǎn)和最后的節(jié)點(diǎn)獲取到所有的文本節(jié)點(diǎn)。

思路就是這么個思路,但是實(shí)現(xiàn)起來是很復(fù)雜的。

面臨深坑,肯定不可能硬剛。

畢竟我已經(jīng)不是當(dāng)年頭鐵的愣頭青了,做項(xiàng)目是有時間和精力成本的,如果要填掉這個坑,那么加班是不可避免的,最重要的是在有限時間內(nèi)填的這個坑可能還有各種BUG和兼容性問題。

對待這種天坑,一般就給需求來個做不了三連了。

但是這把我想贏,畢竟這個東西看起來確實(shí)簡單。

在外人的眼里,如此之簡單,分分鐘搞定的事情。這都做不了,我還怎么在前端的圈子里繼續(xù)劃水?

所以我要動用程序員的入門技——寫輪眼。

然而百度、谷歌無效,根本沒有這個解決方案,有的全是些我最初的簡單實(shí)現(xiàn)。

但是回憶我們以前見到的各種網(wǎng)頁應(yīng)用與場景,很容易就能想到上面的這種操作我們是見過的。

那就是從遠(yuǎn)古IE時代就已經(jīng)出現(xiàn)的各種富文本編輯器組件。

目標(biāo)確認(rèn),百度的ueditor,這波我要贏。

分析ueditor與復(fù)制

上github兩三下拿到ueditor源碼,開始讀源碼分析代碼。

中間過程不再多說,精簡代碼,除去一些不需要的代碼和兼容性處理后,拿到了五個文件:browser.js (瀏覽器版本判斷,用于做兼容性處理)

domUtils.js (dom操作)

dtd.js (節(jié)點(diǎn)的類型與元素判斷)

Range.js (封裝的選中范圍對象)

utils.js (工具類)

即使精簡后,代碼也不少,大概兩三千行。不過其中還有很多注釋,壓縮后體積并不大。

由于代碼比較多,這里就不全部展示了,文章最后會給出github的地址。

這里只給出最后的使用代碼:/**

*?添加下劃線

*/addUnderline?=?()?=>?{??this.replaceSelectedStrByEle(styles['custom-underline'])

}/**

*?啟用熒光筆

*/enableNiteWriterPen?=?()?=>?{??this.replaceSelectedStrByEle(styles['nite-writer-pen'])

}/**

*?用元素替換被選中的文本

*/replaceSelectedStrByEle?=?(className)?=>?{??var?getRange?=?()?=>?{????var?me?=?window;????var?range?=?new?Range(me.document);????var?sel?=?window.getSelection();????if?(sel?&&?sel.rangeCount)?{??????var?firstRange?=?sel.getRangeAt(0);??????var?lastRange?=?sel.getRangeAt(sel.rangeCount?-?1);

range.setStart(firstRange.startContainer,?firstRange.startOffset)

.setEnd(lastRange.endContainer,?lastRange.endOffset);

}????return?range

}??var?range?=?getRange();

range.applyInlineStyle('i',?{????class:?className

});

range.select();

}

使用起來還是比較簡單的。

對i元素的處理做的一些修改

如果我們選中的是已經(jīng)被包裹在i元素中的一段文本,那么調(diào)用后會發(fā)現(xiàn)并沒有加上class屬性。

這是因?yàn)楦晃谋揪庉嬈骱臀覀兊男枨蟛灰粯?#xff0c;通過操作想把選中文本變?yōu)閕元素,而文本外面本來就是i元素了,自然不會進(jìn)行剩下的操作。

在填充元素的最后會有一個mergeToParent的操作,他會在填充元素的標(biāo)簽和其父級元素的標(biāo)簽一樣后將元素替換為文本。if?(parent.tagName?==?node.tagName?||?parent.tagName?==?"A")?{??//...}

那么這里我們要修改源碼加上一個判斷if?((parent.tagName?==?node.tagName?&&?parent.className?==?node.className)?||?parent.tagName?==?"A")?{??//...}

至于其它的邏輯保持不變即可。

為支持回退操作做的一些修改

這里getRange拿到的對象range在選中內(nèi)容并替換樣式后依然可以使用。

可以調(diào)用range.removeInlineStyle('i')

移除之前添加的樣式。

也就是說這里如果使用一個命令模式之類的,是可以實(shí)現(xiàn)回退操作的。

不過這里還是有一個坑,就是removeInlineStyle會移除掉選中內(nèi)容中所有的i元素,于是我修改了

Range.js中removeInlineStyle這個方法,多加了一個className參數(shù),每次去掉i元素時都會判斷是否參數(shù)等于className。

然后我們調(diào)用時就是range.removeInlineStyle('i',styles['nite-writer-pen'])

總結(jié)

作為一個暗藏天坑的小需求,搞定之后其實(shí)還挺有成就感的。

粗略閱讀了源碼后才發(fā)現(xiàn)如果自己做會有多坑,基本上沒個三五天下不來,并且在多掉了N根頭發(fā)后仍然會發(fā)現(xiàn)到處都是考慮不周和各種BUG。

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的java实现给选中文字添加样式,天坑之路:用js给选中文字添加样式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲第一成年人网站 | 男女啪啪在线观看 | 在线免费观看亚洲 | xx在线视频 | 黄色成人av在线 | 国产乱妇乱子 | 午夜国产一区二区三区 | 日本福利小视频 | 色婷婷aⅴ一区二区三区 | jizz日本免费 | 日本综合色 | 亲嘴扒胸摸屁股免费视频日本网站 | 久久久久亚洲视频 | av久色| 色香av| 18禁一区二区三区 | 奇米影视四色在线 | 青青青操 | 亚洲网在线| 中国大陆毛片 | 激情片 | 人人插人人爽 | 天天操天天草 | 国产精品无码自拍 | 性猛交富婆╳xxx乱大交麻豆 | 久久七| 丝袜 亚洲 另类 欧美 重口 | 日韩成人av网| 久久精品6 | 成人免费黄色小视频 | 性――交――性――乱 | 国产粉嫩在线 | 欧美日韩国产一区在线 | 九七影院在线观看免费观看电视 | 国产精品视频一二三区 | 国产乱码一区二区 | 黄色录像三级 | 97中文字幕在线观看 | 色呦呦中文字幕 | 欧美拍拍 | 欧美日韩三 | www.午夜av | youjizz少妇 | 久色视频在线播放 | 神马久久久久久久久久久 | 在线观看亚洲一区 | 欧美日韩性视频 | 天天干天天爽天天射 | 国产精品毛片va一区二区三区 | 96久久精品 | 综合网激情 | 美女av网 | 激情天堂网| 爱情岛论坛亚洲入口 | 天天操天天做 | 空姐毛片 | 日本黄动漫 | 国产视频中文字幕 | aa黄色大片 | 一区二区三区四区在线播放 | 一区二区三区在线免费 | 亚洲欧美少妇 | 中文字幕日韩人妻在线视频 | 亚洲另类色图 | xxxxⅹxxxhd日本8hd| 99综合视频 | 黄色片网站在线免费观看 | 色臀| 欧美私人情侣网站 | 日韩一区二区三区四区 | 午夜国产福利在线观看 | 国产激情综合五月久久 | 狠狠做| 国产又爽又黄的激情精品视频 | 日本韩国欧美一区二区三区 | 大胸喷奶水www视频妖精网站 | 久久综合伊人77777蜜臀 | 朴麦妮原版视频高清资源 | 成人精品一区二区三区电影 | 四虎av影院| 国产精品污www一区二区三区 | 亚洲卡一卡二卡三 | 欧美v视频 | 国产毛片毛片毛片毛片毛片 | 欧美少妇xx | 国产一区二区影院 | 美女撒尿无遮挡网站 | 日韩一区二区a片免费观看 伊人网综合在线 | 影音先锋亚洲资源 | 欧洲高潮三级做爰 | 久久久久亚洲AV成人无在 | 99re99| 老太太av| 欧美18av | 日批网站在线观看 | www天天操 | 亚洲天堂视频在线播放 | 国产无毛av | 国产精品自偷自拍 |