Выберите теги, которые начинаются с "x-" в jQuery

Как я могу выбрать узлы, которые начинаются с "x-" имя тега, вот пример иерархического дерева DOM:

<div>
  <x-tab>
    <div></div>
    <div>
      <x-map></x-map>
    </div>
  </x-tab>
</div>
<x-footer></x-footer>

JQuery не позволяет мне запрашивать $('x-*')Есть ли способ, которым я мог бы достичь этого?

9 ответов

Решение

Нет никакого собственного способа сделать это, у него худшая производительность, так что просто сделайте это сами.

Пример:

var results = $("div").find("*").filter(function(){
    return /^x\-/i.test(this.nodeName);
});

Полный пример:

http://jsfiddle.net/6b8YY/3/

Примечания: (Обновлено, см. Комментарии)

Если вам интересно, почему я использую этот способ для проверки имени тега, см.:
JavaScript: поиск без учета регистра
и увидеть комментарии.

Кроме того, если вам интересно find метод вместо добавления к селектору, поскольку селекторы сопоставляются справа, а не слева, может быть лучше отделить селектор. Я также мог бы сделать это:
$("*", $("div")), Желательно, хотя вместо того, чтобы просто div добавить идентификатор или что-то к нему, чтобы родительское совпадение было быстрым.

В комментариях вы найдете доказательство того, что это не быстрее. Я полагаю, что это относится к очень простым документам, где стоимость создания объекта jQuery выше, чем стоимость поиска всех элементов DOM. В реалистичных размерах страниц, хотя это не будет иметь место.

Обновить:

Мне также очень нравится ответ Тейфи. Вы можете сделать это в одном месте, а затем использовать его везде. Например, позвольте мне смешать мой путь с его:

// In some shared libraries location:
$.extend($.expr[':'], {
    x : function(e) {
            return /^x\-/i.test(this.nodeName);
    }
});

// Then you can use it like:
$(function(){
    // One way
    var results = $("div").find(":x");

    // But even nicer, you can mix with other selectors
    //    Say you want to get <a> tags directly inside x-* tags inside <section>
    var anchors = $("section :x > a");

    // Another example to show the power, say using a class name with it:
    var highlightedResults = $(":x.highlight");
    // Note I made the CSS class right most to be matched first for speed
});

Это тот же удар по производительности, но более удобный API.

Ниже просто работает нормально. Хотя я не уверен в производительности, так как использую регулярные выражения.

$('body *').filter(function(){
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

Рабочая скрипка

PS: в приведенном выше примере, я рассматриваю body пометить как родительский элемент.

ОБНОВЛЕНИЕ:

После проверки сообщения Мохамеда Мелиги кажется, что регулярное выражение быстрее, чем манипулирование строками в этом состоянии. и это может стать более быстрым (или таким же), если мы используем find, Что-то вроде этого:

$('body').find('*').filter(function(){
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

тест jsperf

ОБНОВЛЕНИЕ 2:

Если вы хотите искать в документе, то вы можете сделать ниже, что является самым быстрым:

$(Array.prototype.slice.call(document.all)).filter(function () {
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

тест jsperf

Это может быть неэффективно, но рассмотрите это как последний вариант, если вы не получили никакого ответа.
Попробуйте добавить пользовательский атрибут к этим тегам. Я имею в виду, когда вы добавляете тег, например, для. <x-tag>Добавьте пользовательский атрибут с ним и присвойте ему то же значение, что и тег, чтобы HTML выглядел следующим образом <x-tag CustAttr="x-tag">,
Теперь, чтобы получить теги, начинающиеся с x-, вы можете использовать следующий код jQuery:

$("[CustAttr^=x-]")

и вы получите все теги, которые начинаются с x-

Пользовательский селектор jquery

jQuery(function($) {
    $.extend($.expr[':'], {
        X : function(e) {
            return /^x-/i.test(e.tagName);
        }
    });
});

чем использовать $(":X") или же $("*:X") выбрать ваши узлы.

Хотя это не дает прямого ответа на вопрос, оно может дать решение, "определив" теги в селекторе, вы можете получить все эти типы?

$('x-tab, x-map, x-footer')

Обходной путь: если вы хотите эту вещь более одного раза, возможно, будет гораздо эффективнее добавить класс, основанный на теге, что вы делаете в начале только один раз, а затем отфильтруете для тега тривиальный способ.

Я имею в виду,

function addTagMarks() {
    // call when the document is ready, or when you have new tags

    var prefix = "tag--"; // choose a prefix that avoids collision
    var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already

    newbies.each(function() {
        var tagName = $(this).prop("tagName").toLowerCase();
        $(this).addClass(prefix + tagName);
    });

}

После этого вы можете сделать $("[class^='tag- x-']") или то же самое с querySelectorAll, и это будет достаточно быстро.

Посмотрите, работает ли это!

function getXNodes() {
  var regex = /x-/, i = 0, totalnodes = [];
  while (i !== document.all.length) {
    if (regex.test(document.all[i].nodeName)) {
      totalnodes.push(document.all[i]);
    }
    i++;
  }
  return totalnodes;
}

Демо Фиддл

var i=0;
for(i=0; i< document.all.length; i++){
    if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
        $(document.all[i].nodeName.toLowerCase()).addClass('test');
    }
}

Попробуй это

var test = $('[x-]');
if(test)
    alert('eureka!');

В основном селектор jQuery работает как селектор CSS. Прочитайте API выбора jQuery здесь.

Другие вопросы по тегам