views:

43

answers:

3

I've been trying a few different ways to filter finding of specific nodes within my html.

Here is some example html:

<body>
    <div ui:component="component1"></div>
    <ul ui:component="component2"></ul>
    <article ui:component="component3"></article>
</body>

I've successfully been able to match items by doing a simple filter:

// returns div, ul, article
$('[ui\\:component]').each();

However, when I start filtering it based on a parent node, it starts to fail on me. I've tried:

$('[ui\\:component]', $('body'));   // returns []
$('body').find('[ui\\:component]'); // returns []
$('body').filter('[ui\\:component]'); // returns []
$('body').find('*').filter('[ui\\:component]'); // returns []

What am I doing wrong here? At first I thought it could be the ui namespace, but adding it to the html doc or the body doesn't seem to do anything of significance. Help much appreciated

FULL SOURCE BELOW:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
</head>
<body>
    <div ui:component="component1"></div>
    <ul ui:component="component2"></ul>
    <article ui:component="component3"></article>
</body>
<script type="text/javascript">
$(document).ready(function() {

    // returns div, ul, article
    console.log($('[ui\\:component]'));

    // these all return nada
    console.log($('[ui\\:component]', $('body')));
    console.log($('body').find('[ui\\:component]'));
    console.log($('body').filter('[ui\\:component]'));
    console.log($('body').find('*').filter('[ui\\:component]'));
});
</script>
</html>
A: 

Try <div id="component"></div> instead..

Meke
Not looking to make it an id. I'm looking to assign functionality to specific items based on their ui:component tag.
Daniel Hai
+1  A: 

I'm guessing this is because when you do:

$('[ui\\:component]')

...Sizzle is passing the selector to the browser's document.querySelectorAll() method (when available), effectively bypassing Sizzle.

Whereas when you do .find() or .filter(), Sizzle is being utilized.

So I'd guess that something in the selector is not supported by Sizzle, but is by querySelectorAll(). Perhaps the :.

I think you'll find that this:

document.querySelectorAll('[ui\\:component]').length

and this:

$('[ui\\:component]').length

...will give you similar results

EDIT:

If it helps, a hyphen seems to work fine.

$('body').find('[ui-component]').length

HTML

<ul ui-component="component2"></ul>
patrick dw
+1  A: 

The best way I've found to do this using jQuery is to write a custom selector:

$.expr[':'].nsattr = function(obj, ix, meta) {
    var attr = meta[3];

    return (obj.getAttribute(attr) ? true : false);
};

You can then call this with

$(document.body).find(':nsattr(ui:component)');
$(document.body).children().filter(':nsattr(ui:component)');
$(':nsattr(ui:component)', document.body);

Obviously this is not a neat way of doing this. I suspect this is a bug with jQuery and it might be worth your reporting it as such.

lonesomeday
I'm with you. I filed a bug #7153
Daniel Hai
That looks good, although I'd probably use the native `getAttribute()` instead of creating a jQuery object for each element. You can also make it a little more concise like this: `return !!obj.getAttribute(attr);` instead of the `if()` statement. :o)
patrick dw
@patrick I have changed it to `hasAttribute()` -- good point. This also means I can slim the return right down...
lonesomeday
The `hasAttribute()` method would work, but for the not very surprising fact that [it isn't supported in IE6/7](http://www.quirksmode.org/dom/w3c_core.html#t115). :o(
patrick dw
Gah, had forgotten that `:-(` A ternary is my verbose solution -- I find `!!` hard to read. Thanks, patrick.
lonesomeday
@Daniel, @lonesomeday - Just noting that [this issue is fixed](http://dev.jquery.com/ticket/7153#comment:1) in the [soon to be released `1.4.3`](http://blog.jquery.com/2010/10/10/jquery-1-4-3-release-candidate-1-released/). Tested it against `rc1`, and indeed it is fixed.
patrick dw
Thanks patrick.
Daniel Hai