0

I am trying to figure out how I can get a list of elements from the DOM (top to bottom) containing specific attributes that are prefixed with a given string lets say for the sake of example "monkey" is that string. If any exist.

I had this very loosely put together idea using $.each() and :contains but between the two I see no good coming from it. So I figured I'd come here to pick a few brains.

What I want to do is basically scan my dom when I call to a given function I will end up building up. That will seek elements with attributes that are prefixed with in this case "monkey" think of the data- attribute, and its use. Minus providing a specific selector, and not actually using the data- attribute.

Imagine this HTML

<div monkey-user="bar" monkey-permission="read">
    <span monkey-user="bar" monkey-permission="read">some text</span>
</div>
<div>
    <input type="text" monkey-user="bar" monkey-permission="none">
</div>
<input type="text">
<input type="text">
<input type="text">
<input type="text">

and then this javascript/jquery concept unless something cleaner can be used.

var arr = new Array();
$("*").each(function()
    {
     if($(this).children().length == 0) 
         {
              if($(':contains("monkey-")',this))
              {
                 arr.push($(this));
              }   
         }
 });

The result of arr in this case would be the 3 elements above with monkey- in them otherwise anything else is skipped. also worth noting is user/permission is for the sake of example, in the long run those can be other specific things that will be worked with on a per need basis (those in that case will be similar to working with the data attributes but Im thinking that will be another question for another time less someone wants to throw that in as a bonus.

chris
  • 36,115
  • 52
  • 143
  • 252
  • This doesn't seem like a good idea. Maybe if you describe your actual use for this there is a better approach. – James Montagne Oct 09 '13 at 18:53
  • There is no attribute wildcard selector, therefore anything you do is going to be inefficient. you'll have to loop over every element in the dom, and then loop over every attribute on each of those elements looking for attributes that match. I suggest finding another way of selecting these elements. – Kevin B Oct 09 '13 at 18:53
  • What not actually *use* the `data-` attribute instead of trying to mimick it? – nietonfir Oct 09 '13 at 19:11

1 Answers1

2

You can try this way:

var arr = $("body").find('*').filter(function(){
    var attrs = this.attributes; //get the attributes of the element
    return ($.grep(attrs, function(o){
        return /monkey/.test(o.name); //return the attributes that has name to be matched
    }).length); //return the elements that has at least one of the matched attributes
}).get();
console.log(arr);

Fiddle

But note that these attribute names are not valid for an html element. Consider using data-* attributes instead

If you plan to use data-* then you can use data api(but this will select other data properties set as well which are not attributes of the element)

var arr = $("body").find('*').filter(function(){
    var attrs = Object.keys($(this).data());
    return ($.grep(attrs, function(o){
        return /monkey/.test(o) === true;
    }).length);
}).get();

Fiddle

But these methods can really slow down and are inefficient i would suggest you to add another attribute say data-hasmonkey to all the attributes that has your monkey- attributes. Then you can make an attribute selector more simpler and better: $("[data-hasmonkey]");

PSL
  • 123,204
  • 21
  • 253
  • 243
  • Slowness was and is one of my concerns, as I know Its looping essentially over everything in the DOM to do it. But its for use in proprietary needs for the company I work for, as well as they want it for "organizational" needs.. – chris Oct 09 '13 at 19:35
  • @chris is you know which all element types have a chance of having this attribute then you can atleast filter to look only in those element types rather than a `*`. – PSL Oct 09 '13 at 19:39
  • Unfortunately it could be anything.. from a simple span, to a div, to form elements.. to basically anything you would append within the opening and closing body tag. This is why I needed to come pick some brains on stack.. I can't wrap my head around a sane logic, was hoping someone else might have. I think the idea from the bosses is based on angular.js and seeing how it has `ng-` in its tags to tie things together – chris Oct 09 '13 at 19:41