2009-09-27 90 views
4

我想獲取用戶突出顯示區域中的所有元素。問題是,當元素位於樹的不同部分時,我不知道如何遍歷DOM的不同部分。到目前爲止,我的代碼只能從選擇範圍的startContainer中獲取元素。我需要某種遞歸嗎?這裏是我的代碼:如何獲取突出顯示的所有元素

getSelectedElementTags:function() 
{ 
    var range, sel, container; 
    sel = content.window.getSelection(); 
    if (sel.getRangeAt) 
    { 
     if (sel.rangeCount > 0) 
     { 
      range = sel.getRangeAt(0);    
     } 
    } 
    else 
    {  
     range = content.window.createRange(); 
     range.setStart(sel.anchorNode, sel.anchorOffset); 
     range.setEnd(sel.focusNode, sel.focusOffset); 
     alert("range created"); 
    } 


    if (range) 
    { 
     container = range["startContainer"]; 
     var elms = container.parentNode.getElementsByTagName("*");   
     elmlist = "parent: "+container.parentNode.tagName + " (" + elms.length + ")\n"; 
     for (i in elms) 
     { 
      if (elms[i].tagName != null) 
      { 
       elmlist += elms[i].tagName+"\n"; 
      } 
     } 

     alert(elmlist); 
    } 
}, 
+0

你可以使用jQuery嗎?哪些瀏覽器必須工作(請不要全部說明,因爲我懷疑支持Netscape 4)。 – 2009-09-27 05:33:55

+0

只是Firefox,因爲這是一個擴展。 – 2009-09-27 06:36:03

回答

16

你可以使用document.createTreeWalker使用TreeWalker。下面是一個例子。它列出了部分或全部選定的所有元素。您可以通過修改傳遞給document.createTreeWalker的參數來輕鬆更改行爲。

請注意,在Firefox中,您不需要檢查是否存在選擇的getRangeAt方法。此檢查僅適用於較舊版本的WebKit。另外,IE < 9不支持TreeWalker或Range,因此以下內容在這些瀏覽器中不起作用。

編輯根據下面的註釋修復。

function rangeIntersectsNode(range, node) { 
    var nodeRange; 
    if (range.intersectsNode) { 
     return range.intersectsNode(node); 
    } else { 
     nodeRange = node.ownerDocument.createRange(); 
     try { 
      nodeRange.selectNode(node); 
     } catch (e) { 
      nodeRange.selectNodeContents(node); 
     } 

     return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 && 
      range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1; 
    } 
} 

function getSelectedElementTags(win) { 
    var range, sel, elmlist, treeWalker, containerElement; 
    sel = win.getSelection(); 
    if (sel.rangeCount > 0) { 
     range = sel.getRangeAt(0); 
    } 

    if (range) { 
     containerElement = range.commonAncestorContainer; 
     if (containerElement.nodeType != 1) { 
      containerElement = containerElement.parentNode; 
     } 

     treeWalker = win.document.createTreeWalker(
      containerElement, 
      NodeFilter.SHOW_ELEMENT, 
      function(node) { return rangeIntersectsNode(range, node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; }, 
      false 
     ); 

     elmlist = [treeWalker.currentNode]; 
     while (treeWalker.nextNode()) { 
      elmlist.push(treeWalker.currentNode); 
     } 

     console.log(elmlist); 
    } 
} 

<input type="button" onclick="getSelectedElementTags(window)" value="Get selected elements"> 
+0

非常感謝Tim,它的效果非常好。只有一個小問題...當一個元素被選中時,列表是空的。 – 2009-09-27 17:43:49

+0

不知道這是否是最好的方法,但我通過測試來解決問題,如果startContainer和endContainer的範圍相同。如果它們是相同的,我會跳過treewalker並獲取startContainer的parentNode。 – 2009-09-27 19:14:41

+0

你是對的。有兩個問題:第一,我忘了將第一個節點包含在TreeWalker的列表中,第二,如果整個選擇包含在單個文本節點中,則不會返回任何元素。兩者現在都在解決。 – 2009-09-27 20:43:41