Select tags that starts with “x-” in jQuery

徘徊边缘 提交于 2019-12-30 08:12:42

问题


How can I select nodes that begin with a "x-" tag name, here is an hierarchy DOM tree example:

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

jQuery does not allow me to query $('x-*'), is there any way that I could achieve this?


回答1:


There is no native way to do this, it has worst performance, so, just do it yourself.

Example:

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

Full example:

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

Notes: (Updated, see comments)

If you are wondering why I use this way for checking tag name, see:
JavaScript: case-insensitive search
and see comments as well.

Also, if you are wondering about the find method instead of adding to selector, since selectors are matched from right not from left, it may be better to separate the selector. I could also do this:
$("*", $("div")). Preferably though instead of just div add an ID or something to it so that parent match is quick.

In the comments you'll find a proof that it's not faster. This applies to very simple documents though I believe, where the cost of creating a jQuery object is higher than the cost of searching all DOM elements. In realistic page sizes though this will not be the case.

Update:

I also really like Teifi's answer. You can do it in one place and then reuse it everywhere. For example, let me mix my way with his:

// 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
});

It's the same performance hit, but more convenient API.




回答2:


The below is just working fine. Though I am not sure about performance as I am using regex.

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

Working fiddle

PS: In above sample, I am considering body tag as parent element.

UPDATE :

After checking Mohamed Meligy's post, It seems regex is faster than string manipulation in this condition. and It could become more faster (or same) if we use find. Something like this:

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

jsperf test

UPDATE 2:

If you want to search in document then you can do the below which is fastest:

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

jsperf test




回答3:


It might not be efficient, but consider it as a last option if you do not get any answer.
Try adding a custom attribute to these tags. What i mean is when you add a tag for eg. <x-tag>, add a custom attribute with it and assign it the same value as the tag, so the html looks like <x-tag CustAttr="x-tag">.
Now to get tags starting with x-, you can use the following jQuery code:

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

and you will get all the tags that start with x-




回答4:


custom jquery selector

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

than, use $(":X") or $("*:X") to select your nodes.




回答5:


Although this does not answer the question directly it could provide a solution, by "defining" the tags in the selector you can get all of that type?

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



回答6:


Workaround: if you want this thing more than once, it might be a lot more efficient to add a class based on the tag - which you only do once at the beginning, and then you filter for the tag the trivial way.

What I mean is,

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);
    });

}

After this, you can do a $("[class^='tag--x-']") or the same thing with querySelectorAll and it will be reasonably fast.




回答7:


See if this works!

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;
}



回答8:


Demo Fiddle

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');
    }
}



回答9:


Try this

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

Basically jQuery selector works like CSS selector. Read jQuery selector API here.



来源:https://stackoverflow.com/questions/17140783/select-tags-that-starts-with-x-in-jquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!