Tuesday, May 21, 2024
 Popular · Latest · Hot · Upcoming
168
rated 0 times [  174] [ 6]  / answers: 1 / hits: 41543  / 13 Years ago, fri, july 22, 2011, 12:00:00

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?


More From » javascript

 Answers
9

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()


[#91058] Thursday, July 21, 2011, 13 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
reecep

Total Points: 141
Total Questions: 95
Total Answers: 113

Location: Finland
Member since Mon, Nov 8, 2021
3 Years ago
;