W3C home > Mailing lists > Public > www-style@w3.org > October 2008

Re: Selectors in jQuery

From: John Resig <jresig@mozilla.com>
Date: Thu, 9 Oct 2008 07:58:28 -0700 (PDT)
To: Daniel Glazman <daniel.glazman@disruptive-innovations.com>
Cc: www-style@w3.org
Message-ID: <13867588.252681223564308747.JavaMail.root@cm-mail02.mozilla.org>

Hi Daniel -

Thanks for taking the time to look these over. Comments below.

> missing
> -------
> :nth-last-child()
> :nth-of-type()
> :nth-last-of-type()
> :first-of-type
> :last-of-type
> :only-of-type
> :lang()
> :root

I should note that all of these are selectors that are possible to implement but we opt not to (root might make a comeback, since jQuery is seeing a lot of use in XML documents - but it's still very rare that someone doesn't know the name of the root element).

> :link
> :visited
> :active
> :hover
> :focus
> :target

These are much harder to implement as we either A) Don't have enough information provided by the browser to implement them properly or B) Would have to introduce undue catches to make sure they work (like attaching a global mouseover/mouseout handler to make :hover works).

> A few observations:
> 
> - :even is redundant with :nth-child(even)
> - :odd is redundant with :nth-child(odd)
> - :gt(n) and :lt(n) are redundant with combinations of :not()
>    and :nth-child() but are far easier to manage if n is high

There is also :first and :last - and no they are not equivalent to using nth-child. They are scoped to the entire matched selector - for example doing 'div:first' would find the first div on the page - not all divs that are the first child element.

This might be much harder to implement in current CSS selector engines, but not impossible.

> - :header is just a html-centric convenience for a group of
>    selectors

Sure, but it helps to make things like the construction of TOCs very simple.

  #body > :header

Previously one would have to write:

  #body > h1, #body > h2, #body > h3, #body > h4, #body > h5, #body > h6

> - :animated is a weird thing since it relies on currently executed
>    scripts or CSS transitions, making a rule dependent on the
> computed
>    value of a property

I wouldn't worry about this one too much - although if the CSS Transforms spec gets closer to fruition perhaps it would be a larger concern.

> - :contains() was included in the old CSS 3 Selectors draft

Correct. I think we borrowed it from there and it's been relatively useful to us.

> - :has() is an old request of the community

Hugely useful - definitely one of the most useful extensions we include. It makes the construction of menus an absolute breeze.

  ul:has(ul)

> - :parent is redundant with :not(:empty)

Yep.

> - :hidden and :visible can also be dependant on the computed
>    value of CSS properties (BTW, display and/or visibility ?)

Correct (and we check both display and visibility). It seems like this would be an addition that would be better-suited to a specific API (like the Selectors API).

> - the last additions are just shortcuts for lightly more complex
>    selectors

Not so in all cases.

These are all shortcuts for [type=FOO]
> :text,
> :password,
> :radio,
> :checkbox,
> :submit,
> :image,
> :reset,
> :file 

But these are more complicated:

> :input,

This is equivalent to (textarea, input, select, button)
 
> :button

And this is equivalent to ([type=button], button)

> Of course, pseudo-elements are not here, but there's a :selected
> pseudo-class.

I should note that :selected, in our case, refers to a selected option in a <select> element.

I should also note that we have a few other custom selectors here, as well:

[NAME!=VALUE] - We take to be equivalent to :not([NAME=VALUE]). There's been a little disagreement between frameworks since this will match elements that, not only, don't match the value but also don't have the attribute. It's possible that it might be changed to mean: [NAME]:not([NAME=VALUE]).

:not(a#id) - Complex selectors in :not().

:not(div > p) - Full selectors in :not().

:not(div, p, a) - Multiple selectors in :not(). In all of these cases they could be treated as a simple set operation. Take the current set of match elements, find the set of elements located within the :not(...) expression, and subtract the two from each other.

I don't remember if it's made explicitly clear in the CSS spec but we allow :not(:nth-child(2)) (parentheses within parentheses).

Right now we're looking at making two additions to the selector engine:

  div > (a, p)

Allowing for grouping of queries together (the above would be equivalent to: div > a, div > p). It's possible that this might have another syntax, for example :and() as a complement to :not().

  div > :not(a, p)
  div > :and(a, p)

And allowing jQuery methods to be called as if they were selectors. We support a number of directional methods, for example:

  $("p").parents("div")

The above finds all divs that have a p ancestor. We would want to make this accessible from the jQuery selector engine (syntax is still up in the air):

  p.parents(div)

> John, is there a way we could make jQuery's list of accepted
> selectors
> converge with CSS 3 Selectors ?

It's doubtful that jQuery selectors will reduce down to the level of CSS 3 Selectors. We would absolutely be open to seeing some of these become standardized, where appropriate.

> Does the Selectors API help here ?

Only to a point. We have to fall back in a number of cases in order to make selectors work properly. There's one case, that I know about, where we currently struggle: [selected]. Traditionally we've inspected the .selected expando of DOM elements to verify the attributes existence (where appropriate) but the Selectors API only checks DOM attributes. This means that cases like:

  <select><option>I should be selected by default.</option></select>

fail because not selected attribute exists. (Although, in this case, the confusingly-named :checked works in CSS - :selected works in jQuery.)

I want to bring up a couple other points, namely that there's a lot of standardization starting to occur within the JavaScript-based CSS selector engine space. I've been working on a new selector engine, named Sizzle, which will become the new default engine of jQuery. I'm working with the MochiKit and Prototype projects, as well, to standardize on the same code base. Thus any features included in this implementation would become de facto standards.

That being said there are already two de facto standards (even without official standardization): :has() and [NAME!=VALUE]. Virtually all frameworks support them in some capacity. If there was a good place to start with proper standardization, this would be it.

--John
Received on Thursday, 9 October 2008 14:59:10 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:55:15 GMT