JavaScript找到之间的元素

时间:2012-11-13 19:01:36

标签: javascript events

我正在寻找最精彩的主意。重点是效率 - 让我们试着避免一堆循环=)

没有图书馆。这是一个纯JS天才的练习。如果他们完成了这个,可以随意引用库中的函数。不需要对糟糕的旧浏览器(即:IE)进行回退。

设置

我正在尝试创建事件委托。我将事件侦听器绑定到此元素中发生的每个事件类型的容器元素(上下文)(单击,鼠标中等)。监听器引用一个函数,我们称之为“路由”。

有一个对象,单独创建,看起来像这样(例子):

myarr['click']['.myclass'] = functionReference1;
myarr['click']['#myid'] = functionReference2;
myarr['click']['div>a'] = functionReference3;

route需要event.type(此处为“点击”)并转到myarr并获取所有click条记录。 route然后遍历每个选择键并将其与event.target匹配。如果匹配,则调用函数引用,如果愿意,则调用callback

这一切都很好。相当快速,直截了当。

问题

event.target可能是与选择键匹配的元素的子元素。我正在寻找疯狂平滑的伏都教黑魔法,以确定父母是否在我们的上下文元素和event.target之间。优选地,一些本机浏览器功能。

理想,例如,我可以按照

的方式做点什么

context.querySelectorAll(key + " " + event.target);

但很明显,据我所知,我无法将对象传递给querySelectorAll。

已尝试的内容

尝试了两种方法。两个都工作。两者都不漂亮。

1)

循环遍历event.target.parentNode,直到找到匹配项。这个手提包可以做到,但它在我现有的循环中创建了一个循环。当页面上有多个选择键和许多元素时,开始变慢。

if (event['target'].matchesSelector(key)) {
    //do callback
} else {
    var et = event['target'];
    while (et['parentNode'] !== null and et['parentNode'] !== this) {
        et = et['parentNode'];
        if (et.matchesSelector(key)) {
            //do callback
            break;
        }
    }
}

2)

使用范围。我为这个问题感到自豪,但它有同样的多循环问题。没有过多地测试性能,但是这里发生了很多事情,如果有很多元素匹配选择键,这可能会损害效率。

if (event['target'].matchesSelector(key)){
    //do callback
} else {
    var range2 = document.createRange();
    range2.selectNode(event.target);
    var range = document.createRange();         
    var allthese = document.querySelectorAll(key)
    for (var i = 0; i < allthese.length; i++){
        range.selectNode(allthese[i]);
        if (range2.compareBoundaryPoints(range2.START_TO_START, range) && range2.compareBoundaryPoints(range2.END_TO_END, range) <= 0){
            //do callback
            break;
        }
    }
}

MAGIC VOODOO - 找我一些,当我再次拥有代表时,我会创造一笔巨额赏金。

2 个答案:

答案 0 :(得分:3)

也许你应该试试这个:

event['target'].matchesSelector(key) || event['target'].matchesSelector(key + ' *')

这里我的第二个条件是检查目标是否是键选择器的后代

正如您在此JSFIDDLE中所看到的(仅限webkit中的小提琴作品(仅限Chrome)浏览器)使用父选择器匹配子/后代

PS:如果您还需要与实际键匹配的元素,此方法将不起作用,但在您的问题中,您说“疯狂平滑巫毒黑魔法,以确定该父级是否在我们的上下文元素和event.target之间” ,所以我想你不需要实际的元素

答案 1 :(得分:1)

这个怎么样:

        if (event['target'].matchesSelector(key)) {
           //do callback
         } else {
            var allthese = document.querySelectorAll(key) //this array has order
           //use  "binary search" here to improve perfomance.
            for (var i = 0; i < allthese.length; i++){
                if(event['target'].compareDocumentPosition(allthese[i])&&DOCUMENT_POSITION_CONTAINS){
                    //do callback
                }
            }
        }
     }

您可以使用二进制搜索之类的算法来提高性能(所有这些都是有序数组)。

compareDocumentPosition的返回值为:

  • DOCUMENT_POSITION_DISCONNECTED 1
  • DOCUMENT_POSITION_PRECEDING 2
  • DOCUMENT_POSITION_FOLLOWING 4
  • DOCUMENT_POSITION_CONTAINS 8
  • DOCUMENT_POSITION_CONTAINED_BY 16
  • DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32

因此,您可以使用搜索算法搜索该数组“document.querySelectorAll(key)”。