CSS3 Selectors

Recently, i continued porting the DENG1 CSS parser to ECMAScript 4 (AS2, to be specific), and making it fully compliant to the CSS3 specification. The current AS1 version of the parser already has many CSS3 features implemented, but not all of them (like the nth-child(), nth-last-child(), nth-of-type() and nth-last-of-type() pseudo classes for example, that required a special type of argument that wasn’t supported by the parser yet).

Part of the work was commenting changes in the grammar, to know what was added or changed from the CSS2.1 grammar, and to verify if the existing code fully conforms to the CSS3 grammar.

I figured this might be an interesting read for some of you, so here it is. Disclaimer: Please note that the comments might not be accurate or complete. In doubt, please refer directly to the Selectors module of the CSS3 specification at W3C.

Commented grammar for CSS3 Selectors Module

It is now specified that only one pseudo element is allowed in a selector, and that this pseudo element has to occur as the very last element. Pseudo classes can occur anywhere in a simple selector sequence.

selector
  /* there is at least one sequence of simple selectors */
  /* in a selector and the pseudo-elements occur only */
  /* in the last sequence; only one pseudo-element may */
  /* occur */
  : [ simple_selector_sequence combinator ]*
       simple_selector_sequence [ pseudo_element ]?
  ;

New combinators ~ (indirect adjacent combinator) and * (descendant combinator) have been introduced (the * combinator is not contained in the current CSS3 grammar though).

combinator
  /* combinators can be surrounded by white space */
  : S* [ '+' | '>' | '~' | /* empty */ ] S*
  ;

Typeselectors and the universal selector (*) have an optional namespace prefix now. Both the typeselector and the universal selector are optional.

The grammar for negation is missing in the current CSS3 grammar, it should look similar to the rule for pseudo_class, with a function identifier not() and one or more negation_args as function argument. The grammar is incomplete here. Example: a:not([href]).

simple_selector_sequence
  /* the universal selector is optional */
  : [ type_selector | universal ]?
        [ HASH | 
          class | 
          attrib | 
          pseudo_class | 
          negation ]+ |
    type_selector | universal
  ;

type_selector
  : [ namespace_prefix ]? element_name
  ;

element_name
  : IDENT
  ;

A namespace prefix, if used, needs a preceding @namespace rule, where the namespace prefix is associated with a namespace URL. Let’s assume we want to mix SVG and XHTML markup in the same document. Both SVG and XHTML feature the <a> element. We most likely want the <a> element to appear different in the SVG context (i.e. shape appears with a stroke) than in the XHTML context (text appears underlined).

Using the @namespace rule and namespaced prefixes we can write rules that apply either to SVG’s or to XHTML’s <a> element:

@namespace xhtml url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);
xhtml|a[href] { text-decoration: underlined; }
svg|a[href] { stroke-width: 2px; }
namespace_prefix
  : [ IDENT | '*' ]? '|'
  ;

universal
  : [ namespace_prefix ]? '*'
  ;

class
  : '.' IDENT
  ;

Attribute simple selectors allow an optional namespace prefix for the attribute ident now.

Prefixmatch (^=), suffixmatch ($=) and substringmatch (*=) operators have been introduced.

Example: we want to style <a> elements with the href attribute set to an URL starting with "http://wahlers.com.br" differently than other <a> elements. we are using the prefixmatch operator:

a[href] {
   font-weight: bold;
}
a[href ^= "http://wahlers.com.br"] {
   font-style: italic;
}

All <a> elements with the href attribute set appear bold, <a> elements with a href attribute starting with "http://wahlers.com.br" appear bold and italic.

attrib
  : '[' S* [ namespace_prefix ]? IDENT S*
        [ [ PREFIXMATCH |
            SUFFIXMATCH |
            SUBSTRINGMATCH |
            '=' |
            INCLUDES |
            DASHMATCH ] S* [ IDENT | STRING ] S*
        ]? ']'
  ;

pseudo_class
  /* a pseudo-class is an ident, or a function taking */
  /* an ident or a string or a number or a simple  */
  /* selector (excluding negation and pseudo- */
  /* elements) or a an+b expression for argument */
  : ':' [ IDENT | functional_pseudo ]
  ;

"an+b" expressions have been introduced as argument for functional pseudo classes (select nodes depending on their position). Allowed argument types include string, number, "an+b" expression and negation now, in addition to ident (the only allowed argument type in CSS2.1).

Example: style even and odd rows of a table differently:

tr { background-color: #eee; }
tr:nth-child(2n) { background-color: #ccc; }
functional_pseudo
  : FUNCTION S* [ IDENT | STRING | NUMBER |
      expression | negation_arg ] S* ')'
  ;

expression
  :  [ [ '-' | INTEGER ]? 'n' [ SIGNED_INTEGER ]? ] |
      INTEGER
  ;

negation_arg
  : type_selector |
    universal |
    HASH |
    class |
    attrib |
    pseudo_class
  ;

Pseudo elements are now prefixed by :: (instead of : in CSS2.1) to distinguish between pseudo elements and pseudo classes. For backwards compatibility with CSS2.1 and previous, user agents have to accept the : notation for pseudo elements defined in earlier specs (like :before and :after).

pseudo_element
  : [ ':' ]? ':' IDENT
  ;
Posted in CSS

XForms For The Masses

The FormFaces project team announced their open source ECMAScript XForms solution today. The engine processes XForms entirely on the client side and runs on any ECMAScript and DOM Level 2 powered Webbrowser (Internet Explorer, Mozilla, Opera, Konquerer, Safari and others). All the author has to do is add one JavaScript include to her XHTML/XForms document: <script type="javascript" src="xforms.js"></script>.

Given that the engine lives up to its promise, this release may mark the end of the UGO Project as we know it today. The goal would have been achieved and developers can finally start writing sophisticated forms applications without the hassle of messing with error-prone, homegrown JavaScript to overcome the limits of current HTML forms implementations.

FormFaces is currently in alpha and scheduled to be released in April.

My Search Engine Friendly Flash Site

I am currently working on a unobtrusive method to deploy Flash on top of XHTML websites. The method is based on a simplified version of the sIFR (Scalable Inman Flash Replacement) JavaScript code. It solves several problems Flash developers have to deal with when deploying Flash:

  • Search Engine friendly
  • Permalink friendly
  • Unobtrusive Flash detection/integration
  • <embed> issue in XHTML
  • 100% height issue in XHTML

The main idea is to show a Flash version of the site if and only if the user has JavaScript, CSS and Flash enabled in her browser, and show the original XHTML document otherwise. If the user’s browser qualifies for showing Flash content, the XHTML document is loaded back from the Flash movie and serves as the data provider.

A beta version of this method is available here:
http://codeazur.com.br/stuff/fugsp/

The code is tested in the following browsers so far:

  • Firefox (Windows, Linux, OSX)
  • IE 6 (Windows)
  • Opera 7.* (Windows)

I know the code is still with problems on Safari. If you’re on a Mac and have some minutes, could you be so kind and debug the JavaScript on Safari? I have no Mac here to test, and it would help me a lot as i want the code to be fully crossbrowser. Thanks a lot!

New GMail Features: HTML Fallback, Picasa Integration

GMail feature: HTML fallback interfaceI don’t know if this is news, i just noticed it today: In addition to the JavaScript application Google GMail now features a fallback HTML interface that works with previously unsupported browsers (or with browser that don’t have JavaScript enabled).
Also, GMail is now integrated into Google’s photo archive software Picasa, enabling users to send their pictures directly from within Picasa.
Note to self: Buy Google stocks…