2013-12-15 26 views
0

我希望能夠將鼠標懸停在網頁上的任何單詞上,並在該單詞上方顯示彈出單詞。這似乎幾乎不可能沒有巨大的性能問題,所以我試圖做雙擊而不是懸停。如何使用範圍包裝所選單詞

隨着雙擊,我可以檢測到單詞的文本,但我無法對頁面中的單詞進行任何操作。基本上,我想用span標籤包裹選定的文本,以便相對於它定位事物。我以前用熒光筆看過它,但我不知道如何。

注意:這隻需要在Firefox中工作。

+1

我也許可以幫助,但需要更多的細節。首先,您是否希望將此功能添加到現有網頁,或者是您自己的網頁。這當然會產生很大的差異;)另外,如果你可以發佈一個演示你正在嘗試完成的小提琴(fiddlejs.net),那也可以幫助你做很多事情。乍一看,事件代表團和延遲加載似乎是你的朋友。 –

+0

這是爲現有的網頁(它是一個Firefox插件)。 – Ian

回答

3

您可以使用這些功能:

var range = window.getSelection().getRangeAt(0); 
var newNode = document.createElement("b"); 
range.surroundContents(newNode); 

這與周圍的B標記您的選擇。

+0

任何'b'標籤都可以有類的方式? – Ian

+1

似乎按預期工作'var range = window.getSelection()。getRangeAt(0); range.surroundContents($(「」,{'class':'test'})[0]);' – megawac

+0

'newNode .className ='foo''。 –

1

mouseover事件並非不可能。您可以使用在Firefox 20及更高版本中標準化並支持的document.caretPositionFromPoint(),並返回到WebKit專有的等效版本。

http://jsfiddle.net/2zzjL/6/

處理鼠標事件時的步驟如下:

  • 隱藏字彈出,如果顯示
  • 獲取光標從事件
  • 座標創建從一個範圍使用document.caretPositionFromPoint()或等效的光標座標
  • 如果範圍的容器節點是文本節點,則它的偏移量是一個字符索引wi薄文本節點的文本
  • 從那裏,向前和向後擴大在文本節點的文本,直到我們打空白得到了這個詞
  • 更新涵蓋的範圍全詞
  • 呼叫getBoundingClientRect()得到的範圍內字
  • 位置的座標,從這些座標偏移路程,在一些字彈出元素表現出來

演示是非常有限的(例如,它不跨越元素的字工作邊界,這個詞的檢測非常粗糙和re有很多優化的空間),但應該足以讓你開始。它適用於當前的瀏覽器,但IE不支持document.caretPositionFromPoint()

這裏是關鍵代碼:

function expandToWord(str, offset) { 
    var start = offset; 
    while (start >= 1 && /\S/.test(str.charAt(start - 1))) { 
     --start; 
    } 

    var end = offset, len = str.length; 
    while (end < len && /\S/.test(str.charAt(end))) { 
     ++end; 
    } 

    return { 
     start: start, 
     end: end, 
     word: str.slice(start, end) 
    }; 
} 

var wordDiv = document.createElement("div"); 
wordDiv.className = "word"; 

var createRangeFromPoint = (function(doc) { 
    // Try standards-based method first 
    if (typeof doc.caretPositionFromPoint != "undefined") { 
     return function(x, y) { 
      var pos = doc.caretPositionFromPoint(x, y); 
      var range = null; 
      if (pos) { 
       range = doc.createRange(); 
       range.setStart(pos.offsetNode, pos.offset); 
       range.collapse(true); 
      } 
      return range; 
     }; 
    } 

    // Now try WebKit's proprietary method 
    else if (typeof doc.caretRangeFromPoint != "undefined") { 
     return function(x, y) { 
      return doc.caretRangeFromPoint(x, y); 
     }; 
    } 

    // Give up 
    else { 
     return function() { return null; }; 
    } 
})(document); 

function mouseEventHandler(e) { 
    if (wordDiv.parentNode) { 
     wordDiv.parentNode.removeChild(wordDiv); 
    } 
    var range = createRangeFromPoint(e.clientX, e.clientY); 
    if (range) { 
     if (range.startContainer.nodeType == 3) { 
      var wordInfo = expandToWord(range.startContainer.data, range.startOffset); 
      if (wordInfo.word) { 
       range.setStart(range.startContainer, wordInfo.start); 
       range.setEnd(range.startContainer, wordInfo.end); 

       var rect = range.getBoundingClientRect(); 

       // Get the difference between client and page coordinates from the event 
       // for positioning the word div 
       var offsetX = e.clientX - e.pageX; 
       var offsetY = e.clientY - e.pageY; 

       wordDiv.style.left = (rect.left + offsetX) + "px"; 
       wordDiv.style.top = (rect.top + offsetY - 20) + "px"; 
       wordDiv.innerHTML = ""; 
       wordDiv.appendChild(document.createTextNode(wordInfo.word)); 

       document.body.appendChild(wordDiv); 
      } 
     } 
    } 
} 

document.onmousemove = mouseEventHandler; 
document.onmouseover = mouseEventHandler; 
document.onmouseout = mouseEventHandler; 
+0

你能解釋這段代碼嗎?我檢測到了插入位置,但是它如何檢測插入符號下的單詞? – Ian

+0

@Ian:它從插入位置得到的範圍有一個文本節點和節點文本內的偏移量的引用,從中可以使用示例中的expandToWord()函數將其推斷爲單詞。 –