2011-03-07 46 views
8

我想突出顯示我網站上的部分文字。該突出顯示的文本將被保存爲數據庫中的特定用戶,並且當文檔再次打開時,它將顯示先前突出顯示的文本。我認爲我會使用JavaScript來突出顯示文本,但我似乎無法找到一種方法來查明我突出顯示的單詞的位置。如何在整個文檔中找出單詞或選擇?

function getSelText() 
{ 
    var txt = ''; 
    if (window.getSelection) 
    { 
     txt = window.getSelection(); 
      } 
    else if (document.getSelection) 
    { 
     txt = document.getSelection(); 
      } 
    else if (document.selection) 
    { 
     txt = document.selection.createRange().text; 
      } 
    else return ""; 
    return txt; 
} 

我正在使用它來獲得選擇,但我無法弄清楚選擇在文本中的位置。最大的煩惱是當我在行或文本中有重複項時,如果我使用搜索,那麼我會找到第一個實例,而不是我正在尋找的那個。

所以問題是:你如何在整個文檔中找出一個詞或一個選擇?

回答

4

您可以使用我的Rangy庫和它的selection serialization module。 Rangy的核心爲所有瀏覽器提供了一致的選擇和範圍API,並且通過將每個選擇邊界轉換爲文檔中的路徑,串行器模塊在此基礎上進行構建。有關更多詳細信息,請參閱鏈接文檔

1

createRange創建一個textRange對象。它具有所有各種有用的信息:

  var range = document.selection.createRange(); 

      var left = range.boundingLeft; 
      var top = range.boundingTop; 
+0

因爲我沒有textarea可言,所以這不會真正起作用,我只是從文件中讀出數據並顯示出來。 – vman 2011-03-07 03:31:40

3

這當然不是一件容易的事情,因爲你面對當前文檔中定位文本,然後能夠找到它的兩大問題再次在後續頁面加載。如果您的頁面內容可能發生變化,問題就會變得更加複雜,因爲您甚至不能依靠文本的相對位置來保持相同。

你可能要考慮這是否是任何你要完成給定所需要的努力,最好的辦法,但這裏的東西,可能讓你在正確的方向開始:

function getSelection() { 
    var selection, position; 

    if (window.getSelection) { 
     selection = window.getSelection(); 

     if (selection && !selection.isCollapsed) { 
      position = { 
       'offset': selection.anchorOffset, 
       'length': selection.toString().length, 
       // We're assuming this will be a text node 
       'node': selection.anchorNode.parentNode 
      }; 
     } 
    } else if (document.selection) { 
     selection = document.selection.createRange(); 

     if (selection && selection.text.length) { 
      var text = selection.parentElement().innerText, 
       range = document.body.createTextRange(), 
       last = 0, index = -1; 

      range.moveToElementText(selection.parentElement()); 

      // Figure out which instance of the selected text in the overall 
      // text is the correct one by walking through the occurrences 
      while ((index = text.indexOf(selection.text, ++index)) !== -1) { 
       range.moveStart('character', index - last); 
       last = index; 

       if (selection.offsetLeft == range.offsetLeft && selection.offsetTop == range.offsetTop) { 
        break; 
       } 
      } 

      position = { 
       'offset': index, 
       'length': selection.text.length, 
       'node': selection.parentElement() 
      }; 
     } 
    } 

    return position; 
} 

以及一種方法再次選擇文本:

function setSelection(position) { 
    if (!position || !position.node) { 
     return; 
    } 

    var selection, range, element; 

    if (document.createRange) { 
     element = position.node.childNodes[0]; 
     range = document.createRange(); 
     range.setStart(element, position.offset); 
     range.setEnd(element, position.offset + position.length); 
     selection = window.getSelection(); 
     selection.removeAllRanges(); 
     selection.addRange(range); 
    } else if (document.body.createTextRange) { 
     range = document.body.createTextRange(); 
     range.moveToElementText(position.node); 
     range.collapse(true); 
     range.move('character', position.offset); 
     range.moveEnd('character', position.length); 
     range.select(); 
    } 
} 

該代碼使得比較幼稚假設所選文本的所有駐留在相同的DOM元素。機會很大,如果用戶選擇任意文本,情況就不會如此。

鑑於Selection object佔這與anchorNodefocusNode屬性,您可以嘗試解決這個問題,雖然涉及Internet Explorer中的TextRange object可能被證明是有點難度。

還有一個問題,就是如何跟蹤頁面請求中的position.node值。在我的jsFiddle sample中,我使用了selector-generating jQuery function的一個稍微修改過的版本來生成一個選擇器字符串,可以保存該選擇器字符串並用於稍後重新選擇正確的節點。請注意,這個過程相對比較簡單,所以如果沒有jQuery –,只需要在這種情況下節省一些工作量即可輕鬆完成。

當然,如果您在訪問之間更改DOM,此方法可能會相當不穩定。如果你不是,我覺得它可能是更可靠的選擇之一。

+1

這是一個和我的Rangy庫中的串行器模塊類似的(但不太完全實現)的方法:http://code.google.com/p/rangy/wiki/SerializerModule – 2011-03-07 10:35:42

+0

@TimDown哦哇,我有點慚愧考慮到我過去積極的經驗,我在寫出答案時沒有想到Rangy。感謝您的鏈接。 – 2011-03-07 15:57:53

+0

非常感謝一羣rangy圖書館做的伎倆。 – vman 2011-03-14 02:26:30

相關問題