I'm working on a javascript library, and I use this function to match elements:
$ = function (a) { var x; if (typeof a !== "string" || typeof a === "undefined"){ return a;} //Pick the quickest method for each kind of selector if(a.match(/^#([\w\-]+$)/)) { return document.getElementById(a.split('#')[1]); } else if(a.match(/^([\w\-]+)$/)) { x = document.getElementsByTagName(a); } else { x = document.querySelectorAll(a); } //Return the single object if applicable return (x.length === 1) ? x[0] : x; };
There are occasions where I would want to filter the result of this function, like pick out a div span
, or a #id div
or some other fairly simple selector.
How can I filter these results? Can I create a document fragment, and use the querySelectorAll method on that fragment, or do I have to resort to manual string manipulation?
I only care about modern browsers and IE8+.
If you want to look at the rest of my library, it's here: https://github.com/timw4mail/kis-js
Edit:
To clarify, I want to be able to do something like $_(selector).children(other_selector) and return the children elements matching that selector.
Edit:
So here's my potential solution to the simplest selectors:
tag_reg = /^([\w\-]+)$/; id_reg = /#([\w\-]+$)/; class_reg = /\.([\w\-]+)$/; function _sel_filter(filter, curr_sel) { var i, len = curr_sel.length, matches = []; if(typeof filter !== "string") { return filter; } //Filter by tag if(filter.match(tag_reg)) { for(i=0;i<len;i++) { if(curr_sell[i].tagName.toLowerCase() == filter.toLowerCase()) { matches.push(curr_sel[i]); } } } else if(filter.match(class_reg)) { for(i=0;i<len;i++) { if(curr_sel[i].classList.contains(filter)) { matches.push(curr_sel[i]); } } } else if(filter.match(id_reg)) { return document.getElementById(filter); } else { console.log(filter+" is not a valid filter"); } return (matches.length === 1) ? matches[0] : matches; }
It takes a tag like div
, an id, or a class selector, and returns the matching elements with the curr_sel
argument.
I don't want to have to resort to a full selector engine, so is there a better way?
To retrieve all copies of a specific element, you can simply pass the name of the element as its argument. You can also select elements by other attributes like target or value : // return all elements with target="_blank" document. querySelectorAll("[target=_blank]"); // return all elements with value="red" document.
The querySelectorAll() method in HTML is used to return a collection of an element's child elements that match a specified CSS selector(s), as a static NodeList object. The NodeList object represents a collection of nodes. The nodes can be accessed by index numbers. The index starts at 0.
The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors.
I don't think I get the question right. Why would you want to "filter" the result of querySelectorAll()
which infact, is some kind of a filter itself. If you query for div span
or even better #id div
, those results are already filtered, no ?
However, you can apply Array.prototype.filter
to the static result of querySelectorAll
like follows:
var filter = Array.prototype.filter, result = document.querySelectorAll('div'), filtered = filter.call( result, function( node ) { return !!node.querySelectorAll('span').length; });
That code would first use querySelectorAll()
to query for all <div>
nodes within the document. Afterwards it'll filter for <div>
nodes which contain at least one <span>
. That code doesn't make much sense and is just for demonstrative purposes (just in case some SO member wants to create a donk comment)
update
You can also filter with Element.compareDocumentPosition
. I'll also tell if Elements are disconnected
, following
, preceding
, or contained
. See MDC .compareDocumentPosition()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With