2011-02-23 22:03:38 +01:00
/* jQuery.Entwine - Copyright 2009-2011 Hamish Friedlander and SilverStripe. Version . */
2009-11-21 03:33:06 +01:00
/* vendor/jquery.selector/jquery.class.js */
/ * *
* Very basic Class utility . Based on base and jquery . class .
*
* Class definition : var Foo = Base . extend ( { init : function ( ) { Constructor } ; method _name : function ( ) { Method } } ) ;
*
* Inheritance : var Bar = Foo . extend ( { method _name : function ( ) { this . _super ( ) ; } } ) ;
*
* new - less Constructor : new Foo ( arg ) < - same as - > Foo ( arg )
* /
var Base ;
( function ( ) {
2010-04-13 07:45:29 +02:00
var marker = { } , fnTest = /xyz/ . test ( function ( ) { var xyz ; } ) ? /\b_super\b/ : /.*/ ;
2009-11-21 03:33:06 +01:00
// The base Class implementation (does nothing)
Base = function ( ) { } ;
Base . addMethod = function ( name , func ) {
2010-04-13 07:45:29 +02:00
var parent = this . _super && this . _super . prototype ;
if ( parent && fnTest . test ( func ) ) {
2009-11-21 03:33:06 +01:00
this . prototype [ name ] = function ( ) {
var tmp = this . _super ;
2010-04-13 07:45:29 +02:00
this . _super = parent [ name ] ;
2009-11-21 03:33:06 +01:00
try {
var ret = func . apply ( this , arguments ) ;
}
finally {
this . _super = tmp ;
}
return ret ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
}
else this . prototype [ name ] = func ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
Base . addMethods = function ( props ) {
for ( var name in props ) {
if ( typeof props [ name ] == 'function' ) this . addMethod ( name , props [ name ] ) ;
else this . prototype [ name ] = props [ name ] ;
}
2010-04-13 07:45:29 +02:00
} ;
Base . subclassOf = function ( parentkls ) {
var kls = this ;
while ( kls ) {
if ( kls === parentkls ) return true ;
kls = kls . _super ;
}
} ;
2009-11-21 03:33:06 +01:00
// Create a new Class that inherits from this class
Base . extend = function ( props ) {
// The dummy class constructor
var Kls = function ( ) {
if ( arguments [ 0 ] === marker ) return ;
if ( this instanceof Kls ) {
if ( this . init ) this . init . apply ( this , arguments ) ;
}
else {
var ret = new Kls ( marker ) ; if ( ret . init ) ret . init . apply ( ret , arguments ) ; return ret ;
}
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
// Add the common class variables and methods
Kls . constructor = Kls ;
Kls . extend = Base . extend ;
Kls . addMethod = Base . addMethod ;
Kls . addMethods = Base . addMethods ;
2010-04-13 07:45:29 +02:00
Kls . subclassOf = Base . subclassOf ;
Kls . _super = this ;
2009-11-21 03:33:06 +01:00
// Attach the parent object to the inheritance chain
Kls . prototype = new this ( marker ) ;
2010-04-13 07:45:29 +02:00
Kls . prototype . constructor = Kls ;
2009-11-21 03:33:06 +01:00
// Copy the properties over onto the new prototype
Kls . addMethods ( props ) ;
return Kls ;
} ;
} ) ( ) ; ;
/* vendor/jquery.selector/jquery.selector.js */
( function ( $ ) {
var tokens = {
UNICODE : /\\[0-9a-f]{1,6}(?:\r\n|[ \n\r\t\f])?/ ,
ESCAPE : /(?:UNICODE)|\\[^\n\r\f0-9a-f]/ ,
NONASCII : /[^\x00-\x7F]/ ,
NMSTART : /[_a-z]|(?:NONASCII)|(?:ESCAPE)/ ,
NMCHAR : /[_a-z0-9-]|(?:NONASCII)|(?:ESCAPE)/ ,
IDENT : /-?(?:NMSTART)(?:NMCHAR)*/ ,
NL : /\n|\r\n|\r|\f/ ,
STRING : /(?:STRING1)|(?:STRING2)|(?:STRINGBARE)/ ,
STRING1 : /"(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\"])*"/ ,
STRING2 : /'(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\'])*'/ ,
STRINGBARE : /(?:(?:ESCAPE)|\\(?:NL)|[^\n\r\f\]])*/ ,
FUNCTION : /(?:IDENT)\(\)/ ,
INTEGER : /[0-9]+/ ,
WITHN : /([-+])?(INTEGER)?(n)\s*(?:([-+])\s*(INTEGER))?/ ,
WITHOUTN : /([-+])?(INTEGER)/
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
var rx = {
not : /:not\(/ ,
not _end : /\)/ ,
tag : /((?:IDENT)|\*)/ ,
id : /#(IDENT)/ ,
cls : /\.(IDENT)/ ,
attr : /\[\s*(IDENT)\s*(?:([^=]?=)\s*(STRING)\s*)?\]/ ,
pseudo _el : /(?::(first-line|first-letter|before|after))|(?:::((?:FUNCTION)|(?:IDENT)))/ ,
pseudo _cls _nth : /:nth-child\(\s*(?:(?:WITHN)|(?:WITHOUTN)|(odd|even))\s*\)/ ,
pseudo _cls : /:(IDENT)/ ,
comb : /\s*(\+|~|>)\s*|\s+/ ,
comma : /\s*,\s*/ ,
important : /\s+!important\s*$/
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
/* Replace placeholders with actual regex, and mark all as case insensitive */
var token = /[A-Z][A-Z0-9]+/ ;
for ( var k in rx ) {
2010-04-13 07:45:29 +02:00
var m , src = rx [ k ] . source ;
2009-11-21 03:33:06 +01:00
while ( m = src . match ( token ) ) src = src . replace ( m [ 0 ] , tokens [ m [ 0 ] ] . source ) ;
rx [ k ] = new RegExp ( src , 'gi' ) ;
}
/ * *
* A string that matches itself against regexii , and keeps track of how much of itself has been matched
* /
var ConsumableString = Base . extend ( {
init : function ( str ) {
this . str = str ;
this . pos = 0 ;
} ,
match : function ( rx ) {
var m ;
rx . lastIndex = this . pos ;
if ( ( m = rx . exec ( this . str ) ) && m . index == this . pos ) {
this . pos = rx . lastIndex ? rx . lastIndex : this . str . length ;
return m ;
}
return null ;
} ,
peek : function ( rx ) {
var m ;
rx . lastIndex = this . pos ;
if ( ( m = rx . exec ( this . str ) ) && m . index == this . pos ) return m ;
return null ;
} ,
showpos : function ( ) {
return this . str . slice ( 0 , this . pos ) + '<HERE>' + this . str . slice ( this . pos ) ;
} ,
done : function ( ) {
return this . pos == this . str . length ;
}
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
/* A base class that all Selectors inherit off */
var SelectorBase = Base . extend ( { } ) ;
/ * *
* A class representing a Simple Selector , as per the CSS3 selector spec
* /
var SimpleSelector = SelectorBase . extend ( {
init : function ( ) {
this . tag = null ;
this . id = null ;
this . classes = [ ] ;
this . attrs = [ ] ;
this . nots = [ ] ;
this . pseudo _classes = [ ] ;
this . pseudo _els = [ ] ;
} ,
parse : function ( selector ) {
var m ;
/* Pull out the initial tag first, if there is one */
if ( m = selector . match ( rx . tag ) ) this . tag = m [ 1 ] ;
/* Then for each selection type, try and find a match */
do {
if ( m = selector . match ( rx . not ) ) {
2010-04-13 07:45:29 +02:00
this . nots [ this . nots . length ] = SelectorsGroup ( ) . parse ( selector ) ;
2009-11-21 03:33:06 +01:00
if ( ! ( m = selector . match ( rx . not _end ) ) ) {
throw 'Invalid :not term in selector' ;
}
}
else if ( m = selector . match ( rx . id ) ) this . id = m [ 1 ] ;
else if ( m = selector . match ( rx . cls ) ) this . classes [ this . classes . length ] = m [ 1 ] ;
else if ( m = selector . match ( rx . attr ) ) this . attrs [ this . attrs . length ] = [ m [ 1 ] , m [ 2 ] , m [ 3 ] ] ;
else if ( m = selector . match ( rx . pseudo _el ) ) this . pseudo _els [ this . pseudo _els . length ] = m [ 1 ] || m [ 2 ] ;
else if ( m = selector . match ( rx . pseudo _cls _nth ) ) {
if ( m [ 3 ] ) {
var a = parseInt ( ( m [ 1 ] || '' ) + ( m [ 2 ] || '1' ) ) ;
var b = parseInt ( ( m [ 4 ] || '' ) + ( m [ 5 ] || '0' ) ) ;
}
else {
var a = m [ 8 ] ? 2 : 0 ;
var b = m [ 8 ] ? ( 4 - m [ 8 ] . length ) : parseInt ( ( m [ 6 ] || '' ) + m [ 7 ] ) ;
}
this . pseudo _classes [ this . pseudo _classes . length ] = [ 'nth-child' , [ a , b ] ] ;
}
else if ( m = selector . match ( rx . pseudo _cls ) ) this . pseudo _classes [ this . pseudo _classes . length ] = [ m [ 1 ] ] ;
} while ( m && ! selector . done ( ) ) ;
return this ;
}
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
/ * *
* A class representing a Selector , as per the CSS3 selector spec
* /
var Selector = SelectorBase . extend ( {
init : function ( ) {
this . parts = [ ] ;
} ,
parse : function ( cons ) {
this . parts [ this . parts . length ] = SimpleSelector ( ) . parse ( cons ) ;
while ( ! cons . done ( ) && ! cons . peek ( rx . comma ) && ( m = cons . match ( rx . comb ) ) ) {
this . parts [ this . parts . length ] = m [ 1 ] || ' ' ;
this . parts [ this . parts . length ] = SimpleSelector ( ) . parse ( cons ) ;
}
return this . parts . length == 1 ? this . parts [ 0 ] : this ;
}
} ) ;
/ * *
* A class representing a sequence of selectors , as per the CSS3 selector spec
* /
var SelectorsGroup = SelectorBase . extend ( {
init : function ( ) {
this . parts = [ ] ;
} ,
parse : function ( cons ) {
this . parts [ this . parts . length ] = Selector ( ) . parse ( cons ) ;
while ( ! cons . done ( ) && ( m = cons . match ( rx . comma ) ) ) {
this . parts [ this . parts . length ] = Selector ( ) . parse ( cons ) ;
}
return this . parts . length == 1 ? this . parts [ 0 ] : this ;
}
} ) ;
$ . selector = function ( s ) {
var cons = ConsumableString ( s ) ;
var res = SelectorsGroup ( ) . parse ( cons ) ;
res . selector = s ;
if ( ! cons . done ( ) ) throw 'Could not parse selector - ' + cons . showpos ( ) ;
else return res ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
$ . selector . SelectorBase = SelectorBase ;
$ . selector . SimpleSelector = SimpleSelector ;
$ . selector . Selector = Selector ;
$ . selector . SelectorsGroup = SelectorsGroup ;
2010-04-13 07:45:29 +02:00
} ) ( jQuery ) ;
2009-11-21 03:33:06 +01:00
;
/* vendor/jquery.selector/jquery.selector.specifity.js */
( function ( $ ) {
$ . selector . SimpleSelector . addMethod ( 'specifity' , function ( ) {
if ( this . spec ) return this . spec ;
var spec = [
this . id ? 1 : 0 ,
this . classes . length + this . attrs . length + this . pseudo _classes . length ,
( ( this . tag && this . tag != '*' ) ? 1 : 0 ) + this . pseudo _els . length
] ;
$ . each ( this . nots , function ( i , not ) {
var ns = not . specifity ( ) ; spec [ 0 ] += ns [ 0 ] ; spec [ 1 ] += ns [ 1 ] ; spec [ 2 ] += ns [ 2 ] ;
} ) ;
return this . spec = spec ;
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
$ . selector . Selector . addMethod ( 'specifity' , function ( ) {
if ( this . spec ) return this . spec ;
var spec = [ 0 , 0 , 0 ] ;
$ . each ( this . parts , function ( i , part ) {
if ( i % 2 ) return ;
var ps = part . specifity ( ) ; spec [ 0 ] += ps [ 0 ] ; spec [ 1 ] += ps [ 1 ] ; spec [ 2 ] += ps [ 2 ] ;
} ) ;
return this . spec = spec ;
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
$ . selector . SelectorsGroup . addMethod ( 'specifity' , function ( ) {
if ( this . spec ) return this . spec ;
var spec = [ 0 , 0 , 0 ] ;
$ . each ( this . parts , function ( i , part ) {
var ps = part . specifity ( ) ; spec [ 0 ] += ps [ 0 ] ; spec [ 1 ] += ps [ 1 ] ; spec [ 2 ] += ps [ 2 ] ;
} ) ;
return this . spec = spec ;
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
} ) ( jQuery ) ;
;
/* vendor/jquery.selector/jquery.selector.matches.js */
/ *
This attempts to do the opposite of Sizzle .
Sizzle is good for finding elements for a selector , but not so good for telling if an individual element matches a selector
* /
( function ( $ ) {
/**** CAPABILITY TESTS ****/
var div = document . createElement ( 'div' ) ;
div . innerHTML = '<form id="test"><input name="id" type="text"/></form>' ;
// In IE 6-7, getAttribute often does the wrong thing (returns similar to el.attr), so we need to use getAttributeNode on that browser
var getAttributeDodgy = div . firstChild . getAttribute ( 'id' ) !== 'test' ;
// Does browser support Element.firstElementChild, Element.previousElementSibling, etc.
var hasElementTraversal = div . firstElementChild && div . firstElementChild . tagName == 'FORM' ;
// Does browser support Element.children
var hasChildren = div . children && div . children [ 0 ] . tagName == 'FORM' ;
2010-04-13 07:45:29 +02:00
var FUNC _IN = /^\s*function\s*\([^)]*\)\s*\{/ ;
2009-11-21 03:33:06 +01:00
var FUNC _OUT = /}\s*$/ ;
var funcToString = function ( f ) {
return ( '' + f ) . replace ( FUNC _IN , '' ) . replace ( FUNC _OUT , '' ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
// Can we use Function#toString ?
try {
2010-04-13 07:45:29 +02:00
var testFunc = function ( ) { return 'good' ; } ;
2009-11-21 03:33:06 +01:00
if ( ( new Function ( '' , funcToString ( testFunc ) ) ) ( ) != 'good' ) funcToString = false ;
}
catch ( e ) { funcToString = false ; console . log ( e . message ) ; /*pass*/ }
/**** INTRO ****/
var GOOD = /GOOD/g ;
var BAD = /BAD/g ;
var STARTS _WITH _QUOTES = /^['"]/g ;
var join = function ( js ) {
return js . join ( '\n' ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
var join _complex = function ( js ) {
2010-04-13 07:45:29 +02:00
var code = new String ( js . join ( '\n' ) ) ; // String objects can have properties set. strings can't
2009-11-21 03:33:06 +01:00
code . complex = true ;
return code ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
/**** ATTRIBUTE ACCESSORS ****/
2010-04-13 07:45:29 +02:00
// Not all attribute names can be used as identifiers, so we encode any non-acceptable characters as hex
var varForAttr = function ( attr ) {
return '_' + attr . replace ( /^[^A-Za-z]|[^A-Za-z0-9]/g , function ( m ) { return '_0x' + m . charCodeAt ( 0 ) . toString ( 16 ) + '_' ; } ) ;
} ;
2009-11-21 03:33:06 +01:00
var getAttr ;
// Good browsers
if ( ! getAttributeDodgy ) {
2010-04-13 07:45:29 +02:00
getAttr = function ( attr ) { return 'var ' + varForAttr ( attr ) + ' = el.getAttribute("' + attr + '");' ; } ;
2009-11-21 03:33:06 +01:00
}
// IE 6, 7
else {
// On IE 6 + 7, getAttribute still has to be called with DOM property mirror name, not attribute name. Map attributes to those names
var getAttrIEMap = { 'class' : 'className' , 'for' : 'htmlFor' } ;
getAttr = function ( attr ) {
var ieattr = getAttrIEMap [ attr ] || attr ;
2010-04-13 07:45:29 +02:00
return 'var ' + varForAttr ( attr ) + ' = el.getAttribute("' + ieattr + '",2) || (el.getAttributeNode("' + attr + '")||{}).nodeValue;' ;
} ;
2009-11-21 03:33:06 +01:00
}
/**** ATTRIBUTE COMPARITORS ****/
var attrchecks = {
2010-04-13 07:45:29 +02:00
'-' : '!K' ,
'=' : 'K != "V"' ,
'!=' : 'K == "V"' ,
'~=' : '_WS_K.indexOf(" V ") == -1' ,
'^=' : '!K || K.indexOf("V") != 0' ,
'*=' : '!K || K.indexOf("V") == -1' ,
'$=' : '!K || K.substr(K.length-"V".length) != "V"'
} ;
2009-11-21 03:33:06 +01:00
/**** STATE TRACKER ****/
var State = $ . selector . State = Base . extend ( {
init : function ( ) {
this . reset ( ) ;
} ,
reset : function ( ) {
this . attrs = { } ; this . wsattrs = { } ;
} ,
prev : function ( ) {
this . reset ( ) ;
if ( hasElementTraversal ) return 'el = el.previousElementSibling' ;
return 'while((el = el.previousSibling) && el.nodeType != 1) {}' ;
} ,
next : function ( ) {
this . reset ( ) ;
if ( hasElementTraversal ) return 'el = el.nextElementSibling' ;
return 'while((el = el.nextSibling) && el.nodeType != 1) {}' ;
} ,
prevLoop : function ( body ) {
this . reset ( ) ;
if ( hasElementTraversal ) return join ( [ 'while(el = el.previousElementSibling){' , body ] ) ;
return join ( [
'while(el = el.previousSibling){' ,
'if (el.nodeType != 1) continue;' ,
2010-04-13 07:45:29 +02:00
body
2009-11-21 03:33:06 +01:00
] ) ;
} ,
parent : function ( ) {
this . reset ( ) ;
return 'el = el.parentNode;' ;
} ,
parentLoop : function ( body ) {
this . reset ( ) ;
return join ( [
'while((el = el.parentNode) && el.nodeType == 1){' ,
body ,
'}'
] ) ;
} ,
uses _attr : function ( attr ) {
if ( this . attrs [ attr ] ) return ;
this . attrs [ attr ] = true ;
return getAttr ( attr ) ;
} ,
uses _wsattr : function ( attr ) {
if ( this . wsattrs [ attr ] ) return ;
this . wsattrs [ attr ] = true ;
2010-04-13 07:45:29 +02:00
return join ( [ this . uses _attr ( attr ) , 'var _WS_' + varForAttr ( attr ) + ' = " "+' + varForAttr ( attr ) + '+" ";' ] ) ;
2009-11-21 03:33:06 +01:00
} ,
save : function ( lbl ) {
return 'var el' + lbl + ' = el;' ;
} ,
restore : function ( lbl ) {
this . reset ( ) ;
return 'el = el' + lbl + ';' ;
}
} ) ;
/**** PSEUDO-CLASS DETAILS ****/
var pseudoclschecks = {
'first-child' : join ( [
'var cel = el;' ,
2010-04-13 07:45:29 +02:00
'while(cel = cel.previousSibling){ if (cel.nodeType === 1) BAD; }'
2009-11-21 03:33:06 +01:00
] ) ,
'last-child' : join ( [
'var cel = el;' ,
'while(cel = cel.nextSibling){ if (cel.nodeType === 1) BAD; }'
] ) ,
'nth-child' : function ( a , b ) {
var get _i = join ( [
'var i = 1, cel = el;' ,
'while(cel = cel.previousSibling){' ,
'if (cel.nodeType === 1) i++;' ,
2010-04-13 07:45:29 +02:00
'}'
2009-11-21 03:33:06 +01:00
] ) ;
if ( a == 0 ) return join ( [
get _i ,
'if (i- ' + b + ' != 0) BAD;'
] ) ;
else if ( b == 0 && a >= 0 ) return join ( [
get _i ,
'if (i%' + a + ' != 0 || i/' + a + ' < 0) BAD;'
] ) ;
else if ( b == 0 && a < 0 ) return join ( [
'BAD;'
] ) ;
else return join ( [
get _i ,
'if ((i- ' + b + ')%' + a + ' != 0 || (i- ' + b + ')/' + a + ' < 0) BAD;'
] ) ;
}
} ;
// Needs to refence contents of object, so must be injected after definition
pseudoclschecks [ 'only-child' ] = join ( [
pseudoclschecks [ 'first-child' ] ,
pseudoclschecks [ 'last-child' ]
] ) ;
/**** SimpleSelector ****/
$ . selector . SimpleSelector . addMethod ( 'compile' , function ( el ) {
var js = [ ] ;
/* Check against element name */
if ( this . tag && this . tag != '*' ) {
js [ js . length ] = 'if (el.tagName != "' + this . tag . toUpperCase ( ) + '") BAD;' ;
}
/* Check against ID */
if ( this . id ) {
js [ js . length ] = el . uses _attr ( 'id' ) ;
js [ js . length ] = 'if (_id !== "' + this . id + '") BAD;' ;
}
/* Build className checking variable */
if ( this . classes . length ) {
js [ js . length ] = el . uses _wsattr ( 'class' ) ;
/* Check against class names */
$ . each ( this . classes , function ( i , cls ) {
2010-04-13 07:45:29 +02:00
js [ js . length ] = 'if (_WS__class.indexOf(" ' + cls + ' ") == -1) BAD;' ;
} ) ;
2009-11-21 03:33:06 +01:00
}
/* Check against attributes */
$ . each ( this . attrs , function ( i , attr ) {
js [ js . length ] = ( attr [ 1 ] == '~=' ) ? el . uses _wsattr ( attr [ 0 ] ) : el . uses _attr ( attr [ 0 ] ) ;
var check = attrchecks [ attr [ 1 ] || '-' ] ;
2010-04-13 07:45:29 +02:00
check = check . replace ( /K/g , varForAttr ( attr [ 0 ] ) ) . replace ( /V/g , attr [ 2 ] && attr [ 2 ] . match ( STARTS _WITH _QUOTES ) ? attr [ 2 ] . slice ( 1 , - 1 ) : attr [ 2 ] ) ;
2009-11-21 03:33:06 +01:00
js [ js . length ] = 'if (' + check + ') BAD;' ;
} ) ;
/* Check against nots */
$ . each ( this . nots , function ( i , not ) {
var lbl = ++ lbl _id ;
var func = join ( [
'l' + lbl + ':{' ,
not . compile ( el ) . replace ( BAD , 'break l' + lbl ) . replace ( GOOD , 'BAD' ) ,
'}'
] ) ;
if ( ! ( not instanceof $ . selector . SimpleSelector ) ) func = join ( [
el . save ( lbl ) ,
func ,
el . restore ( lbl )
2010-04-13 07:45:29 +02:00
] ) ;
2009-11-21 03:33:06 +01:00
js [ js . length ] = func ;
} ) ;
/* Check against pseudo-classes */
$ . each ( this . pseudo _classes , function ( i , pscls ) {
var check = pseudoclschecks [ pscls [ 0 ] ] ;
if ( check ) {
js [ js . length ] = ( typeof check == 'function' ? check . apply ( this , pscls [ 1 ] ) : check ) ;
}
else if ( check = $ . find . selectors . filters [ pscls [ 0 ] ] ) {
if ( funcToString ) {
js [ js . length ] = funcToString ( check ) . replace ( /elem/g , 'el' ) . replace ( /return([^;]+);/ , 'if (!($1)) BAD;' ) ;
}
else {
2010-04-13 07:45:29 +02:00
js [ js . length ] = 'if (!$.find.selectors.filters.' + pscls [ 0 ] + '(el)) BAD;' ;
2009-11-21 03:33:06 +01:00
}
}
} ) ;
js [ js . length ] = 'GOOD' ;
/* Pass */
return join ( js ) ;
} ) ;
var lbl _id = 0 ;
/** Turns an compiled fragment into the first part of a combination */
function as _subexpr ( f ) {
if ( f . complex )
return join ( [
'l' + ( ++ lbl _id ) + ':{' ,
f . replace ( GOOD , 'break l' + lbl _id ) ,
2010-04-13 07:45:29 +02:00
'}'
2009-11-21 03:33:06 +01:00
] ) ;
else
return f . replace ( GOOD , '' ) ;
}
var combines = {
' ' : function ( el , f1 , f2 ) {
return join _complex ( [
f2 ,
'while(true){' ,
el . parent ( ) ,
'if (!el || el.nodeType !== 1) BAD;' ,
f1 . compile ( el ) . replace ( BAD , 'continue' ) ,
'}'
] ) ;
} ,
'>' : function ( el , f1 , f2 ) {
return join ( [
f2 ,
el . parent ( ) ,
'if (!el || el.nodeType !== 1) BAD;' ,
f1 . compile ( el )
] ) ;
} ,
'~' : function ( el , f1 , f2 ) {
return join _complex ( [
f2 ,
el . prevLoop ( ) ,
f1 . compile ( el ) . replace ( BAD , 'continue' ) ,
'}' ,
'BAD;'
] ) ;
} ,
'+' : function ( el , f1 , f2 ) {
return join ( [
f2 ,
el . prev ( ) ,
'if (!el) BAD;' ,
f1 . compile ( el )
] ) ;
}
} ;
$ . selector . Selector . addMethod ( 'compile' , function ( el ) {
2010-04-13 07:45:29 +02:00
var l = this . parts . length ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var expr = this . parts [ -- l ] . compile ( el ) ;
2009-11-21 03:33:06 +01:00
while ( l ) {
2010-04-13 07:45:29 +02:00
var combinator = this . parts [ -- l ] ;
2009-11-21 03:33:06 +01:00
expr = combines [ combinator ] ( el , this . parts [ -- l ] , as _subexpr ( expr ) ) ;
}
return expr ;
} ) ;
$ . selector . SelectorsGroup . addMethod ( 'compile' , function ( el ) {
var expr = [ ] , lbl = ++ lbl _id ;
for ( var i = 0 ; i < this . parts . length ; i ++ ) {
expr [ expr . length ] = join ( [
i == 0 ? el . save ( lbl ) : el . restore ( lbl ) ,
'l' + lbl + '_' + i + ':{' ,
this . parts [ i ] . compile ( el ) . replace ( BAD , 'break l' + lbl + '_' + i ) ,
'}'
] ) ;
}
expr [ expr . length ] = 'BAD;' ;
return join ( expr ) ;
} ) ;
$ . selector . SelectorBase . addMethod ( 'matches' , function ( el ) {
this . matches = new Function ( 'el' , join ( [
'if (!el) return false;' ,
this . compile ( new State ( ) ) . replace ( BAD , 'return false' ) . replace ( GOOD , 'return true' )
] ) ) ;
return this . matches ( el ) ;
} ) ;
} ) ( jQuery ) ;
;
/* src/jquery.focusinout.js */
( function ( $ ) {
/ * *
* Add focusin and focusout support to bind and live for browers other than IE . Designed to be usable in a delegated fashion ( like $ . live )
* Copyright ( c ) 2007 Jörn Zaefferer
* /
$ . support . focusInOut = ! ! ( $ . browser . msie ) ;
if ( ! $ . support . focusInOut ) {
// Emulate focusin and focusout by binding focus and blur in capturing mode
$ . each ( { focus : 'focusin' , blur : 'focusout' } , function ( original , fix ) {
$ . event . special [ fix ] = {
setup : function ( ) {
if ( ! this . addEventListener ) return false ;
this . addEventListener ( original , $ . event . special [ fix ] . handler , true ) ;
} ,
teardown : function ( ) {
if ( ! this . removeEventListener ) return false ;
this . removeEventListener ( original , $ . event . special [ fix ] . handler , true ) ;
} ,
handler : function ( e ) {
arguments [ 0 ] = $ . event . fix ( e ) ;
arguments [ 0 ] . type = fix ;
return $ . event . handle . apply ( this , arguments ) ;
}
} ;
} ) ;
}
( function ( ) {
//IE has some trouble with focusout with select and keyboard navigation
var activeFocus = null ;
$ ( document )
. bind ( 'focusin' , function ( e ) {
var target = e . realTarget || e . target ;
if ( activeFocus && activeFocus !== target ) {
e . type = 'focusout' ;
$ ( activeFocus ) . trigger ( e ) ;
e . type = 'focusin' ;
e . target = target ;
}
activeFocus = target ;
} )
. bind ( 'focusout' , function ( e ) {
activeFocus = null ;
} ) ;
} ) ( ) ;
} ) ( jQuery ) ; ;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.js */
2009-11-21 03:33:06 +01:00
2011-05-12 08:11:41 +02:00
try {
console . log ;
}
catch ( e ) {
window . console = undefined ;
}
2009-11-21 03:33:06 +01:00
( function ( $ ) {
var namespaces = { } ;
2010-04-13 07:45:29 +02:00
$ . entwine = function ( ) {
$ . fn . entwine . apply ( null , arguments ) ;
} ;
2009-11-21 03:33:06 +01:00
/ * *
* A couple of utility functions for accessing the store outside of this closure , and for making things
* operate in a little more easy - to - test manner
* /
2010-04-13 07:45:29 +02:00
$ . extend ( $ . entwine , {
2009-11-21 03:33:06 +01:00
/ * *
* Get all the namespaces . Useful for introspection ? Internal interface of Namespace not guaranteed consistant
* /
namespaces : namespaces ,
/ * *
2010-04-13 07:45:29 +02:00
* Remove all entwine rules
2009-11-21 03:33:06 +01:00
* /
clear _all _rules : function ( ) {
// Remove proxy functions
2011-02-23 22:03:38 +01:00
for ( var k in $ . fn ) { if ( $ . fn [ k ] . isentwinemethod ) delete $ . fn [ k ] ; }
2010-04-13 07:45:29 +02:00
// Remove bound events - TODO: Make this pluggable, so this code can be moved to jquery.entwine.events.js
$ ( document ) . unbind ( '.entwine' ) ;
2009-11-21 03:33:06 +01:00
// Remove namespaces, and start over again
2010-04-13 07:45:29 +02:00
namespaces = $ . entwine . namespaces = { } ;
2009-11-21 03:33:06 +01:00
} ,
WARN _LEVEL _NONE : 0 ,
WARN _LEVEL _IMPORTANT : 1 ,
WARN _LEVEL _BESTPRACTISE : 2 ,
/ * *
* Warning level . Set to a higher level to get warnings dumped to console .
* /
warningLevel : 0 ,
/** Utility to optionally display warning messages depending on level */
warn : function ( message , level ) {
2010-04-13 07:45:29 +02:00
if ( level <= $ . entwine . warningLevel && console && console . warn ) {
2009-11-21 03:33:06 +01:00
console . warn ( message ) ;
if ( console . trace ) console . trace ( ) ;
}
2010-04-13 07:45:29 +02:00
} ,
warn _exception : function ( where , /* optional: */ on , e ) {
if ( $ . entwine . WARN _LEVEL _IMPORTANT <= $ . entwine . warningLevel && console && console . warn ) {
if ( arguments . length == 2 ) { e = on ; on = null ; }
if ( on ) console . warn ( 'Uncaught exception' , e , 'in' , where , 'on' , on ) ;
else console . warn ( 'Uncaught exception' , e , 'in' , where ) ;
if ( e . stack ) console . warn ( "Stack Trace:\n" + e . stack ) ;
}
2009-11-21 03:33:06 +01:00
}
} ) ;
/** Stores a count of definitions, so that we can sort identical selectors by definition order */
var rulecount = 0 ;
var Rule = Base . extend ( {
init : function ( selector , name ) {
this . selector = selector ;
this . specifity = selector . specifity ( ) ;
this . important = 0 ;
this . name = name ;
this . rulecount = rulecount ++ ;
}
} ) ;
Rule . compare = function ( a , b ) {
var as = a . specifity , bs = b . specifity ;
return ( a . important - b . important ) ||
( as [ 0 ] - bs [ 0 ] ) ||
( as [ 1 ] - bs [ 1 ] ) ||
( as [ 2 ] - bs [ 2 ] ) ||
( a . rulecount - b . rulecount ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
$ . entwine . RuleList = function ( ) {
2009-11-21 03:33:06 +01:00
var list = [ ] ;
list . addRule = function ( selector , name ) {
var rule = Rule ( selector , name ) ;
list [ list . length ] = rule ;
list . sort ( Rule . compare ) ;
return rule ;
} ;
return list ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
var handlers = [ ] ;
/ * *
2010-04-13 07:45:29 +02:00
* A Namespace holds all the information needed for adding entwine methods to a namespace ( including the _null _ namespace )
2009-11-21 03:33:06 +01:00
* /
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace = Base . extend ( {
2009-11-21 03:33:06 +01:00
init : function ( name ) {
2010-04-13 07:45:29 +02:00
if ( name && ! name . match ( /^[A-Za-z0-9.]+$/ ) ) $ . entwine . warn ( 'Entwine namespace ' + name + ' is not formatted as period seperated identifiers' , $ . entwine . WARN _LEVEL _BESTPRACTISE ) ;
2009-11-21 03:33:06 +01:00
name = name || '__base' ;
this . name = name ;
this . store = { } ;
namespaces [ name ] = this ;
if ( name == "__base" ) {
2010-04-13 07:45:29 +02:00
this . injectee = $ . fn ;
2009-11-21 03:33:06 +01:00
this . $ = $ ;
}
else {
// We're in a namespace, so we build a Class that subclasses the jQuery Object Class to inject namespace functions into
2011-02-23 22:03:38 +01:00
// jQuery 1.5 already provides a nice way to subclass, so use it
if ( $ . sub ) {
this . $ = $ . sub ( ) ;
this . injectee = this . $ . prototype ;
}
// For jQuery < 1.5 we have to do it ourselves
else {
var subfn = function ( ) { } ;
this . injectee = subfn . prototype = new $ ;
// And then we provide an overriding $ that returns objects of our new Class, and an overriding pushStack to catch further selection building
var bound$ = this . $ = function ( a ) {
// Try the simple way first
var jq = $ . fn . init . apply ( new subfn ( ) , arguments ) ;
if ( jq instanceof subfn ) return jq ;
2009-11-21 03:33:06 +01:00
2011-02-23 22:03:38 +01:00
// That didn't return a bound object, so now we need to copy it
var rv = new subfn ( ) ;
rv . selector = jq . selector ; rv . context = jq . context ; var i = rv . length = jq . length ;
while ( i -- ) rv [ i ] = jq [ i ] ;
return rv ;
} ;
this . injectee . pushStack = function ( elems , name , selector ) {
var ret = bound$ ( elems ) ;
2009-11-21 03:33:06 +01:00
2011-02-23 22:03:38 +01:00
// Add the old object onto the stack (as a reference)
ret . prevObject = this ;
ret . context = this . context ;
2009-11-21 03:33:06 +01:00
2011-02-23 22:03:38 +01:00
if ( name === "find" ) ret . selector = this . selector + ( this . selector ? " " : "" ) + selector ;
else if ( name ) ret . selector = this . selector + "." + name + "(" + selector + ")" ;
2009-11-21 03:33:06 +01:00
2011-02-23 22:03:38 +01:00
// Return the newly-formed element set
return ret ;
} ;
2009-11-21 03:33:06 +01:00
2011-02-23 22:03:38 +01:00
// Copy static functions through from $ to this.$ so e.g. $.ajax still works
// @bug, @cantfix: Any class functions added to $ after this call won't get mirrored through
$ . extend ( this . $ , $ ) ;
}
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
// We override entwine to inject the name of this namespace when defining blocks inside this namespace
var entwine _wrapper = this . injectee . entwine = function ( spacename ) {
2009-11-21 03:33:06 +01:00
var args = arguments ;
if ( ! spacename || typeof spacename != 'string' ) { args = $ . makeArray ( args ) ; args . unshift ( name ) ; }
else if ( spacename . charAt ( 0 ) != '.' ) args [ 0 ] = name + '.' + spacename ;
2010-04-13 07:45:29 +02:00
return $ . fn . entwine . apply ( this , args ) ;
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
this . $ . entwine = function ( ) {
entwine _wrapper . apply ( null , arguments ) ;
} ;
2009-11-21 03:33:06 +01:00
for ( var i = 0 ; i < handlers . length ; i ++ ) {
var handler = handlers [ i ] , builder ;
// Inject jQuery object method overrides
if ( builder = handler . namespaceMethodOverrides ) {
var overrides = builder ( this ) ;
for ( var k in overrides ) this . injectee [ k ] = overrides [ k ] ;
}
2010-04-13 07:45:29 +02:00
// Inject $.entwine function overrides
2009-11-21 03:33:06 +01:00
if ( builder = handler . namespaceStaticOverrides ) {
var overrides = builder ( this ) ;
2010-04-13 07:45:29 +02:00
for ( var k in overrides ) this . $ . entwine [ k ] = overrides [ k ] ;
2009-11-21 03:33:06 +01:00
}
}
}
} ,
/ * *
* Returns a function that does selector matching against the function list for a function name
* Used by proxy for all calls , and by ctorProxy to handle _super calls
* @ param { String } name - name of the function as passed in the construction object
* @ param { String } funcprop - the property on the Rule object that gives the actual function to call
2010-04-13 07:45:29 +02:00
* @ param { function } basefunc - the non - entwine function to use as the catch - all function at the bottom of the stack
2009-11-21 03:33:06 +01:00
* /
2010-04-13 07:45:29 +02:00
one : function ( name , funcprop , basefunc ) {
2009-11-21 03:33:06 +01:00
var namespace = this ;
var funcs = this . store [ name ] ;
var one = function ( el , args , i ) {
if ( i === undefined ) i = funcs . length ;
while ( i -- ) {
if ( funcs [ i ] . selector . matches ( el ) ) {
var ret , tmp _i = el . i , tmp _f = el . f ;
el . i = i ; el . f = one ;
try { ret = funcs [ i ] [ funcprop ] . apply ( namespace . $ ( el ) , args ) ; }
finally { el . i = tmp _i ; el . f = tmp _f ; }
return ret ;
}
}
2010-04-13 07:45:29 +02:00
// If we didn't find a entwine-defined function, but there is a non-entwine function to use as a base, try that
if ( basefunc ) return basefunc . apply ( namespace . $ ( el ) , args ) ;
} ;
2009-11-21 03:33:06 +01:00
return one ;
} ,
/ * *
* A proxy is a function attached to a callable object ( either the base jQuery . fn or a subspace object ) which handles
* finding and calling the correct function for each member of the current jQuery context
* @ param { String } name - name of the function as passed in the construction object
2010-04-13 07:45:29 +02:00
* @ param { function } basefunc - the non - entwine function to use as the catch - all function at the bottom of the stack
2009-11-21 03:33:06 +01:00
* /
2010-04-13 07:45:29 +02:00
build _proxy : function ( name , basefunc ) {
var one = this . one ( name , 'func' , basefunc ) ;
2009-11-21 03:33:06 +01:00
var prxy = function ( ) {
var rv , ctx = $ ( this ) ;
var i = ctx . length ;
while ( i -- ) rv = one ( ctx [ i ] , arguments ) ;
return rv ;
} ;
return prxy ;
} ,
bind _proxy : function ( selector , name , func ) {
2010-04-13 07:45:29 +02:00
var rulelist = this . store [ name ] || ( this . store [ name ] = $ . entwine . RuleList ( ) ) ;
2009-11-21 03:33:06 +01:00
var rule = rulelist . addRule ( selector , name ) ; rule . func = func ;
2011-02-23 22:03:38 +01:00
if ( ! this . injectee . hasOwnProperty ( name ) || ! this . injectee [ name ] . isentwinemethod ) {
2010-04-13 07:45:29 +02:00
this . injectee [ name ] = this . build _proxy ( name , this . injectee . hasOwnProperty ( name ) ? this . injectee [ name ] : null ) ;
2011-02-23 22:03:38 +01:00
this . injectee [ name ] . isentwinemethod = true ;
2009-11-21 03:33:06 +01:00
}
2011-02-23 22:03:38 +01:00
if ( ! this . injectee [ name ] . isentwinemethod ) {
2010-04-13 07:45:29 +02:00
$ . entwine . warn ( 'Warning: Entwine function ' + name + ' clashes with regular jQuery function - entwine function will not be callable directly on jQuery object' , $ . entwine . WARN _LEVEL _IMPORTANT ) ;
2009-11-21 03:33:06 +01:00
}
} ,
add : function ( selector , data ) {
// For every item in the hash, try ever method handler, until one returns true
for ( var k in data ) {
var v = data [ k ] ;
for ( var i = 0 ; i < handlers . length ; i ++ ) {
if ( handlers [ i ] . bind && handlers [ i ] . bind . call ( this , selector , k , v ) ) break ;
}
}
} ,
has : function ( ctx , name ) {
var rulelist = this . store [ name ] ;
if ( ! rulelist ) return false ;
/* We go forward this time, since low specifity is likely to knock out a bunch of elements quickly */
for ( var i = 0 ; i < rulelist . length ; i ++ ) {
ctx = ctx . not ( rulelist [ i ] . selector ) ;
if ( ! ctx . length ) return true ;
}
return false ;
}
} ) ;
/ * *
* A handler is some javascript code that adds support for some time of key / value pair passed in the hash to the Namespace add method .
* The default handlers provided ( and included by default ) are event , ctor and properties
* /
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addHandler = function ( handler ) {
2009-11-21 03:33:06 +01:00
for ( var i = 0 ; i < handlers . length && handlers [ i ] . order < handler . order ; i ++ ) { /* Pass */ }
handlers . splice ( i , 0 , handler ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addHandler ( {
2009-11-21 03:33:06 +01:00
order : 50 ,
bind : function ( selector , k , v ) {
if ( $ . isFunction ( v ) ) {
this . bind _proxy ( selector , k , v ) ;
return true ;
}
}
} ) ;
$ . extend ( $ . fn , {
/ * *
2010-04-13 07:45:29 +02:00
* Main entwine function . Used for new definitions , calling into a namespace ( or forcing the base namespace ) and entering a using block
2009-11-21 03:33:06 +01:00
*
* /
2010-04-13 07:45:29 +02:00
entwine : function ( spacename ) {
2009-11-21 03:33:06 +01:00
var i = 0 ;
2010-04-13 07:45:29 +02:00
/ * D o n ' t a c t u a l l y w o r k o u t s e l e c t o r u n t i l w e t r y a n d d e f i n e s o m e t h i n g o n i t - w e m i g h t b e o p e n i n g a n a m e s p a c e o n a n f u n c t i o n - t r a v e r e s e d o b j e c t
which have non - standard selectors like . parents ( . foo ) . slice ( 0 , 1 ) * /
var selector = null ;
2009-11-21 03:33:06 +01:00
/* By default we operator on the base namespace */
2010-04-13 07:45:29 +02:00
var namespace = namespaces . _ _base || $ . entwine . Namespace ( ) ;
2009-11-21 03:33:06 +01:00
/* If the first argument is a string, then it's the name of a namespace. Look it up */
if ( typeof spacename == 'string' ) {
if ( spacename . charAt ( '0' ) == '.' ) spacename = spacename . substr ( 1 ) ;
2010-04-13 07:45:29 +02:00
if ( spacename ) namespace = namespaces [ spacename ] || $ . entwine . Namespace ( spacename ) ;
2009-11-21 03:33:06 +01:00
i = 1 ;
}
/* All remaining arguments should either be using blocks or definition hashs */
while ( i < arguments . length ) {
var res = arguments [ i ++ ] ;
2010-04-13 07:45:29 +02:00
// If it's a function, call it - either it's a using block or it's a namespaced entwine definition
2009-11-21 03:33:06 +01:00
if ( $ . isFunction ( res ) ) {
2010-04-13 07:45:29 +02:00
if ( res . length != 1 ) $ . entwine . warn ( 'Function block inside entwine definition does not take $ argument properly' , $ . entwine . WARN _LEVEL _IMPORTANT ) ;
2009-11-21 03:33:06 +01:00
res = res . call ( namespace . $ ( this ) , namespace . $ ) ;
}
2010-04-13 07:45:29 +02:00
// If we have a entwine definition hash, inject it into namespace
2009-11-21 03:33:06 +01:00
if ( res ) {
2010-04-13 07:45:29 +02:00
if ( selector === null ) selector = this . selector ? $ . selector ( this . selector ) : false ;
2009-11-21 03:33:06 +01:00
if ( selector ) namespace . add ( selector , res ) ;
2010-04-13 07:45:29 +02:00
else $ . entwine . warn ( 'Entwine block given to entwine call without selector. Make sure you call $(selector).entwine when defining blocks' , $ . entwine . WARN _LEVEL _IMPORTANT ) ;
2009-11-21 03:33:06 +01:00
}
}
/* Finally, return the jQuery object 'this' refers to, wrapped in the new namespace */
return namespace . $ ( this ) ;
} ,
/ * *
2010-04-13 07:45:29 +02:00
* Calls the next most specific version of the current entwine method
2009-11-21 03:33:06 +01:00
* /
_super : function ( ) {
var rv , i = this . length ;
while ( i -- ) {
var el = this [ 0 ] ;
rv = el . f ( el , arguments , el . i ) ;
}
return rv ;
}
} ) ;
} ) ( jQuery ) ;
;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.dommaybechanged.js */
2009-11-21 03:33:06 +01:00
( function ( $ ) {
/** What to call to run a function 'soon'. Normally setTimeout, but for syncronous mode we override so soon === now */
var runSoon = window . setTimeout ;
/** The timer handle for the asyncronous matching call */
var check _id = null ;
/** Fire the change event. Only fires on the document node, so bind to that */
var triggerEvent = function ( ) {
$ ( document ) . triggerHandler ( 'DOMMaybeChanged' ) ;
check _id = null ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
$ . extend ( $ . entwine , {
2009-11-21 03:33:06 +01:00
/ * *
* Make onmatch and onunmatch work in synchronous mode - that is , new elements will be detected immediately after
* the DOM manipulation that made them match . This is only really useful for during testing , since it ' s pretty slow
* ( otherwise we ' d make it the default ) .
* /
synchronous _mode : function ( ) {
if ( check _id ) clearTimeout ( check _id ) ; check _id = null ;
2010-04-13 07:45:29 +02:00
runSoon = function ( func , delay ) { func . call ( this ) ; return null ; } ;
2009-11-21 03:33:06 +01:00
} ,
/ * *
* Trigger onmatch and onunmatch now - usefull for after DOM manipulation by methods other than through jQuery .
* Called automatically on document . ready
* /
triggerMatching : function ( ) {
matching ( ) ;
}
} ) ;
function registerMutateFunction ( ) {
$ . each ( arguments , function ( i , func ) {
var old = $ . fn [ func ] ;
$ . fn [ func ] = function ( ) {
var rv = old . apply ( this , arguments ) ;
if ( ! check _id ) check _id = runSoon ( triggerEvent , 100 ) ;
return rv ;
2010-04-13 07:45:29 +02:00
} ;
} ) ;
2009-11-21 03:33:06 +01:00
}
function registerSetterGetterFunction ( ) {
$ . each ( arguments , function ( i , func ) {
var old = $ . fn [ func ] ;
$ . fn [ func ] = function ( a , b ) {
var rv = old . apply ( this , arguments ) ;
if ( ! check _id && ( b !== undefined || typeof a != 'string' ) ) check _id = runSoon ( triggerEvent , 100 ) ;
return rv ;
2010-04-13 07:45:29 +02:00
} ;
} ) ;
2009-11-21 03:33:06 +01:00
}
// Register core DOM manipulation methods
registerMutateFunction ( 'append' , 'prepend' , 'after' , 'before' , 'wrap' , 'removeAttr' , 'addClass' , 'removeClass' , 'toggleClass' , 'empty' , 'remove' ) ;
registerSetterGetterFunction ( 'attr' ) ;
// And on DOM ready, trigger matching once
2010-04-13 07:45:29 +02:00
$ ( function ( ) { triggerEvent ( ) ; } ) ;
2009-11-21 03:33:06 +01:00
} ) ( jQuery ) ; ;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.events.js */
2009-11-21 03:33:06 +01:00
( function ( $ ) {
2011-05-12 08:11:41 +02:00
/** Taken from jQuery 1.5.2 for backwards compatibility */
if ( $ . support . changeBubbles == undefined ) {
$ . support . changeBubbles = true ;
var el = document . createElement ( "div" ) ;
eventName = "onchange" ;
if ( el . attachEvent ) {
var isSupported = ( eventName in el ) ;
if ( ! isSupported ) {
el . setAttribute ( eventName , "return;" ) ;
isSupported = typeof el [ eventName ] === "function" ;
}
$ . support . changeBubbles = isSupported ;
}
}
2009-11-21 03:33:06 +01:00
/* Return true if node b is the same as, or is a descendant of, node a */
if ( document . compareDocumentPosition ) {
var is _or _contains = function ( a , b ) {
return a && b && ( a == b || ! ! ( a . compareDocumentPosition ( b ) & 16 ) ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
}
else {
var is _or _contains = function ( a , b ) {
return a && b && ( a == b || ( a . contains ? a . contains ( b ) : true ) ) ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
}
/* Add the methods to handle event binding to the Namespace class */
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addMethods ( {
2009-11-21 03:33:06 +01:00
build _event _proxy : function ( name ) {
var one = this . one ( name , 'func' ) ;
2010-04-13 07:45:29 +02:00
var prxy = function ( e , data ) {
// For events that do not bubble we manually trigger delegation (see delegate_submit below)
// If this event is a manual trigger, the event we actually want to bubble is attached as a property of the passed event
e = e . delegatedEvent || e ;
2009-11-21 03:33:06 +01:00
var el = e . target ;
2010-04-13 07:45:29 +02:00
while ( el && el . nodeType == 1 && ! e . isPropagationStopped ( ) ) {
2009-11-21 03:33:12 +01:00
var ret = one ( el , arguments ) ;
if ( ret !== undefined ) e . result = ret ;
if ( ret === false ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
2009-11-21 03:33:06 +01:00
el = el . parentNode ;
}
} ;
return prxy ;
} ,
build _mouseenterleave _proxy : function ( name ) {
var one = this . one ( name , 'func' ) ;
var prxy = function ( e ) {
var el = e . target ;
var rel = e . relatedTarget ;
2010-04-13 07:45:29 +02:00
while ( el && el . nodeType == 1 && ! e . isPropagationStopped ( ) ) {
2009-11-21 03:33:06 +01:00
/* We know el contained target. If it also contains relatedTarget then we didn't mouseenter / leave . What ' s more , every ancestor will also
contan el and rel , and so we can just stop bubbling * /
if ( is _or _contains ( el , rel ) ) break ;
2009-11-21 03:33:12 +01:00
var ret = one ( el , arguments ) ;
if ( ret !== undefined ) e . result = ret ;
if ( ret === false ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
2009-11-21 03:33:06 +01:00
el = el . parentNode ;
}
} ;
return prxy ;
} ,
build _change _proxy : function ( name ) {
var one = this . one ( name , 'func' ) ;
2011-05-12 08:11:41 +02:00
/ *
This change bubble emulation code is taken mostly from jQuery 1.6 - unfortunately we can ' t easily reuse any of
it without duplication , so we ' ll have to re - migrate any bugfixes
* /
// Get the value of an item. Isn't supposed to be interpretable, just stable for some value, and different
// once the value changes
var getVal = function ( elem ) {
var type = elem . type , val = elem . value ;
if ( type === "radio" || type === "checkbox" ) {
val = elem . checked ;
}
else if ( type === "select-multiple" ) {
val = "" ;
if ( elem . selectedIndex > - 1 ) {
val = jQuery . map ( elem . options , function ( elem ) { return elem . selected ; } ) . join ( "-" ) ;
2009-11-21 03:33:06 +01:00
}
}
2011-05-12 08:11:41 +02:00
else if ( jQuery . nodeName ( elem , "select" ) ) {
val = elem . selectedIndex ;
2009-11-21 03:33:06 +01:00
}
2011-05-12 08:11:41 +02:00
return val ;
} ;
// Test if a node name is a form input
var rformElems = /^(?:textarea|input|select)$/i ;
// Check if this event is a change, and bubble the change event if it is
var testChange = function ( e ) {
var elem = e . target , data , val ;
if ( ! rformElems . test ( elem . nodeName ) || elem . readOnly ) return ;
data = jQuery . data ( elem , "_entwine_change_data" ) ;
val = getVal ( elem ) ;
// the current data will be also retrieved by beforeactivate
if ( e . type !== "focusout" || elem . type !== "radio" ) {
jQuery . data ( elem , "_entwine_change_data" , val ) ;
}
if ( data === undefined || val === data ) return ;
if ( data != null || val ) {
e . type = "change" ;
while ( elem && elem . nodeType == 1 && ! e . isPropagationStopped ( ) ) {
var ret = one ( elem , arguments ) ;
2009-11-21 03:33:12 +01:00
if ( ret !== undefined ) e . result = ret ;
if ( ret === false ) { e . preventDefault ( ) ; e . stopPropagation ( ) ; }
2011-05-12 08:11:41 +02:00
elem = elem . parentNode ;
2009-11-21 03:33:06 +01:00
}
}
} ;
2011-05-12 08:11:41 +02:00
// The actual proxy - responds to several events, some of which triger a change check, some
// of which just store the value for future change checks
var prxy = function ( e ) {
var event = e . type , elem = e . target , type = jQuery . nodeName ( elem , "input" ) ? elem . type : "" ;
switch ( event ) {
case 'focusout' :
case 'beforedeactivate' :
testChange . apply ( this , arguments ) ;
break ;
case 'click' :
if ( type === "radio" || type === "checkbox" || jQuery . nodeName ( elem , "select" ) ) {
testChange . apply ( this , arguments ) ;
}
break ;
// Change has to be called before submit
// Keydown will be called before keypress, which is used in submit-event delegation
case 'keydown' :
if (
( e . keyCode === 13 && ! jQuery . nodeName ( elem , "textarea" ) ) ||
( e . keyCode === 32 && ( type === "checkbox" || type === "radio" ) ) ||
type === "select-multiple"
) {
testChange . apply ( this , arguments ) ;
}
break ;
// Beforeactivate happens also before the previous element is blurred
// with this event you can't trigger a change event, but you can store
// information
case 'focusin' :
case 'beforeactivate' :
jQuery . data ( elem , "_entwine_change_data" , getVal ( elem ) ) ;
break ;
}
}
2009-11-21 03:33:06 +01:00
return prxy ;
} ,
bind _event : function ( selector , name , func , event ) {
2010-04-13 07:45:29 +02:00
var funcs = this . store [ name ] || ( this . store [ name ] = $ . entwine . RuleList ( ) ) ;
2009-11-21 03:33:06 +01:00
var proxies = funcs . proxies || ( funcs . proxies = { } ) ;
var rule = funcs . addRule ( selector , name ) ; rule . func = func ;
if ( ! proxies [ name ] ) {
switch ( name ) {
case 'onmouseenter' :
proxies [ name ] = this . build _mouseenterleave _proxy ( name ) ;
event = 'mouseover' ;
break ;
case 'onmouseleave' :
proxies [ name ] = this . build _mouseenterleave _proxy ( name ) ;
event = 'mouseout' ;
break ;
case 'onchange' :
2011-05-12 08:11:41 +02:00
if ( ! $ . support . changeBubbles ) {
2009-11-21 03:33:06 +01:00
proxies [ name ] = this . build _change _proxy ( name ) ;
2011-05-12 08:11:41 +02:00
event = 'click keydown focusin focusout beforeactivate beforedeactivate' ;
2009-11-21 03:33:06 +01:00
}
break ;
case 'onsubmit' :
2010-04-13 07:45:29 +02:00
event = 'delegatedSubmit' ;
break ;
2009-11-21 03:33:06 +01:00
case 'onfocus' :
case 'onblur' :
2010-04-13 07:45:29 +02:00
$ . entwine . warn ( 'Event ' + event + ' not supported - using focusin / focusout instead' , $ . entwine . WARN _LEVEL _IMPORTANT ) ;
2009-11-21 03:33:06 +01:00
}
2010-04-13 07:45:29 +02:00
// If none of the special handlers created a proxy, use the generic proxy
2009-11-21 03:33:06 +01:00
if ( ! proxies [ name ] ) proxies [ name ] = this . build _event _proxy ( name ) ;
2011-05-12 08:11:41 +02:00
$ ( document ) . bind ( event . replace ( /(\s+|$)/g , '.entwine$1' ) , proxies [ name ] ) ;
2009-11-21 03:33:06 +01:00
}
}
} ) ;
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addHandler ( {
2009-11-21 03:33:06 +01:00
order : 40 ,
bind : function ( selector , k , v ) {
2009-11-21 03:33:26 +01:00
var match , event ;
2009-11-21 03:33:06 +01:00
if ( $ . isFunction ( v ) && ( match = k . match ( /^on(.*)/ ) ) ) {
event = match [ 1 ] ;
this . bind _event ( selector , k , v , event ) ;
return true ;
}
}
} ) ;
2010-04-13 07:45:29 +02:00
// Find all forms and bind onsubmit to trigger on the document too.
// This is the only event that can't be grabbed via delegation
2009-11-21 03:33:06 +01:00
var form _binding _cache = $ ( [ ] ) ; // A cache for already-handled form elements
2010-04-13 07:45:29 +02:00
var delegate _submit = function ( e , data ) {
var delegationEvent = $ . Event ( 'delegatedSubmit' ) ; delegationEvent . delegatedEvent = e ;
return $ ( document ) . trigger ( delegationEvent , data ) ;
} ;
2009-11-21 03:33:06 +01:00
$ ( document ) . bind ( 'DOMMaybeChanged' , function ( ) {
var forms = $ ( 'form' ) ;
// Only bind to forms we haven't processed yet
forms . not ( form _binding _cache ) . bind ( 'submit' , delegate _submit ) ;
// Then remember the current set of forms
form _binding _cache = forms ;
} ) ;
} ) ( jQuery ) ;
;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.ctors.js */
2009-11-21 03:33:06 +01:00
( function ( $ ) {
/* Add the methods to handle constructor & destructor binding to the Namespace class */
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addMethods ( {
2009-11-21 03:33:06 +01:00
bind _condesc : function ( selector , name , func ) {
2010-04-13 07:45:29 +02:00
var ctors = this . store . ctors || ( this . store . ctors = $ . entwine . RuleList ( ) ) ;
2009-11-21 03:33:06 +01:00
var rule ;
for ( var i = 0 ; i < ctors . length ; i ++ ) {
if ( ctors [ i ] . selector . selector == selector . selector ) {
rule = ctors [ i ] ; break ;
}
}
if ( ! rule ) {
rule = ctors . addRule ( selector , 'ctors' ) ;
}
rule [ name ] = func ;
if ( ! ctors [ name + 'proxy' ] ) {
var one = this . one ( 'ctors' , name ) ;
var namespace = this ;
var proxy = function ( els , i , func ) {
var j = els . length ;
while ( j -- ) {
var el = els [ j ] ;
var tmp _i = el . i , tmp _f = el . f ;
el . i = i ; el . f = one ;
2010-04-13 07:45:29 +02:00
try { func . call ( namespace . $ ( el ) ) ; }
catch ( e ) { $ . entwine . warn _exception ( name , el , e ) ; }
finally { el . i = tmp _i ; el . f = tmp _f ; }
2009-11-21 03:33:06 +01:00
}
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
ctors [ name + 'proxy' ] = proxy ;
}
}
} ) ;
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addHandler ( {
2009-11-21 03:33:06 +01:00
order : 30 ,
bind : function ( selector , k , v ) {
if ( $ . isFunction ( v ) && ( k == 'onmatch' || k == 'onunmatch' ) ) {
this . bind _condesc ( selector , k , v ) ;
return true ;
}
}
} ) ;
/ * *
* Finds all the elements that now match a different rule ( or have been removed ) and call onmatch on onunmatch as appropriate
*
* Because this has to scan the DOM , and is therefore fairly slow , this is normally triggered off a short timeout , so that
* a series of DOM manipulations will only trigger this once .
*
* The downside of this is that things like :
* $ ( '#foo' ) . addClass ( 'tabs' ) ; $ ( '#foo' ) . tabFunctionBar ( ) ;
* won ' t work .
* /
$ ( document ) . bind ( 'DOMMaybeChanged' , function ( ) {
// For every namespace
2010-04-13 07:45:29 +02:00
for ( var k in $ . entwine . namespaces ) {
2009-11-21 03:33:06 +01:00
// That has constructors or destructors
2010-04-13 07:45:29 +02:00
var ctors = $ . entwine . namespaces [ k ] . store . ctors ;
2009-11-21 03:33:06 +01:00
if ( ctors ) {
// Keep a record of elements that have matched already
2010-04-13 07:45:29 +02:00
var matched = $ ( [ ] ) , add , rem , res , rule , sel , ctor , dtor ;
2009-11-21 03:33:06 +01:00
// Stepping through each selector from most to least specific
var j = ctors . length ;
while ( j -- ) {
2010-04-13 07:45:29 +02:00
// Build some quick-access variables
rule = ctors [ j ] ;
sel = rule . selector . selector ;
ctor = rule . onmatch ;
dtor = rule . onunmatch ;
2009-11-21 03:33:06 +01:00
// Get the list of elements that match this selector, that haven't yet matched a more specific selector
res = add = $ ( sel ) . not ( matched ) ;
2010-04-13 07:45:29 +02:00
// If this selector has a list of elements it matched against last time
if ( rule . cache ) {
2009-11-21 03:33:06 +01:00
// Find the ones that are extra this time
2010-04-13 07:45:29 +02:00
add = res . not ( rule . cache ) ;
if ( dtor ) {
// Find the ones that are gone this time
rem = rule . cache . not ( res ) ;
// And call the destructor on them
2011-03-07 20:25:06 +01:00
if ( rem . length && ! rule . onunmatchRunning ) {
rule . onunmatchRunning = true ;
ctors . onunmatchproxy ( rem , j , dtor ) ;
rule . onunmatchRunning = false ;
}
2010-04-13 07:45:29 +02:00
}
2009-11-21 03:33:06 +01:00
}
// Call the constructor on the newly matched ones
2011-03-07 20:25:06 +01:00
if ( add . length && ctor && ! rule . onmatchRunning ) {
rule . onmatchRunning = true ;
ctors . onmatchproxy ( add , j , ctor ) ;
rule . onmatchRunning = false ;
}
2009-11-21 03:33:06 +01:00
// Add these matched ones to the list tracking all elements matched so far
matched = matched . add ( res ) ;
// And remember this list of matching elements again this selector, so next matching we can find the unmatched ones
ctors [ j ] . cache = res ;
}
}
}
2010-04-13 07:45:29 +02:00
} ) ;
2009-11-21 03:33:06 +01:00
} ) ( jQuery ) ;
;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.properties.js */
2009-11-21 03:33:06 +01:00
( function ( $ ) {
2010-04-13 07:45:29 +02:00
var entwine _prepend = '__entwine!' ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var getEntwineData = function ( el , namespace , property ) {
return el . data ( entwine _prepend + namespace + '!' + property ) ;
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var setEntwineData = function ( el , namespace , property , value ) {
return el . data ( entwine _prepend + namespace + '!' + property , value ) ;
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var getEntwineDataAsHash = function ( el , namespace ) {
2009-11-21 03:33:06 +01:00
var hash = { } ;
var id = jQuery . data ( el [ 0 ] ) ;
2010-04-13 07:45:29 +02:00
var matchstr = entwine _prepend + namespace + '!' ;
2009-11-21 03:33:06 +01:00
var matchlen = matchstr . length ;
var cache = jQuery . cache [ id ] ;
for ( var k in cache ) {
if ( k . substr ( 0 , matchlen ) == matchstr ) hash [ k . substr ( matchlen ) ] = cache [ k ] ;
}
return hash ;
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var setEntwineDataFromHash = function ( el , namespace , hash ) {
for ( var k in hash ) setEntwineData ( namespace , k , hash [ k ] ) ;
} ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var entwineData = function ( el , namespace , args ) {
2009-11-21 03:33:06 +01:00
switch ( args . length ) {
case 0 :
2010-04-13 07:45:29 +02:00
return getEntwineDataAsHash ( el , namespace ) ;
2009-11-21 03:33:06 +01:00
case 1 :
2010-04-13 07:45:29 +02:00
if ( typeof args [ 0 ] == 'string' ) return getEntwineData ( el , namespace , args [ 0 ] ) ;
else return setEntwineDataFromHash ( el , namespace , args [ 0 ] ) ;
2009-11-21 03:33:06 +01:00
default :
2010-04-13 07:45:29 +02:00
return setEntwineData ( el , namespace , args [ 0 ] , args [ 1 ] ) ;
2009-11-21 03:33:06 +01:00
}
2010-04-13 07:45:29 +02:00
} ;
2009-11-21 03:33:06 +01:00
$ . extend ( $ . fn , {
2010-04-13 07:45:29 +02:00
entwineData : function ( ) {
return entwineData ( this , '__base' , arguments ) ;
2009-11-21 03:33:06 +01:00
}
} ) ;
2010-04-13 07:45:29 +02:00
$ . entwine . Namespace . addHandler ( {
2009-11-21 03:33:06 +01:00
order : 60 ,
bind : function ( selector , k , v ) {
2010-04-13 07:45:29 +02:00
if ( k . charAt ( 0 ) != k . charAt ( 0 ) . toUpperCase ( ) ) $ . entwine . warn ( 'Entwine property ' + k + ' does not start with a capital letter' , $ . entwine . WARN _LEVEL _BESTPRACTISE ) ;
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
// Create the getters and setters
2009-11-21 03:33:06 +01:00
2010-04-13 07:45:29 +02:00
var getterName = 'get' + k ;
var setterName = 'set' + k ;
2009-11-21 03:33:06 +01:00
2011-05-12 08:11:41 +02:00
this . bind _proxy ( selector , getterName , function ( ) { var r = this . entwineData ( k ) ; return r === undefined ? v : r ; } ) ;
2010-04-13 07:45:29 +02:00
this . bind _proxy ( selector , setterName , function ( v ) { return this . entwineData ( k , v ) ; } ) ;
// Get the get and set proxies we just created
var getter = this . injectee [ getterName ] ;
var setter = this . injectee [ setterName ] ;
// And bind in the jQuery-style accessor
this . bind _proxy ( selector , k , function ( v ) { return ( arguments . length == 1 ? setter : getter ) . call ( this , v ) ; } ) ;
2009-11-21 03:33:06 +01:00
return true ;
} ,
namespaceMethodOverrides : function ( namespace ) {
return {
2010-04-13 07:45:29 +02:00
entwineData : function ( ) {
return entwineData ( this , namespace . name , arguments ) ;
2009-11-21 03:33:06 +01:00
}
} ;
}
} ) ;
} ) ( jQuery ) ;
;
2010-04-13 07:45:29 +02:00
/* src/jquery.entwine.legacy.js */
( function ( $ ) {
// Adds back concrete methods for backwards compatibility
$ . concrete = $ . entwine ;
$ . fn . concrete = $ . fn . entwine ;
$ . fn . concreteData = $ . fn . entwineData ;
// Use addHandler to hack in the namespace.$.concrete equivilent to the namespace.$.entwine namespace-injection
$ . entwine . Namespace . addHandler ( {
order : 100 ,
bind : function ( selector , k , v ) { return false ; } ,
namespaceMethodOverrides : function ( namespace ) {
namespace . $ . concrete = namespace . $ . entwine ;
namespace . injectee . concrete = namespace . injectee . entwine ;
namespace . injectee . concreteData = namespace . injectee . entwineData ;
return { } ;
}
} ) ;
} ) ( jQuery ) ;
;