2011-05-19 79 views
4

在Javascript中,我想確定一個元素,比如A元素是否存在於給定範圍/ textRange內。目的是確定用戶的當前選擇是否包含鏈接。我正在構建一個富文本編輯器控件。如何知道在選擇中是否存在鏈接元素

範圍對象具有commonAncestorContainer(W3C)或parentElement()(Microsoft)方法,該方法返回範圍中所有元素的最接近的通用響應者。但是,查看A元素的元素將不起作用,因爲此公共祖先可能還包含不在該範圍內的元素,因爲該範圍可以通過父項的一部分開始或結束。

你會怎麼做到這一點?

回答

3

我結束了這樣一個解決方案去:

 var findinselection = function(tagname, container) { 
      var 
       i, len, el, 
       rng = getrange(), 
       comprng, 
       selparent; 
      if (rng) { 
       selparent = rng.commonAncestorContainer || rng.parentElement(); 
       // Look for an element *around* the selected range 
       for (el = selparent; el !== container; el = el.parentNode) { 
        if (el.tagName && el.tagName.toLowerCase() === tagname) { 
         return el; 
        } 
       } 
       // Look for an element *within* the selected range 
       if (!rng.collapsed && (rng.text === undefined || rng.text) && 
        selparent.getElementsByTagName) { 
        el = selparent.getElementsByTagName(tagname); 
        comprng = document.createRange ? 
         document.createRange() : document.body.createTextRange(); 
        for (i = 0, len = el.length; i < len; i++) { 

         // determine if element el[i] is within the range 
         if (document.createRange) { // w3c 
          comprng.selectNodeContents(el[i]); 
          if (rng.compareBoundaryPoints(Range.END_TO_START, comprng) < 0 && 
           rng.compareBoundaryPoints(Range.START_TO_END, comprng) > 0) { 
           return el[i]; 
          } 
         } 
         else { // microsoft 
          comprng.moveToElementText(el[i]); 
          if (rng.compareEndPoints("StartToEnd", comprng) < 0 && 
           rng.compareEndPoints("EndToStart", comprng) > 0) { 
           return el[i]; 
          } 
         } 
        } 
       } 
      } 
     }; 

凡getrange()是我的另一個函數來獲取當前選擇的範圍對象。

要使用,這樣稱呼它

var link = findselection('a', editor); 

如果編輯器是CONTENTEDITABLE元素,或者在iframe中的designMode身體。

+0

這對我來說很好。這幾乎和我在這裏所做的一樣:http://stackoverflow.com/questions/5801347/how-to-get-selection-inside-a-div-using-jquery-javascript/5801903#5801903 – 2011-06-06 00:06:27

5

selection.containsNode怎麼樣? https://developer.mozilla.org/en/DOM/Selection/containsNode

類似:

var selection = window.getSelection(); 
var range = selection.getRangeAt(0); 
var result = $('a', range.commonAncestorContainer).filter(function() { 
    return selection.containsNode(this); 
}); 
console.log(result); 
+0

這是好事,但需要jQuery和韓元不適用於任何版本的IE。不知道WebKit有多久'containsNode()',但目前的版本支持它。 – 2011-05-19 09:24:19

+0

containsNode()看起來很完美,謝謝,但不是跨瀏覽器。現在我只需要一個與微軟相當的軟件(也許是舊版Chrome/Safari的東西) – thomasrutter 2011-05-19 10:10:01

+0

我找不到任何與containsNode()相同的Microsoft(或Opera?),所以我將不得不使用其他解決方案。目前,這是一個比較混亂的涉及compareEndPoints/compareBoundaryPoints ... – thomasrutter 2011-05-20 04:07:31

2

這是一個位在流浪漢做跨瀏覽器的痛苦。你可以使用我的Rangy庫,這可能是矯枉過正只是爲了這個任務,但確實使它更直接,並在所有主流瀏覽器工作。以下代碼假定只有一個範圍選擇:

var sel = rangy.getSelection(); 
if (sel.rangeCount) { 
    var range = sel.getRangeAt(0); 
    var links = range.getNodes([1], function(node) { 
     return node.tagName.toLowerCase() == "a" && range.containsNode(node); 
    }); 
} 
+0

感謝您指出你的rangy圖書館。我的話,這是巨大的! – thomasrutter 2011-05-20 00:26:30

+0

@thomasrutter:是的,它比我想要的大一點,我認爲它會讓人們失望。我會盡量減少它,也許會更加積極地壓縮它,但是對我來說並沒有太大的浪費。 – 2011-05-20 08:30:36

+0

我一直在研究選擇和範圍的東西連續2天,嘗試做類似於cssClassApplier模塊的東西...感謝您的鏈接,這個庫真的很有幫助。 – 2012-05-08 19:16:49

0

我使用這個代碼與IE/Chrome瀏覽器/ FF工作:(我用它來選擇行< TR>在表格中)

// yourLink is the DOM element you want to check 
var selection = window.getSelection().getRangeAt(0) 
var node = document.createRange() 
node.selectNode(yourLink) 
var s2s = selection.compareBoundaryPoints(Range.START_TO_END, node) 
var s2e = selection.compareBoundaryPoints(Range.START_TO_START, node) 
var e2s = selection.compareBoundaryPoints(Range.END_TO_START, node) 
var e2e = selection.compareBoundaryPoints(Range.END_TO_END, node) 
if ((s2s != s2e) || (e2s != e2e) || (s2s!=e2e)) 
    console.log("your node is inside selection")