/*------------------------------------------------------------------------------ Function: eCSStender.css3-selectors.js Author: Aaron Gustafson (aaron at easy-designs dot net) Creation Date: 2009-09-17 Version: 0.3 Homepage: http://github.com/easy-designs/eCSStender.css3-selectors.js License: MIT License Note: If you change or improve on this script, please let us know by emailing the author (above) with a link to your demo page. ------------------------------------------------------------------------------*/ (function(e){ if ( typeof e == 'undefined' ){ return; } var // aliases $ = e.methods.findBySelector, supported = e.isSupported, embedCSS = e.embedCSS, style = e.applyWeightedStyle, embed = function( selector, properties, medium ) { var style_block = EMPTY, prop; for ( prop in properties ) { if ( e.isInheritedProperty( properties, prop ) ) { continue; }; style_block += prop + COLON + properties[prop] + SEMICOL; } if ( style_block != EMPTY ) { embedCSS( selector + CURLY_O + style_block + CURLY_C, medium ); } }, inline = function( selector, properties, medium, specificity ) { if ( notScreen( medium ) ){ return; } try { var $els = $( selector ), i = $els.length; while ( i-- ) { style( $els[i], properties, specificity ); } } catch(e) { // throw new Error( LIB_ERROR + selector ); } }, eFunc = function(){}, // methods notScreen = function( medium ) { return medium != 'screen'; }, cleanNth = function( selector ) { return selector.replace( re_nth, '$1$2$3$4$5' ); }, // Event stuff // Based on John Resig's work addEvent = function( el, evt, handler ) { if ( el.addEventListener ) { addEvent = function( el, evt, handler ) { el.addEventListener( evt, handler, false ); }; } else { addEvent = function( el, evt, handler ) { var E = 'e'; el[E+evt+handler] = handler; el[evt+handler] = function(){ var e = window.event; e.target = e.srcElement; e.preventDefault = function(){ this.returnValue = false; }; e.stopPropagation = function(){ this.cancelBubble = true; }; el[E+evt+handler]( e ); }; el.attachEvent( 'on'+evt, el[evt+handler] ); }; } addEvent( el, evt, handler ); }, // strings EASY = 'net.easy-designs.', SELECTOR = 'selector', PROPERTIES = 'properties', SPECIFICITY = 'specificity', CLICK = 'click', EVERYTHING = '*', EMPTY = '', CURLY_O = '{', CURLY_C = '}', PAREN_O = '(', PAREN_C = ')', COLON = ':', SEMICOL = ';', HYPHEN = '-', DOT = '.', LIB_ERROR = 'Your chosen selector library does not support this selector: ', // Regular Expressions re_nth = /(.*\()\s*(?:(\d+n?|odd|even)\s*(\+|-)?\s*(\d+)?)\s*(\).*)/g, // elements div = document.createElement('div'), para = document.createElement('p'); // define our selector engine or die if ( ! ( $ instanceof Function ) ) { throw new Error('eCSStender.methods.findBySelector is not defined. eCSStender.css3-selectors.js is quitting.'); } // CLASSES // compound class selection (no other class selections seem to be an issue) e.register( { fingerprint: EASY + 'compound-class-selector', selector: /(?:\.\S+){2,}/, test: function(){ // the markup var d = div.cloneNode(true), p = para.cloneNode(true); p.className = 'foo'; d.appendChild( p ); // the test return ( supported( SELECTOR, 'div p.bar.foo', d, p ) ); } }, EVERYTHING, function( selector, properties, medium, specificity ){ // we need to invert the selection and get anything without the first class var regex = /((?:\.\S+){2,})/, classes = selector.replace( regex, '$1' ), false_positive, matches, j; // get the classes classes = classes.split('.'); classes.shift(); false_positive = classes.pop(); // re-apply all affected styles matches = e.lookup( { selector: new RegExp( '\\.' + false_positive ), specificity: specificity, media: medium }, EVERYTHING ); for ( j=0; j