1

I have seen the questions of similar title, but they are not exactly the same.

First, I am using YUI (3.2.0 for compatibility with Liferay 6.0).

I already have a Node reference. My goal would be to get the first child of that Node which matches a given CSS selector. At first, I was doing this:

...
parse: function(node) {
    var title = node.one('>span, >div, >a, >h1');
    ...
},
...

And this works in Firefox, Chrome and IE 9+. However, we must support IE 8. So I dig in and find the w3c reference stating:

A child selector is made up of two or more selectors separated by ">"

This seems to indicate that, per the spec, a parent is required, even though in practice that doesn't seem to be the case. So I search a little more and see that jQuery actually mentions that this specific case is being deprecated:

Note: The $("> elem", context) selector will be deprecated in a future release. Its usage is thus discouraged in lieu of using alternative selectors.

I cannot find explicit mention of this case in the YUI documentation, but I still don't think it would be safe to use it (and it's not supported in IE8 anyway). I tried a bunch of things including using *>span, *>div, ..., *:first-child+span, ..., but they did not work. So what I am left with is this:

var title = node.get('children').filter('>span, >div, >a, >h1').item(0);

But this seems inelegant and inefficient as the code behind it would have a lot of loops (since filter will not short circuit and all I want is the first match). Anyone have a better suggestion?

Community
  • 1
  • 1
Lucas
  • 14,227
  • 9
  • 74
  • 124
  • [Selectors level 3](http://www.w3.org/TR/css3-selectors) has a clearer description of the grammar; the child selector, which is a combinator, requires having a selector on each side in order to say "this is a child of that", hence the "two or more" bit. Selector libraries employ a syntax that is currently non-standard. However, [Selectors API 2](http://www.w3.org/TR/selectors-api2/#relative-selector-string) is looking to allow a combinator at the start of a selector string, calling it a relative selector string. – BoltClock Dec 18 '12 at 05:40
  • @BoltClock, great references. Any idea which browsers support which selector levels? A quick google doesn't seem to turn much up... – Lucas Dec 18 '12 at 18:10
  • @BoltClock, it turns out IE8 does work, and your links to Selectors API forced me to reconfirm. [Here is the jsFiddle](http://jsfiddle.net/GJTAZ/6/). If you would like to write something up, i would be happy to give you the answer. – Lucas Dec 18 '12 at 18:34
  • The latest versions of all browsers currently support Selectors 3 and Selectors API 1. Some may support bits and pieces of Selectors 4 and API 2 as hidden gems... as you've found. – BoltClock Dec 19 '12 at 02:20

1 Answers1

2

In this case, maybe it makes sense to take a step back. Currently your requirement is framed as, "match this CSS selector." Can you frame it instead as, "get first child of this node that is a span, a div, an anchor, or an h1" (or something similar?)

If so, ditch the selector engine. Instead, call node.get('children') and then iterate through the resulting NodeList -- your iterator function can simply check to see if the node name is of the right value and short-circuit if so. That should give you solid performance, and should be fairly readable as well.

Evan
  • 680
  • 3
  • 5
  • Good suggestion, that would work in my case as I am just matching tag names. With a good helper method it should behave just fine. On a side note, I just read your book... Submitted one errata (erratum?) as well :) – Lucas Dec 17 '12 at 23:30
  • You could use the NodeList.first() function to search. This function is provided by http://yuilibrary.com/gallery/show/nodelist-extras – John Lindal Dec 18 '12 at 04:02
  • @John, that link says YUI version 3.3, and I am forced to use 3.2.0 as it is provided by Liferay 6.0 which is our current production deployment. – Lucas Dec 18 '12 at 16:33
  • nodelist-extras should work with YUI 3.2, too. YUI 3.3 is simply the latest version with which the module was tested. – John Lindal Dec 19 '12 at 17:53