2011-05-19 82 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")