Find custom items that start with the specified prefix

I have a bunch of Custom Elements that start with 'food-cta-'. I am looking for a way in JavaScript / jQuery to be able to select these elements. This is similar to how I can use $('*[class^="food-cta-"]') to select all classes starting with food-cta- . Can I search for items starting with "food-cta -"?

Please note that I will enter this search into the page, so I will not have access to Angular.

Example custom elements:

  • <food-cta-download>
  • <food-cta-external>
  • <food-cta-internal>

EDIT: The code I'm looking at looks like this:

 <food-cta-download type="primary" description="Download Recipe"> <img src=""> <h2></h2> <p></p> </food-cta-download> 

The application uses AngularJS to create custom elements, which I think are called directives.

+5
source share
4 answers

You can use XPath with expression

  //*[starts-with(name(),'food-cta-')] 

Where

  • //* is a wildcard for all nodes
  • starts-with() - this is an XPath function for checking the line starts with some value
  • name() gets the name QName (node)
  • and 'food-cta-' - search query

Go to document.evaluate and you will get an XPathResult that will give you the nodes that were mapped.

 var result = document.evaluate( "//*[starts-with(name(),'food-cta-')]", document, null, XPathResult.ANY_TYPE, null ); 

Note that you can use any node as the root, you do not need to use document . Thus, you can, for example, replace document with some div:

 var container = document.getElementById("#container"); var result = document.evaluate( "//*[starts-with(name(),'food-cta-')]", container, null, XPathResult.ANY_TYPE, null ); 

Demo

 let result = document.evaluate( "//*[starts-with(name(),'food-cta-')]", document, null, XPathResult.ANY_TYPE, null ); let nodes = []; let anode = null; while( (anode = result.iterateNext()) ){ nodes.push( anode.nodeName ); } console.log(nodes); 
 <div id="container"> <br> <food-cta-download type="primary" description="Download Recipe"> <img src=""> <h2></h2> <p></p> </food-cta-download> <span>Some span</span> <food-cta-something> <img src=""> <h2></h2> <p></p> </food-cta-something> <div>In between <food-cta-sub> <img src=""> <h2></h2> <p></p> </food-cta-sub> </div> <food-cta-hello> <img src=""> </food-cta-hello> <food-cta-whattt> </food-cta-whattt> </div> 
+1
source

You probably just need to go to the elements in question and check if their tagName begins with a given line ...

 var myPrefix = "mycustom-thing-"; $("body").children().each(function() { if (this.tagName.substr(0, myPrefix.length).toLowerCase() == myPrefix) { console.log(this.innerHTML); // or what ever } }) 

https://jsfiddle.net/svArtist/duLo2d0z/

EDITOR: Included for effectiveness:

If you can predict where the elements will be, you can, of course, indicate this circumstance. In my example, these elements were direct children of the body , so I could use .children() to get them. It will not go through lower levels.

Reduce the need for workarounds by:

Start at the lowest level ( $("#specific-id") , not $("body") )

If all elements are found as direct children of the container:

  • Use $.children() in the container to get only immediate children

Else

  • Use $.find("*")

If you can say something about the containing context, filter this

For example $("#specific-id").find(".certain-container-class .child-class *")

0
source

Try it.

 let customElements = $('*') .filter((index,element) => /FOOD-CTI-/.test(element.tagName)); 

Note. .tagName should return the result in upper case. This should give you a jQuery object for the elements you want. However, this will go through the entire DOM. It will be slow.

It uses the "all selector" .

Caution: the "all" or "universal" selector works very slowly, unless it is used on its own.

You can cross less than the whole house by specifying something like $("body *") . You don’t know where you placed your custom elements and where they are allowed.

Aside, I would not use custom elements, microformats are the best idea, at least for now, they are also better supported, and they are less likely to change.

0
source

Why not extend your jquery selector ?

 $(':tag(^=food-cta-)') 

It would be possible with the following implementation:

 $.expr[':'].tag = function tag(element, index, match) { // prepare dummy attribute // avoid string processing when possible by using element.localName // instead of element.tagName.toLowerCase() tag.$.attr('data-tag', element.localName || element.tagName.toLowerCase()); // in :tag(`pattern`), match[3] = `pattern` var pattern = tag.re.exec(match[3]); // [data-tag`m`="`pattern`"] var selector = '[data-tag' + (pattern[1] || '') + '="' + pattern[2] + '"]'; // test if custom tag selector matches element // using dummy attribute polyfill return tag.$.is(selector); }; // dummy element to run attribute selectors on $.expr[':'].tag.$ = $('<div/>'); // cache RegExp for parsing ":tag(m=pattern)" $.expr[':'].tag.re = /^(?:([~\|\^\$\*])?=)?(.*)$/; // some tests console.log('^=food-cta-', $(':tag(^=food-cta-)').toArray()); console.log('*=cta-s', $(':tag(*=cta-s)').toArray()); console.log('food-cta-hello', $(':tag(food-cta-hello)').toArray()); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="container"> <br> <food-cta-download type="primary" description="Download Recipe"> <img src=""> <h2></h2> <p></p> </food-cta-download> <span>Some span</span> <food-cta-something> <img src=""> <h2></h2> <p></p> </food-cta-something> <div>In between <food-cta-sub> <img src=""> <h2></h2> <p></p> </food-cta-sub> </div> <food-cta-hello> <img src=""> </food-cta-hello> <food-cta-whattt> </food-cta-whattt> </div> 

This supports a pseudo-CSS style attribute selector with the syntax:

 :tag(m=pattern) 

Or simply

 :tag(pattern) 

where m is ~,|,^,$,* , and pattern is your tag.

0
source

All Articles