我想突出顯示(應用css)某個文本範圍,以其開始和結束位置表示。這比看起來更不明顯,因爲文本中可能有其他標籤,需要忽略。使用JavaScript突出顯示文本範圍
例:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
需要突出"cdef
「不刪除標記
我一直在使用一個TextRange對象試過了,但都沒有成功
提前感謝
!我想突出顯示(應用css)某個文本範圍,以其開始和結束位置表示。這比看起來更不明顯,因爲文本中可能有其他標籤,需要忽略。使用JavaScript突出顯示文本範圍
例:
<div>abcd<em>efg</em>hij</div>
highlight(2, 6)
需要突出"cdef
「不刪除標記
我一直在使用一個TextRange對象試過了,但都沒有成功
提前感謝
!下面是設置一個特定元素中選擇的一對字符偏移量的函數。這是天真的實現:它沒有考慮任何可能被隱藏的文本(例如,通過CSS或者通過在<script>
或<style>
元素中),並且可能存在瀏覽器差異(IE與其他所有內容)和換行符,並且不考慮摺疊的空白(例如,2個或多個連續的空格字符摺疊到頁面上的一個可見空間)。但是,它適用於所有主流瀏覽器中的示例。
對於其他部分,突出顯示,我建議使用document.execCommand()
。您可以使用我的以下功能設置選項,然後致電document.execCommand()
。您需要在非IE瀏覽器中臨時編輯文檔才能使該命令生效。見我的答案在這裏代碼:getSelection & surroundContents across multiple tags
這裏是展示整個事情的jsfiddle例如,在所有主要的瀏覽器中工作:http://jsfiddle.net/8mdX4/1211/
和選擇設置代碼:
function getTextNodesIn(node) {
var textNodes = [];
if (node.nodeType == 3) {
textNodes.push(node);
} else {
var children = node.childNodes;
for (var i = 0, len = children.length; i < len; ++i) {
textNodes.push.apply(textNodes, getTextNodesIn(children[i]));
}
}
return textNodes;
}
function setSelectionRange(el, start, end) {
if (document.createRange && window.getSelection) {
var range = document.createRange();
range.selectNodeContents(el);
var textNodes = getTextNodesIn(el);
var foundStart = false;
var charCount = 0, endCharCount;
for (var i = 0, textNode; textNode = textNodes[i++];) {
endCharCount = charCount + textNode.length;
if (!foundStart && start >= charCount
&& (start < endCharCount ||
(start == endCharCount && i <= textNodes.length))) {
range.setStart(textNode, start - charCount);
foundStart = true;
}
if (foundStart && end <= endCharCount) {
range.setEnd(textNode, end - charCount);
break;
}
charCount = endCharCount;
}
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection && document.body.createTextRange) {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(true);
textRange.moveEnd("character", end);
textRange.moveStart("character", start);
textRange.select();
}
}
輝煌的解決方案@ tim-down!您的代碼適用於整合嵌套HTML格式的文本。 http://stackoverflow.com/questions/16226671/consolidate-stacked-dom-formatting-elements-contenteditable-div – 2013-04-26 20:59:38
當我運行這段代碼時,span標籤被添加到所有突出顯示的文本中,我可以添加一個類並點擊事件的跨度標籤? – Prateek 2013-09-13 09:15:53
@prateek:我認爲你的意思是突出顯示的代碼?由於跨度是由瀏覽器自動添加的,因此找到並修改它們並不容易。您可以使用我的[Rangy](https://code.google.com/p/rangy)庫的[class applier module](https://code.google.com/p/rangy/wiki/CSSClassApplierModule) 。 – 2013-09-13 09:23:37
以下解決方案不適用於IE,您需要應用TextRange對象等。這款採用選擇執行此,它不應該打破HTML在正常情況下,例如:
<div>abcd<span>efg</span>hij</div>
隨着highlight(3,6);
輸出:
<div>abc<em>d<span>ef</span></em><span>g</span>hij</div>
必須注意它是如何包裝第一跨越的字符變爲em
,然後將其餘的span
轉換爲新的字符。在那裏,好像它只是打開它在字符3和第6個字母結束,它會給合法的標記,如:
<div>abc<em>d<span>ef</em>g</span>hij</div>
代碼:
var r = document.createRange();
var s = window.getSelection()
r.selectNode($('div')[0]);
s.removeAllRanges();
s.addRange(r);
// not quite sure why firefox has problems with this
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
function highlight(start,end){
for(var st=0;st<start;st++){
s.modify("move", "forward", "character");
}
for(var st=0;st<(end-start);st++){
s.modify("extend", "forward", "character");
}
}
highlight(2,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
例子:http://jsfiddle.net/niklasvh/4NDb9/
編輯看起來像至少我的FF4有一些問題
s.modify("move", "backward", "documentboundary");
,但在同一時間,似乎沒有它的工作,所以我只是把它改爲
if ($.browser.webkit) {
s.modify("move", "backward", "documentboundary");
}
編輯 蒂姆指出的那樣,修改只能從FF4起,所以我採取了不同的方法來獲得選擇,而不需要修改方法,希望能夠讓瀏覽器兼容一些(IE仍然需要它自己的解決方案)。
的代碼:
var r = document.createRange();
var s = window.getSelection()
var pos = 0;
function dig(el){
$(el).contents().each(function(i,e){
if (e.nodeType==1){
// not a textnode
dig(e);
}else{
if (pos<start){
if (pos+e.length>=start){
range.setStart(e, start-pos);
}
}
if (pos<end){
if (pos+e.length>=end){
range.setEnd(e, end-pos);
}
}
pos = pos+e.length;
}
});
}
var start,end, range;
function highlight(element,st,en){
range = document.createRange();
start = st;
end = en;
dig(element);
s.addRange(range);
}
highlight($('div'),3,6);
var ra = s.getRangeAt(0);
var newNode = document.createElement("em");
newNode.appendChild(ra.extractContents());
ra.insertNode(newNode);
自Firefox 4.0以來,Firefox只實現'Selection.modify()',並且不支持WebKit所做的所有粒度設置。具體而言,它不支持「文檔邊界」。請參閱https://developer.mozilla.org/en/DOM/selection/modify – 2011-06-05 10:15:17
這似乎只在頁面上沒有其他內容時才起作用。請參閱:http://jsfiddle.net/4NDb9/89/。儘管Hello world在div之外,但它被突出顯示,而不是div內的文本。 – Vincent 2011-06-05 11:02:45
@Tim Down非常好的一點。我重寫了它的很大一部分來擺脫現在的modify()方法。 – Niklas 2011-06-05 11:05:42
你可以看看這個功能強大的JavaScript實用程序支持多DOM元素選擇:
MASHA(Mark的簡寫&股)讓你標記的網頁內容有趣的部分,並分享
http://mashajs.com/index_eng.html
這也是在GitHub上https://github.com/SmartTeleMax/MaSha
即使在移動Safari和IE作品!
您可以剝離臨時字符串中的標籤,然後從該字符串中獲取子字符串嗎? – mc10 2011-06-05 00:28:29
你不能忽略標籤,否則你會以不合法的html結尾:'ab cd ef f'。您需要執行以下操作:ab cd ef g' –
serg
2011-06-05 00:37:10
當然,我不能忽略這些標籤,但如果瀏覽器能夠以某種方式爲我解決這些問題,那將會很不錯。 – Vincent 2011-06-05 11:03:59