diff options
Diffstat (limited to 'themes/default')
81 files changed, 21019 insertions, 10501 deletions
diff --git a/themes/default/fix-ie5-ie6.css b/themes/default/fix-ie5-ie6.css index 7d5442095..4c2f7e96e 100644 --- a/themes/default/fix-ie5-ie6.css +++ b/themes/default/fix-ie5-ie6.css @@ -69,5 +69,4 @@ H1, #theHeader { .imageInfo {display:block; line-height:16px;} .imageInfo dt {display:block; text-align:left; font-weight:bold; padding-right:0.5em;} .imageInfo dd {display:block; text-align:left; font-weight:normal;} -.relSwitchBox {position:static;} #imageInfos dd { margin: 0 0 5px 20px;}
\ No newline at end of file diff --git a/themes/default/fix-ie7.css b/themes/default/fix-ie7.css index 479f39f7a..fb77bfcc2 100644 --- a/themes/default/fix-ie7.css +++ b/themes/default/fix-ie7.css @@ -26,5 +26,4 @@ .imageInfo {display:block; line-height:16px;} .imageInfo dt {display:block; text-align:left; font-weight:bold; padding-right:0.5em;} .imageInfo dd {display:block; text-align:left; font-weight:normal;} -.relSwitchBox {position:static;} #imageInfos dd { margin: 0 0 5px 20px;}
\ No newline at end of file diff --git a/themes/default/icon/index.php b/themes/default/icon/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/icon/index.php +++ b/themes/default/icon/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/icon/mimetypes/index.php b/themes/default/icon/mimetypes/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/icon/mimetypes/index.php +++ b/themes/default/icon/mimetypes/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/iconset.css b/themes/default/iconset.css index 8c6d29039..6c8e7a1b6 100644 --- a/themes/default/iconset.css +++ b/themes/default/iconset.css @@ -39,6 +39,7 @@ .pwg-icon-category-edit {background-position: -26px -52px} .pwg-icon-sort {background-position: -52px -52px} .pwg-icon-sizes {background-position: -78px -52px} +.pwg-icon-menu {background-position: -130px -52px} .pwg-icon-category-view-normal {background-position: -156px -52px} .pwg-icon-category-view-flat {background-position: -182px -52px} diff --git a/themes/default/images/index.php b/themes/default/images/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/images/index.php +++ b/themes/default/images/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/index.php b/themes/default/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/index.php +++ b/themes/default/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/js/datepicker.js b/themes/default/js/datepicker.js index 93e712e02..ff2c2d4d2 100644 --- a/themes/default/js/datepicker.js +++ b/themes/default/js/datepicker.js @@ -16,13 +16,13 @@ function pwg_common_initialization_datepicker(buttonImageName, day, month, year, // return if linked_date is valid date function is_valid_linked_value(linked_date_name) { - array_date = $(linked_date_name).val().split('-'); - return ( - (array_date.length == 3) && - (array_date[0] != "") && - (array_date[1] != "") && (array_date[1] != "0") && - (array_date[2] != "") && (array_date[2] != "0") - ) + var array_date = $(linked_date_name).val().split('-'); + return ( + (array_date.length == 3) && + (array_date[0].length) && + (array_date[1].length) && (array_date[1] != "0") && + (array_date[2].length) && (array_date[2] != "0") + ) } // Action on change date value @@ -31,16 +31,16 @@ function pwg_common_initialization_datepicker(buttonImageName, day, month, year, pwg_check_date(); if (checked_on_change != null) { - $(checked_on_change).attr("checked", "true"); + $(checked_on_change).prop("checked", true); } } // In order to desable element of list function pwg_disabled_selection() { - array_date = $(linked_date).val().split('-'); - y = array_date[0]; - m = array_date[1]; + var array_date = $(linked_date).val().split('-') + , y = array_date[0] + , m = array_date[1]; // Init list $(day + " option").removeAttr("disabled"); @@ -95,7 +95,8 @@ function pwg_common_initialization_datepicker(buttonImageName, day, month, year, // Prevent selection of invalid dates through the select controls function pwg_check_date() { - last_date = $(linked_date).val(); + var last_date = $(linked_date).val() + , cancel=false; $(linked_date).val(pwg_get_fmt_from_ctrls()); @@ -107,14 +108,10 @@ function pwg_common_initialization_datepicker(buttonImageName, day, month, year, { cancel = ($(max_linked_date).datepicker("getDate") < $(linked_date).datepicker("getDate")); } - else - { - cancel = false; - } if (cancel) { - array_date = last_date.split('-'); + var array_date = last_date.split('-'); $(year).val(array_date[0]); $(month).val(array_date[1]); $(day).val(array_date[2]); @@ -157,7 +154,7 @@ function pwg_common_initialization_datepicker(buttonImageName, day, month, year, } else { - array_date = date.split('-'); + var array_date = date.split('-'); $(year).val(array_date[0]); $(month).val(array_date[1]); $(day).val(array_date[2]); diff --git a/themes/default/js/image.loader.js b/themes/default/js/image.loader.js deleted file mode 100644 index cd8b9cc52..000000000 --- a/themes/default/js/image.loader.js +++ /dev/null @@ -1,84 +0,0 @@ - -function ImageLoader(opts) { - this.opts = jQuery.extend( { - maxRequests: 6, - onChanged: jQuery.noop - }, opts||{} ); -} - -ImageLoader.prototype = { - loaded: 0, - errors: 0, - errorEma: 0, - - pause: false, - - current: [], - queue: [], - pool: [], - - remaining: function() { - return this.current.length + this.queue.length; - }, - - add: function(urls) { - this.queue = this.queue.concat( urls ); - this._fireChanged("add"); - this._checkQueue(); - }, - - clear: function() { - this.queue.length = 0; - while (this.current.length) - jQuery( this.current.pop() ).unbind(); - this.loaded = this.errors = this.errorEma = 0; - }, - - pause: function(val) { - if (val !== undefined) - { - this.paused = val; - this._checkQueue(); - } - return this.paused; - }, - - _checkQueue: function() { - while (!this.paused - && this.queue.length - && this.current.length < this.opts.maxRequests) - { - this._processOne( this.queue.shift() ); - } - }, - - _processOne: function(url) { - var img = this.pool.shift() || new Image; - this.current.push(img); - var that = this; - jQuery(img).bind( "load error abort", function(e) { - //img.onload = function(e) { - jQuery(img).unbind(); - img.onload=null; - that.current.splice(jQuery.inArray(img, that.current), 1); - if (e.type==="load") { - that.loaded++; - that.errorEma *= 0.9; - } - else { - that.errors++; - that.errorEma++; - if (that.errorEma>=20 && that.errorEma<21) - that.paused = true; - } - that._fireChanged(e.type, img); - that._checkQueue(); - that.pool.push(img); - } ); - img.src = url; - }, - - _fireChanged: function(type, img) { - this.opts.onChanged(type, img); - } -}
\ No newline at end of file diff --git a/themes/default/js/jquery.js b/themes/default/js/jquery.js index 8c24ffc61..c5c648255 100644 --- a/themes/default/js/jquery.js +++ b/themes/default/js/jquery.js @@ -1,28 +1,38 @@ /*! - * jQuery JavaScript Library v1.8.3 + * jQuery JavaScript Library v1.10.2 * http://jquery.com/ * * Includes Sizzle.js * http://sizzlejs.com/ * - * Copyright 2012 jQuery Foundation and other contributors + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time) + * Date: 2013-07-03T13:48Z */ (function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; var + // The deferred used on DOM ready + readyList, + // A central reference to the root jQuery(document) rootjQuery, - // The deferred used on DOM ready - readyList, + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, // Use the correct document accordingly with window argument (sandbox) - document = window.document, location = window.location, - navigator = window.navigator, + document = window.document, + docElem = document.documentElement, // Map over jQuery in case of overwrite _jQuery = window.jQuery, @@ -30,13 +40,22 @@ var // Map over the $ in case of overwrite _$ = window.$, + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + // Save a reference to some core methods - core_push = Array.prototype.push, - core_slice = Array.prototype.slice, - core_indexOf = Array.prototype.indexOf, - core_toString = Object.prototype.toString, - core_hasOwn = Object.prototype.hasOwnProperty, - core_trim = String.prototype.trim, + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -45,18 +64,18 @@ var }, // Used for matching numbers - core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, - // Used for detecting and trimming whitespace - core_rnotwhite = /\S/, - core_rspace = /\s+/, + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, // A simple way to check for HTML strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) - rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, @@ -65,7 +84,7 @@ var rvalidchars = /^[\],:{}\s]*$/, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, - rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, // Matches dashed string for camelizing rmsPrefix = /^-ms-/, @@ -73,42 +92,43 @@ var // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); + return letter.toUpperCase(); }, - // The ready event handler and self cleanup method - DOMContentLoaded = function() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - } else if ( document.readyState === "complete" ) { - // we're here because readyState === "complete" in oldIE - // which is good enough for us to call the dom ready! - document.detachEvent( "onreadystatechange", DOMContentLoaded ); + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); jQuery.ready(); } }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); - // [[Class]] -> type pairs - class2type = {}; + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + constructor: jQuery, init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; + var match, elem; - // Handle $(""), $(null), $(undefined), $(false) + // HANDLE: $(""), $(null), $(undefined), $(false) if ( !selector ) { return this; } - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - // Handle HTML strings if ( typeof selector === "string" ) { if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { @@ -125,15 +145,29 @@ jQuery.fn = jQuery.prototype = { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; - doc = ( context && context.nodeType ? context.ownerDocument || context : document ); // scripts is true for back-compat - selector = jQuery.parseHTML( match[1], doc, true ); + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - this.attr.call( selector, context, true ); + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } } - return jQuery.merge( this, selector ); + return this; // HANDLE: $(#id) } else { @@ -168,6 +202,12 @@ jQuery.fn = jQuery.prototype = { return this.constructor( context ).find( selector ); } + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { @@ -185,17 +225,9 @@ jQuery.fn = jQuery.prototype = { // Start with an empty selector selector: "", - // The current version of jQuery being used - jquery: "1.8.3", - // The default length of a jQuery object is 0 length: 0, - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - toArray: function() { return core_slice.call( this ); }, @@ -214,22 +246,15 @@ jQuery.fn = jQuery.prototype = { // Take an array of elements and push it onto the stack // (returning the new matched element set) - pushStack: function( elems, name, selector ) { + pushStack: function( elems ) { // Build a new jQuery matched element set var ret = jQuery.merge( this.constructor(), elems ); // Add the old object onto the stack (as a reference) ret.prevObject = this; - ret.context = this.context; - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - // Return the newly-formed element set return ret; }, @@ -248,11 +273,8 @@ jQuery.fn = jQuery.prototype = { return this; }, - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); }, first: function() { @@ -263,9 +285,10 @@ jQuery.fn = jQuery.prototype = { return this.eq( -1 ); }, - slice: function() { - return this.pushStack( core_slice.apply( this, arguments ), - "slice", core_slice.call(arguments).join(",") ); + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); }, map: function( callback ) { @@ -289,7 +312,7 @@ jQuery.fn = jQuery.prototype = { jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, + var src, copyIsArray, copy, name, options, clone, target = arguments[0] || {}, i = 1, length = arguments.length, @@ -353,6 +376,10 @@ jQuery.extend = jQuery.fn.extend = function() { }; jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; @@ -391,7 +418,7 @@ jQuery.extend({ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); + return setTimeout( jQuery.ready ); } // Remember that the DOM is ready @@ -423,6 +450,7 @@ jQuery.extend({ }, isWindow: function( obj ) { + /* jshint eqeqeq: false */ return obj != null && obj == obj.window; }, @@ -431,12 +459,17 @@ jQuery.extend({ }, type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ core_toString.call(obj) ] || "object"; + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; }, isPlainObject: function( obj ) { + var key; + // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well @@ -456,10 +489,16 @@ jQuery.extend({ return false; } + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. - - var key; for ( key in obj ) {} return key === undefined || core_hasOwn.call( obj, key ); @@ -479,50 +518,59 @@ jQuery.extend({ // data: string of html // context (optional): If specified, the fragment will be created in this context, defaults to document - // scripts (optional): If true, will include scripts passed in the html string - parseHTML: function( data, context, scripts ) { - var parsed; + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { if ( !data || typeof data !== "string" ) { return null; } if ( typeof context === "boolean" ) { - scripts = context; - context = 0; + keepScripts = context; + context = false; } context = context || document; + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + // Single tag - if ( (parsed = rsingleTag.exec( data )) ) { + if ( parsed ) { return [ context.createElement( parsed[1] ) ]; } - parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] ); - return jQuery.merge( [], - (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes ); + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); }, parseJSON: function( data ) { - if ( !data || typeof data !== "string") { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { + if ( data === null ) { + return data; + } - return ( new Function( "return " + data ) )(); + if ( typeof data === "string" ) { + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } } + jQuery.error( "Invalid JSON: " + data ); }, @@ -556,7 +604,7 @@ jQuery.extend({ // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { - if ( data && core_rnotwhite.test( data ) ) { + if ( data && jQuery.trim( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox @@ -578,21 +626,25 @@ jQuery.extend({ // args is for internal usage only each: function( obj, callback, args ) { - var name, + var value, i = 0, length = obj.length, - isObj = length === undefined || jQuery.isFunction( obj ); + isArray = isArraylike( obj ); if ( args ) { - if ( isObj ) { - for ( name in obj ) { - if ( callback.apply( obj[ name ], args ) === false ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { break; } } } else { - for ( ; i < length; ) { - if ( callback.apply( obj[ i++ ], args ) === false ) { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { break; } } @@ -600,15 +652,19 @@ jQuery.extend({ // A special, fast, case for the most common use of each } else { - if ( isObj ) { - for ( name in obj ) { - if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { break; } } } else { - for ( ; i < length; ) { - if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { break; } } @@ -635,18 +691,16 @@ jQuery.extend({ // results is for internal usage only makeArray: function( arr, results ) { - var type, - ret = results || []; + var ret = results || []; if ( arr != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - type = jQuery.type( arr ); - - if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) { - core_push.call( ret, arr ); + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); } else { - jQuery.merge( ret, arr ); + core_push.call( ret, arr ); } } @@ -684,7 +738,6 @@ jQuery.extend({ for ( ; j < l; j++ ) { first[ i++ ] = second[ j ]; } - } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; @@ -717,12 +770,11 @@ jQuery.extend({ // arg is for internal usage only map: function( elems, callback, arg ) { - var value, key, - ret = [], + var value, i = 0, length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + isArray = isArraylike( elems ), + ret = []; // Go through the array, translating each of the items to their if ( isArray ) { @@ -736,8 +788,8 @@ jQuery.extend({ // Go through every key on the object, } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; @@ -746,7 +798,7 @@ jQuery.extend({ } // Flatten any nested arrays - return ret.concat.apply( [], ret ); + return core_concat.apply( [], ret ); }, // A global GUID counter for objects @@ -755,7 +807,7 @@ jQuery.extend({ // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { - var tmp, args, proxy; + var args, proxy, tmp; if ( typeof context === "string" ) { tmp = fn[ context ]; @@ -772,7 +824,7 @@ jQuery.extend({ // Simulated bind args = core_slice.call( arguments, 2 ); proxy = function() { - return fn.apply( context, args.concat( core_slice.call( arguments ) ) ); + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed @@ -783,46 +835,46 @@ jQuery.extend({ // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function - access: function( elems, fn, key, value, chainable, emptyGet, pass ) { - var exec, - bulk = key == null, - i = 0, - length = elems.length; + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; // Sets many values - if ( key && typeof key === "object" ) { + if ( jQuery.type( key ) === "object" ) { + chainable = true; for ( i in key ) { - jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); } - chainable = 1; // Sets one value } else if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = pass === undefined && jQuery.isFunction( value ); + chainable = true; - if ( bulk ) { - // Bulk operations only iterate when executing function values - if ( exec ) { - exec = fn; - fn = function( elem, key, value ) { - return exec.call( jQuery( elem ), value ); - }; + if ( !jQuery.isFunction( value ) ) { + raw = true; + } - // Otherwise they run against the entire set - } else { + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { fn.call( elems, value ); fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; } } if ( fn ) { - for (; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); } } - - chainable = 1; } return chainable ? @@ -836,6 +888,29 @@ jQuery.extend({ now: function() { return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; } }); @@ -849,23 +924,23 @@ jQuery.ready.promise = function( obj ) { // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready, 1 ); + setTimeout( jQuery.ready ); // Standards-based browsers support DOMContentLoaded } else if ( document.addEventListener ) { // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + document.addEventListener( "DOMContentLoaded", completed, false ); // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); + window.addEventListener( "load", completed, false ); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); + document.attachEvent( "onreadystatechange", completed ); // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); + window.attachEvent( "onload", completed ); // If IE and not a frame // continually check to see if the document is ready @@ -887,6 +962,9 @@ jQuery.ready.promise = function( obj ) { return setTimeout( doScrollCheck, 50 ); } + // detach all dom ready events + detach(); + // and execute any waiting functions jQuery.ready(); } @@ -898,19 +976,2015 @@ jQuery.ready.promise = function( obj ) { }; // Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + // All jQuery objects should point back to these rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "<div class='a'></div><div class='a i'></div>"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = "<select><option selected=''></option></select>"; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = "<a href='#'></a>"; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = "<input/>"; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); // String to Object options format cache var optionsCache = {}; // Convert String-formatted options into Object-formatted ones and store in cache function createOptions( options ) { var object = optionsCache[ options ] = {}; - jQuery.each( options.split( core_rspace ), function( _, flag ) { + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; }); return object; @@ -946,18 +3020,18 @@ jQuery.Callbacks = function( options ) { ( optionsCache[ options ] || createOptions( options ) ) : jQuery.extend( {}, options ); - var // Last fire value (for non-forgettable lists) + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) memory, // Flag to know if list was already fired fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, // Actual callback list list = [], // Stack of fire calls for repeatable lists @@ -1043,13 +3117,15 @@ jQuery.Callbacks = function( options ) { } return this; }, - // Control if a given callback is in the list + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { - return jQuery.inArray( fn, list ) > -1; + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); }, // Remove all callbacks from the list empty: function() { list = []; + firingLength = 0; return this; }, // Have the list do nothing anymore @@ -1075,9 +3151,9 @@ jQuery.Callbacks = function( options ) { }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; if ( firing ) { stack.push( args ); } else { @@ -1122,22 +3198,19 @@ jQuery.extend({ return jQuery.Deferred(function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { var action = tuple[ 0 ], - fn = fns[ i ]; + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ]( jQuery.isFunction( fn ) ? - function() { - var returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - } : - newDefer[ action ] - ); + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); }); fns = null; }).promise(); @@ -1171,8 +3244,11 @@ jQuery.extend({ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); } - // deferred[ resolve | reject | notify ] = list.fire - deferred[ tuple[0] ] = list.fire; + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; deferred[ tuple[0] + "With" ] = list.fireWith; }); @@ -1240,30 +3316,20 @@ jQuery.extend({ return deferred.promise(); } }); -jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - fragment, - eventName, - i, - isSupported, - clickFn, +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, div = document.createElement("div"); // Setup div.setAttribute( "className", "t" ); div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; - // Support tests won't run in some limited or non-browser environments - all = div.getElementsByTagName("*"); + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; a = div.getElementsByTagName("a")[ 0 ]; - if ( !all || !a || !all.length ) { - return {}; + if ( !a || !a.style || !all.length ) { + return support; } // First batch of tests @@ -1272,69 +3338,60 @@ jQuery.support = (function() { input = div.getElementsByTagName("input")[ 0 ]; a.style.cssText = "top:1px;float:left;opacity:.5"; - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.5/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form (#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", - - // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode - boxModel: ( document.compatMode === "CSS1Compat" ), - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true, - boxSizingReliable: true, - pixelPosition: false - }; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; // Make sure checked status is properly cloned input.checked = true; @@ -1345,76 +3402,71 @@ jQuery.support = (function() { select.disabled = true; support.optDisabled = !opt.disabled; - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer + // Support: IE<9 try { delete div.test; } catch( e ) { support.deleteExpando = false; } - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", clickFn = function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent("onclick"); - div.detachEvent( "onclick", clickFn ); - } - - // Check if a radio maintains its value - // after being appended to the DOM + // Check if we can trust getAttribute("value") input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio input.value = "t"; input.setAttribute( "type", "radio" ); support.radioValue = input.value === "t"; - input.setAttribute( "checked", "checked" ); - // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); input.setAttribute( "name", "t" ); - div.appendChild( input ); fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + fragment.appendChild( input ); // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; - fragment.removeChild( input ); - fragment.appendChild( div ); + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() if ( div.attachEvent ) { - for ( i in { - submit: true, - change: true, - focusin: true - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; } + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + // Run tests that need a body at doc ready jQuery(function() { - var container, div, tds, marginDiv, - divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;", + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", body = document.getElementsByTagName("body")[0]; if ( !body ) { @@ -1423,20 +3475,17 @@ jQuery.support = (function() { } container = document.createElement("div"); - container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px"; - body.insertBefore( container, body.firstChild ); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); + body.appendChild( container ).appendChild( div ); + // Support: IE8 // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; tds = div.getElementsByTagName("td"); tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; @@ -1445,277 +3494,297 @@ jQuery.support = (function() { tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; + // Support: IE8 // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - // Check box-sizing and margin behavior + // Check box-sizing and margin behavior. div.innerHTML = ""; div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; - support.boxSizing = ( div.offsetWidth === 4 ); - support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); - // NOTE: To any future maintainer, we've window.getComputedStyle - // because jsdom on node.js will break without it. + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. if ( window.getComputedStyle ) { support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 + // gets computed margin-right based on width of container. (#3333) // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - marginDiv = document.createElement("div"); + marginDiv = div.appendChild( document.createElement("div") ); marginDiv.style.cssText = div.style.cssText = divReset; marginDiv.style.marginRight = marginDiv.style.width = "0"; div.style.width = "1px"; - div.appendChild( marginDiv ); + support.reliableMarginRight = !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); } - if ( typeof div.style.zoom !== "undefined" ) { + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout - // (IE < 8 does this) div.innerHTML = ""; div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + // Support: IE6 // Check if elements with layout shrink-wrap their children - // (IE 6 does this) div.style.display = "block"; - div.style.overflow = "visible"; div.innerHTML = "<div></div>"; div.firstChild.style.width = "5px"; support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); - container.style.zoom = 1; + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } } - // Null elements to avoid leaks in IE body.removeChild( container ); + + // Null elements to avoid leaks in IE container = div = tds = marginDiv = null; }); // Null elements to avoid leaks in IE - fragment.removeChild( div ); - all = a = select = opt = input = fragment = div = null; + all = select = fragment = opt = a = input = null; return support; -})(); +})({}); + var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, rmultiDash = /([A-Z])/g; -jQuery.extend({ - cache: {}, +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } - deletedIds: [], + var ret, thisCache, + internalKey = jQuery.expando, - // Remove at next major release (1.9/2.0) - uuid: 0, + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; } + } - var thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); } + } - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } + thisCache = cache[ id ]; - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; } - thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } + thisCache = thisCache.data; + } - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { - // First Try to find as-is property data - ret = thisCache[ name ]; + // First Try to find as-is property data + ret = thisCache[ name ]; - // Test for null|undefined property data - if ( ret == null ) { + // Test for null|undefined property data + if ( ret == null ) { - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; } + } else { + ret = thisCache; + } - return ret; - }, + return ret; +} - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } - var thisCache, i, l, + var thisCache, i, + isNode = elem.nodeType, - isNode = elem.nodeType, + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } + if ( name ) { - if ( name ) { + thisCache = pvt ? cache[ id ] : cache[ id ].data; - thisCache = pvt ? cache[ id ] : cache[ id ].data; + if ( thisCache ) { - if ( thisCache ) { + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { - // try the string as a key before any manipulation + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); if ( name in thisCache ) { name = [ name ]; } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split(" "); - } + name = name.split(" "); } } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { - return; - } + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; } } + } - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; } + } - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - } else if ( jQuery.support.deleteExpando || cache != cache.window ) { - delete cache[ id ]; + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; - // When all else fails, null - } else { - cache[ id ] = null; - } + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); }, // For internal use only. _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; // nodes accept data unless otherwise specified; rejection can be conditional @@ -1725,10 +3794,13 @@ jQuery.extend({ jQuery.fn.extend({ data: function( key, value ) { - var parts, part, attr, name, l, - elem = this[0], + var attrs, name, + data = null, i = 0, - data = null; + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves // Gets all values if ( key === undefined ) { @@ -1736,12 +3808,12 @@ jQuery.fn.extend({ data = jQuery.data( elem ); if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - attr = elem.attributes; - for ( l = attr.length; i < l; i++ ) { - name = attr[i].name; + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; - if ( !name.indexOf( "data-" ) ) { - name = jQuery.camelCase( name.substring(5) ); + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); dataAttr( elem, name, data[ name ] ); } @@ -1760,35 +3832,16 @@ jQuery.fn.extend({ }); } - parts = key.split( ".", 2 ); - parts[1] = parts[1] ? "." + parts[1] : ""; - part = parts[1] + "!"; - - return jQuery.access( this, function( value ) { - - if ( value === undefined ) { - data = this.triggerHandler( "getData" + part, [ parts[0] ] ); - - // Try to fetch any internally stored data first - if ( data === undefined && elem ) { - data = jQuery.data( elem, key ); - data = dataAttr( elem, key, data ); - } + return arguments.length > 1 ? - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - } - - parts[1] = value; + // Sets one value this.each(function() { - var self = jQuery( this ); - - self.triggerHandler( "setData" + part, parts ); jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + part, parts ); - }); - }, null, value, arguments.length > 1, null, false ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; }, removeData: function( key ) { @@ -1810,12 +3863,12 @@ function dataAttr( elem, key, data ) { if ( typeof data === "string" ) { try { data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; } catch( e ) {} // Make sure we set the data so it isn't changed later @@ -1905,8 +3958,8 @@ jQuery.extend({ var key = type + "queueHooks"; return jQuery._data( elem, key ) || jQuery._data( elem, key, { empty: jQuery.Callbacks("once memory").add(function() { - jQuery.removeData( elem, type + "queue", true ); - jQuery.removeData( elem, key, true ); + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); }) }); } @@ -1991,14 +4044,14 @@ jQuery.fn.extend({ return defer.promise( obj ); } }); -var nodeHook, boolHook, fixSpecified, - rclass = /[\t\r\n]/g, +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea|)$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute; + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; jQuery.fn.extend({ attr: function( name, value ) { @@ -2027,35 +4080,37 @@ jQuery.fn.extend({ }, addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); + jQuery( this ).addClass( value.call( this, j, this.className ) ); }); } - if ( value && typeof value === "string" ) { - classNames = value.split( core_rspace ); + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; - for ( i = 0, l = this.length; i < l; i++ ) { + for ( ; i < len; i++ ) { elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) { - setClass += classNames[ c ] + " "; - } + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; } - elem.className = jQuery.trim( setClass ); } + elem.className = jQuery.trim( cur ); + } } } @@ -2064,30 +4119,36 @@ jQuery.fn.extend({ }, removeClass: function( value ) { - var removes, className, elem, c, cl, i, l; + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); + jQuery( this ).removeClass( value.call( this, j, this.className ) ); }); } - if ( (value && typeof value === "string") || value === undefined ) { - removes = ( value || "" ).split( core_rspace ); + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; - for ( i = 0, l = this.length; i < l; i++ ) { + for ( ; i < len; i++ ) { elem = this[ i ]; - if ( elem.nodeType === 1 && elem.className ) { - - className = (" " + elem.className + " ").replace( rclass, " " ); + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); - // loop over each item in the removal list - for ( c = 0, cl = removes.length; c < cl; c++ ) { - // Remove until there is nothing to remove, - while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) { - className = className.replace( " " + removes[ c ] + " " , " " ); + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); } } - elem.className = value ? jQuery.trim( className ) : ""; + elem.className = value ? jQuery.trim( cur ) : ""; } } } @@ -2096,8 +4157,11 @@ jQuery.fn.extend({ }, toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { @@ -2111,22 +4175,28 @@ jQuery.fn.extend({ var className, i = 0, self = jQuery( this ), - state = stateVal, - classNames = value.split( core_rspace ); + classNames = value.match( core_rnotwhite ) || []; while ( (className = classNames[ i++ ]) ) { // check each className given, space separated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } } - } else if ( type === "undefined" || type === "boolean" ) { + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } - // toggle whole className + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); @@ -2146,7 +4216,7 @@ jQuery.fn.extend({ }, val: function( value ) { - var hooks, ret, isFunction, + var ret, hooks, isFunction, elem = this[0]; if ( !arguments.length ) { @@ -2172,15 +4242,14 @@ jQuery.fn.extend({ isFunction = jQuery.isFunction( value ); return this.each(function( i ) { - var val, - self = jQuery(this); + var val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { - val = value.call( this, i, self.val() ); + val = value.call( this, i, jQuery( this ).val() ); } else { val = value; } @@ -2210,10 +4279,11 @@ jQuery.extend({ valHooks: { option: { get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; } }, select: { @@ -2255,13 +4325,20 @@ jQuery.extend({ }, set: function( elem, value ) { - var values = jQuery.makeArray( value ); + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } - if ( !values.length ) { + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { elem.selectedIndex = -1; } return values; @@ -2269,11 +4346,8 @@ jQuery.extend({ } }, - // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9 - attrFn: {}, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, + attr: function( elem, name, value ) { + var hooks, ret, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes @@ -2281,31 +4355,25 @@ jQuery.extend({ return; } - if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) { - return jQuery( elem )[ name ]( value ); - } - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { + if ( typeof elem.getAttribute === core_strundefined ) { return jQuery.prop( elem, name, value ); } - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - // All attributes are lowercase // Grab necessary hook if one is defined - if ( notxml ) { + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); - return; - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { @@ -2313,47 +4381,46 @@ jQuery.extend({ return value; } - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { - - ret = elem.getAttribute( name ); + ret = jQuery.find.attr( elem, name ); // Non-existent attributes return null, we normalize to undefined - return ret === null ? + return ret == null ? undefined : ret; } }, removeAttr: function( elem, value ) { - var propName, attrNames, name, isBool, - i = 0; - - if ( value && elem.nodeType === 1 ) { - - attrNames = value.split( core_rspace ); - - for ( ; i < attrNames.length; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = jQuery.propFix[ name ] || name; - isBool = rboolean.test( name ); + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); - // See #9699 for explanation of this approach (setting first, then removal) - // Do not do this for boolean attributes (see #10870) - if ( !isBool ) { - jQuery.attr( elem, name, "" ); - } - elem.removeAttribute( getSetAttribute ? name : propName ); + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; - // Set corresponding property to false for boolean attributes - if ( isBool && propName in elem ) { + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); } + + elem.removeAttribute( getSetAttribute ? name : propName ); } } }, @@ -2361,13 +4428,9 @@ jQuery.extend({ attrHooks: { type: { set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation + // Reset value to default in case type is set after value during creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { @@ -2376,41 +4439,12 @@ jQuery.extend({ return value; } } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } } }, propFix: { - tabindex: "tabIndex", - readonly: "readOnly", "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" + "class": "className" }, prop: function( elem, name, value ) { @@ -2431,20 +4465,14 @@ jQuery.extend({ } if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; } }, @@ -2453,115 +4481,154 @@ jQuery.extend({ get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : + return tabindex ? + parseInt( tabindex, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : - undefined; + -1; } } } }); -// Hook for boolean attributes +// Hooks for boolean attributes boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, set: function( elem, value, name ) { - var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); - elem.setAttribute( name, name.toLowerCase() ); + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; } + return name; } }; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !getSetAttribute ) { - fixSpecified = { - name: true, - id: true, - coords: true - }; - // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ? - ret.value : - undefined; - }, + nodeHook = { set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); } - return ( ret.value = value + "" ); + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); } }; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + jQuery.attrHooks[ name ] = { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } - }); + }; }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; } // Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; + return elem.getAttribute( name, 4 ); } - }); + }; }); } @@ -2569,8 +4636,9 @@ if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; }, set: function( elem, value ) { return ( elem.style.cssText = value + "" ); @@ -2581,7 +4649,7 @@ if ( !jQuery.support.style ) { // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + jQuery.propHooks.selected = { get: function( elem ) { var parent = elem.parentNode; @@ -2595,43 +4663,65 @@ if ( !jQuery.support.optSelected ) { } return null; } - }); + }; } +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + // IE6/7 call enctype encoding if ( !jQuery.support.enctype ) { jQuery.propFix.enctype = "encoding"; } // Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + jQuery.valHooks[ this ] = { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } - }); + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } }); -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/, - rhoverHack = /(?:^|\s)hover(\.\S+|)\b/, +var rformElems = /^(?:input|select|textarea)$/i, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - hoverHack = function( events ) { - return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} /* * Helper functions for managing events -- not part of the public interface. @@ -2639,14 +4729,16 @@ var rformElems = /^(?:textarea|input|select)$/i, */ jQuery.event = { - add: function( elem, types, handler, data, selector ) { + global: {}, - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, handlers, special; + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { return; } @@ -2663,16 +4755,14 @@ jQuery.event = { } // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; + if ( !(events = elemData.events) ) { + events = elemData.events = {}; } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; @@ -2681,13 +4771,17 @@ jQuery.event = { } // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; @@ -2701,7 +4795,7 @@ jQuery.event = { // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, - origType: tns[1], + origType: origType, data: data, handler: handler, guid: handler.guid, @@ -2711,8 +4805,7 @@ jQuery.event = { }, handleObjIn ); // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { + if ( !(handlers = events[ type ]) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; @@ -2751,13 +4844,12 @@ jQuery.event = { elem = null; }, - global: {}, - // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { - - var t, tns, type, origType, namespaces, origCount, - j, events, special, eventType, handleObj, + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, elemData = jQuery.hasData( elem ) && jQuery._data( elem ); if ( !elemData || !(events = elemData.events) ) { @@ -2765,11 +4857,12 @@ jQuery.event = { } // Once for each type.namespace in types; type may be omitted - types = jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { @@ -2780,23 +4873,23 @@ jQuery.event = { } special = jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); if ( handleObj.selector ) { - eventType.delegateCount--; + handlers.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); @@ -2806,7 +4899,7 @@ jQuery.event = { // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( origCount && !handlers.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } @@ -2821,80 +4914,48 @@ jQuery.event = { // removeData also checks for emptiness and clears the expando if empty // so use it instead of delete - jQuery.removeData( elem, "events", true ); + jQuery._removeData( elem, "events" ); } }, - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } - // Event object or event type - var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType, - type = event.type || event, - namespaces = []; - // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { + if ( type.indexOf(".") >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } + ontype = type.indexOf(":") < 0 && "on" + type; - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; // Clean up the event in case it is being reused event.result = undefined; @@ -2903,44 +4964,50 @@ jQuery.event = { } // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - for ( old = elem; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old === (elem.ownerDocument || document) ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - cur = eventPath[i][0]; - event.type = eventPath[i][1]; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + // jQuery handler handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } - // Note that this is a bare JS function and not a jQuery handler + + // Native handler handle = ontype && cur[ ontype ]; if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { event.preventDefault(); @@ -2951,29 +5018,33 @@ jQuery.event = { // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction() check here because IE6/7 fails that test. // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; + tmp = elem[ ontype ]; - if ( old ) { + if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; - elem[ type ](); + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } jQuery.event.triggered = undefined; - if ( old ) { - elem[ ontype ] = old; + if ( tmp ) { + elem[ ontype ] = tmp; } } } @@ -2985,15 +5056,13 @@ jQuery.event = { dispatch: function( event ) { // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event || window.event ); + event = jQuery.event.fix( event ); - var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related, - handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, + var i, ret, handleObj, matched, j, + handlerQueue = [], args = core_slice.call( arguments ), - run_all = !event.exclusive && !event.namespace, - special = jQuery.event.special[ event.type ] || {}, - handlerQueue = []; + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; @@ -3004,81 +5073,142 @@ jQuery.event = { return; } - // Determine handlers that should run if there are delegated events + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG <use> instance trees (#13180) // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !(event.button && event.type === "click") ) { + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ - // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - selMatch = {}; + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { matches = []; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; - sel = handleObj.selector; - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = handleObj.needsContext ? + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? jQuery( sel, this ).index( cur ) >= 0 : jQuery.find( sel, this, null, [ cur ] ).length; } - if ( selMatch[ sel ] ) { + if ( matches[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); + handlerQueue.push({ elem: cur, handlers: matches }); } } } } // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); } - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; + return handlerQueue; + }, - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; - event.data = handleObj.data; - event.handleObj = handleObj; + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); + event = new jQuery.Event( originalEvent ); - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; } - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; } - return event.result; + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; }, // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, @@ -3098,7 +5228,7 @@ jQuery.event = { mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { - var eventDoc, doc, body, + var body, eventDoc, doc, button = original.button, fromElement = original.fromElement; @@ -3127,64 +5257,57 @@ jQuery.event = { } }, - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8) - event.metaKey = !!event.metaKey; - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, - focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, delegateType: "focusin" }, blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, delegateType: "focusout" }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; } }, - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; } } } @@ -3197,7 +5320,8 @@ jQuery.event = { var e = jQuery.extend( new jQuery.Event(), event, - { type: type, + { + type: type, isSimulated: true, originalEvent: {} } @@ -3213,10 +5337,6 @@ jQuery.event = { } }; -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -jQuery.event.handle = jQuery.event.dispatch; - jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { @@ -3230,7 +5350,7 @@ jQuery.removeEvent = document.removeEventListener ? // #8545, #7054, preventing memory leaks for custom events in IE6-8 // detachEvent needed property on element, by name of that event, to properly expose it to GC - if ( typeof elem[ name ] === "undefined" ) { + if ( typeof elem[ name ] === core_strundefined ) { elem[ name ] = null; } @@ -3271,54 +5391,51 @@ jQuery.Event = function( src, props ) { this[ jQuery.expando ] = true; }; -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + preventDefault: function() { var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; if ( !e ) { return; } - // if preventDefault exists run it on the original event + // If preventDefault exists, run it on the original event if ( e.preventDefault ) { e.preventDefault(); - // otherwise set the returnValue property of the original event to false (IE) + // Support: IE + // Otherwise set the returnValue property of the original event to false } else { e.returnValue = false; } }, stopPropagation: function() { - this.isPropagationStopped = returnTrue; - var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; if ( !e ) { return; } - // if stopPropagation exists run it on the original event + // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } - // otherwise set the cancelBubble property of the original event to true (IE) + + // Support: IE + // Set the cancelBubble property of the original event to true e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse + } }; // Create mouseenter/leave events using mouseover/out and event-time checks @@ -3334,8 +5451,7 @@ jQuery.each({ var ret, target = this, related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector; + handleObj = event.handleObj; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window @@ -3364,11 +5480,11 @@ if ( !jQuery.support.submitBubbles ) { // Node name check avoids a VML-related crash in IE (#9807) var elem = e.target, form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !jQuery._data( form, "_submit_attached" ) ) { + if ( form && !jQuery._data( form, "submitBubbles" ) ) { jQuery.event.add( form, "submit._submit", function( event ) { event._submit_bubble = true; }); - jQuery._data( form, "_submit_attached", true ); + jQuery._data( form, "submitBubbles", true ); } }); // return undefined since we don't need an event listener @@ -3427,13 +5543,13 @@ if ( !jQuery.support.changeBubbles ) { jQuery.event.add( this, "beforeactivate._change", function( e ) { var elem = e.target; - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) { + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { jQuery.event.add( elem, "change._change", function( event ) { if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { jQuery.event.simulate( "change", this.parentNode, event, true ); } }); - jQuery._data( elem, "_change_attached", true ); + jQuery._data( elem, "changeBubbles", true ); } }); }, @@ -3483,12 +5599,12 @@ if ( !jQuery.support.focusinBubbles ) { jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; + var type, origFn; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { // && selector != null + if ( typeof selector !== "string" ) { // ( types-Object, data ) data = data || selector; selector = undefined; @@ -3570,1790 +5686,20 @@ jQuery.fn.extend({ }); }, - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - }, - trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( rkeyEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - outermostContext, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - Token = String, - document = window.document, - docElem = document.documentElement, - dirruns = 0, - done = 0, - pop = [].pop, - push = [].push, - slice = [].slice, - // Use a stripped-down indexOf if a native one is unavailable - indexOf = [].indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value == null || value; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157) - return (cache[ key + " " ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "POS": new RegExp( pos, "i" ), - "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = "<a href='#'></a>"; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = "<select></select>"; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>"; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>"; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, - results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -// Returns a function to use in pseudos for positionals -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var val, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( (val = Expr.attrHandle[ name ]) ) { - return val( elem ); - } - if ( xml || assertAttributes ) { - return elem.getAttribute( name ); - } - val = elem.getAttributeNode( name ); - return val ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - val.specified ? val.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": assertUsableName && function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": assertUsableClassName && function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem, context ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.substr( result.length - check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - return function( elem ) { - var node, diff, - parent = elem.parentNode; - - if ( first === 1 && last === 0 ) { - return true; - } - - if ( parent ) { - diff = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - diff++; - if ( elem === node ) { - break; - } - } - } - } - - // Incorporate the offset (or cast to NaN), then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - }, - - // Positional types - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - for ( var i = 0; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - for ( var i = 1; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - i = 1, - j = 0; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - - // Cast descendant combinators to space - matched.type = match[0].replace( rtrim, " " ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - matched.type = type; - matched.matches = match; - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && combinator.dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( !xml ) { - var cache, - dirkey = dirruns + " " + doneName + " ", - cachedkey = dirkey + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context, xml ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( matcher( elem, context, xml ) ) { - return elem; - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && tokens.join("") - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Nested matchers should use non-integer dirruns - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = superMatcher.el; - } - - // Add elements passing elementMatchers directly to results - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - for ( j = 0; (matcher = elementMatchers[j]); j++ ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++superMatcher.el; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - for ( j = 0; (matcher = setMatchers[j]); j++ ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - superMatcher.el = 0; - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ expando ][ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function select( selector, context, results, seed, xml ) { - var i, tokens, token, type, find, - match = tokenize( selector ), - j = match.length; - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && !xml && - Expr.relative[ tokens[1].type ] ) { - - context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - // Fetch a seed set for right-to-left matching - for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( rbackslash, "" ), - rsibling.test( tokens[0].type ) && context.parentNode || context, - xml - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && tokens.join(""); - if ( !selector ) { - push.apply( results, slice.call( seed, 0 ) ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - xml, - results, - rsibling.test( selector ) - ); - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - - // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA - // A support test would require too much code (would include document ready) - rbuggyQSA = [ ":focus" ], - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [ ":active" ], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select><option selected=''></option></select>"; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "<p test=''></p>"; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = "<input type='hidden'/>"; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - // rbuggyQSA always contains :focus, so no need for a length check - rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && !rbuggyQSA.test( selector ) ) { - var groups, i, - old = true, - nid = expando, - newContext = context, - newSelector = context.nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + groups[i].join(""); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, slice.call( newContext.querySelectorAll( - newSelector - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( "!=", pseudos ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active and :focus, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Back-compat -function setFilters() {} -Expr.filters = setFilters.prototype = Expr.pseudos; -Expr.setFilters = new setFilters(); - -// Override sizzle attribute retrieval -Sizzle.attr = jQuery.attr; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})( window ); -var runtil = /Until$/, +var isSimple = /^.[^:#\[\.,]*$/, rparentsprev = /^(?:parents|prev(?:Until|All))/, - isSimple = /^.[^:#\[\.,]*$/, rneedsContext = jQuery.expr.match.needsContext, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { @@ -5365,38 +5711,28 @@ var runtil = /Until$/, jQuery.fn.extend({ find: function( selector ) { - var i, l, length, n, r, ret, - self = this; + var i, + ret = [], + self = this, + len = self.length; if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } - }); + }) ); } - ret = this.pushStack( "", "find", selector ); - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); } + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; return ret; }, @@ -5415,22 +5751,24 @@ jQuery.fn.extend({ }, not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); + return this.pushStack( winnow(this, selector || [], true) ); }, filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); + return this.pushStack( winnow(this, selector || [], false) ); }, is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - rneedsContext.test( selector ) ? - jQuery( selector, this.context ).index( this[0] ) >= 0 : - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; }, closest: function( selectors, context ) { @@ -5443,20 +5781,22 @@ jQuery.fn.extend({ 0; for ( ; i < l; i++ ) { - cur = this[i]; + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { - while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); + cur = ret.push( cur ); break; } - cur = cur.parentNode; } } - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); }, // Determine the position of an element within @@ -5465,7 +5805,7 @@ jQuery.fn.extend({ // No argument, return index in parent if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; } // index in selector @@ -5485,9 +5825,7 @@ jQuery.fn.extend({ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); + return this.pushStack( jQuery.unique(all) ); }, addBack: function( selector ) { @@ -5497,14 +5835,6 @@ jQuery.fn.extend({ } }); -jQuery.fn.andSelf = jQuery.fn.addBack; - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - function sibling( cur, dir ) { do { cur = cur[ dir ]; @@ -5557,7 +5887,7 @@ jQuery.each({ jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); - if ( !runtil.test( name ) ) { + if ( name.slice( -5 ) !== "Until" ) { selector = until; } @@ -5565,25 +5895,35 @@ jQuery.each({ ret = jQuery.filter( selector, ret ); } - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } - if ( this.length > 1 && rparentsprev.test( name ) ) { - ret = ret.reverse(); + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } } - return this.pushStack( ret, name, core_slice.call( arguments ).join(",") ); + return this.pushStack( ret ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + if ( not ) { expr = ":not(" + expr + ")"; } - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); }, dir: function( elem, dir, until ) { @@ -5613,42 +5953,37 @@ jQuery.extend({ }); // Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - +function winnow( elements, qualifier, not ) { if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; }); - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); + } - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; }); + } + + if ( typeof qualifier === "string" ) { if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); + return jQuery.filter( qualifier, elements, not ); } + + qualifier = jQuery.filter( qualifier, elements ); } - return jQuery.grep(elements, function( elem, i ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; }); } function createSafeFragment( document ) { var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); + safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) { while ( list.length ) { @@ -5663,28 +5998,34 @@ function createSafeFragment( document ) { var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, rtagName = /<([\w:]+)/, rtbody = /<tbody/i, rhtml = /<|&#?\w+;/, rnoInnerhtml = /<(?:script|style|link)/i, - rnocache = /<(?:script|object|embed|option|style)/i, - rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), - rcheckableType = /^(?:checkbox|radio)$/, + manipulation_rcheckableType = /^(?:checkbox|radio)$/i, // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /\/(java|ecma)script/i, - rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g, + rscriptType = /^$|\/(?:java|ecma)script/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, + + // We have to close these tags to support XHTML (#13200) wrapMap = { option: [ 1, "<select multiple='multiple'>", "</select>" ], legend: [ 1, "<fieldset>", "</fieldset>" ], + area: [ 1, "<map>", "</map>" ], + param: [ 1, "<object>", "</object>" ], thead: [ 1, "<table>", "</table>" ], tr: [ 2, "<table><tbody>", "</tbody></table>" ], - td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], - area: [ 1, "<map>", "</map>" ], - _default: [ 0, "", "" ] + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ] }, safeFragment = createSafeFragment( document ), fragmentDiv = safeFragment.appendChild( document.createElement("div") ); @@ -5693,12 +6034,6 @@ wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; -// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, -// unless wrapped in a div with non-breaking characters in front of it. -if ( !jQuery.support.htmlSerialize ) { - wrapMap._default = [ 1, "X<div>", "</div>" ]; -} - jQuery.fn.extend({ text: function( value ) { return jQuery.access( this, function( value ) { @@ -5708,128 +6043,57 @@ jQuery.fn.extend({ }, null, value, arguments.length ); }, - wrapAll: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapAll( html.call(this, i) ); - }); - } - - if ( this[0] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); - - if ( this[0].parentNode ) { - wrap.insertBefore( this[0] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { - elem = elem.firstChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function(i) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - }, - append: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.appendChild( elem ); + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); } }); }, prepend: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.insertBefore( elem, this.firstChild ); + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); } }); }, before: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( set, this ), "before", this.selector ); - } + } + }); }, after: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( this, set ), "after", this.selector ); - } + } + }); }, // keepData is for internal use only--do not document remove: function( selector, keepData ) { var elem, + elems = selector ? jQuery.filter( selector, this ) : this, i = 0; - for ( ; (elem = this[i]) != null; i++ ) { - if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); - jQuery.cleanData( [ elem ] ); - } + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); } + elem.parentNode.removeChild( elem ); } } @@ -5843,13 +6107,19 @@ jQuery.fn.extend({ for ( ; (elem = this[i]) != null; i++ ) { // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( getAll( elem, false ) ); } // Remove any remaining nodes while ( elem.firstChild ) { elem.removeChild( elem.firstChild ); } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } } return this; @@ -5889,7 +6159,7 @@ jQuery.fn.extend({ // Remove element nodes and prevent memory leaks elem = this[i] || {}; if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName( "*" ) ); + jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } @@ -5906,73 +6176,65 @@ jQuery.fn.extend({ }, null, value, arguments.length ); }, - replaceWith: function( value ) { - if ( !isDisconnected( this[0] ) ) { - // Make sure that the elements are removed from the DOM before they are inserted - // this can help fix replacing a parent with child elements - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this), old = self.html(); - self.replaceWith( value.call( this, i, old ) ); - }); - } + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; - if ( typeof value !== "string" ) { - value = jQuery( value ).detach(); - } + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; - return this.each(function() { - var next = this.nextSibling, - parent = this.parentNode; - - jQuery( this ).remove(); - - if ( next ) { - jQuery(next).before( value ); - } else { - jQuery(parent).append( value ); + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; } - }); - } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); - return this.length ? - this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : - this; + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); }, detach: function( selector ) { return this.remove( selector, true ); }, - domManip: function( args, table, callback ) { + domManip: function( args, callback, allowIntersection ) { // Flatten any nested arrays - args = [].concat.apply( [], args ); + args = core_concat.apply( [], args ); - var results, first, fragment, iNoClone, + var first, node, hasScripts, + scripts, doc, fragment, i = 0, + l = this.length, + set = this, + iNoClone = l - 1, value = args[0], - scripts = [], - l = this.length; + isFunction = jQuery.isFunction( value ); // We can't cloneNode fragments that contain checked, in WebKit - if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) { - return this.each(function() { - jQuery(this).domManip( args, table, callback ); - }); - } - - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - args[0] = value.call( this, i, table ? self.html() : undefined ); - self.domManip( args, table, callback ); + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); }); } - if ( this[0] ) { - results = jQuery.buildFragment( args, this, scripts ); - fragment = results.fragment; + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); first = fragment.firstChild; if ( fragment.childNodes.length === 1 ) { @@ -5980,49 +6242,50 @@ jQuery.fn.extend({ } if ( first ) { - table = table && jQuery.nodeName( first, "tr" ); + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; // Use the original fragment for the last item instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). - // Fragments from the fragment cache must always be cloned and never used in place. - for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) { - callback.call( - table && jQuery.nodeName( this[i], "table" ) ? - findOrAppend( this[i], "tbody" ) : - this[i], - i === iNoClone ? - fragment : - jQuery.clone( fragment, true, true ) - ); - } - } + for ( ; i < l; i++ ) { + node = fragment; - // Fix #11809: Avoid leaking memory - fragment = first = null; + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); - if ( scripts.length ) { - jQuery.each( scripts, function( i, elem ) { - if ( elem.src ) { - if ( jQuery.ajax ) { - jQuery.ajax({ - url: elem.src, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); - } else { - jQuery.error("no ajax"); + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); } - } else { - jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) ); } - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } } - }); + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; } } @@ -6030,8 +6293,39 @@ jQuery.fn.extend({ } }); -function findOrAppend( elem, tag ) { - return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } } function cloneCopyEvent( src, dest ) { @@ -6062,31 +6356,36 @@ function cloneCopyEvent( src, dest ) { } } -function cloneFixAttributes( src, dest ) { - var nodeName; +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; // We do not need to do anything for non-Elements if ( dest.nodeType !== 1 ) { return; } - // clearAttributes removes the attributes, which we don't want, - // but also removes the attachEvent events, which we *do* want - if ( dest.clearAttributes ) { - dest.clearAttributes(); - } + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } - // mergeAttributes, in contrast, only merges back on the - // original attributes, not the events - if ( dest.mergeAttributes ) { - dest.mergeAttributes( src ); + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); } - nodeName = dest.nodeName.toLowerCase(); + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); - if ( nodeName === "object" ) { - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { if ( dest.parentNode ) { dest.outerHTML = src.outerHTML; } @@ -6095,11 +6394,11 @@ function cloneFixAttributes( src, dest ) { // element in IE9, the outerHTML strategy above is not sufficient. // If the src has innerHTML and the destination does not, // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) { + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { dest.innerHTML = src.innerHTML; } - } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { // IE6-8 fails to persist the checked state of a cloned checkbox // or radio button. Worse, IE6-7 fail to give the cloned element // a checked appearance if the defaultChecked value isn't also set @@ -6115,66 +6414,15 @@ function cloneFixAttributes( src, dest ) { // IE6-8 fails to return the selected option to the default selected // state when cloning options } else if ( nodeName === "option" ) { - dest.selected = src.defaultSelected; + dest.defaultSelected = dest.selected = src.defaultSelected; // IE6-8 fails to set the defaultValue to the correct value when // cloning other types of input fields } else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; - - // IE blanks contents when cloning scripts - } else if ( nodeName === "script" && dest.text !== src.text ) { - dest.text = src.text; } - - // Event data gets referenced instead of copied if the expando - // gets copied too - dest.removeAttribute( jQuery.expando ); } -jQuery.buildFragment = function( args, context, scripts ) { - var fragment, cacheable, cachehit, - first = args[ 0 ]; - - // Set context from what may come in as undefined or a jQuery collection or a node - // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 & - // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception - context = context || document; - context = !context.nodeType && context[0] || context; - context = context.ownerDocument || context; - - // Only cache "small" (1/2 KB) HTML strings that are associated with the main document - // Cloning options loses the selected state, so don't cache them - // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment - // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache - // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 - if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document && - first.charAt(0) === "<" && !rnocache.test( first ) && - (jQuery.support.checkClone || !rchecked.test( first )) && - (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { - - // Mark cacheable and look for a hit - cacheable = true; - fragment = jQuery.fragments[ first ]; - cachehit = fragment !== undefined; - } - - if ( !fragment ) { - fragment = context.createDocumentFragment(); - jQuery.clean( args, context, fragment, scripts ); - - // Update the cache, but only store false - // unless this is a second parsing of the same content - if ( cacheable ) { - jQuery.fragments[ first ] = cachehit && fragment; - } - } - - return { fragment: fragment, cacheable: cacheable }; -}; - -jQuery.fragments = {}; - jQuery.each({ appendTo: "append", prependTo: "prepend", @@ -6187,49 +6435,53 @@ jQuery.each({ i = 0, ret = [], insert = jQuery( selector ), - l = insert.length, - parent = this.length === 1 && this[0].parentNode; + last = insert.length - 1; - if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) { - insert[ original ]( this[0] ); - return this; - } else { - for ( ; i < l; i++ ) { - elems = ( i > 0 ? this.clone(true) : this ).get(); - jQuery( insert[i] )[ original ]( elems ); - ret = ret.concat( elems ); - } + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); - return this.pushStack( ret, name, insert.selector ); + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); } + + return this.pushStack( ret ); }; }); -function getAll( elem ) { - if ( typeof elem.getElementsByTagName !== "undefined" ) { - return elem.getElementsByTagName( "*" ); - - } else if ( typeof elem.querySelectorAll !== "undefined" ) { - return elem.querySelectorAll( "*" ); +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; - } else { - return []; + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; } -// Used in clean, fixes the defaultChecked property +// Used in buildFragment, fixes the defaultChecked property function fixDefaultChecked( elem ) { - if ( rcheckableType.test( elem.type ) ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { elem.defaultChecked = elem.checked; } } jQuery.extend({ clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var srcElements, - destElements, - i, - clone; + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { clone = elem.cloneNode( true ); @@ -6242,185 +6494,175 @@ jQuery.extend({ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { - // IE copies events bound via attachEvent when using cloneNode. - // Calling detachEvent on the clone will also remove the events - // from the original. In order to get around this, we use some - // proprietary methods to clear the events. Thanks to MooTools - // guys for this hotness. - cloneFixAttributes( elem, clone ); - - // Using Sizzle here is crazy slow, so we use getElementsByTagName instead - srcElements = getAll( elem ); + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); + srcElements = getAll( elem ); - // Weird iteration because IE will replace the length property - // with an element if you are cloning the body and one of the - // elements on the page has a name or id of "length" - for ( i = 0; srcElements[i]; ++i ) { + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { // Ensure that the destination node is not null; Fixes #9587 if ( destElements[i] ) { - cloneFixAttributes( srcElements[i], destElements[i] ); + fixCloneNodeIssues( node, destElements[i] ); } } } // Copy the events from the original to the clone if ( dataAndEvents ) { - cloneCopyEvent( elem, clone ); - if ( deepDataAndEvents ) { - srcElements = getAll( elem ); - destElements = getAll( clone ); + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); - for ( i = 0; srcElements[i]; ++i ) { - cloneCopyEvent( srcElements[i], destElements[i] ); + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); } + } else { + cloneCopyEvent( elem, clone ); } } - srcElements = destElements = null; + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; // Return the cloned set return clone; }, - clean: function( elems, context, fragment, scripts ) { - var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags, - safe = context === document && safeFragment, - ret = []; + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, - // Ensure that context is a document - if ( !context || typeof context.createDocumentFragment === "undefined" ) { - context = document; - } + // Ensure a safe fragment + safe = createSafeFragment( context ), - // Use the already-created safe fragment if context permits - for ( i = 0; (elem = elems[i]) != null; i++ ) { - if ( typeof elem === "number" ) { - elem += ""; - } + nodes = [], + i = 0; - if ( !elem ) { - continue; - } + for ( ; i < l; i++ ) { + elem = elems[ i ]; - // Convert html string into DOM nodes - if ( typeof elem === "string" ) { - if ( !rhtml.test( elem ) ) { - elem = context.createTextNode( elem ); - } else { - // Ensure a safe container in which to render the html - safe = safe || createSafeFragment( context ); - div = context.createElement("div"); - safe.appendChild( div ); + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(rxhtmlTag, "<$1></$2>"); + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); - // Go to html and back, then peel off extra wrappers + // Deserialize a standard representation tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; - depth = wrap[0]; - div.innerHTML = wrap[1] + elem + wrap[2]; - // Move to the right depth - while ( depth-- ) { - div = div.lastChild; + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); } // Remove IE's autoinserted <tbody> from table fragments if ( !jQuery.support.tbody ) { // String was a <table>, *may* have spurious <tbody> - hasBody = rtbody.test(elem); - tbody = tag === "table" && !hasBody ? - div.firstChild && div.firstChild.childNodes : - - // String was a bare <thead> or <tfoot> - wrap[1] === "<table>" && !hasBody ? - div.childNodes : - []; - - for ( j = tbody.length - 1; j >= 0 ; --j ) { - if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { - tbody[ j ].parentNode.removeChild( tbody[ j ] ); + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); } } } - // IE completely kills leading whitespace when innerHTML is used - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); - } + jQuery.merge( nodes, tmp.childNodes ); - elem = div.childNodes; + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; - // Take out of fragment container (we need a fresh div each time) - div.parentNode.removeChild( div ); - } - } + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } - if ( elem.nodeType ) { - ret.push( elem ); - } else { - jQuery.merge( ret, elem ); + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } } } - // Fix #11356: Clear elements from safeFragment - if ( div ) { - elem = div = safe = null; + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); } // Reset defaultChecked for any radios and checkboxes // about to be appended to the DOM in IE 6/7 (#8060) if ( !jQuery.support.appendChecked ) { - for ( i = 0; (elem = ret[i]) != null; i++ ) { - if ( jQuery.nodeName( elem, "input" ) ) { - fixDefaultChecked( elem ); - } else if ( typeof elem.getElementsByTagName !== "undefined" ) { - jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); - } - } + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); } - // Append elements to a provided document fragment - if ( fragment ) { - // Special handling of each script element - handleScript = function( elem ) { - // Check if we consider it executable - if ( !elem.type || rscriptType.test( elem.type ) ) { - // Detach the script and store it in the scripts array (if provided) or the fragment - // Return truthy to indicate that it has been handled - return scripts ? - scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) : - fragment.appendChild( elem ); - } - }; + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); - for ( i = 0; (elem = ret[i]) != null; i++ ) { - // Check if we're done after handling an executable script - if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) { - // Append to fragment and handle embedded scripts - fragment.appendChild( elem ); - if ( typeof elem.getElementsByTagName !== "undefined" ) { - // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration - jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript ); - - // Splice the scripts into ret after their former ancestor and advance our index beyond them - ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); - i += jsTags.length; + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); } } } } - return ret; + tmp = null; + + return safe; }, cleanData: function( elems, /* internal */ acceptData ) { - var data, id, elem, type, + var elem, type, id, data, i = 0, internalKey = jQuery.expando, cache = jQuery.cache, @@ -6458,86 +6700,100 @@ jQuery.extend({ if ( deleteExpando ) { delete elem[ internalKey ]; - } else if ( elem.removeAttribute ) { + } else if ( typeof elem.removeAttribute !== core_strundefined ) { elem.removeAttribute( internalKey ); } else { elem[ internalKey ] = null; } - jQuery.deletedIds.push( id ); + core_deletedIds.push( id ); } } } } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); } }); -// Limit scope pollution from any deprecated API -(function() { +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } -var matched, browser; + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); -// Use of jQuery.browser is frowned upon. -// More details: http://api.jquery.com/jQuery.browser -// jQuery.uaMatch maintained for back-compat -jQuery.uaMatch = function( ua ) { - ua = ua.toLowerCase(); + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } - var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || - /(webkit)[ \/]([\w.]+)/.exec( ua ) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || - /(msie) ([\w.]+)/.exec( ua ) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || - []; + wrap.map(function() { + var elem = this; - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; -}; + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } -matched = jQuery.uaMatch( navigator.userAgent ); -browser = {}; + return elem; + }).append( this ); + } -if ( matched.browser ) { - browser[ matched.browser ] = true; - browser.version = matched.version; -} + return this; + }, -// Chrome is Webkit, but Webkit is also Safari. -if ( browser.chrome ) { - browser.webkit = true; -} else if ( browser.webkit ) { - browser.safari = true; -} + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } -jQuery.browser = browser; + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); -jQuery.sub = function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } + if ( contents.length ) { + contents.wrapAll( html ); - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; -}; + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, -})(); -var curCSS, iframe, iframeDoc, + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, ralpha = /alpha\([^)]*\)/i, - ropacity = /opacity=([^)]*)/, + ropacity = /opacity\s*=\s*([^)]*)/, rposition = /^(top|right|bottom|left)$/, // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display @@ -6545,7 +6801,7 @@ var curCSS, iframe, iframeDoc, rmargin = /^margin/, rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), - rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), elemdisplay = { BODY: "block" }, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, @@ -6555,9 +6811,7 @@ var curCSS, iframe, iframeDoc, }, cssExpand = [ "Top", "Right", "Bottom", "Left" ], - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], - - eventsToggle = jQuery.fn.toggle; + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; // return a css property mapped to a potentially vendor prefixed property function vendorPropName( style, name ) { @@ -6583,12 +6837,14 @@ function vendorPropName( style, name ) { } function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument elem = el || elem; return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); } function showHide( elements, show ) { - var elem, display, + var display, elem, hidden, values = [], index = 0, length = elements.length; @@ -6598,11 +6854,13 @@ function showHide( elements, show ) { if ( !elem.style ) { continue; } + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; if ( show ) { // Reset the inline display of this element to learn if it is // being hidden by cascaded rules or not - if ( !values[ index ] && elem.style.display === "none" ) { + if ( !values[ index ] && display === "none" ) { elem.style.display = ""; } @@ -6613,10 +6871,13 @@ function showHide( elements, show ) { values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); } } else { - display = curCSS( elem, "display" ); - if ( !values[ index ] && display !== "none" ) { - jQuery._data( elem, "olddisplay", display ); + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } } } } @@ -6639,6 +6900,21 @@ function showHide( elements, show ) { jQuery.fn.extend({ css: function( name, value ) { return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + return value !== undefined ? jQuery.style( elem, name, value ) : jQuery.css( elem, name ); @@ -6650,15 +6926,13 @@ jQuery.fn.extend({ hide: function() { return showHide( this ); }, - toggle: function( state, fn2 ) { - var bool = typeof state === "boolean"; - - if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) { - return eventsToggle.apply( this, arguments ); + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); } return this.each(function() { - if ( bool ? state : isHidden( this ) ) { + if ( isHidden( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); @@ -6677,18 +6951,19 @@ jQuery.extend({ // We should always get a number back from opacity var ret = curCSS( elem, "opacity" ); return ret === "" ? "1" : ret; - } } } }, - // Exclude the following css properties to add px + // Don't automatically add "px" to these possibly-unitless properties cssNumber: { + "columnCount": true, "fillOpacity": true, "fontWeight": true, "lineHeight": true, "opacity": true, + "order": true, "orphans": true, "widows": true, "zIndex": true, @@ -6741,8 +7016,15 @@ jQuery.extend({ value += "px"; } + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + // If a hook was provided, use that value, otherwise just set the specified value if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided // Fixes bug #5509 try { @@ -6761,8 +7043,8 @@ jQuery.extend({ } }, - css: function( elem, name, numeric, extra ) { - var val, num, hooks, + css: function( elem, name, extra, styles ) { + var num, val, hooks, origName = jQuery.camelCase( name ); // Make sure that we're working with the right name @@ -6779,7 +7061,7 @@ jQuery.extend({ // Otherwise, if a way to get the computed value exists, use that if ( val === undefined ) { - val = curCSS( elem, name ); + val = curCSS( elem, name, styles ); } //convert "normal" to computed value @@ -6788,47 +7070,30 @@ jQuery.extend({ } // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( numeric || extra !== undefined ) { + if ( extra === "" || extra ) { num = parseFloat( val ); - return numeric || jQuery.isNumeric( num ) ? num || 0 : val; + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; } return val; - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; } }); -// NOTE: To any future maintainer, we've window.getComputedStyle +// NOTE: we've included the "window" in window.getComputedStyle // because jsdom on node.js will break without it. if ( window.getComputedStyle ) { - curCSS = function( elem, name ) { - var ret, width, minWidth, maxWidth, - computed = window.getComputedStyle( elem, null ), - style = elem.style; + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; - if ( computed ) { + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), // getPropertyValue is only needed for .css('filter') in IE9, see #12537 - ret = computed.getPropertyValue( name ) || computed[ name ]; + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { ret = jQuery.style( elem, name ); @@ -6839,13 +7104,17 @@ if ( window.getComputedStyle ) { // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values width = style.width; minWidth = style.minWidth; maxWidth = style.maxWidth; + // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret; ret = computed.width; + // Revert the changed values style.width = width; style.minWidth = minWidth; style.maxWidth = maxWidth; @@ -6855,9 +7124,14 @@ if ( window.getComputedStyle ) { return ret; }; } else if ( document.documentElement.currentStyle ) { - curCSS = function( elem, name ) { - var left, rsLeft, - ret = elem.currentStyle && elem.currentStyle[ name ], + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, style = elem.style; // Avoid setting ret to empty string here @@ -6877,11 +7151,12 @@ if ( window.getComputedStyle ) { // Remember the original values left = style.left; - rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; // Put in the new values to get a computed value out if ( rsLeft ) { - elem.runtimeStyle.left = elem.currentStyle.left; + rs.left = elem.currentStyle.left; } style.left = name === "fontSize" ? "1em" : ret; ret = style.pixelLeft + "px"; @@ -6889,7 +7164,7 @@ if ( window.getComputedStyle ) { // Revert the changed values style.left = left; if ( rsLeft ) { - elem.runtimeStyle.left = rsLeft; + rs.left = rsLeft; } } @@ -6900,11 +7175,12 @@ if ( window.getComputedStyle ) { function setPositiveNumber( elem, value, subtract ) { var matches = rnumsplit.exec( value ); return matches ? - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; } -function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { var i = extra === ( isBorderBox ? "border" : "content" ) ? // If we already have the right measurement, avoid augmentation 4 : @@ -6916,29 +7192,26 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { for ( ; i < 4; i += 2 ) { // both box models exclude margin, so add it if we want it if ( extra === "margin" ) { - // we use jQuery.css instead of curCSS here - // because of the reliableMarginRight CSS hook! - val += jQuery.css( elem, extra + cssExpand[ i ], true ); + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); } - // From this point on we use curCSS for maximum performance (relevant in animations) if ( isBorderBox ) { // border-box includes padding, so remove it if we want content if ( extra === "content" ) { - val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); } // at this point, extra isn't border nor margin, so remove border if ( extra !== "margin" ) { - val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } else { // at this point, extra isn't content, so add padding - val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); // at this point, extra isn't content nor padding, so add border if ( extra !== "padding" ) { - val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); } } } @@ -6949,16 +7222,17 @@ function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { function getWidthOrHeight( elem, name, extra ) { // Start with offset property, which is equivalent to the border-box value - var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - valueIsBorderBox = true, - isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; // some non-html elements return undefined for offsetWidth, so check for null/undefined // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 if ( val <= 0 || val == null ) { // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name ); + val = curCSS( elem, name, styles ); if ( val < 0 || val == null ) { val = elem.style[ name ]; } @@ -6982,52 +7256,49 @@ function getWidthOrHeight( elem, name, extra ) { elem, name, extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox + valueIsBorderBox, + styles ) ) + "px"; } - // Try to determine the default display value of an element function css_defaultDisplay( nodeName ) { - if ( elemdisplay[ nodeName ] ) { - return elemdisplay[ nodeName ]; - } + var doc = document, + display = elemdisplay[ nodeName ]; - var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ), - display = elem.css("display"); - elem.remove(); + if ( !display ) { + display = actualDisplay( nodeName, doc ); - // If the simple way fails, - // get element's real default display by attaching it to a temp iframe - if ( display === "none" || display === "" ) { - // Use the already-created iframe if possible - iframe = document.body.appendChild( - iframe || jQuery.extend( document.createElement("iframe"), { - frameBorder: 0, - width: 0, - height: 0 - }) - ); + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("<iframe frameborder='0' width='0' height='0'/>") + .css( "cssText", "display:block !important" ) + ).appendTo( doc.documentElement ); - // Create a cacheable copy of the iframe document on first call. - // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML - // document to it; WebKit & Firefox won't allow reusing the iframe document. - if ( !iframeDoc || !iframe.createElement ) { - iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; - iframeDoc.write("<!doctype html><html><body>"); - iframeDoc.close(); - } + // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse + doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document; + doc.write("<!doctype html><html><body>"); + doc.close(); - elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) ); + display = actualDisplay( nodeName, doc ); + iframe.detach(); + } - display = curCSS( elem, "display" ); - document.body.removeChild( iframe ); + // Store the correct default display + elemdisplay[ nodeName ] = display; } - // Store the correct default display - elemdisplay[ nodeName ] = display; + return display; +} +// Called ONLY from within css_defaultDisplay +function actualDisplay( name, doc ) { + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + display = jQuery.css( elem[0], "display" ); + elem.remove(); return display; } @@ -7037,23 +7308,23 @@ jQuery.each([ "height", "width" ], function( i, name ) { if ( computed ) { // certain elements can have dimension info if we invisibly show them // however, it must have a current display style that would benefit from this - if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) { - return jQuery.swap( elem, cssShow, function() { + return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ? + jQuery.swap( elem, cssShow, function() { return getWidthOrHeight( elem, name, extra ); - }); - } else { - return getWidthOrHeight( elem, name, extra ); - } + }) : + getWidthOrHeight( elem, name, extra ); } }, set: function( elem, value, extra ) { + var styles = extra && getStyles( elem ); return setPositiveNumber( elem, value, extra ? augmentWidthOrHeight( elem, name, extra, - jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" + jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles ) : 0 ); } @@ -7080,16 +7351,18 @@ if ( !jQuery.support.opacity ) { style.zoom = 1; // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 - if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" && - style.removeAttribute ) { + // if value === "", then remove inline opacity #12685 + if ( ( value >= 1 || value === "" ) && + jQuery.trim( filter.replace( ralpha, "" ) ) === "" && + style.removeAttribute ) { // Setting style.filter to null, "" & " " still leave "filter:" in the cssText // if "filter:" is present at all, clearType is disabled, we want to avoid this // style.removeAttribute is IE Only, but so apparently is this code path... style.removeAttribute( "filter" ); - // if there there is no filter style applied in a css rule, we are done - if ( currentStyle && !currentStyle.filter ) { + // if there is no filter style applied in a css rule or unset inline opacity, we are done + if ( value === "" || currentStyle && !currentStyle.filter ) { return; } } @@ -7108,13 +7381,12 @@ jQuery(function() { if ( !jQuery.support.reliableMarginRight ) { jQuery.cssHooks.marginRight = { get: function( elem, computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, function() { - if ( computed ) { - return curCSS( elem, "marginRight" ); - } - }); + if ( computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + return jQuery.swap( elem, { "display": "inline-block" }, + curCSS, [ elem, "marginRight" ] ); + } } }; } @@ -7127,9 +7399,11 @@ jQuery(function() { jQuery.cssHooks[ prop ] = { get: function( elem, computed ) { if ( computed ) { - var ret = curCSS( elem, prop ); + computed = curCSS( elem, prop ); // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret; + return rnumnonpx.test( computed ) ? + jQuery( elem ).position()[ prop ] + "px" : + computed; } } }; @@ -7140,7 +7414,10 @@ jQuery(function() { if ( jQuery.expr && jQuery.expr.filters ) { jQuery.expr.filters.hidden = function( elem ) { - return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none"); + // Support: Opera <= 12.12 + // Opera reports offsetWidths and offsetHeights less than zero on some elements + return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 || + (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); }; jQuery.expr.filters.visible = function( elem ) { @@ -7156,13 +7433,13 @@ jQuery.each({ }, function( prefix, suffix ) { jQuery.cssHooks[ prefix + suffix ] = { expand: function( value ) { - var i, + var i = 0, + expanded = {}, // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ], - expanded = {}; + parts = typeof value === "string" ? value.split(" ") : [ value ]; - for ( i = 0; i < 4; i++ ) { + for ( ; i < 4; i++ ) { expanded[ prefix + cssExpand[ i ] + suffix ] = parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; } @@ -7178,8 +7455,8 @@ jQuery.each({ var r20 = /%20/g, rbracket = /\[\]$/, rCRLF = /\r?\n/g, - rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, - rselectTextarea = /^(?:select|textarea)/i; + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; jQuery.fn.extend({ serialize: function() { @@ -7187,12 +7464,16 @@ jQuery.fn.extend({ }, serializeArray: function() { return this.map(function(){ - return this.elements ? jQuery.makeArray( this.elements ) : this; + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; }) .filter(function(){ - return this.name && !this.disabled && - ( this.checked || rselectTextarea.test( this.nodeName ) || - rinput.test( this.type ) ); + var type = this.type; + // Use .is(":disabled") so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !manipulation_rcheckableType.test( type ) ); }) .map(function( i, elem ){ var val = jQuery( this ).val(); @@ -7200,7 +7481,7 @@ jQuery.fn.extend({ return val == null ? null : jQuery.isArray( val ) ? - jQuery.map( val, function( val, i ){ + jQuery.map( val, function( val ){ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; }) : { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; @@ -7254,13 +7535,7 @@ function buildParams( prefix, obj, traditional, add ) { add( prefix, v ); } else { - // If array item is non-scalar (array or object), encode its - // numeric index to resolve deserialization ambiguity issues. - // Note that rack (as of 1.0.0) can't currently deserialize - // nested arrays properly, and attempting to do so may cause - // a server error. Possible fixes are to modify rack's - // deserialization algorithm or to provide an option or flag - // to force array serialization to be shallow. + // Item is non-scalar (array or object), encode its numeric index. buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); } }); @@ -7276,21 +7551,53 @@ function buildParams( prefix, obj, traditional, add ) { add( prefix, obj ); } } +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +}); + +jQuery.fn.extend({ + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + } +}); var // Document location ajaxLocParts, ajaxLocation, + ajax_nonce = jQuery.now(), + ajax_rquery = /\?/, rhash = /#.*$/, + rts = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, - rquery = /\?/, - rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, - rts = /([?&])_=[^&]*/, - rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, + rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, // Keep a copy of the old load method _load = jQuery.fn.load, @@ -7314,7 +7621,7 @@ var transports = {}, // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = ["*/"] + ["*"]; + allTypes = "*/".concat("*"); // #8138, IE may throw an exception when accessing // a field from window.location if document.domain has been set @@ -7342,83 +7649,69 @@ function addToPrefiltersOrTransports( structure ) { dataTypeExpression = "*"; } - var dataType, list, placeBefore, - dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ), + var dataType, i = 0, - length = dataTypes.length; + dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || []; if ( jQuery.isFunction( func ) ) { // For each dataType in the dataTypeExpression - for ( ; i < length; i++ ) { - dataType = dataTypes[ i ]; - // We control if we're asked to add before - // any existing element - placeBefore = /^\+/.test( dataType ); - if ( placeBefore ) { - dataType = dataType.substr( 1 ) || "*"; + while ( (dataType = dataTypes[i++]) ) { + // Prepend if requested + if ( dataType[0] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); + + // Otherwise append + } else { + (structure[ dataType ] = structure[ dataType ] || []).push( func ); } - list = structure[ dataType ] = structure[ dataType ] || []; - // then we add to the structure accordingly - list[ placeBefore ? "unshift" : "push" ]( func ); } } }; } // Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, - dataType /* internal */, inspected /* internal */ ) { - - dataType = dataType || options.dataTypes[ 0 ]; - inspected = inspected || {}; - - inspected[ dataType ] = true; - - var selection, - list = structure[ dataType ], - i = 0, - length = list ? list.length : 0, - executeOnly = ( structure === prefilters ); - - for ( ; i < length && ( executeOnly || !selection ); i++ ) { - selection = list[ i ]( options, originalOptions, jqXHR ); - // If we got redirected to another dataType - // we try there if executing only and not done already - if ( typeof selection === "string" ) { - if ( !executeOnly || inspected[ selection ] ) { - selection = undefined; - } else { - options.dataTypes.unshift( selection ); - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, selection, inspected ); +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); } - } - } - // If we're only executing or nothing was selected - // we try the catchall dataType if not done already - if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, "*", inspected ); + }); + return selected; } - // unnecessary when only executing (prefilters) - // but it'll be ignored by the caller in that case - return selection; + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); } // A special extend for ajax options // that takes "flat" options (not to be deep extended) // Fixes #9887 function ajaxExtend( target, src ) { - var key, deep, + var deep, key, flatOptions = jQuery.ajaxSettings.flatOptions || {}; + for ( key in src ) { if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; } } if ( deep ) { jQuery.extend( true, target, deep ); } + + return target; } jQuery.fn.load = function( url, params, callback ) { @@ -7426,12 +7719,7 @@ jQuery.fn.load = function( url, params, callback ) { return _load.apply( this, arguments ); } - // Don't do a request if no elements are being requested - if ( !this.length ) { - return this; - } - - var selector, type, response, + var selector, response, type, self = this, off = url.indexOf(" "); @@ -7452,105 +7740,61 @@ jQuery.fn.load = function( url, params, callback ) { type = "POST"; } - // Request the remote document - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params, - complete: function( jqXHR, status ) { - if ( callback ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - } - } - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; + // If we have elements to modify, make the request + if ( self.length > 0 ) { + jQuery.ajax({ + url: url, - // See if a selector was specified - self.html( selector ? + // if "type" variable is undefined, then "GET" method will be used + type: type, + dataType: "html", + data: params + }).done(function( responseText ) { - // Create a dummy div to hold the results - jQuery("<div>") + // Save response for use in complete callback + response = arguments; - // inject the contents of the document in, removing the scripts - // to avoid any 'Permission Denied' errors in IE - .append( responseText.replace( rscript, "" ) ) + self.html( selector ? - // Locate the specified elements - .find( selector ) : + // If a selector was specified, locate the right elements in a dummy div + // Exclude scripts to avoid IE 'Permission Denied' errors + jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : - // If not, just inject the full result - responseText ); + // Otherwise use the full result + responseText ); - }); + }).complete( callback && function( jqXHR, status ) { + self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); + }); + } return this; }; // Attach a bunch of functions for handling common AJAX events -jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ - jQuery.fn[ o ] = function( f ){ - return this.on( o, f ); - }; -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - type: method, - url: url, - data: data, - success: callback, - dataType: type - }); +jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){ + jQuery.fn[ type ] = function( fn ){ + return this.on( type, fn ); }; }); jQuery.extend({ - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, + // Counter for holding the number of active queries + active: 0, - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - if ( settings ) { - // Building a settings object - ajaxExtend( target, jQuery.ajaxSettings ); - } else { - // Extending ajaxSettings - settings = target; - target = jQuery.ajaxSettings; - } - ajaxExtend( target, settings ); - return target; - }, + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, ajaxSettings: { url: ajaxLocation, + type: "GET", isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), global: true, - type: "GET", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", processData: true, async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", /* timeout: 0, data: null, @@ -7564,11 +7808,11 @@ jQuery.extend({ */ accepts: { - xml: "application/xml, text/xml", - html: "text/html", + "*": allTypes, text: "text/plain", - json: "application/json, text/javascript", - "*": allTypes + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" }, contents: { @@ -7579,16 +7823,16 @@ jQuery.extend({ responseFields: { xml: "responseXML", - text: "responseText" + text: "responseText", + json: "responseJSON" }, - // List of data converters - // 1) key format is "source_type destination_type" (a single space in-between) - // 2) the catchall symbol "*" can be used for source_type + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space converters: { // Convert anything to text - "* text": window.String, + "* text": String, // Text to html (true = no transformation) "text html": true, @@ -7605,11 +7849,24 @@ jQuery.extend({ // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { - context: true, - url: true + url: true, + context: true } }, + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), ajaxTransport: addToPrefiltersOrTransports( transports ), @@ -7625,34 +7882,34 @@ jQuery.extend({ // Force options to be an object options = options || {}; - var // ifModified key - ifModifiedKey, - // Response headers + var // Cross-domain detection vars + parts, + // Loop variable + i, + // URL without anti-cache param + cacheURL, + // Response headers as string responseHeadersString, - responseHeaders, - // transport - transport, // timeout handle timeoutTimer, - // Cross-domain detection vars - parts, + // To know if global events are to be dispatched fireGlobals, - // Loop variable - i, + + transport, + // Response headers + responseHeaders, // Create the final options object s = jQuery.ajaxSetup( {}, options ), // Callbacks context callbackContext = s.context || s, - // Context for global events - // It's the callbackContext if one was provided in the options - // and if it's a DOM node or a jQuery collection - globalEventContext = callbackContext !== s && - ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? - jQuery( callbackContext ) : jQuery.event, + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, // Deferreds deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), + completeDeferred = jQuery.Callbacks("once memory"), // Status-dependent callbacks statusCode = s.statusCode || {}, // Headers (they are sent all at once) @@ -7664,37 +7921,36 @@ jQuery.extend({ strAbort = "canceled", // Fake xhr jqXHR = { - readyState: 0, - // Caches the header - setRequestHeader: function( name, value ) { - if ( !state ) { - var lname = name.toLowerCase(); - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - // Builds headers hashtable if needed getResponseHeader: function( key ) { var match; if ( state === 2 ) { if ( !responseHeaders ) { responseHeaders = {}; - while( ( match = rheaders.exec( responseHeadersString ) ) ) { + while ( (match = rheaders.exec( responseHeadersString )) ) { responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; } } match = responseHeaders[ key.toLowerCase() ]; } - return match === undefined ? null : match; + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + var lname = name.toLowerCase(); + if ( !state ) { + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; }, // Overrides response content-type header @@ -7705,164 +7961,58 @@ jQuery.extend({ return this; }, + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( state < 2 ) { + for ( code in map ) { + // Lazy-add the new callback in a way that preserves old ones + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } else { + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } + } + return this; + }, + // Cancel the request abort: function( statusText ) { - statusText = statusText || strAbort; + var finalText = statusText || strAbort; if ( transport ) { - transport.abort( statusText ); + transport.abort( finalText ); } - done( 0, statusText ); + done( 0, finalText ); return this; } }; - // Callback for when everything is done - // It is defined here because jslint complains if it is declared - // at the end of the function (which would be more logical and readable) - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // If successful, handle type chaining - if ( status >= 200 && status < 300 || status === 304 ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ ifModifiedKey ] = modified; - } - modified = jqXHR.getResponseHeader("Etag"); - if ( modified ) { - jQuery.etag[ ifModifiedKey ] = modified; - } - } - - // If not modified - if ( status === 304 ) { - - statusText = "notmodified"; - isSuccess = true; - - // If we have data - } else { - - isSuccess = ajaxConvert( s, response ); - statusText = isSuccess.state; - success = isSuccess.data; - error = isSuccess.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( !statusText || status ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - // Attach deferreds - deferred.promise( jqXHR ); + deferred.promise( jqXHR ).complete = completeDeferred.add; jqXHR.success = jqXHR.done; jqXHR.error = jqXHR.fail; - jqXHR.complete = completeDeferred.add; - - // Status-dependent callbacks - jqXHR.statusCode = function( map ) { - if ( map ) { - var tmp; - if ( state < 2 ) { - for ( tmp in map ) { - statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; - } - } else { - tmp = map[ jqXHR.status ]; - jqXHR.always( tmp ); - } - } - return this; - }; // Remove hash character (#7531: and string promotion) // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // Handle falsy url in the settings object (#10093: consistency with old signature) // We also use the url parameter if available - s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace ); + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""]; // A cross-domain request is in order when we have a protocol:host:port mismatch if ( s.crossDomain == null ) { parts = rurl.exec( s.url.toLowerCase() ); s.crossDomain = !!( parts && ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || - ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != - ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) ); } @@ -7882,58 +8032,58 @@ jQuery.extend({ // We can fire global events as of now if asked to fireGlobals = s.global; + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger("ajaxStart"); + } + // Uppercase the type s.type = s.type.toUpperCase(); // Determine if request has content s.hasContent = !rnoContent.test( s.type ); - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + cacheURL = s.url; // More options handling for requests with no content if ( !s.hasContent ) { // If data is available, append data to url if ( s.data ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); // #9682: remove data so that it's not used in an eventual retry delete s.data; } - // Get ifModifiedKey before adding the anti-cache parameter - ifModifiedKey = s.url; - // Add anti-cache in url if needed if ( s.cache === false ) { + s.url = rts.test( cacheURL ) ? - var ts = jQuery.now(), - // try replacing _= if it is there - ret = s.url.replace( rts, "$1_=" + ts ); + // If there is already a '_' parameter, set its value + cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) : - // if nothing was replaced, add timestamp to the end - s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + // Otherwise add one to the end + cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++; } } - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { - ifModifiedKey = ifModifiedKey || s.url; - if ( jQuery.lastModified[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); } - if ( jQuery.etag[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); } } + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + // Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( "Accept", @@ -7949,9 +8099,8 @@ jQuery.extend({ // Allow custom headers/mimetypes and early abort if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - + // Abort if not done already and return + return jqXHR.abort(); } // aborting is no longer a cancellation @@ -7970,21 +8119,22 @@ jQuery.extend({ done( -1, "No Transport" ); } else { jqXHR.readyState = 1; + // Send global event if ( fireGlobals ) { globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); } // Timeout if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout( function(){ - jqXHR.abort( "timeout" ); + timeoutTimer = setTimeout(function() { + jqXHR.abort("timeout"); }, s.timeout ); } try { state = 1; transport.send( requestHeaders, done ); - } catch (e) { + } catch ( e ) { // Propagate exception as error if not done if ( state < 2 ) { done( -1, e ); @@ -7995,42 +8145,164 @@ jQuery.extend({ } } + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader("Last-Modified"); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader("etag"); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger("ajaxStop"); + } + } + } + return jqXHR; }, - // Counter for holding the number of active queries - active: 0, + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, - // Last-Modified header cache for next request - lastModified: {}, - etag: {} + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +}); +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + url: url, + type: method, + dataType: type, + data: data, + success: callback + }); + }; }); /* Handles responses to an ajax request: - * - sets all responseXXX fields accordingly * - finds the right dataType (mediates between content-type and expected dataType) * - returns the corresponding response */ function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, + var firstDataType, ct, finalDataType, type, contents = s.contents, - dataTypes = s.dataTypes, - responseFields = s.responseFields; - - // Fill responseXXX fields - for ( type in responseFields ) { - if ( type in responses ) { - jqXHR[ responseFields[type] ] = responses[ type ]; - } - } + dataTypes = s.dataTypes; // Remove auto dataType and get content-type in the process while( dataTypes[ 0 ] === "*" ) { dataTypes.shift(); if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); + ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); } } @@ -8073,20 +8345,14 @@ function ajaxHandleResponses( s, jqXHR, responses ) { } } -// Chain conversions given the request and the original response -function ajaxConvert( s, response ) { - - var conv, conv2, current, tmp, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(), - prev = dataTypes[ 0 ], +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, converters = {}, - i = 0; - - // Apply the dataFilter if provided - if ( s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); // Create converters map with lowercased keys if ( dataTypes[ 1 ] ) { @@ -8095,14 +8361,32 @@ function ajaxConvert( s, response ) { } } - // Convert to each sequential dataType, tolerating list modification - for ( ; (current = dataTypes[++i]); ) { + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); - // There's only work to do if current dataType is non-auto - if ( current !== "*" ) { + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; // Convert response if prev dataType is non-auto and differs from current - if ( prev !== "*" && prev !== current ) { + } else if ( prev !== "*" && prev !== current ) { // Seek a direct converter conv = converters[ prev + " " + current ] || converters[ "* " + current ]; @@ -8112,7 +8396,7 @@ function ajaxConvert( s, response ) { for ( conv2 in converters ) { // If conv2 outputs current - tmp = conv2.split(" "); + tmp = conv2.split( " " ); if ( tmp[ 1 ] === current ) { // If prev can be converted to accepted input @@ -8126,9 +8410,8 @@ function ajaxConvert( s, response ) { // Otherwise, insert the intermediate dataType } else if ( converters[ conv2 ] !== true ) { current = tmp[ 0 ]; - dataTypes.splice( i--, 0, current ); + dataTypes.unshift( tmp[ 1 ] ); } - break; } } @@ -8139,7 +8422,7 @@ function ajaxConvert( s, response ) { if ( conv !== true ) { // Unless errors are allowed to bubble, catch and return them - if ( conv && s["throws"] ) { + if ( conv && s[ "throws" ] ) { response = conv( response ); } else { try { @@ -8150,108 +8433,18 @@ function ajaxConvert( s, response ) { } } } - - // Update prev for next iteration - prev = current; } } return { state: "success", data: response }; } -var oldCallbacks = [], - rquestion = /\?/, - rjsonp = /(=)\?(?=&|$)|\?\?/, - nonce = jQuery.now(); - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - data = s.data, - url = s.url, - hasCallback = s.jsonp !== false, - replaceInUrl = hasCallback && rjsonp.test( url ), - replaceInData = hasCallback && !replaceInUrl && typeof data === "string" && - !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && - rjsonp.test( data ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - overwritten = window[ callbackName ]; - - // Insert callback into url or form data - if ( replaceInUrl ) { - s.url = url.replace( rjsonp, "$1" + callbackName ); - } else if ( replaceInData ) { - s.data = data.replace( rjsonp, "$1" + callbackName ); - } else if ( hasCallback ) { - s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); // Install script dataType jQuery.ajaxSetup({ accepts: { script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" }, contents: { - script: /javascript|ecmascript/ + script: /(?:java|ecma)script/ }, converters: { "text script": function( text ) { @@ -8279,15 +8472,15 @@ jQuery.ajaxTransport( "script", function(s) { if ( s.crossDomain ) { var script, - head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; + head = document.head || jQuery("head")[0] || document.documentElement; return { send: function( _, callback ) { - script = document.createElement( "script" ); + script = document.createElement("script"); - script.async = "async"; + script.async = true; if ( s.scriptCharset ) { script.charset = s.scriptCharset; @@ -8304,12 +8497,12 @@ jQuery.ajaxTransport( "script", function(s) { script.onload = script.onreadystatechange = null; // Remove the script - if ( head && script.parentNode ) { - head.removeChild( script ); + if ( script.parentNode ) { + script.parentNode.removeChild( script ); } // Dereference the script - script = undefined; + script = null; // Callback if not abort if ( !isAbort ) { @@ -8317,28 +8510,110 @@ jQuery.ajaxTransport( "script", function(s) { } } }; - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709 and #4378). + + // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending + // Use native DOM manipulation to avoid our domManip AJAX trickery head.insertBefore( script, head.firstChild ); }, abort: function() { if ( script ) { - script.onload( 0, 1 ); + script.onload( undefined, true ); } } }; } }); -var xhrCallbacks, +var oldCallbacks = [], + rjsonp = /(=)\?(?=&|$)|\?\?/; + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) ); + this[ callback ] = true; + return callback; + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var callbackName, overwritten, responseContainer, + jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? + "url" : + typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" + ); + + // Handle iff the expected data type is "jsonp" or we have a parameter to set + if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { + + // Get callback name, remembering preexisting value associated with it + callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? + s.jsonpCallback() : + s.jsonpCallback; + + // Insert callback into url or form data + if ( jsonProp ) { + s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); + } else if ( s.jsonp !== false ) { + s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; + } + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( !responseContainer ) { + jQuery.error( callbackName + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Install callback + overwritten = window[ callbackName ]; + window[ callbackName ] = function() { + responseContainer = arguments; + }; + + // Clean-up function (fires after converters) + jqXHR.always(function() { + // Restore preexisting value + window[ callbackName ] = overwritten; + + // Save back as free + if ( s[ callbackName ] ) { + // make sure that re-using the options doesn't screw things around + s.jsonpCallback = originalSettings.jsonpCallback; + + // save the callback name for future use + oldCallbacks.push( callbackName ); + } + + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( overwritten ) ) { + overwritten( responseContainer[ 0 ] ); + } + + responseContainer = overwritten = undefined; + }); + + // Delegate to script + return "script"; + } +}); +var xhrCallbacks, xhrSupported, + xhrId = 0, // #5280: Internet Explorer will keep connections alive if we don't abort on unload - xhrOnUnloadAbort = window.ActiveXObject ? function() { + xhrOnUnloadAbort = window.ActiveXObject && function() { // Abort all pending requests - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ]( 0, 1 ); + var key; + for ( key in xhrCallbacks ) { + xhrCallbacks[ key ]( undefined, true ); } - } : false, - xhrId = 0; + }; // Functions to create xhrs function createStandardXHR() { @@ -8349,7 +8624,7 @@ function createStandardXHR() { function createActiveXHR() { try { - return new window.ActiveXObject( "Microsoft.XMLHTTP" ); + return new window.ActiveXObject("Microsoft.XMLHTTP"); } catch( e ) {} } @@ -8369,15 +8644,12 @@ jQuery.ajaxSettings.xhr = window.ActiveXObject ? createStandardXHR; // Determine support properties -(function( xhr ) { - jQuery.extend( jQuery.support, { - ajax: !!xhr, - cors: !!xhr && ( "withCredentials" in xhr ) - }); -})( jQuery.ajaxSettings.xhr() ); +xhrSupported = jQuery.ajaxSettings.xhr(); +jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +xhrSupported = jQuery.support.ajax = !!xhrSupported; // Create transport if the browser can provide an xhr -if ( jQuery.support.ajax ) { +if ( xhrSupported ) { jQuery.ajaxTransport(function( s ) { // Cross domain only allowed if supported through XMLHttpRequest @@ -8418,7 +8690,7 @@ if ( jQuery.support.ajax ) { // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if ( !s.crossDomain && !headers["X-Requested-With"] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; + headers["X-Requested-With"] = "XMLHttpRequest"; } // Need an extra try/catch for cross domain requests in Firefox 3 @@ -8426,7 +8698,7 @@ if ( jQuery.support.ajax ) { for ( i in headers ) { xhr.setRequestHeader( i, headers[ i ] ); } - } catch( _ ) {} + } catch( err ) {} // Do send the request // This may raise an exception which is actually @@ -8435,12 +8707,7 @@ if ( jQuery.support.ajax ) { // Listener callback = function( _, isAbort ) { - - var status, - statusText, - responseHeaders, - responses, - xml; + var status, responseHeaders, statusText, responses; // Firefox throws exceptions when accessing properties // of an xhr when a network error occurred @@ -8468,21 +8735,14 @@ if ( jQuery.support.ajax ) { xhr.abort(); } } else { + responses = {}; status = xhr.status; responseHeaders = xhr.getAllResponseHeaders(); - responses = {}; - xml = xhr.responseXML; - - // Construct response list - if ( xml && xml.documentElement /* #4958 */ ) { - responses.xml = xml; - } // When requesting binary data, IE6-9 will throw an exception // on any attempt to access responseText (#11426) - try { + if ( typeof xhr.responseText === "string" ) { responses.text = xhr.responseText; - } catch( e ) { } // Firefox throws an exception when accessing @@ -8525,7 +8785,7 @@ if ( jQuery.support.ajax ) { } else if ( xhr.readyState === 4 ) { // (IE6 & IE7) if it's in cache and has been // retrieved directly we need to fire the callback - setTimeout( callback, 0 ); + setTimeout( callback ); } else { handle = ++xhrId; if ( xhrOnUnloadAbort ) { @@ -8544,7 +8804,7 @@ if ( jQuery.support.ajax ) { abort: function() { if ( callback ) { - callback(0,1); + callback( undefined, true ); } } }; @@ -8553,49 +8813,56 @@ if ( jQuery.support.ajax ) { } var fxNow, timerId, rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), + rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), rrun = /queueHooks$/, animationPrefilters = [ defaultPrefilter ], tweeners = { "*": [function( prop, value ) { - var end, unit, - tween = this.createTween( prop, value ), - parts = rfxnum.exec( value ), + var tween = this.createTween( prop, value ), target = tween.cur(), - start = +target || 0, + parts = rfxnum.exec( value ), + unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && + rfxnum.exec( jQuery.css( tween.elem, prop ) ), scale = 1, maxIterations = 20; - if ( parts ) { - end = +parts[2]; - unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + if ( start && start[ 3 ] !== unit ) { + // Trust units reported by jQuery.css + unit = unit || start[ 3 ]; - // We need to compute starting value - if ( unit !== "px" && start ) { - // Iteratively approximate from a nonzero starting point - // Prefer the current property, because this process will be trivial if it uses the same units - // Fallback to end or a simple constant - start = jQuery.css( tween.elem, prop, true ) || end || 1; + // Make sure we update the tween properties later on + parts = parts || []; - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; + // Iteratively approximate from a nonzero starting point + start = +target || 1; - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); + do { + // If previous iteration zeroed out, double until we get *something* + // Use a string for doubling factor so we don't accidentally see scale as unchanged below + scale = scale || ".5"; - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } + // Adjust and apply + start = start / scale; + jQuery.style( tween.elem, prop, start + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // And breaking the loop if scale is unchanged or perfect, or if we've just had enough + } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); + } + // Update tween properties + if ( parts ) { + start = tween.start = +start || +target || 0; tween.unit = unit; - tween.start = start; // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; + tween.end = parts[ 1 ] ? + start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : + +parts[ 2 ]; } + return tween; }] }; @@ -8604,35 +8871,37 @@ var fxNow, timerId, function createFxNow() { setTimeout(function() { fxNow = undefined; - }, 0 ); + }); return ( fxNow = jQuery.now() ); } -function createTweens( animation, props ) { - jQuery.each( props, function( prop, value ) { - var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( collection[ index ].call( animation, prop, value ) ) { +function createTween( value, prop, animation ) { + var tween, + collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( (tween = collection[ index ].call( animation, prop, value )) ) { - // we're done with this property - return; - } + // we're done with this property + return tween; } - }); + } } function Animation( elem, properties, options ) { var result, + stopped, index = 0, - tweenerIndex = 0, length = animationPrefilters.length, deferred = jQuery.Deferred().always( function() { // don't match elem in the :animated selector delete tick.elem; }), tick = function() { + if ( stopped ) { + return false; + } var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) @@ -8663,7 +8932,7 @@ function Animation( elem, properties, options ) { startTime: fxNow || createFxNow(), duration: options.duration, tweens: [], - createTween: function( prop, end, easing ) { + createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); @@ -8674,7 +8943,10 @@ function Animation( elem, properties, options ) { // if we are going to the end, we want to run all the tweens // otherwise we skip this part length = gotoEnd ? animation.tweens.length : 0; - + if ( stopped ) { + return this; + } + stopped = true; for ( ; index < length ; index++ ) { animation.tweens[ index ].run( 1 ); } @@ -8700,7 +8972,7 @@ function Animation( elem, properties, options ) { } } - createTweens( animation, props ); + jQuery.map( props, createTween, animation ); if ( jQuery.isFunction( animation.opts.start ) ) { animation.opts.start.call( elem, animation ); @@ -8708,9 +8980,9 @@ function Animation( elem, properties, options ) { jQuery.fx.timer( jQuery.extend( tick, { + elem: elem, anim: animation, - queue: animation.opts.queue, - elem: elem + queue: animation.opts.queue }) ); @@ -8789,12 +9061,13 @@ jQuery.Animation = jQuery.extend( Animation, { }); function defaultPrefilter( elem, props, opts ) { - var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire, + /* jshint validthis: true */ + var prop, value, toggle, tween, hooks, oldfire, anim = this, - style = elem.style, orig = {}, - handled = [], - hidden = elem.nodeType && isHidden( elem ); + style = elem.style, + hidden = elem.nodeType && isHidden( elem ), + dataShow = jQuery._data( elem, "fxshow" ); // handle queue: false promises if ( !opts.queue ) { @@ -8849,7 +9122,7 @@ function defaultPrefilter( elem, props, opts ) { if ( opts.overflow ) { style.overflow = "hidden"; if ( !jQuery.support.shrinkWrapBlocks ) { - anim.done(function() { + anim.always(function() { style.overflow = opts.overflow[ 0 ]; style.overflowX = opts.overflow[ 1 ]; style.overflowY = opts.overflow[ 2 ]; @@ -8859,23 +9132,25 @@ function defaultPrefilter( elem, props, opts ) { // show/hide pass - for ( index in props ) { - value = props[ index ]; + for ( prop in props ) { + value = props[ prop ]; if ( rfxtypes.exec( value ) ) { - delete props[ index ]; + delete props[ prop ]; toggle = toggle || value === "toggle"; if ( value === ( hidden ? "hide" : "show" ) ) { continue; } - handled.push( index ); + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); } } - length = handled.length; - if ( length ) { - dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; + if ( !jQuery.isEmptyObject( orig ) ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = jQuery._data( elem, "fxshow", {} ); } // store state if its toggle - enables .stop().toggle() to "reverse" @@ -8891,15 +9166,13 @@ function defaultPrefilter( elem, props, opts ) { } anim.done(function() { var prop; - jQuery.removeData( elem, "fxshow", true ); + jQuery._removeData( elem, "fxshow" ); for ( prop in orig ) { jQuery.style( elem, prop, orig[ prop ] ); } }); - for ( index = 0 ; index < length ; index++ ) { - prop = handled[ index ]; - tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 ); - orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop ); + for ( prop in orig ) { + tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); if ( !( prop in dataShow ) ) { dataShow[ prop ] = tween.start; @@ -8973,11 +9246,11 @@ Tween.propHooks = { return tween.elem[ tween.prop ]; } - // passing any value as a 4th parameter to .css will automatically + // passing an empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails // so, simple values such as "10px" are parsed to Float. // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, false, "" ); + result = jQuery.css( tween.elem, tween.prop, "" ); // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === "auto" ? 0 : result; }, @@ -8995,8 +9268,8 @@ Tween.propHooks = { } }; -// Remove in 2.0 - this supports IE8's panic based approach -// to setting things on disconnected nodes +// Support: IE <=9 +// Panic based approach to setting things on disconnected nodes Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { set: function( tween ) { @@ -9009,9 +9282,7 @@ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { var cssFn = jQuery.fn[ name ]; jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" || - // special check for .toggle( handler, handler, ... ) - ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ? + return speed == null || typeof speed === "boolean" ? cssFn.apply( this, arguments ) : this.animate( genFx( name, true ), speed, easing, callback ); }; @@ -9033,11 +9304,12 @@ jQuery.fn.extend({ // Operate on a copy of prop so per-property easing won't be lost var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - // Empty animations resolve immediately - if ( empty ) { + // Empty animations, or finishing resolves immediately + if ( empty || jQuery._data( this, "finish" ) ) { anim.stop( true ); } }; + doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : @@ -9092,6 +9364,47 @@ jQuery.fn.extend({ jQuery.dequeue( this, type ); } }); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each(function() { + var index, + data = jQuery._data( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // enable finishing flag on private data + data.finish = true; + + // empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // turn off finishing flag + delete data.finish; + }); } }); @@ -9195,13 +9508,19 @@ jQuery.fx.tick = function() { }; jQuery.fx.timer = function( timer ) { - if ( timer() && jQuery.timers.push( timer ) && !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); + if ( timer() && jQuery.timers.push( timer ) ) { + jQuery.fx.start(); } }; jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( !timerId ) { + timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); + } +}; + jQuery.fx.stop = function() { clearInterval( timerId ); timerId = null; @@ -9224,8 +9543,6 @@ if ( jQuery.expr && jQuery.expr.filters ) { }).length; }; } -var rroot = /^(?:body|html)$/i; - jQuery.fn.offset = function( options ) { if ( arguments.length ) { return options === undefined ? @@ -9235,7 +9552,7 @@ jQuery.fn.offset = function( options ) { }); } - var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, + var docElem, win, box = { top: 0, left: 0 }, elem = this[ 0 ], doc = elem && elem.ownerDocument; @@ -9244,10 +9561,6 @@ jQuery.fn.offset = function( options ) { return; } - if ( (body = doc.body) === elem ) { - return jQuery.offset.bodyOffset( elem ); - } - docElem = doc.documentElement; // Make sure it's not a disconnected DOM node @@ -9257,34 +9570,18 @@ jQuery.fn.offset = function( options ) { // If we don't have gBCR, just use 0,0 rather than error // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== "undefined" ) { + if ( typeof elem.getBoundingClientRect !== core_strundefined ) { box = elem.getBoundingClientRect(); } win = getWindow( doc ); - clientTop = docElem.clientTop || body.clientTop || 0; - clientLeft = docElem.clientLeft || body.clientLeft || 0; - scrollTop = win.pageYOffset || docElem.scrollTop; - scrollLeft = win.pageXOffset || docElem.scrollLeft; return { - top: box.top + scrollTop - clientTop, - left: box.left + scrollLeft - clientLeft + top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ), + left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 ) }; }; jQuery.offset = { - bodyOffset: function( body ) { - var top = body.offsetTop, - left = body.offsetLeft; - - if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { - top += parseFloat( jQuery.css(body, "marginTop") ) || 0; - left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; - } - - return { top: top, left: left }; - }, - setOffset: function( elem, options, i ) { var position = jQuery.css( elem, "position" ); @@ -9333,43 +9630,49 @@ jQuery.offset = { jQuery.fn.extend({ position: function() { - if ( !this[0] ) { + if ( !this[ 0 ] ) { return; } - var elem = this[0], + var offsetParent, offset, + parentOffset = { top: 0, left: 0 }, + elem = this[ 0 ]; + + // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent + if ( jQuery.css( elem, "position" ) === "fixed" ) { + // we assume that getBoundingClientRect is available when computed position is fixed + offset = elem.getBoundingClientRect(); + } else { + // Get *real* offsetParent + offsetParent = this.offsetParent(); - // Get *real* offsetParent - offsetParent = this.offsetParent(), + // Get correct offsets + offset = this.offset(); + if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { + parentOffset = offsetParent.offset(); + } - // Get correct offsets - offset = this.offset(), - parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + // Add offsetParent borders + parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); + parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); + } - // Subtract element margins + // Subtract parent offsets and element margins // note: when an element has margin: auto the offsetLeft and marginLeft // are the same in Safari causing offset.left to incorrectly be 0 - offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; - offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; - - // Add offsetParent borders - parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; - parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; - - // Subtract the two offsets return { - top: offset.top - parentOffset.top, - left: offset.left - parentOffset.left + top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), + left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true) }; }, offsetParent: function() { return this.map(function() { - var offsetParent = this.offsetParent || document.body; - while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + var offsetParent = this.offsetParent || docElem; + while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) { offsetParent = offsetParent.offsetParent; } - return offsetParent || document.body; + return offsetParent || docElem; }); } }); @@ -9392,7 +9695,7 @@ jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( me if ( win ) { win.scrollTo( !top ? val : jQuery( win ).scrollLeft(), - top ? val : jQuery( win ).scrollTop() + top ? val : jQuery( win ).scrollTop() ); } else { @@ -9442,7 +9745,7 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { return value === undefined ? // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, value, extra ) : + jQuery.css( elem, type, extra ) : // Set width or height on the element jQuery.style( elem, type, value, extra ); @@ -9450,23 +9753,37 @@ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { }; }); }); -// Expose jQuery to the global object -window.jQuery = window.$ = jQuery; - -// Expose jQuery as an AMD module, but only for AMD loaders that -// understand the issues with loading multiple versions of jQuery -// in a page that all might call define(). The loader will indicate -// they have special allowances for multiple jQuery versions by -// specifying define.amd.jQuery = true. Register as a named module, -// since jQuery can be concatenated with other files that may use define, -// but not use a proper concatenation script that understands anonymous -// AMD modules. A named AMD is safest and most robust way to register. -// Lowercase jquery is used because AMD module names are derived from -// file names, and jQuery is normally delivered in a lowercase file name. -// Do this after creating the global so that if an AMD module wants to call -// noConflict to hide this version of jQuery, it will work. -if ( typeof define === "function" && define.amd && define.amd.jQuery ) { - define( "jquery", [], function () { return jQuery; } ); +// Limit scope pollution from any deprecated API +// (function() { + +// The number of elements contained in the matched element set +jQuery.fn.size = function() { + return this.length; +}; + +jQuery.fn.andSelf = jQuery.fn.addBack; + +// })(); +if ( typeof module === "object" && module && typeof module.exports === "object" ) { + // Expose jQuery as module.exports in loaders that implement the Node + // module pattern (including browserify). Do not create the global, since + // the user will be storing it themselves locally, and globals are frowned + // upon in the Node module world. + module.exports = jQuery; +} else { + // Otherwise expose jQuery to the global object as usual + window.jQuery = window.$ = jQuery; + + // Register as a named AMD module, since jQuery can be concatenated with other + // files that may use define, but not via a proper concatenation script that + // understands anonymous AMD modules. A named AMD is safest and most robust + // way to register. Lowercase jquery is used because AMD module names are + // derived from file names, and jQuery is normally delivered in a lowercase + // file name. Do this after creating the global so that if an AMD module wants + // to call noConflict to hide this version of jQuery, it will work. + if ( typeof define === "function" && define.amd ) { + define( "jquery", [], function () { return jQuery; } ); + } } })( window ); diff --git a/themes/default/js/jquery.min.js b/themes/default/js/jquery.min.js index 388377952..da4170647 100644 --- a/themes/default/js/jquery.min.js +++ b/themes/default/js/jquery.min.js @@ -1,2 +1,6 @@ -/*! jQuery v1.8.3 jquery.com | jquery.org/license */ -(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window);
\ No newline at end of file +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav></:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("<div>").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window); diff --git a/themes/default/js/plugins/chosen-sprite@2x.png b/themes/default/js/plugins/chosen-sprite@2x.png Binary files differnew file mode 100644 index 000000000..ffe4d7d11 --- /dev/null +++ b/themes/default/js/plugins/chosen-sprite@2x.png diff --git a/themes/default/js/plugins/chosen.css b/themes/default/js/plugins/chosen.css index 8f6db26f4..d203a0719 100644 --- a/themes/default/js/plugins/chosen.css +++ b/themes/default/js/plugins/chosen.css @@ -1,413 +1,430 @@ /* @group Base */ -.chzn-container { - font-size: 13px; +.chosen-container { position: relative; display: inline-block; + vertical-align: middle; + font-size: 13px; zoom: 1; *display: inline; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; } -.chzn-container .chzn-drop { - background: #fff; +.chosen-container .chosen-drop { + position: absolute; + top: 100%; + left: -9999px; + z-index: 1010; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; border: 1px solid #aaa; border-top: 0; - position: absolute; - top: 29px; + background: #fff; + box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15); +} +.chosen-container.chosen-with-drop .chosen-drop { left: 0; - -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15); - -moz-box-shadow : 0 4px 5px rgba(0,0,0,.15); - box-shadow : 0 4px 5px rgba(0,0,0,.15); - z-index: 1010; } -/* @end */ +.chosen-container a { + cursor: pointer; +} +/* @end */ /* @group Single Chosen */ -.chzn-container-single .chzn-single { - background-color: #ffffff; - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 ); - background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4)); - background-image: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background-image: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background-image: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - background-image: linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); - -webkit-border-radius: 5px; - -moz-border-radius : 5px; - border-radius : 5px; - -moz-background-clip : padding; - -webkit-background-clip: padding-box; - background-clip : padding-box; - border: 1px solid #aaaaaa; - -webkit-box-shadow: 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1); - -moz-box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1); - box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1); +.chosen-container-single .chosen-single { + position: relative; display: block; overflow: hidden; - white-space: nowrap; - position: relative; - height: 23px; - line-height: 24px; padding: 0 0 0 8px; - color: #444444; + height: 23px; + border: 1px solid #aaa; + border-radius: 5px; + background-color: #fff; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4)); + background: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); + background: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); + background: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); + background: linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%); + background-clip: padding-box; + box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1); + color: #444; text-decoration: none; + white-space: nowrap; + line-height: 24px; } -.chzn-container-single .chzn-default { +.chosen-container-single .chosen-default { color: #999; } -.chzn-container-single .chzn-single span { - margin-right: 26px; +.chosen-container-single .chosen-single span { display: block; overflow: hidden; - white-space: nowrap; - -o-text-overflow: ellipsis; - -ms-text-overflow: ellipsis; + margin-right: 26px; text-overflow: ellipsis; + white-space: nowrap; } -.chzn-container-single .chzn-single abbr { - display: block; +.chosen-container-single .chosen-single-with-deselect span { + margin-right: 38px; +} +.chosen-container-single .chosen-single abbr { position: absolute; - right: 26px; top: 6px; + right: 26px; + display: block; width: 12px; height: 12px; - font-size: 1px; background: url('chosen-sprite.png') -42px 1px no-repeat; + font-size: 1px; } -.chzn-container-single .chzn-single abbr:hover { +.chosen-container-single .chosen-single abbr:hover { background-position: -42px -10px; } -.chzn-container-single.chzn-disabled .chzn-single abbr:hover { +.chosen-container-single.chosen-disabled .chosen-single abbr:hover { background-position: -42px -10px; } -.chzn-container-single .chzn-single div { +.chosen-container-single .chosen-single div { position: absolute; - right: 0; top: 0; + right: 0; display: block; - height: 100%; width: 18px; + height: 100%; } -.chzn-container-single .chzn-single div b { - background: url('chosen-sprite.png') no-repeat 0px 2px; +.chosen-container-single .chosen-single div b { display: block; width: 100%; height: 100%; + background: url('chosen-sprite.png') no-repeat 0px 2px; } -.chzn-container-single .chzn-search { - padding: 3px 4px; +.chosen-container-single .chosen-search { position: relative; + z-index: 1010; margin: 0; + padding: 3px 4px; white-space: nowrap; - z-index: 1010; } -.chzn-container-single .chzn-search input { - background: #fff url('chosen-sprite.png') no-repeat 100% -20px; - background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); - background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%); +.chosen-container-single .chosen-search input[type="text"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; margin: 1px 0; padding: 4px 20px 4px 5px; + width: 100%; + height: auto; outline: 0; border: 1px solid #aaa; - font-family: sans-serif; + background: white url('chosen-sprite.png') no-repeat 100% -20px; + background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); + background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%); font-size: 1em; + font-family: sans-serif; + line-height: normal; + border-radius: 0; } -.chzn-container-single .chzn-drop { - -webkit-border-radius: 0 0 4px 4px; - -moz-border-radius : 0 0 4px 4px; - border-radius : 0 0 4px 4px; - -moz-background-clip : padding; - -webkit-background-clip: padding-box; - background-clip : padding-box; +.chosen-container-single .chosen-drop { + margin-top: -1px; + border-radius: 0 0 4px 4px; + background-clip: padding-box; } -/* @end */ - -.chzn-container-single-nosearch .chzn-search input { +.chosen-container-single.chosen-container-single-nosearch .chosen-search { position: absolute; - left: -9000px; + left: -9999px; } +/* @end */ +/* @group Results */ +.chosen-container .chosen-results { + position: relative; + overflow-x: hidden; + overflow-y: auto; + margin: 0 4px 4px 0; + padding: 0 0 0 4px; + max-height: 240px; + -webkit-overflow-scrolling: touch; +} +.chosen-container .chosen-results li { + display: none; + margin: 0; + padding: 5px 6px; + list-style: none; + line-height: 15px; +} +.chosen-container .chosen-results li.active-result { + display: list-item; + cursor: pointer; +} +.chosen-container .chosen-results li.disabled-result { + display: list-item; + color: #ccc; + cursor: default; +} +.chosen-container .chosen-results li.highlighted { + background-color: #3875d7; + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); + background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%); + background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%); + background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%); + background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); + color: #fff; +} +.chosen-container .chosen-results li.no-results { + display: list-item; + background: #f4f4f4; +} +.chosen-container .chosen-results li.group-result { + display: list-item; + font-weight: bold; + cursor: default; +} +.chosen-container .chosen-results li.group-option { + padding-left: 15px; +} +.chosen-container .chosen-results li em { + font-style: normal; + text-decoration: underline; +} + +/* @end */ /* @group Multi Chosen */ -.chzn-container-multi .chzn-choices { - background-color: #fff; - background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); - background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background-image: linear-gradient(#eeeeee 1%, #ffffff 15%); - border: 1px solid #aaa; +.chosen-container-multi .chosen-choices { + position: relative; + overflow: hidden; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; margin: 0; padding: 0; - cursor: text; - overflow: hidden; + width: 100%; height: auto !important; height: 1%; - position: relative; + border: 1px solid #aaa; + background-color: #fff; + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); + background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); + background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); + background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%); + background-image: linear-gradient(#eeeeee 1%, #ffffff 15%); + cursor: text; } -.chzn-container-multi .chzn-choices li { +.chosen-container-multi .chosen-choices li { float: left; list-style: none; } -.chzn-container-multi .chzn-choices .search-field { - white-space: nowrap; +.chosen-container-multi .chosen-choices li.search-field { margin: 0; padding: 0; + white-space: nowrap; } -.chzn-container-multi .chzn-choices .search-field input { - color: #666; - background: transparent !important; - border: 0 !important; - font-family: sans-serif; - font-size: 100%; - height: 15px; - padding: 5px; +.chosen-container-multi .chosen-choices li.search-field input[type="text"] { margin: 1px 0; + padding: 5px; + height: 15px; outline: 0; - -webkit-box-shadow: none; - -moz-box-shadow : none; - box-shadow : none; + border: 0 !important; + background: transparent !important; + box-shadow: none; + color: #666; + font-size: 100%; + font-family: sans-serif; + line-height: normal; + border-radius: 0; } -.chzn-container-multi .chzn-choices .search-field .default { +.chosen-container-multi .chosen-choices li.search-field .default { color: #999; } -.chzn-container-multi .chzn-choices .search-choice { - -webkit-border-radius: 3px; - -moz-border-radius : 3px; - border-radius : 3px; - -moz-background-clip : padding; - -webkit-background-clip: padding-box; - background-clip : padding-box; +.chosen-container-multi .chosen-choices li.search-choice { + position: relative; + margin: 3px 0 3px 5px; + padding: 3px 20px 3px 5px; + border: 1px solid #aaa; + border-radius: 3px; background-color: #e4e4e4; - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); - background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); - -moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); - box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); + background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-clip: padding-box; + box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05); color: #333; - border: 1px solid #aaaaaa; line-height: 13px; - padding: 3px 20px 3px 5px; - margin: 3px 0 3px 5px; - position: relative; cursor: default; } -.chzn-container-multi .chzn-choices .search-choice.search-choice-disabled { - background-color: #e4e4e4; - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); - color: #666; - border: 1px solid #cccccc; - padding-right: 5px; -} -.chzn-container-multi .chzn-choices .search-choice-focus { - background: #d4d4d4; -} -.chzn-container-multi .chzn-choices .search-choice .search-choice-close { - display: block; +.chosen-container-multi .chosen-choices li.search-choice .search-choice-close { position: absolute; - right: 3px; top: 4px; + right: 3px; + display: block; width: 12px; height: 12px; - font-size: 1px; background: url('chosen-sprite.png') -42px 1px no-repeat; + font-size: 1px; } -.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover { +.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover { background-position: -42px -10px; } -.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close { - background-position: -42px -10px; +.chosen-container-multi .chosen-choices li.search-choice-disabled { + padding-right: 5px; + border: 1px solid #ccc; + background-color: #e4e4e4; + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); + background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + color: #666; } -/* @end */ - -/* @group Results */ -.chzn-container .chzn-results { - margin: 0 4px 4px 0; - max-height: 240px; - padding: 0 0 0 4px; - position: relative; - overflow-x: hidden; - overflow-y: auto; - -webkit-overflow-scrolling: touch; +.chosen-container-multi .chosen-choices li.search-choice-focus { + background: #d4d4d4; } -.chzn-container-multi .chzn-results { - margin: -1px 0 0; - padding: 0; +.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close { + background-position: -42px -10px; } -.chzn-container .chzn-results li { - display: none; - line-height: 15px; - padding: 5px 6px; +.chosen-container-multi .chosen-results { margin: 0; - list-style: none; -} -.chzn-container .chzn-results .active-result { - cursor: pointer; - display: list-item; -} -.chzn-container .chzn-results .highlighted { - background-color: #3875d7; - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 ); - background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc)); - background-image: -webkit-linear-gradient(top, #3875d7 20%, #2a62bc 90%); - background-image: -moz-linear-gradient(top, #3875d7 20%, #2a62bc 90%); - background-image: -o-linear-gradient(top, #3875d7 20%, #2a62bc 90%); - background-image: linear-gradient(#3875d7 20%, #2a62bc 90%); - color: #fff; -} -.chzn-container .chzn-results li em { - background: #feffde; - font-style: normal; -} -.chzn-container .chzn-results .highlighted em { - background: transparent; + padding: 0; } -.chzn-container .chzn-results .no-results { - background: #f4f4f4; +.chosen-container-multi .chosen-drop .result-selected { display: list-item; -} -.chzn-container .chzn-results .group-result { + color: #ccc; cursor: default; - color: #999; - font-weight: bold; } -.chzn-container .chzn-results .group-option { - padding-left: 15px; -} -.chzn-container-multi .chzn-drop .result-selected { - display: none; -} -.chzn-container .chzn-results-scroll { - background: white; - margin: 0 4px; - position: absolute; - text-align: center; - width: 321px; /* This should by dynamic with js */ - z-index: 1; -} -.chzn-container .chzn-results-scroll span { - display: inline-block; - height: 17px; - text-indent: -5000px; - width: 9px; -} -.chzn-container .chzn-results-scroll-down { - bottom: 0; -} -.chzn-container .chzn-results-scroll-down span { - background: url('chosen-sprite.png') no-repeat -4px -3px; -} -.chzn-container .chzn-results-scroll-up span { - background: url('chosen-sprite.png') no-repeat -22px -3px; -} -/* @end */ +/* @end */ /* @group Active */ -.chzn-container-active .chzn-single { - -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); - -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); - box-shadow : 0 0 5px rgba(0,0,0,.3); +.chosen-container-active .chosen-single { border: 1px solid #5897fb; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); } -.chzn-container-active .chzn-single-with-drop { +.chosen-container-active.chosen-with-drop .chosen-single { border: 1px solid #aaa; - -webkit-box-shadow: 0 1px 0 #fff inset; - -moz-box-shadow : 0 1px 0 #fff inset; - box-shadow : 0 1px 0 #fff inset; - background-color: #eee; - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 ); - background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff)); - background-image: -webkit-linear-gradient(top, #eeeeee 20%, #ffffff 80%); - background-image: -moz-linear-gradient(top, #eeeeee 20%, #ffffff 80%); - background-image: -o-linear-gradient(top, #eeeeee 20%, #ffffff 80%); - background-image: linear-gradient(#eeeeee 20%, #ffffff 80%); - -webkit-border-bottom-left-radius : 0; - -webkit-border-bottom-right-radius: 0; - -moz-border-radius-bottomleft : 0; -moz-border-radius-bottomright: 0; - border-bottom-left-radius : 0; border-bottom-right-radius: 0; + -moz-border-radius-bottomleft: 0; + border-bottom-left-radius: 0; + background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff)); + background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%); + background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%); + background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%); + background-image: linear-gradient(#eeeeee 20%, #ffffff 80%); + box-shadow: 0 1px 0 #fff inset; } -.chzn-container-active .chzn-single-with-drop div { - background: transparent; +.chosen-container-active.chosen-with-drop .chosen-single div { border-left: none; + background: transparent; } -.chzn-container-active .chzn-single-with-drop div b { +.chosen-container-active.chosen-with-drop .chosen-single div b { background-position: -18px 2px; } -.chzn-container-active .chzn-choices { - -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); - -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); - box-shadow : 0 0 5px rgba(0,0,0,.3); +.chosen-container-active .chosen-choices { border: 1px solid #5897fb; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); } -.chzn-container-active .chzn-choices .search-field input { +.chosen-container-active .chosen-choices li.search-field input[type="text"] { color: #111 !important; } -/* @end */ +/* @end */ /* @group Disabled Support */ -.chzn-disabled { +.chosen-disabled { + opacity: 0.5 !important; cursor: default; - opacity:0.5 !important; } -.chzn-disabled .chzn-single { +.chosen-disabled .chosen-single { cursor: default; } -.chzn-disabled .chzn-choices .search-choice .search-choice-close { +.chosen-disabled .chosen-choices .search-choice .search-choice-close { cursor: default; } +/* @end */ /* @group Right to Left */ -.chzn-rtl { text-align: right; } -.chzn-rtl .chzn-single { padding: 0 8px 0 0; overflow: visible; } -.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; direction: rtl; } - -.chzn-rtl .chzn-single div { left: 3px; right: auto; } -.chzn-rtl .chzn-single abbr { +.chosen-rtl { + text-align: right; +} +.chosen-rtl .chosen-single { + overflow: visible; + padding: 0 8px 0 0; +} +.chosen-rtl .chosen-single span { + margin-right: 0; + margin-left: 26px; + direction: rtl; +} +.chosen-rtl .chosen-single-with-deselect span { + margin-left: 38px; +} +.chosen-rtl .chosen-single div { + right: auto; + left: 3px; +} +.chosen-rtl .chosen-single abbr { + right: auto; left: 26px; +} +.chosen-rtl .chosen-choices li { + float: right; +} +.chosen-rtl .chosen-choices li.search-field input[type="text"] { + direction: rtl; +} +.chosen-rtl .chosen-choices li.search-choice { + margin: 3px 5px 3px 0; + padding: 3px 5px 3px 19px; +} +.chosen-rtl .chosen-choices li.search-choice .search-choice-close { right: auto; + left: 4px; } -.chzn-rtl .chzn-choices .search-field input { direction: rtl; } -.chzn-rtl .chzn-choices li { float: right; } -.chzn-rtl .chzn-choices .search-choice { padding: 3px 5px 3px 19px; margin: 3px 5px 3px 0; } -.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 4px; right: auto; } -.chzn-rtl.chzn-container-single .chzn-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; } -.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 15px; } -.chzn-rtl.chzn-container-active .chzn-single-with-drop div { border-right: none; } -.chzn-rtl .chzn-search input { - background: #fff url('chosen-sprite.png') no-repeat -30px -20px; - background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); - background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); - background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%); +.chosen-rtl.chosen-container-single-nosearch .chosen-search, +.chosen-rtl .chosen-drop { + left: 9999px; +} +.chosen-rtl.chosen-container-single .chosen-results { + margin: 0 0 4px 4px; + padding: 0 4px 0 0; +} +.chosen-rtl .chosen-results li.group-option { + padding-right: 15px; + padding-left: 0; +} +.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { + border-right: none; +} +.chosen-rtl .chosen-search input[type="text"] { padding: 4px 5px 4px 20px; + background: white url('chosen-sprite.png') no-repeat -30px -20px; + background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); + background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(#eeeeee 1%, #ffffff 15%); + background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%); direction: rtl; } -.chzn-container-single.chzn-rtl .chzn-single div b { +.chosen-rtl.chosen-container-single .chosen-single div b { background-position: 6px 2px; } -.chzn-container-single.chzn-rtl .chzn-single-with-drop div b { +.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b { background-position: -12px 2px; } -/* @end */ +/* @end */ /* @group Retina compatibility */ -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) { - .chzn-rtl .chzn-search input, .chzn-container-single .chzn-single abbr, .chzn-container-single .chzn-single div b, .chzn-container-single .chzn-search input, .chzn-container-multi .chzn-choices .search-choice .search-choice-close, .chzn-container .chzn-results-scroll-down span, .chzn-container .chzn-results-scroll-up span { - background-image: url('chosen-sprite@2x.png') !important; - background-repeat: no-repeat !important; - background-size: 52px 37px !important; +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) { + .chosen-rtl .chosen-search input[type="text"], + .chosen-container-single .chosen-single abbr, + .chosen-container-single .chosen-single div b, + .chosen-container-single .chosen-search input[type="text"], + .chosen-container-multi .chosen-choices .search-choice .search-choice-close, + .chosen-container .chosen-results-scroll-down span, + .chosen-container .chosen-results-scroll-up span { + background-image: url('chosen-sprite@2x.png') !important; + background-size: 52px 37px !important; + background-repeat: no-repeat !important; } } /* @end */ diff --git a/themes/default/js/plugins/chosen.jquery.min.js b/themes/default/js/plugins/chosen.jquery.min.js index 2ee0d7f8f..ad430c46a 100644 --- a/themes/default/js/plugins/chosen.jquery.min.js +++ b/themes/default/js/plugins/chosen.jquery.min.js @@ -1,10 +1,2 @@ -// Chosen, a Select Box Enhancer for jQuery and Protoype -// by Patrick Filler for Harvest, http://getharvest.com -// -// Version 0.9.11 -// Full source at https://github.com/harvesthq/chosen -// Copyright (c) 2011 Harvest http://getharvest.com - -// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -// This file is generated by `cake build`, do not edit it by hand. -(function(){var e;e=function(){function e(){this.options_index=0,this.parsed=[]}return e.prototype.add_node=function(e){return e.nodeName.toUpperCase()==="OPTGROUP"?this.add_group(e):this.add_option(e)},e.prototype.add_group=function(e){var t,n,r,i,s,o;t=this.parsed.length,this.parsed.push({array_index:t,group:!0,label:e.label,children:0,disabled:e.disabled}),s=e.childNodes,o=[];for(r=0,i=s.length;r<i;r++)n=s[r],o.push(this.add_option(n,t,e.disabled));return o},e.prototype.add_option=function(e,t,n){if(e.nodeName.toUpperCase()==="OPTION")return e.text!==""?(t!=null&&(this.parsed[t].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:e.value,text:e.text,html:e.innerHTML,selected:e.selected,disabled:n===!0?n:e.disabled,group_array_index:t,classes:e.className,style:e.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1},e}(),e.select_to_array=function(t){var n,r,i,s,o;r=new e,o=t.childNodes;for(i=0,s=o.length;i<s;i++)n=o[i],r.add_node(n);return r.parsed},this.SelectParser=e}).call(this),function(){var e,t;t=this,e=function(){function e(e,t){this.form_field=e,this.options=t!=null?t:{},this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.finish_setup()}return e.prototype.set_default_values=function(){var e=this;return this.click_test_action=function(t){return e.test_active_click(t)},this.activate_action=function(t){return e.activate_field(t)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.result_single_selected=null,this.allow_single_deselect=this.options.allow_single_deselect!=null&&this.form_field.options[0]!=null&&this.form_field.options[0].text===""?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=this.options.enable_split_word_search!=null?this.options.enable_split_word_search:!0,this.search_contains=this.options.search_contains||!1,this.choices=0,this.single_backstroke_delete=this.options.single_backstroke_delete||!1,this.max_selected_options=this.options.max_selected_options||Infinity,this.inherit_select_classes=this.options.inherit_select_classes||!1},e.prototype.set_default_text=function(){return this.form_field.getAttribute("data-placeholder")?this.default_text=this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.default_text=this.options.placeholder_text_multiple||this.options.placeholder_text||"Select Some Options":this.default_text=this.options.placeholder_text_single||this.options.placeholder_text||"Select an Option",this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||"No results match"},e.prototype.mouse_enter=function(){return this.mouse_on_container=!0},e.prototype.mouse_leave=function(){return this.mouse_on_container=!1},e.prototype.input_focus=function(e){var t=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return t.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},e.prototype.input_blur=function(e){var t=this;if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(){return t.blur_test()},100)},e.prototype.result_add_option=function(e){var t,n;return e.disabled?"":(e.dom_id=this.container_id+"_o_"+e.array_index,t=e.selected&&this.is_multiple?[]:["active-result"],e.selected&&t.push("result-selected"),e.group_array_index!=null&&t.push("group-option"),e.classes!==""&&t.push(e.classes),n=e.style.cssText!==""?' style="'+e.style+'"':"",'<li id="'+e.dom_id+'" class="'+t.join(" ")+'"'+n+">"+e.html+"</li>")},e.prototype.results_update_field=function(){return this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.result_single_selected=null,this.results_build()},e.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},e.prototype.results_search=function(e){return this.results_showing?this.winnow_results():this.results_show()},e.prototype.keyup_checker=function(e){var t,n;t=(n=e.which)!=null?n:e.keyCode,this.search_field_scale();switch(t){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:e.preventDefault();if(this.results_showing)return this.result_select(e);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},e.prototype.generate_field_id=function(){var e;return e=this.generate_random_id(),this.form_field.id=e,e},e.prototype.generate_random_char=function(){var e,t,n;return e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",n=Math.floor(Math.random()*e.length),t=e.substring(n,n+1)},e}(),t.AbstractChosen=e}.call(this),function(){var e,t,n,r,i={}.hasOwnProperty,s=function(e,t){function r(){this.constructor=e}for(var n in t)i.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};r=this,e=jQuery,e.fn.extend({chosen:function(n){var r,i,s;return s=navigator.userAgent.toLowerCase(),i=/(msie) ([\w.]+)/.exec(s)||[],r={name:i[1]||"",version:i[2]||"0"},r.name==="msie"&&(r.version==="6.0"||r.version==="7.0"&&document.documentMode===7)?this:this.each(function(r){var i;i=e(this);if(!i.hasClass("chzn-done"))return i.data("chosen",new t(this,n))})}}),t=function(t){function i(){return i.__super__.constructor.apply(this,arguments)}return s(i,t),i.prototype.setup=function(){return this.form_field_jq=e(this.form_field),this.current_value=this.form_field_jq.val(),this.is_rtl=this.form_field_jq.hasClass("chzn-rtl")},i.prototype.finish_setup=function(){return this.form_field_jq.addClass("chzn-done")},i.prototype.set_up_html=function(){var t,r,i,s,o,u;return this.container_id=this.form_field.id.length?this.form_field.id.replace(/[^\w]/g,"_"):this.generate_field_id(),this.container_id+="_chzn",t=["chzn-container"],t.push("chzn-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&t.push(this.form_field.className),this.is_rtl&&t.push("chzn-rtl"),this.f_width=this.form_field_jq.outerWidth(),i={id:this.container_id,"class":t.join(" "),style:"width: "+this.f_width+"px;",title:this.form_field.title},r=e("<div />",i),this.is_multiple?r.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>'):r.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>'),this.form_field_jq.hide().after(r),this.container=e("#"+this.container_id),this.dropdown=this.container.find("div.chzn-drop").first(),s=this.container.height(),o=this.f_width-n(this.dropdown),this.dropdown.css({width:o+"px",top:s+"px"}),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chzn-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chzn-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chzn-search").first(),this.selected_item=this.container.find(".chzn-single").first(),u=o-n(this.search_container)-n(this.search_field),this.search_field.css({width:u+"px"})),this.results_build(),this.set_tab_index(),this.form_field_jq.trigger("liszt:ready",{chosen:this})},i.prototype.register_observers=function(){var e=this;return this.container.mousedown(function(t){return e.container_mousedown(t)}),this.container.mouseup(function(t){return e.container_mouseup(t)}),this.container.mouseenter(function(t){return e.mouse_enter(t)}),this.container.mouseleave(function(t){return e.mouse_leave(t)}),this.search_results.mouseup(function(t){return e.search_results_mouseup(t)}),this.search_results.mouseover(function(t){return e.search_results_mouseover(t)}),this.search_results.mouseout(function(t){return e.search_results_mouseout(t)}),this.form_field_jq.bind("liszt:updated",function(t){return e.results_update_field(t)}),this.form_field_jq.bind("liszt:activate",function(t){return e.activate_field(t)}),this.form_field_jq.bind("liszt:open",function(t){return e.container_mousedown(t)}),this.search_field.blur(function(t){return e.input_blur(t)}),this.search_field.keyup(function(t){return e.keyup_checker(t)}),this.search_field.keydown(function(t){return e.keydown_checker(t)}),this.search_field.focus(function(t){return e.input_focus(t)}),this.is_multiple?this.search_choices.click(function(t){return e.choices_click(t)}):this.container.click(function(e){return e.preventDefault()})},i.prototype.search_field_disabled=function(){this.is_disabled=this.form_field_jq[0].disabled;if(this.is_disabled)return this.container.addClass("chzn-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus",this.activate_action),this.close_field();this.container.removeClass("chzn-disabled"),this.search_field[0].disabled=!1;if(!this.is_multiple)return this.selected_item.bind("focus",this.activate_action)},i.prototype.container_mousedown=function(t){var n;if(!this.is_disabled)return n=t!=null?e(t.target).hasClass("search-choice-close"):!1,t&&t.type==="mousedown"&&!this.results_showing&&t.preventDefault(),!this.pending_destroy_click&&!n?(this.active_field?!this.is_multiple&&t&&(e(t.target)[0]===this.selected_item[0]||e(t.target).parents("a.chzn-single").length)&&(t.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),e(document).click(this.click_test_action),this.results_show()),this.activate_field()):this.pending_destroy_click=!1},i.prototype.container_mouseup=function(e){if(e.target.nodeName==="ABBR"&&!this.is_disabled)return this.results_reset(e)},i.prototype.blur_test=function(e){if(!this.active_field&&this.container.hasClass("chzn-container-active"))return this.close_field()},i.prototype.close_field=function(){return e(document).unbind("click",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chzn-container-active"),this.winnow_results_clear(),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},i.prototype.activate_field=function(){return this.container.addClass("chzn-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},i.prototype.test_active_click=function(t){return e(t.target).parents("#"+this.container_id).length?this.active_field=!0:this.close_field()},i.prototype.results_build=function(){var e,t,n,i,s;this.parsing=!0,this.results_data=r.SelectParser.select_to_array(this.form_field),this.is_multiple&&this.choices>0?(this.search_choices.find("li.search-choice").remove(),this.choices=0):this.is_multiple||(this.selected_item.addClass("chzn-default").find("span").text(this.default_text),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?this.container.addClass("chzn-container-single-nosearch"):this.container.removeClass("chzn-container-single-nosearch")),e="",s=this.results_data;for(n=0,i=s.length;n<i;n++)t=s[n],t.group?e+=this.result_add_group(t):t.empty||(e+=this.result_add_option(t),t.selected&&this.is_multiple?this.choice_build(t):t.selected&&!this.is_multiple&&(this.selected_item.removeClass("chzn-default").find("span").text(t.text),this.allow_single_deselect&&this.single_deselect_control_build()));return this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.search_results.html(e),this.parsing=!1},i.prototype.result_add_group=function(t){return t.disabled?"":(t.dom_id=this.container_id+"_g_"+t.array_index,'<li id="'+t.dom_id+'" class="group-result">'+e("<div />").text(t.label).html()+"</li>")},i.prototype.result_do_highlight=function(e){var t,n,r,i,s;if(e.length){this.result_clear_highlight(),this.result_highlight=e,this.result_highlight.addClass("highlighted"),r=parseInt(this.search_results.css("maxHeight"),10),s=this.search_results.scrollTop(),i=r+s,n=this.result_highlight.position().top+this.search_results.scrollTop(),t=n+this.result_highlight.outerHeight();if(t>=i)return this.search_results.scrollTop(t-r>0?t-r:0);if(n<s)return this.search_results.scrollTop(n)}},i.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},i.prototype.results_show=function(){var e;if(!this.is_multiple)this.selected_item.addClass("chzn-single-with-drop"),this.result_single_selected&&this.result_do_highlight(this.result_single_selected);else if(this.max_selected_options<=this.choices)return this.form_field_jq.trigger("liszt:maxselected",{chosen:this}),!1;return e=this.is_multiple?this.container.height():this.container.height()-1,this.form_field_jq.trigger("liszt:showing_dropdown",{chosen:this}),this.dropdown.css({top:e+"px",left:0}),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results()},i.prototype.results_hide=function(){return this.is_multiple||this.selected_item.removeClass("chzn-single-with-drop"),this.result_clear_highlight(),this.form_field_jq.trigger("liszt:hiding_dropdown",{chosen:this}),this.dropdown.css({left:"-9000px"}),this.results_showing=!1},i.prototype.set_tab_index=function(e){var t;if(this.form_field_jq.attr("tabindex"))return t=this.form_field_jq.attr("tabindex"),this.form_field_jq.attr("tabindex",-1),this.search_field.attr("tabindex",t)},i.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},i.prototype.search_results_mouseup=function(t){var n;n=e(t.target).hasClass("active-result")?e(t.target):e(t.target).parents(".active-result").first();if(n.length)return this.result_highlight=n,this.result_select(t),this.search_field.focus()},i.prototype.search_results_mouseover=function(t){var n;n=e(t.target).hasClass("active-result")?e(t.target):e(t.target).parents(".active-result").first();if(n)return this.result_do_highlight(n)},i.prototype.search_results_mouseout=function(t){if(e(t.target).hasClass("active-result"))return this.result_clear_highlight()},i.prototype.choices_click=function(t){t.preventDefault();if(this.active_field&&!e(t.target).hasClass("search-choice")&&!this.results_showing)return this.results_show()},i.prototype.choice_build=function(t){var n,r,i,s=this;return this.is_multiple&&this.max_selected_options<=this.choices?(this.form_field_jq.trigger("liszt:maxselected",{chosen:this}),!1):(n=this.container_id+"_c_"+t.array_index,this.choices+=1,t.disabled?r='<li class="search-choice search-choice-disabled" id="'+n+'"><span>'+t.html+"</span></li>":r='<li class="search-choice" id="'+n+'"><span>'+t.html+'</span><a href="javascript:void(0)" class="search-choice-close" rel="'+t.array_index+'"></a></li>',this.search_container.before(r),i=e("#"+n).find("a").first(),i.click(function(e){return s.choice_destroy_link_click(e)}))},i.prototype.choice_destroy_link_click=function(t){return t.preventDefault(),this.is_disabled?t.stopPropagation:(this.pending_destroy_click=!0,this.choice_destroy(e(t.target)))},i.prototype.choice_destroy=function(e){if(this.result_deselect(e.attr("rel")))return this.choices-=1,this.show_search_field_default(),this.is_multiple&&this.choices>0&&this.search_field.val().length<1&&this.results_hide(),e.parents("li").first().remove(),this.search_field_scale()},i.prototype.results_reset=function(){this.form_field.options[0].selected=!0,this.selected_item.find("span").text(this.default_text),this.is_multiple||this.selected_item.addClass("chzn-default"),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change");if(this.active_field)return this.results_hide()},i.prototype.results_reset_cleanup=function(){return this.current_value=this.form_field_jq.val(),this.selected_item.find("abbr").remove()},i.prototype.result_select=function(e){var t,n,r,i;if(this.result_highlight)return t=this.result_highlight,n=t.attr("id"),this.result_clear_highlight(),this.is_multiple?this.result_deactivate(t):(this.search_results.find(".result-selected").removeClass("result-selected"),this.result_single_selected=t,this.selected_item.removeClass("chzn-default")),t.addClass("result-selected"),i=n.substr(n.lastIndexOf("_")+1),r=this.results_data[i],r.selected=!0,this.form_field.options[r.options_index].selected=!0,this.is_multiple?this.choice_build(r):(this.selected_item.find("span").first().text(r.text),this.allow_single_deselect&&this.single_deselect_control_build()),(!e.metaKey&&!e.ctrlKey||!this.is_multiple)&&this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field_jq.val()!==this.current_value)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[r.options_index].value}),this.current_value=this.form_field_jq.val(),this.search_field_scale()},i.prototype.result_activate=function(e){return e.addClass("active-result")},i.prototype.result_deactivate=function(e){return e.removeClass("active-result")},i.prototype.result_deselect=function(t){var n,r;return r=this.results_data[t],this.form_field.options[r.options_index].disabled?!1:(r.selected=!1,this.form_field.options[r.options_index].selected=!1,n=e("#"+this.container_id+"_o_"+t),n.removeClass("result-selected").addClass("active-result").show(),this.result_clear_highlight(),this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[r.options_index].value}),this.search_field_scale(),!0)},i.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect&&this.selected_item.find("abbr").length<1)return this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>')},i.prototype.winnow_results=function(){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y;this.no_results_clear(),f=0,l=this.search_field.val()===this.default_text?"":e("<div/>").text(e.trim(this.search_field.val())).html(),o=this.search_contains?"":"^",s=new RegExp(o+l.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),p=new RegExp(l.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),"i"),y=this.results_data;for(d=0,m=y.length;d<m;d++){n=y[d];if(!n.disabled&&!n.empty)if(n.group)e("#"+n.dom_id).css("display","none");else if(!this.is_multiple||!n.selected){t=!1,a=n.dom_id,u=e("#"+a);if(s.test(n.html))t=!0,f+=1;else if(this.enable_split_word_search&&(n.html.indexOf(" ")>=0||n.html.indexOf("[")===0)){i=n.html.replace(/\[|\]/g,"").split(" ");if(i.length)for(v=0,g=i.length;v<g;v++)r=i[v],s.test(r)&&(t=!0,f+=1)}t?(l.length?(c=n.html.search(p),h=n.html.substr(0,c+l.length)+"</em>"+n.html.substr(c+l.length),h=h.substr(0,c)+"<em>"+h.substr(c)):h=n.html,u.html(h),this.result_activate(u),n.group_array_index!=null&&e("#"+this.results_data[n.group_array_index].dom_id).css("display","list-item")):(this.result_highlight&&a===this.result_highlight.attr("id")&&this.result_clear_highlight(),this.result_deactivate(u))}}return f<1&&l.length?this.no_results(l):this.winnow_results_set_highlight()},i.prototype.winnow_results_clear=function(){var t,n,r,i,s;this.search_field.val(""),n=this.search_results.find("li"),s=[];for(r=0,i=n.length;r<i;r++)t=n[r],t=e(t),t.hasClass("group-result")?s.push(t.css("display","auto")):!this.is_multiple||!t.hasClass("result-selected")?s.push(this.result_activate(t)):s.push(void 0);return s},i.prototype.winnow_results_set_highlight=function(){var e,t;if(!this.result_highlight){t=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),e=t.length?t.first():this.search_results.find(".active-result").first();if(e!=null)return this.result_do_highlight(e)}},i.prototype.no_results=function(t){var n;return n=e('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),n.find("span").first().html(t),this.search_results.append(n)},i.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},i.prototype.keydown_arrow=function(){var t,n;this.result_highlight?this.results_showing&&(n=this.result_highlight.nextAll("li.active-result").first(),n&&this.result_do_highlight(n)):(t=this.search_results.find("li.active-result").first(),t&&this.result_do_highlight(e(t)));if(!this.results_showing)return this.results_show()},i.prototype.keyup_arrow=function(){var e;if(!this.results_showing&&!this.is_multiple)return this.results_show();if(this.result_highlight)return e=this.result_highlight.prevAll("li.active-result"),e.length?this.result_do_highlight(e.first()):(this.choices>0&&this.results_hide(),this.result_clear_highlight())},i.prototype.keydown_backstroke=function(){var e;if(this.pending_backstroke)return this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke();e=this.search_container.siblings("li.search-choice").last();if(e.length&&!e.hasClass("search-choice-disabled"))return this.pending_backstroke=e,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")},i.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},i.prototype.keydown_checker=function(e){var t,n;t=(n=e.which)!=null?n:e.keyCode,this.search_field_scale(),t!==8&&this.pending_backstroke&&this.clear_backstroke();switch(t){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(e),this.mouse_on_container=!1;break;case 13:e.preventDefault();break;case 38:e.preventDefault(),this.keyup_arrow();break;case 40:this.keydown_arrow()}},i.prototype.search_field_scale=function(){var t,n,r,i,s,o,u,a,f;if(this.is_multiple){r=0,u=0,s="position:absolute; left: -1000px; top: -1000px; display:none;",o=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"];for(a=0,f=o.length;a<f;a++)i=o[a],s+=i+":"+this.search_field.css(i)+";";return n=e("<div />",{style:s}),n.text(this.search_field.val()),e("body").append(n),u=n.width()+25,n.remove(),u>this.f_width-10&&(u=this.f_width-10),this.search_field.css({width:u+"px"}),t=this.container.height(),this.dropdown.css({top:t+"px"})}},i.prototype.generate_random_id=function(){var t;t="sel"+this.generate_random_char()+this.generate_random_char()+this.generate_random_char();while(e("#"+t).length>0)t+=this.generate_random_char();return t},i}(AbstractChosen),r.Chosen=t,n=function(e){var t;return t=e.outerWidth()-e.width()},r.get_side_border_padding=n}.call(this);
\ No newline at end of file +/* Chosen v1.0.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */ +!function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),children:0,disabled:a.disabled}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.result_single_selected=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(c.text));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=""!==a.style.cssText?' style="'+a.style+'"':"",'<li class="'+b.join(" ")+'"'+c+' data-option-array-index="'+a.array_index+'">'+a.search_text+"</li>"):"":""},AbstractChosen.prototype.result_add_group=function(a){return a.search_match||a.group_match?a.active_options>0?'<li class="group-result">'+a.search_text+"</li>":"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.result_single_selected=null,this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l,m;for(this.no_results_clear(),e=0,g=this.get_search_text(),a=g.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),d=this.search_contains?"":"^",c=new RegExp(d+a,"i"),j=new RegExp(a,"i"),m=this.results_data,k=0,l=m.length;l>k;k++)b=m[k],b.search_match=!1,f=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(f=this.results_data[b.group_array_index],0===f.active_options&&f.search_match&&(e+=1),f.active_options+=1),(!b.group||this.group_search)&&(b.search_text=b.group?b.label:b.html,b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(e+=1),b.search_match?(g.length&&(h=b.search_text.search(j),i=b.search_text.substr(0,h+g.length)+"</em>"+b.search_text.substr(h+g.length),b.search_text=i.substr(0,h)+"<em>"+i.substr(h)),null!=f&&(f.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>e&&g.length?(this.update_results_content(""),this.no_results(g)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(){var c,d;c=a(this),d=c.data("chosen"),"destroy"===b&&d?d.destroy():d||c.data("chosen",new Chosen(this,b))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("<div />",c),this.is_multiple?this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'):this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(document).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(document).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b,c,d;return b=-(null!=(c=a.originalEvent)?c.wheelDelta:void 0)||(null!=(d=a.originialEvent)?d.detail:void 0),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(document).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){return this.container.is(a(b.target).closest(".chosen-container"))?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results())},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("<li />",{"class":"search-choice"}).html("<span>"+b.html+"</span>"),b.disabled?c.addClass("search-choice-disabled"):(d=a("<a />",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.form_field.options[0].selected=!0,this.selected_option_count=null,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c,d;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):(this.result_single_selected&&(this.result_single_selected.removeClass("result-selected"),d=this.result_single_selected[0].getAttribute("data-option-array-index"),this.results_data[d].selected=!1),this.result_single_selected=b),b.addClass("result-selected"),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(c.text),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").text(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":a("<div/>").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),c.find("span").first().html(b),this.search_results.append(c)},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("<div />",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}.call(this);
\ No newline at end of file diff --git a/themes/default/js/plugins/datatables/css/demo_page.css b/themes/default/js/plugins/datatables/css/demo_page.css new file mode 100644 index 000000000..ba5b2a6c3 --- /dev/null +++ b/themes/default/js/plugins/datatables/css/demo_page.css @@ -0,0 +1,122 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * General page setup + */ +#dt_example { + font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; + margin: 0; + padding: 0; + color: #333; + background-color: #fff; +} + + +#dt_example #container { + width: 800px; + margin: 30px auto; + padding: 0; +} + + +#dt_example #footer { + margin: 50px auto 0 auto; + padding: 0; +} + +#dt_example #demo { + margin: 30px auto 0 auto; +} + +#dt_example .demo_jui { + margin: 30px auto 0 auto; +} + +#dt_example .big { + font-size: 1.3em; + font-weight: bold; + line-height: 1.6em; + color: #4E6CA3; +} + +#dt_example .spacer { + height: 20px; + clear: both; +} + +#dt_example .clear { + clear: both; +} + +#dt_example pre { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +#dt_example h1 { + margin-top: 2em; + font-size: 1.3em; + font-weight: normal; + line-height: 1.6em; + color: #4E6CA3; + border-bottom: 1px solid #B0BED9; + clear: both; +} + +#dt_example h2 { + font-size: 1.2em; + font-weight: normal; + line-height: 1.6em; + color: #4E6CA3; + clear: both; +} + +#dt_example a { + color: #0063DC; + text-decoration: none; +} + +#dt_example a:hover { + text-decoration: underline; +} + +#dt_example ul { + color: #4E6CA3; +} + +.css_right { + float: right; +} + +.css_left { + float: left; +} + +.demo_links { + float: left; + width: 50%; + margin-bottom: 1em; +} + +#demo_info { + padding: 5px; + border: 1px solid #B0BED9; + height: 100px; + width: 100%; + overflow: auto; +} + +#dt_example code { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 2px 4px !important; + white-space: nowrap; + font-size: 0.9em; + + color: #D14; + background-color: #F7F7F9; + + border: 1px solid #E1E1E8; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} diff --git a/themes/default/js/plugins/datatables/css/demo_table.css b/themes/default/js/plugins/datatables/css/demo_table.css new file mode 100644 index 000000000..12f352dac --- /dev/null +++ b/themes/default/js/plugins/datatables/css/demo_table.css @@ -0,0 +1,577 @@ +/* + * File: demo_table.css + * CVS: $Id$ + * Description: CSS descriptions for DataTables demo pages + * Author: Allan Jardine + * Created: Tue May 12 06:47:22 BST 2009 + * Modified: $Date$ by $Author$ + * Language: CSS + * Project: DataTables + * + * Copyright 2009 Allan Jardine. All Rights Reserved. + * + * *************************************************************************** + * DESCRIPTION + * + * The styles given here are suitable for the demos that are used with the standard DataTables + * distribution (see www.datatables.net). You will most likely wish to modify these styles to + * meet the layout requirements of your site. + * + * Common issues: + * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is + * no conflict between the two pagination types. If you want to use full_numbers pagination + * ensure that you either have "example_alt_pagination" as a body class name, or better yet, + * modify that selector. + * Note that the path used for Images is relative. All images are by default located in + * ../images/ - relative to this CSS file. + */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables features + */ + +.dataTables_wrapper { + position: relative; + clear: both; + zoom: 1; /* Feeling sorry for IE */ +} + +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + +.dataTables_length { + width: 40%; + float: left; +} + +.dataTables_filter { + width: 50%; + float: right; + text-align: right; +} + +.dataTables_info { + width: 60%; + float: left; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + +/* Pagination nested */ +.paginate_disabled_previous, .paginate_enabled_previous, +.paginate_disabled_next, .paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, .paginate_enabled_previous:hover, +.paginate_disabled_next:hover, .paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, .paginate_enabled_previous:active, +.paginate_disabled_next:active, .paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, .paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, .paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_disabled_previous { + background: url('../images/back_disabled.png') no-repeat top left; +} + +.paginate_enabled_previous { + background: url('../images/back_enabled.png') no-repeat top left; +} +.paginate_enabled_previous:hover { + background: url('../images/back_enabled_hover.png') no-repeat top left; +} + +.paginate_disabled_next { + background: url('../images/forward_disabled.png') no-repeat top right; +} + +.paginate_enabled_next { + background: url('../images/forward_enabled.png') no-repeat top right; +} +.paginate_enabled_next:hover { + background: url('../images/forward_enabled_hover.png') no-repeat top right; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables display + */ +table.display { + margin: 0 auto; + clear: both; + width: 100%; + + /* Note Firefox 3.5 and before have a bug with border-collapse + * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 ) + * border-spacing: 0; is one possible option. Conditional-css.com is + * useful for this kind of thing + * + * Further note IE 6/7 has problems when calculating widths with border width. + * It subtracts one px relative to the other browsers from the first column, and + * adds one to the end... + * + * If you want that effect I'd suggest setting a border-top/left on th/td's and + * then filling in the gaps with other borders. + */ +} + +table.display thead th { + padding: 3px 18px 3px 10px; + border-bottom: 1px solid black; + font-weight: bold; + cursor: pointer; + * cursor: hand; +} + +table.display tfoot th { + padding: 3px 18px 3px 10px; + border-top: 1px solid black; + font-weight: bold; +} + +table.display tr.heading2 td { + border-bottom: 1px solid #aaa; +} + +table.display td { + padding: 3px 10px; +} + +table.display td.center { + text-align: center; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables sorting + */ + +.sorting_asc { + background: url('../images/sort_asc.png') no-repeat center right; +} + +.sorting_desc { + background: url('../images/sort_desc.png') no-repeat center right; +} + +.sorting { + background: url('../images/sort_both.png') no-repeat center right; +} + +.sorting_asc_disabled { + background: url('../images/sort_asc_disabled.png') no-repeat center right; +} + +.sorting_desc_disabled { + background: url('../images/sort_desc_disabled.png') no-repeat center right; +} + +table.display thead th:active, +table.display thead td:active { + outline: none; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables row classes + */ +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + +table.display tr.odd.gradeC { + background-color: #ddddff; +} + +table.display tr.even.gradeC { + background-color: #eeeeff; +} + +table.display tr.odd.gradeX { + background-color: #ffdddd; +} + +table.display tr.even.gradeX { + background-color: #ffeeee; +} + +table.display tr.odd.gradeU { + background-color: #ddd; +} + +table.display tr.even.gradeU { + background-color: #eee; +} + + +tr.odd { + background-color: #E2E4FF; +} + +tr.even { + background-color: white; +} + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Misc + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + +.top, .bottom { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +.top .dataTables_info { + float: none; +} + +.clear { + clear: both; +} + +.dataTables_empty { + text-align: center; +} + +tfoot input { + margin: 0.5em 0; + width: 100%; + color: #444; +} + +tfoot input.search_init { + color: #999; +} + +td.group { + background-color: #d1cfd0; + border-bottom: 2px solid #A19B9E; + border-top: 2px solid #A19B9E; +} + +td.details { + background-color: #d1cfd0; + border: 2px solid #A19B9E; +} + + +.example_alt_pagination div.dataTables_info { + width: 40%; +} + +.paging_full_numbers { + width: 400px; + height: 22px; + line-height: 22px; +} + +.paging_full_numbers a:active { + outline: none +} + +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, + .paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + +table.display tr.even.row_selected td { + background-color: #B0BED9; +} + +table.display tr.odd.row_selected td { + background-color: #9FAFD1; +} + + +/* + * Sorting classes for columns + */ +/* For the standard odd/even */ +tr.odd td.sorting_1 { + background-color: #D3D6FF; +} + +tr.odd td.sorting_2 { + background-color: #DADCFF; +} + +tr.odd td.sorting_3 { + background-color: #E0E2FF; +} + +tr.even td.sorting_1 { + background-color: #EAEBFF; +} + +tr.even td.sorting_2 { + background-color: #F2F3FF; +} + +tr.even td.sorting_3 { + background-color: #F9F9FF; +} + + +/* For the Conditional-CSS grading rows */ +/* + Colour calculations (based off the main row colours) + Level 1: + dd > c4 + ee > d5 + Level 2: + dd > d1 + ee > e2 + */ +tr.odd.gradeA td.sorting_1 { + background-color: #c4ffc4; +} + +tr.odd.gradeA td.sorting_2 { + background-color: #d1ffd1; +} + +tr.odd.gradeA td.sorting_3 { + background-color: #d1ffd1; +} + +tr.even.gradeA td.sorting_1 { + background-color: #d5ffd5; +} + +tr.even.gradeA td.sorting_2 { + background-color: #e2ffe2; +} + +tr.even.gradeA td.sorting_3 { + background-color: #e2ffe2; +} + +tr.odd.gradeC td.sorting_1 { + background-color: #c4c4ff; +} + +tr.odd.gradeC td.sorting_2 { + background-color: #d1d1ff; +} + +tr.odd.gradeC td.sorting_3 { + background-color: #d1d1ff; +} + +tr.even.gradeC td.sorting_1 { + background-color: #d5d5ff; +} + +tr.even.gradeC td.sorting_2 { + background-color: #e2e2ff; +} + +tr.even.gradeC td.sorting_3 { + background-color: #e2e2ff; +} + +tr.odd.gradeX td.sorting_1 { + background-color: #ffc4c4; +} + +tr.odd.gradeX td.sorting_2 { + background-color: #ffd1d1; +} + +tr.odd.gradeX td.sorting_3 { + background-color: #ffd1d1; +} + +tr.even.gradeX td.sorting_1 { + background-color: #ffd5d5; +} + +tr.even.gradeX td.sorting_2 { + background-color: #ffe2e2; +} + +tr.even.gradeX td.sorting_3 { + background-color: #ffe2e2; +} + +tr.odd.gradeU td.sorting_1 { + background-color: #c4c4c4; +} + +tr.odd.gradeU td.sorting_2 { + background-color: #d1d1d1; +} + +tr.odd.gradeU td.sorting_3 { + background-color: #d1d1d1; +} + +tr.even.gradeU td.sorting_1 { + background-color: #d5d5d5; +} + +tr.even.gradeU td.sorting_2 { + background-color: #e2e2e2; +} + +tr.even.gradeU td.sorting_3 { + background-color: #e2e2e2; +} + + +/* + * Row highlighting example + */ +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted { + background-color: #ECFFB3; +} + +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.even:hover { + background-color: #ECFFB3; +} + +.ex_highlight_row #example tr.even:hover td.sorting_1 { + background-color: #DDFF75; +} + +.ex_highlight_row #example tr.even:hover td.sorting_2 { + background-color: #E7FF9E; +} + +.ex_highlight_row #example tr.even:hover td.sorting_3 { + background-color: #E2FF89; +} + +.ex_highlight_row #example tr.odd:hover { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_1 { + background-color: #D6FF5C; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_2 { + background-color: #E0FF84; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_3 { + background-color: #DBFF70; +} + + +/* + * KeyTable + */ +table.KeyTable td { + border: 3px solid transparent; +} + +table.KeyTable td.focus { + border: 3px solid #3366FF; +} + +table.display tr.gradeA { + background-color: #eeffee; +} + +table.display tr.gradeC { + background-color: #ddddff; +} + +table.display tr.gradeX { + background-color: #ffdddd; +} + +table.display tr.gradeU { + background-color: #ddd; +} + +div.box { + height: 100px; + padding: 10px; + overflow: auto; + border: 1px solid #8080FF; + background-color: #E5E5FF; +} diff --git a/themes/default/js/plugins/datatables/css/demo_table_jui.css b/themes/default/js/plugins/datatables/css/demo_table_jui.css new file mode 100644 index 000000000..a210af51a --- /dev/null +++ b/themes/default/js/plugins/datatables/css/demo_table_jui.css @@ -0,0 +1,501 @@ +/* + * File: demo_table_jui.css + * CVS: $Id$ + * Description: CSS descriptions for DataTables demo pages + * Author: Allan Jardine + * Created: Tue May 12 06:47:22 BST 2009 + * Modified: $Date$ by $Author$ + * Language: CSS + * Project: DataTables + * + * Copyright 2009 Allan Jardine. All Rights Reserved. + * + * *************************************************************************** + * DESCRIPTION + * + * The styles given here are suitable for the demos that are used with the standard DataTables + * distribution (see www.datatables.net). You will most likely wish to modify these styles to + * meet the layout requirements of your site. + * + * Common issues: + * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is + * no conflict between the two pagination types. If you want to use full_numbers pagination + * ensure that you either have "example_alt_pagination" as a body class name, or better yet, + * modify that selector. + * Note that the path used for Images is relative. All images are by default located in + * ../images/ - relative to this CSS file. + */ + + +/* + * jQuery UI specific styling + */ + +.paging_two_button .ui-button { + float: left; + cursor: pointer; + * cursor: hand; +} + +.paging_full_numbers .ui-button { + padding: 2px 6px; + margin: 0; + cursor: pointer; + * cursor: hand; + color: #333 !important; +} + +.dataTables_paginate .ui-button { + margin-right: -0.1em !important; +} + +.paging_full_numbers { + width: 350px !important; +} + +.dataTables_wrapper .ui-toolbar { + padding: 5px; +} + +.dataTables_paginate { + width: auto; +} + +.dataTables_info { + padding-top: 3px; +} + +table.display thead th { + padding: 3px 0px 3px 10px; + cursor: pointer; + * cursor: hand; +} + +div.dataTables_wrapper .ui-widget-header { + font-weight: normal; +} + + +/* + * Sort arrow icon positioning + */ +table.display thead th div.DataTables_sort_wrapper { + position: relative; + padding-right: 20px; +} + +table.display thead th div.DataTables_sort_wrapper span { + position: absolute; + top: 50%; + margin-top: -8px; + right: 0; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Everything below this line is the same as demo_table.css. This file is + * required for 'cleanliness' of the markup + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables features + */ + +.dataTables_wrapper { + position: relative; + clear: both; +} + +.dataTables_processing { + position: absolute; + top: 0px; + left: 50%; + width: 250px; + margin-left: -125px; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 11px; + padding: 2px 0; +} + +.dataTables_length { + width: 40%; + float: left; +} + +.dataTables_filter { + width: 50%; + float: right; + text-align: right; +} + +.dataTables_info { + width: 50%; + float: left; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables display + */ +table.display { + margin: 0 auto; + width: 100%; + clear: both; + border-collapse: collapse; +} + +table.display tfoot th { + padding: 3px 0px 3px 10px; + font-weight: bold; + font-weight: normal; +} + +table.display tr.heading2 td { + border-bottom: 1px solid #aaa; +} + +table.display td { + padding: 3px 10px; +} + +table.display td.center { + text-align: center; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables sorting + */ + +.sorting_asc { + background: url('../images/sort_asc.png') no-repeat center right; +} + +.sorting_desc { + background: url('../images/sort_desc.png') no-repeat center right; +} + +.sorting { + background: url('../images/sort_both.png') no-repeat center right; +} + +.sorting_asc_disabled { + background: url('../images/sort_asc_disabled.png') no-repeat center right; +} + +.sorting_desc_disabled { + background: url('../images/sort_desc_disabled.png') no-repeat center right; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables row classes + */ +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + + + + +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + +table.display tr.odd.gradeC { + background-color: #ddddff; +} + +table.display tr.even.gradeC { + background-color: #eeeeff; +} + +table.display tr.odd.gradeX { + background-color: #ffdddd; +} + +table.display tr.even.gradeX { + background-color: #ffeeee; +} + +table.display tr.odd.gradeU { + background-color: #ddd; +} + +table.display tr.even.gradeU { + background-color: #eee; +} + + +tr.odd { + background-color: #E2E4FF; +} + +tr.even { + background-color: white; +} + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Misc + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + -webkit-overflow-scrolling: touch; +} + +.top, .bottom { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +.top .dataTables_info { + float: none; +} + +.clear { + clear: both; +} + +.dataTables_empty { + text-align: center; +} + +tfoot input { + margin: 0.5em 0; + width: 100%; + color: #444; +} + +tfoot input.search_init { + color: #999; +} + +td.group { + background-color: #d1cfd0; + border-bottom: 2px solid #A19B9E; + border-top: 2px solid #A19B9E; +} + +td.details { + background-color: #d1cfd0; + border: 2px solid #A19B9E; +} + + +.example_alt_pagination div.dataTables_info { + width: 40%; +} + +.paging_full_numbers a.paginate_button, + .paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + +table.display tr.even.row_selected td { + background-color: #B0BED9; +} + +table.display tr.odd.row_selected td { + background-color: #9FAFD1; +} + + +/* + * Sorting classes for columns + */ +/* For the standard odd/even */ +tr.odd td.sorting_1 { + background-color: #D3D6FF; +} + +tr.odd td.sorting_2 { + background-color: #DADCFF; +} + +tr.odd td.sorting_3 { + background-color: #E0E2FF; +} + +tr.even td.sorting_1 { + background-color: #EAEBFF; +} + +tr.even td.sorting_2 { + background-color: #F2F3FF; +} + +tr.even td.sorting_3 { + background-color: #F9F9FF; +} + + +/* For the Conditional-CSS grading rows */ +/* + Colour calculations (based off the main row colours) + Level 1: + dd > c4 + ee > d5 + Level 2: + dd > d1 + ee > e2 + */ +tr.odd.gradeA td.sorting_1 { + background-color: #c4ffc4; +} + +tr.odd.gradeA td.sorting_2 { + background-color: #d1ffd1; +} + +tr.odd.gradeA td.sorting_3 { + background-color: #d1ffd1; +} + +tr.even.gradeA td.sorting_1 { + background-color: #d5ffd5; +} + +tr.even.gradeA td.sorting_2 { + background-color: #e2ffe2; +} + +tr.even.gradeA td.sorting_3 { + background-color: #e2ffe2; +} + +tr.odd.gradeC td.sorting_1 { + background-color: #c4c4ff; +} + +tr.odd.gradeC td.sorting_2 { + background-color: #d1d1ff; +} + +tr.odd.gradeC td.sorting_3 { + background-color: #d1d1ff; +} + +tr.even.gradeC td.sorting_1 { + background-color: #d5d5ff; +} + +tr.even.gradeC td.sorting_2 { + background-color: #e2e2ff; +} + +tr.even.gradeC td.sorting_3 { + background-color: #e2e2ff; +} + +tr.odd.gradeX td.sorting_1 { + background-color: #ffc4c4; +} + +tr.odd.gradeX td.sorting_2 { + background-color: #ffd1d1; +} + +tr.odd.gradeX td.sorting_3 { + background-color: #ffd1d1; +} + +tr.even.gradeX td.sorting_1 { + background-color: #ffd5d5; +} + +tr.even.gradeX td.sorting_2 { + background-color: #ffe2e2; +} + +tr.even.gradeX td.sorting_3 { + background-color: #ffe2e2; +} + +tr.odd.gradeU td.sorting_1 { + background-color: #c4c4c4; +} + +tr.odd.gradeU td.sorting_2 { + background-color: #d1d1d1; +} + +tr.odd.gradeU td.sorting_3 { + background-color: #d1d1d1; +} + +tr.even.gradeU td.sorting_1 { + background-color: #d5d5d5; +} + +tr.even.gradeU td.sorting_2 { + background-color: #e2e2e2; +} + +tr.even.gradeU td.sorting_3 { + background-color: #e2e2e2; +} + + +/* + * Row highlighting example + */ +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted { + background-color: #ECFFB3; +} + +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted { + background-color: #E6FF99; +}
\ No newline at end of file diff --git a/themes/default/js/plugins/datatables/css/jquery.dataTables.css b/themes/default/js/plugins/datatables/css/jquery.dataTables.css new file mode 100644 index 000000000..7da7faec8 --- /dev/null +++ b/themes/default/js/plugins/datatables/css/jquery.dataTables.css @@ -0,0 +1,221 @@ + +/* + * Table + */ +table.dataTable { + margin: 0 auto; + clear: both; + width: 100%; +} + +table.dataTable thead th { + padding: 3px 18px 3px 10px; + border-bottom: 1px solid black; + font-weight: bold; + cursor: pointer; + *cursor: hand; +} + +table.dataTable tfoot th { + padding: 3px 18px 3px 10px; + border-top: 1px solid black; + font-weight: bold; +} + +table.dataTable td { + padding: 3px 10px; +} + +table.dataTable td.center, +table.dataTable td.dataTables_empty { + text-align: center; +} + +table.dataTable tr.odd { background-color: #E2E4FF; } +table.dataTable tr.even { background-color: white; } + +table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; } +table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; } +table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; } +table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; } +table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; } +table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; } + + +/* + * Table wrapper + */ +.dataTables_wrapper { + position: relative; + clear: both; + *zoom: 1; +} + + +/* + * Page length menu + */ +.dataTables_length { + float: left; +} + + +/* + * Filter + */ +.dataTables_filter { + float: right; + text-align: right; +} + + +/* + * Table information + */ +.dataTables_info { + clear: both; + float: left; +} + + +/* + * Pagination + */ +.dataTables_paginate { + float: right; + text-align: right; +} + +/* Two button pagination - previous / next */ +.paginate_disabled_previous, +.paginate_enabled_previous, +.paginate_disabled_next, +.paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, +.paginate_enabled_previous:hover, +.paginate_disabled_next:hover, +.paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, +.paginate_enabled_previous:active, +.paginate_disabled_next:active, +.paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, +.paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, +.paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; } +.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; } +.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; } + +.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; } +.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; } +.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; } + +/* Full number pagination */ +.paging_full_numbers { + height: 22px; + line-height: 22px; +} +.paging_full_numbers a:active { + outline: none +} +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, +.paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + + +/* + * Processing indicator + */ +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + + +/* + * Sorting + */ +.sorting { background: url('../images/sort_both.png') no-repeat center right; } +.sorting_asc { background: url('../images/sort_asc.png') no-repeat center right; } +.sorting_desc { background: url('../images/sort_desc.png') no-repeat center right; } + +.sorting_asc_disabled { background: url('../images/sort_asc_disabled.png') no-repeat center right; } +.sorting_desc_disabled { background: url('../images/sort_desc_disabled.png') no-repeat center right; } + +table.dataTable thead th:active, +table.dataTable thead td:active { + outline: none; +} + + +/* + * Scrolling + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + diff --git a/themes/default/js/plugins/datatables/css/jquery.dataTables_themeroller.css b/themes/default/js/plugins/datatables/css/jquery.dataTables_themeroller.css new file mode 100644 index 000000000..cf1d4ed79 --- /dev/null +++ b/themes/default/js/plugins/datatables/css/jquery.dataTables_themeroller.css @@ -0,0 +1,244 @@ + + +/* + * Table + */ +table.dataTable { + margin: 0 auto; + clear: both; + width: 100%; + border-collapse: collapse; +} + +table.dataTable thead th { + padding: 3px 0px 3px 10px; + cursor: pointer; + *cursor: hand; +} + +table.dataTable tfoot th { + padding: 3px 10px; +} + +table.dataTable td { + padding: 3px 10px; +} + +table.dataTable td.center, +table.dataTable td.dataTables_empty { + text-align: center; +} + +table.dataTable tr.odd { background-color: #E2E4FF; } +table.dataTable tr.even { background-color: white; } + +table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; } +table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; } +table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; } +table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; } +table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; } +table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; } + + +/* + * Table wrapper + */ +.dataTables_wrapper { + position: relative; + clear: both; + *zoom: 1; +} +.dataTables_wrapper .ui-widget-header { + font-weight: normal; +} +.dataTables_wrapper .ui-toolbar { + padding: 5px; +} + + +/* + * Page length menu + */ +.dataTables_length { + float: left; +} + + +/* + * Filter + */ +.dataTables_filter { + float: right; + text-align: right; +} + + +/* + * Table information + */ +.dataTables_info { + padding-top: 3px; + clear: both; + float: left; +} + + +/* + * Pagination + */ +.dataTables_paginate { + float: right; + text-align: right; +} + +.dataTables_paginate .ui-button { + margin-right: -0.1em !important; +} + +.paging_two_button .ui-button { + float: left; + cursor: pointer; + * cursor: hand; +} + +.paging_full_numbers .ui-button { + padding: 2px 6px; + margin: 0; + cursor: pointer; + * cursor: hand; + color: #333 !important; +} + +/* Two button pagination - previous / next */ +.paginate_disabled_previous, +.paginate_enabled_previous, +.paginate_disabled_next, +.paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, +.paginate_enabled_previous:hover, +.paginate_disabled_next:hover, +.paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, +.paginate_enabled_previous:active, +.paginate_disabled_next:active, +.paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, +.paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, +.paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; } +.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; } +.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; } + +.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; } +.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; } +.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; } + +/* Full number pagination */ +.paging_full_numbers a:active { + outline: none +} +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, +.paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + + +/* + * Processing indicator + */ +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + + +/* + * Sorting + */ +table.dataTable thead th div.DataTables_sort_wrapper { + position: relative; + padding-right: 20px; +} + +table.dataTable thead th div.DataTables_sort_wrapper span { + position: absolute; + top: 50%; + margin-top: -8px; + right: 0; +} + +table.dataTable th:active { + outline: none; +} + + +/* + * Scrolling + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + diff --git a/themes/default/js/plugins/datatables/images/Sorting icons.psd b/themes/default/js/plugins/datatables/images/Sorting icons.psd Binary files differnew file mode 100644 index 000000000..53b2e0685 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/Sorting icons.psd diff --git a/themes/default/js/plugins/datatables/images/back_disabled.png b/themes/default/js/plugins/datatables/images/back_disabled.png Binary files differnew file mode 100644 index 000000000..881de7976 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/back_disabled.png diff --git a/themes/default/js/plugins/datatables/images/back_enabled.png b/themes/default/js/plugins/datatables/images/back_enabled.png Binary files differnew file mode 100644 index 000000000..c608682b0 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/back_enabled.png diff --git a/themes/default/js/plugins/datatables/images/back_enabled_hover.png b/themes/default/js/plugins/datatables/images/back_enabled_hover.png Binary files differnew file mode 100644 index 000000000..d300f1064 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/back_enabled_hover.png diff --git a/themes/default/js/plugins/datatables/images/favicon.ico b/themes/default/js/plugins/datatables/images/favicon.ico Binary files differnew file mode 100644 index 000000000..6eeaa2a0d --- /dev/null +++ b/themes/default/js/plugins/datatables/images/favicon.ico diff --git a/themes/default/js/plugins/datatables/images/forward_disabled.png b/themes/default/js/plugins/datatables/images/forward_disabled.png Binary files differnew file mode 100644 index 000000000..6a6ded7de --- /dev/null +++ b/themes/default/js/plugins/datatables/images/forward_disabled.png diff --git a/themes/default/js/plugins/datatables/images/forward_enabled.png b/themes/default/js/plugins/datatables/images/forward_enabled.png Binary files differnew file mode 100644 index 000000000..a4e6b5384 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/forward_enabled.png diff --git a/themes/default/js/plugins/datatables/images/forward_enabled_hover.png b/themes/default/js/plugins/datatables/images/forward_enabled_hover.png Binary files differnew file mode 100644 index 000000000..fc46c5ebf --- /dev/null +++ b/themes/default/js/plugins/datatables/images/forward_enabled_hover.png diff --git a/themes/default/js/plugins/datatables/images/sort_asc.png b/themes/default/js/plugins/datatables/images/sort_asc.png Binary files differnew file mode 100644 index 000000000..a88d7975f --- /dev/null +++ b/themes/default/js/plugins/datatables/images/sort_asc.png diff --git a/themes/default/js/plugins/datatables/images/sort_asc_disabled.png b/themes/default/js/plugins/datatables/images/sort_asc_disabled.png Binary files differnew file mode 100644 index 000000000..4e144cf0b --- /dev/null +++ b/themes/default/js/plugins/datatables/images/sort_asc_disabled.png diff --git a/themes/default/js/plugins/datatables/images/sort_both.png b/themes/default/js/plugins/datatables/images/sort_both.png Binary files differnew file mode 100644 index 000000000..18670406b --- /dev/null +++ b/themes/default/js/plugins/datatables/images/sort_both.png diff --git a/themes/default/js/plugins/datatables/images/sort_desc.png b/themes/default/js/plugins/datatables/images/sort_desc.png Binary files differnew file mode 100644 index 000000000..def071ed5 --- /dev/null +++ b/themes/default/js/plugins/datatables/images/sort_desc.png diff --git a/themes/default/js/plugins/datatables/images/sort_desc_disabled.png b/themes/default/js/plugins/datatables/images/sort_desc_disabled.png Binary files differnew file mode 100644 index 000000000..7824973cc --- /dev/null +++ b/themes/default/js/plugins/datatables/images/sort_desc_disabled.png diff --git a/themes/default/js/plugins/jgrowl-alert.png b/themes/default/js/plugins/jgrowl-alert.png Binary files differnew file mode 100644 index 000000000..350822e8c --- /dev/null +++ b/themes/default/js/plugins/jgrowl-alert.png diff --git a/themes/default/js/plugins/jgrowl-check.png b/themes/default/js/plugins/jgrowl-check.png Binary files differnew file mode 100644 index 000000000..fccf6c78c --- /dev/null +++ b/themes/default/js/plugins/jgrowl-check.png diff --git a/themes/default/js/plugins/jgrowl-error.png b/themes/default/js/plugins/jgrowl-error.png Binary files differnew file mode 100644 index 000000000..542f96311 --- /dev/null +++ b/themes/default/js/plugins/jgrowl-error.png diff --git a/themes/default/js/plugins/jquery.dataTables.js b/themes/default/js/plugins/jquery.dataTables.js new file mode 100644 index 000000000..1d8a220ba --- /dev/null +++ b/themes/default/js/plugins/jquery.dataTables.js @@ -0,0 +1,12099 @@ +/** + * @summary DataTables + * @description Paginate, search and sort HTML tables + * @version 1.9.4 + * @file jquery.dataTables.js + * @author Allan Jardine (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * + * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/ + +(/** @lends <global> */function( window, document, undefined ) { + +(function( factory ) { + "use strict"; + + // Define as an AMD module if possible + if ( typeof define === 'function' && define.amd ) + { + define( ['jquery'], factory ); + } + /* Define using browser globals otherwise + * Prevent multiple instantiations if the script is loaded twice + */ + else if ( jQuery && !jQuery.fn.dataTable ) + { + factory( jQuery ); + } +} +(/** @lends <global> */function( $ ) { + "use strict"; + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a + * highly flexible tool, based upon the foundations of progressive + * enhancement, which will add advanced interaction controls to any + * HTML table. For a full list of features please refer to + * <a href="http://datatables.net">DataTables.net</a>. + * + * Note that the <i>DataTable</i> object is not a global variable but is + * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which + * it may be accessed. + * + * @class + * @param {object} [oInit={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.3+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "bPaginate": false, + * "bSort": false + * } ); + * } ); + */ + var DataTable = function( oInit ) + { + + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + var oDefaults = DataTable.defaults.columns; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "sSortingClass": oSettings.oClasses.sSortable, + "sSortingClassJUI": oSettings.oClasses.sSortJUI, + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.oDefaults : iCol + } ); + oSettings.aoColumns.push( oCol ); + + /* Add a column specific filter */ + if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null ) + { + oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch ); + } + else + { + var oPre = oSettings.aoPreSearchCols[ iCol ]; + + /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */ + if ( oPre.bRegex === undefined ) + { + oPre.bRegex = true; + } + + if ( oPre.bSmart === undefined ) + { + oPre.bSmart = true; + } + + if ( oPre.bCaseInsensitive === undefined ) + { + oPre.bCaseInsensitive = true; + } + } + + /* Use the column options function to initialise classes etc */ + _fnColumnOptions( oSettings, iCol, null ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType !== undefined ) + { + oCol.sType = oOptions.sType; + oCol._bAutoType = false; + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + var mData = _fnGetObjectDataFn( oCol.mData ); + + oCol.fnGetData = function (oData, sSpecific) { + var innerData = mData( oData, sSpecific ); + + if ( oCol.mRender && (sSpecific && sSpecific !== '') ) + { + return mRender( innerData, sSpecific, oData ); + } + return innerData; + }; + oCol.fnSetData = _fnSetObjectDataFn( oCol.mData ); + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + } + + /* Check that the class assignment is correct for sorting */ + if ( !oCol.bSortable || + ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortable; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI; + } + else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableAsc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableDesc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( oSettings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( oSettings.oFeatures.bAutoWidth === false ) + { + return false; + } + + _fnCalculateColumnWidths( oSettings ); + for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth; + } + } + + + /** + * Covert the index of a visible column to the index in the data array (take account + * of hidden columns) + * @param {object} oSettings dataTables settings object + * @param {int} iMatch Visible column index to lookup + * @returns {int} i the data index + * @memberof DataTable#oApi + */ + function _fnVisibleToColumnIndex( oSettings, iMatch ) + { + var aiVis = _fnGetColumns( oSettings, 'bVisible' ); + + return typeof aiVis[iMatch] === 'number' ? + aiVis[iMatch] : + null; + } + + + /** + * Covert the index of an index in the data array and convert it to the visible + * column index (take account of hidden columns) + * @param {int} iMatch Column index to lookup + * @param {object} oSettings dataTables settings object + * @returns {int} i the data index + * @memberof DataTable#oApi + */ + function _fnColumnIndexToVisible( oSettings, iMatch ) + { + var aiVis = _fnGetColumns( oSettings, 'bVisible' ); + var iPos = $.inArray( iMatch, aiVis ); + + return iPos !== -1 ? iPos : null; + } + + + /** + * Get the number of visible columns + * @param {object} oSettings dataTables settings object + * @returns {int} i the number of visible columns + * @memberof DataTable#oApi + */ + function _fnVisbleColumns( oSettings ) + { + return _fnGetColumns( oSettings, 'bVisible' ).length; + } + + + /** + * Get an array of column indexes that match a given property + * @param {object} oSettings dataTables settings object + * @param {string} sParam Parameter in aoColumns to look for - typically + * bVisible or bSearchable + * @returns {array} Array of indexes with matched properties + * @memberof DataTable#oApi + */ + function _fnGetColumns( oSettings, sParam ) + { + var a = []; + + $.map( oSettings.aoColumns, function(val, i) { + if ( val[sParam] ) { + a.push( i ); + } + } ); + + return a; + } + + + /** + * Get the sort type based on an input string + * @param {string} sData data we wish to know the type of + * @returns {string} type (defaults to 'string' if no type can be detected) + * @memberof DataTable#oApi + */ + function _fnDetectType( sData ) + { + var aTypes = DataTable.ext.aTypes; + var iLen = aTypes.length; + + for ( var i=0 ; i<iLen ; i++ ) + { + var sType = aTypes[i]( sData ); + if ( sType !== null ) + { + return sType; + } + } + + return 'string'; + } + + + /** + * Figure out how to reorder a display list + * @param {object} oSettings dataTables settings object + * @returns array {int} aiReturn index list for reordering + * @memberof DataTable#oApi + */ + function _fnReOrderIndex ( oSettings, sColumns ) + { + var aColumns = sColumns.split(','); + var aiReturn = []; + + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + for ( var j=0 ; j<iLen ; j++ ) + { + if ( oSettings.aoColumns[i].sName == aColumns[j] ) + { + aiReturn.push( j ); + break; + } + } + } + + return aiReturn; + } + + + /** + * Get the column ordering that DataTables expects + * @param {object} oSettings dataTables settings object + * @returns {string} comma separated list of names + * @memberof DataTable#oApi + */ + function _fnColumnOrdering ( oSettings ) + { + var sNames = ''; + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + sNames += oSettings.aoColumns[i].sName+','; + } + if ( sNames.length == iLen ) + { + return ""; + } + return sNames.slice(0, -1); + } + + + /** + * Take the column definitions and static columns arrays and calculate how + * they relate to column indexes. The callback function will then apply the + * definition found for a column to a suitable configuration object. + * @param {object} oSettings dataTables settings object + * @param {array} aoColDefs The aoColumnDefs array that is to be applied + * @param {array} aoCols The aoColumns array that defines columns individually + * @param {function} fn Callback function - takes two parameters, the calculated + * column index and the definition for that column. + * @memberof DataTable#oApi + */ + function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) + { + var i, iLen, j, jLen, k, kLen; + + // Column definitions with aTargets + if ( aoColDefs ) + { + /* Loop over the definitions array - loop in reverse so first instance has priority */ + for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) + { + /* Each definition can target multiple columns, as it is an array */ + var aTargets = aoColDefs[i].aTargets; + if ( !$.isArray( aTargets ) ) + { + _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) ); + } + + for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) + { + if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) + { + /* Add columns that we don't yet know about */ + while( oSettings.aoColumns.length <= aTargets[j] ) + { + _fnAddColumn( oSettings ); + } + + /* Integer, basic index */ + fn( aTargets[j], aoColDefs[i] ); + } + else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) + { + /* Negative integer, right to left column counting */ + fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] ); + } + else if ( typeof aTargets[j] === 'string' ) + { + /* Class name matching on TH element */ + for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ ) + { + if ( aTargets[j] == "_all" || + $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) ) + { + fn( k, aoColDefs[i] ); + } + } + } + } + } + } + + // Statically defined columns array + if ( aoCols ) + { + for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) + { + fn( i, aoCols[i] ); + } + } + } + + /** + * Add a data array to the table, creating DOM node etc. This is the parallel to + * _fnGatherData, but for adding rows from a Javascript source, rather than a + * DOM source. + * @param {object} oSettings dataTables settings object + * @param {array} aData data array to be added + * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed + * @memberof DataTable#oApi + */ + function _fnAddData ( oSettings, aDataSupplied ) + { + var oCol; + + /* Take an independent copy of the data source so we can bash it about as we wish */ + var aDataIn = ($.isArray(aDataSupplied)) ? + aDataSupplied.slice() : + $.extend( true, {}, aDataSupplied ); + + /* Create the object for storing information about this new row */ + var iRow = oSettings.aoData.length; + var oData = $.extend( true, {}, DataTable.models.oRow ); + oData._aData = aDataIn; + oSettings.aoData.push( oData ); + + /* Create the cells */ + var nTd, sThisType; + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oCol = oSettings.aoColumns[i]; + + /* Use rendered data for filtering / sorting */ + if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null ) + { + _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) ); + } + else + { + _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) ); + } + + /* See if we should auto-detect the column type */ + if ( oCol._bAutoType && oCol.sType != 'string' ) + { + /* Attempt to auto detect the type - same as _fnGatherData() */ + var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' ); + if ( sVarType !== null && sVarType !== '' ) + { + sThisType = _fnDetectType( sVarType ); + if ( oCol.sType === null ) + { + oCol.sType = sThisType; + } + else if ( oCol.sType != sThisType && oCol.sType != "html" ) + { + /* String is always the 'fallback' option */ + oCol.sType = 'string'; + } + } + } + } + + /* Add to the display array */ + oSettings.aiDisplayMaster.push( iRow ); + + /* Create the DOM information */ + if ( !oSettings.oFeatures.bDeferRender ) + { + _fnCreateTr( oSettings, iRow ); + } + + return iRow; + } + + + /** + * Read in the data from the target table from the DOM + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnGatherData( oSettings ) + { + var iLoop, i, iLen, j, jLen, jInner, + nTds, nTrs, nTd, nTr, aLocalData, iThisIndex, + iRow, iRows, iColumn, iColumns, sNodeName, + oCol, oData; + + /* + * Process by row first + * Add the data object for the whole table - storing the tr node. Note - no point in getting + * DOM based data if we are going to go and replace it with Ajax source data. + */ + if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null ) + { + nTr = oSettings.nTBody.firstChild; + while ( nTr ) + { + if ( nTr.nodeName.toUpperCase() == "TR" ) + { + iThisIndex = oSettings.aoData.length; + nTr._DT_RowIndex = iThisIndex; + oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, { + "nTr": nTr + } ) ); + + oSettings.aiDisplayMaster.push( iThisIndex ); + nTd = nTr.firstChild; + jInner = 0; + while ( nTd ) + { + sNodeName = nTd.nodeName.toUpperCase(); + if ( sNodeName == "TD" || sNodeName == "TH" ) + { + _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) ); + jInner++; + } + nTd = nTd.nextSibling; + } + } + nTr = nTr.nextSibling; + } + } + + /* Gather in the TD elements of the Table - note that this is basically the same as + * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet + * setup! + */ + nTrs = _fnGetTrNodes( oSettings ); + nTds = []; + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + nTd = nTrs[i].firstChild; + while ( nTd ) + { + sNodeName = nTd.nodeName.toUpperCase(); + if ( sNodeName == "TD" || sNodeName == "TH" ) + { + nTds.push( nTd ); + } + nTd = nTd.nextSibling; + } + } + + /* Now process by column */ + for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) + { + oCol = oSettings.aoColumns[iColumn]; + + /* Get the title of the column - unless there is a user set one */ + if ( oCol.sTitle === null ) + { + oCol.sTitle = oCol.nTh.innerHTML; + } + + var + bAutoType = oCol._bAutoType, + bRender = typeof oCol.fnRender === 'function', + bClass = oCol.sClass !== null, + bVisible = oCol.bVisible, + nCell, sThisType, sRendered, sValType; + + /* A single loop to rule them all (and be more efficient) */ + if ( bAutoType || bRender || bClass || !bVisible ) + { + for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ ) + { + oData = oSettings.aoData[iRow]; + nCell = nTds[ (iRow*iColumns) + iColumn ]; + + /* Type detection */ + if ( bAutoType && oCol.sType != 'string' ) + { + sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' ); + if ( sValType !== '' ) + { + sThisType = _fnDetectType( sValType ); + if ( oCol.sType === null ) + { + oCol.sType = sThisType; + } + else if ( oCol.sType != sThisType && + oCol.sType != "html" ) + { + /* String is always the 'fallback' option */ + oCol.sType = 'string'; + } + } + } + + if ( oCol.mRender ) + { + // mRender has been defined, so we need to get the value and set it + nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + } + else if ( oCol.mData !== iColumn ) + { + // If mData is not the same as the column number, then we need to + // get the dev set value. If it is the column, no point in wasting + // time setting the value that is already there! + nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + } + + /* Rendering */ + if ( bRender ) + { + sRendered = _fnRender( oSettings, iRow, iColumn ); + nCell.innerHTML = sRendered; + if ( oCol.bUseRendered ) + { + /* Use the rendered data for filtering / sorting */ + _fnSetCellData( oSettings, iRow, iColumn, sRendered ); + } + } + + /* Classes */ + if ( bClass ) + { + nCell.className += ' '+oCol.sClass; + } + + /* Column visibility */ + if ( !bVisible ) + { + oData._anHidden[iColumn] = nCell; + nCell.parentNode.removeChild( nCell ); + } + else + { + oData._anHidden[iColumn] = null; + } + + if ( oCol.fnCreatedCell ) + { + oCol.fnCreatedCell.call( oSettings.oInstance, + nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn + ); + } + } + } + } + + /* Row created callbacks */ + if ( oSettings.aoRowCreatedCallback.length !== 0 ) + { + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + oData = oSettings.aoData[i]; + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] ); + } + } + } + + + /** + * Take a TR element and convert it to an index in aoData + * @param {object} oSettings dataTables settings object + * @param {node} n the TR element to find + * @returns {int} index if the node is found, null if not + * @memberof DataTable#oApi + */ + function _fnNodeToDataIndex( oSettings, n ) + { + return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; + } + + + /** + * Take a TD element and convert it into a column data index (not the visible index) + * @param {object} oSettings dataTables settings object + * @param {int} iRow The row number the TD/TH can be found in + * @param {node} n The TD/TH element to find + * @returns {int} index if the node is found, -1 if not + * @memberof DataTable#oApi + */ + function _fnNodeToColumnIndex( oSettings, iRow, n ) + { + var anCells = _fnGetTdNodes( oSettings, iRow ); + + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( anCells[i] === n ) + { + return i; + } + } + return -1; + } + + + /** + * Get an array of data for a given row from the internal data cache + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {string} sSpecific data get type ('type' 'filter' 'sort') + * @param {array} aiColumns Array of column indexes to get data from + * @returns {array} Data array + * @memberof DataTable#oApi + */ + function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns ) + { + var out = []; + for ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ ) + { + out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) ); + } + return out; + } + + + /** + * Get the data for a given cell from the internal cache, taking into account data mapping + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {int} iCol Column index + * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort') + * @returns {*} Cell data + * @memberof DataTable#oApi + */ + function _fnGetCellData( oSettings, iRow, iCol, sSpecific ) + { + var sData; + var oCol = oSettings.aoColumns[iCol]; + var oData = oSettings.aoData[iRow]._aData; + + if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined ) + { + if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null ) + { + _fnLog( oSettings, 0, "Requested unknown parameter "+ + (typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+ + " from the data source for row "+iRow ); + oSettings.iDrawError = oSettings.iDraw; + } + return oCol.sDefaultContent; + } + + /* When the data source is null, we can use default column data */ + if ( sData === null && oCol.sDefaultContent !== null ) + { + sData = oCol.sDefaultContent; + } + else if ( typeof sData === 'function' ) + { + /* If the data source is a function, then we run it and use the return */ + return sData(); + } + + if ( sSpecific == 'display' && sData === null ) + { + return ''; + } + return sData; + } + + + /** + * Set the value for a specific cell, into the internal data cache + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {int} iCol Column index + * @param {*} val Value to set + * @memberof DataTable#oApi + */ + function _fnSetCellData( oSettings, iRow, iCol, val ) + { + var oCol = oSettings.aoColumns[iCol]; + var oData = oSettings.aoData[iRow]._aData; + + oCol.fnSetData( oData, val ); + } + + + // Private variable that is used to match array syntax in the data property object + var __reArray = /\[.*?\]$/; + + /** + * Return a function that can be used to get data from a source object, taking + * into account the ability to use nested objects as a source + * @param {string|int|function} mSource The data source for the object + * @returns {function} Data get function + * @memberof DataTable#oApi + */ + function _fnGetObjectDataFn( mSource ) + { + if ( mSource === null ) + { + /* Give an empty string for rendering / sorting etc */ + return function (data, type) { + return null; + }; + } + else if ( typeof mSource === 'function' ) + { + return function (data, type, extra) { + return mSource( data, type, extra ); + }; + } + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) + { + /* If there is a . in the source string then the data source is in a + * nested object so we loop over the data for each level to get the next + * level down. On each loop we test for undefined, and if found immediately + * return. This allows entire objects to be missing and sDefaultContent to + * be used if defined, rather than throwing an error + */ + var fetchData = function (data, type, src) { + var a = src.split('.'); + var arrayNotation, out, innerSrc; + + if ( src !== "" ) + { + for ( var i=0, iLen=a.length ; i<iLen ; i++ ) + { + // Check if we are dealing with an array notation request + arrayNotation = a[i].match(__reArray); + + if ( arrayNotation ) { + a[i] = a[i].replace(__reArray, ''); + + // Condition allows simply [] to be passed in + if ( a[i] !== "" ) { + data = data[ a[i] ]; + } + out = []; + + // Get the remainder of the nested object to get + a.splice( 0, i+1 ); + innerSrc = a.join('.'); + + // Traverse each entry in the array getting the properties requested + for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { + out.push( fetchData( data[j], type, innerSrc ) ); + } + + // If a string is given in between the array notation indicators, that + // is used to join the strings together, otherwise an array is returned + var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); + data = (join==="") ? out : out.join(join); + + // The inner call to fetchData has already traversed through the remainder + // of the source requested, so we exit from the loop + break; + } + + if ( data === null || data[ a[i] ] === undefined ) + { + return undefined; + } + data = data[ a[i] ]; + } + } + + return data; + }; + + return function (data, type) { + return fetchData( data, type, mSource ); + }; + } + else + { + /* Array or flat object mapping */ + return function (data, type) { + return data[mSource]; + }; + } + } + + + /** + * Return a function that can be used to set data from a source object, taking + * into account the ability to use nested objects as a source + * @param {string|int|function} mSource The data source for the object + * @returns {function} Data set function + * @memberof DataTable#oApi + */ + function _fnSetObjectDataFn( mSource ) + { + if ( mSource === null ) + { + /* Nothing to do when the data source is null */ + return function (data, val) {}; + } + else if ( typeof mSource === 'function' ) + { + return function (data, val) { + mSource( data, 'set', val ); + }; + } + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) + { + /* Like the get, we need to get data from a nested object */ + var setData = function (data, val, src) { + var a = src.split('.'), b; + var arrayNotation, o, innerSrc; + + for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) + { + // Check if we are dealing with an array notation request + arrayNotation = a[i].match(__reArray); + + if ( arrayNotation ) + { + a[i] = a[i].replace(__reArray, ''); + data[ a[i] ] = []; + + // Get the remainder of the nested object to set so we can recurse + b = a.slice(); + b.splice( 0, i+1 ); + innerSrc = b.join('.'); + + // Traverse each entry in the array setting the properties requested + for ( var j=0, jLen=val.length ; j<jLen ; j++ ) + { + o = {}; + setData( o, val[j], innerSrc ); + data[ a[i] ].push( o ); + } + + // The inner call to setData has already traversed through the remainder + // of the source and has set the data, thus we can exit here + return; + } + + // If the nested object doesn't currently exist - since we are + // trying to set the value - create it + if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) + { + data[ a[i] ] = {}; + } + data = data[ a[i] ]; + } + + // If array notation is used, we just want to strip it and use the property name + // and assign the value. If it isn't used, then we get the result we want anyway + data[ a[a.length-1].replace(__reArray, '') ] = val; + }; + + return function (data, val) { + return setData( data, val, mSource ); + }; + } + else + { + /* Array or flat object mapping */ + return function (data, val) { + data[mSource] = val; + }; + } + } + + + /** + * Return an array with the full table data + * @param {object} oSettings dataTables settings object + * @returns array {array} aData Master data array + * @memberof DataTable#oApi + */ + function _fnGetDataMaster ( oSettings ) + { + var aData = []; + var iLen = oSettings.aoData.length; + for ( var i=0 ; i<iLen; i++ ) + { + aData.push( oSettings.aoData[i]._aData ); + } + return aData; + } + + + /** + * Nuke the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnClearTable( oSettings ) + { + oSettings.aoData.splice( 0, oSettings.aoData.length ); + oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length ); + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length ); + _fnCalculateEnd( oSettings ); + } + + + /** + * Take an array of integers (index array) and remove a target integer (value - not + * the key!) + * @param {array} a Index array to target + * @param {int} iTarget value to find + * @memberof DataTable#oApi + */ + function _fnDeleteIndex( a, iTarget ) + { + var iTargetIndex = -1; + + for ( var i=0, iLen=a.length ; i<iLen ; i++ ) + { + if ( a[i] == iTarget ) + { + iTargetIndex = i; + } + else if ( a[i] > iTarget ) + { + a[i]--; + } + } + + if ( iTargetIndex != -1 ) + { + a.splice( iTargetIndex, 1 ); + } + } + + + /** + * Call the developer defined fnRender function for a given cell (row/column) with + * the required parameters and return the result. + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData index for the row + * @param {int} iCol aoColumns index for the column + * @returns {*} Return of the developer's fnRender function + * @memberof DataTable#oApi + */ + function _fnRender( oSettings, iRow, iCol ) + { + var oCol = oSettings.aoColumns[iCol]; + + return oCol.fnRender( { + "iDataRow": iRow, + "iDataColumn": iCol, + "oSettings": oSettings, + "aData": oSettings.aoData[iRow]._aData, + "mDataProp": oCol.mData + }, _fnGetCellData(oSettings, iRow, iCol, 'display') ); + } + /** + * Create a new TR element (and it's TD children) for a row + * @param {object} oSettings dataTables settings object + * @param {int} iRow Row to consider + * @memberof DataTable#oApi + */ + function _fnCreateTr ( oSettings, iRow ) + { + var oData = oSettings.aoData[iRow]; + var nTd; + + if ( oData.nTr === null ) + { + oData.nTr = document.createElement('tr'); + + /* Use a private property on the node to allow reserve mapping from the node + * to the aoData array for fast look up + */ + oData.nTr._DT_RowIndex = iRow; + + /* Special parameters can be given by the data source to be used on the row */ + if ( oData._aData.DT_RowId ) + { + oData.nTr.id = oData._aData.DT_RowId; + } + + if ( oData._aData.DT_RowClass ) + { + oData.nTr.className = oData._aData.DT_RowClass; + } + + /* Process each column */ + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + var oCol = oSettings.aoColumns[i]; + nTd = document.createElement( oCol.sCellType ); + + /* Render if needed - if bUseRendered is true then we already have the rendered + * value in the data source - so can just use that + */ + nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ? + _fnRender( oSettings, iRow, i ) : + _fnGetCellData( oSettings, iRow, i, 'display' ); + + /* Add user defined class */ + if ( oCol.sClass !== null ) + { + nTd.className = oCol.sClass; + } + + if ( oCol.bVisible ) + { + oData.nTr.appendChild( nTd ); + oData._anHidden[i] = null; + } + else + { + oData._anHidden[i] = nTd; + } + + if ( oCol.fnCreatedCell ) + { + oCol.fnCreatedCell.call( oSettings.oInstance, + nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i + ); + } + } + + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] ); + } + } + + + /** + * Create the HTML header for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnBuildHead( oSettings ) + { + var i, nTh, iLen, j, jLen; + var iThs = $('th, td', oSettings.nTHead).length; + var iCorrector = 0; + var jqChildren; + + /* If there is a header in place - then use it - otherwise it's going to get nuked... */ + if ( iThs !== 0 ) + { + /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */ + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + nTh.setAttribute('role', 'columnheader'); + if ( oSettings.aoColumns[i].bSortable ) + { + nTh.setAttribute('tabindex', oSettings.iTabIndex); + nTh.setAttribute('aria-controls', oSettings.sTableId); + } + + if ( oSettings.aoColumns[i].sClass !== null ) + { + $(nTh).addClass( oSettings.aoColumns[i].sClass ); + } + + /* Set the title of the column if it is user defined (not what was auto detected) */ + if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML ) + { + nTh.innerHTML = oSettings.aoColumns[i].sTitle; + } + } + } + else + { + /* We don't have a header in the DOM - so we are going to have to create one */ + var nTr = document.createElement( "tr" ); + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + nTh.innerHTML = oSettings.aoColumns[i].sTitle; + nTh.setAttribute('tabindex', '0'); + + if ( oSettings.aoColumns[i].sClass !== null ) + { + $(nTh).addClass( oSettings.aoColumns[i].sClass ); + } + + nTr.appendChild( nTh ); + } + $(oSettings.nTHead).html( '' )[0].appendChild( nTr ); + _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead ); + } + + /* ARIA role for the rows */ + $(oSettings.nTHead).children('tr').attr('role', 'row'); + + /* Add the extra markup needed by jQuery UI's themes */ + if ( oSettings.bJUI ) + { + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + + var nDiv = document.createElement('div'); + nDiv.className = oSettings.oClasses.sSortJUIWrapper; + $(nTh).contents().appendTo(nDiv); + + var nSpan = document.createElement('span'); + nSpan.className = oSettings.oClasses.sSortIcon; + nDiv.appendChild( nSpan ); + nTh.appendChild( nDiv ); + } + } + + if ( oSettings.oFeatures.bSort ) + { + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable !== false ) + { + _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i ); + } + else + { + $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone ); + } + } + } + + /* Deal with the footer - add classes if required */ + if ( oSettings.oClasses.sFooterTH !== "" ) + { + $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH ); + } + + /* Cache the footer elements */ + if ( oSettings.nTFoot !== null ) + { + var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter ); + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( anCells[i] ) + { + oSettings.aoColumns[i].nTf = anCells[i]; + if ( oSettings.aoColumns[i].sClass ) + { + $(anCells[i]).addClass( oSettings.aoColumns[i].sClass ); + } + } + } + } + } + + + /** + * Draw the header (or footer) element based on the column visibility states. The + * methodology here is to use the layout array from _fnDetectHeader, modified for + * the instantaneous column visibility, to construct the new layout. The grid is + * traversed over cell at a time in a rows x columns grid fashion, although each + * cell insert can cover multiple elements in the grid - which is tracks using the + * aApplied array. Cell inserts in the grid will only occur where there isn't + * already a cell in that position. + * @param {object} oSettings dataTables settings object + * @param array {objects} aoSource Layout array from _fnDetectHeader + * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, + * @memberof DataTable#oApi + */ + function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) + { + var i, iLen, j, jLen, k, kLen, n, nLocalTr; + var aoLocal = []; + var aApplied = []; + var iColumns = oSettings.aoColumns.length; + var iRowspan, iColspan; + + if ( bIncludeHidden === undefined ) + { + bIncludeHidden = false; + } + + /* Make a copy of the master layout array, but without the visible columns in it */ + for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) + { + aoLocal[i] = aoSource[i].slice(); + aoLocal[i].nTr = aoSource[i].nTr; + + /* Remove any columns which are currently hidden */ + for ( j=iColumns-1 ; j>=0 ; j-- ) + { + if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) + { + aoLocal[i].splice( j, 1 ); + } + } + + /* Prep the applied array - it needs an element for each row */ + aApplied.push( [] ); + } + + for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) + { + nLocalTr = aoLocal[i].nTr; + + /* All cells are going to be replaced, so empty out the row */ + if ( nLocalTr ) + { + while( (n = nLocalTr.firstChild) ) + { + nLocalTr.removeChild( n ); + } + } + + for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) + { + iRowspan = 1; + iColspan = 1; + + /* Check to see if there is already a cell (row/colspan) covering our target + * insert point. If there is, then there is nothing to do. + */ + if ( aApplied[i][j] === undefined ) + { + nLocalTr.appendChild( aoLocal[i][j].cell ); + aApplied[i][j] = 1; + + /* Expand the cell to cover as many rows as needed */ + while ( aoLocal[i+iRowspan] !== undefined && + aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) + { + aApplied[i+iRowspan][j] = 1; + iRowspan++; + } + + /* Expand the cell to cover as many columns as needed */ + while ( aoLocal[i][j+iColspan] !== undefined && + aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) + { + /* Must update the applied array over the rows for the columns */ + for ( k=0 ; k<iRowspan ; k++ ) + { + aApplied[i+k][j+iColspan] = 1; + } + iColspan++; + } + + /* Do the actual expansion in the DOM */ + aoLocal[i][j].cell.rowSpan = iRowspan; + aoLocal[i][j].cell.colSpan = iColspan; + } + } + } + } + + + /** + * Insert the required TR nodes into the table for display + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnDraw( oSettings ) + { + /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ + var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); + if ( $.inArray( false, aPreDraw ) !== -1 ) + { + _fnProcessingDisplay( oSettings, false ); + return; + } + + var i, iLen, n; + var anRows = []; + var iRowCount = 0; + var iStripes = oSettings.asStripeClasses.length; + var iOpenRows = oSettings.aoOpenRows.length; + + oSettings.bDrawing = true; + + /* Check and see if we have an initial draw position from state saving */ + if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 ) + { + if ( oSettings.oFeatures.bServerSide ) + { + oSettings._iDisplayStart = oSettings.iInitDisplayStart; + } + else + { + oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ? + 0 : oSettings.iInitDisplayStart; + } + oSettings.iInitDisplayStart = -1; + _fnCalculateEnd( oSettings ); + } + + /* Server-side processing draw intercept */ + if ( oSettings.bDeferLoading ) + { + oSettings.bDeferLoading = false; + oSettings.iDraw++; + } + else if ( !oSettings.oFeatures.bServerSide ) + { + oSettings.iDraw++; + } + else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) + { + return; + } + + if ( oSettings.aiDisplay.length !== 0 ) + { + var iStart = oSettings._iDisplayStart; + var iEnd = oSettings._iDisplayEnd; + + if ( oSettings.oFeatures.bServerSide ) + { + iStart = 0; + iEnd = oSettings.aoData.length; + } + + for ( var j=iStart ; j<iEnd ; j++ ) + { + var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ]; + if ( aoData.nTr === null ) + { + _fnCreateTr( oSettings, oSettings.aiDisplay[j] ); + } + + var nRow = aoData.nTr; + + /* Remove the old striping classes and then add the new one */ + if ( iStripes !== 0 ) + { + var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ]; + if ( aoData._sRowStripe != sStripe ) + { + $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); + aoData._sRowStripe = sStripe; + } + } + + /* Row callback functions - might want to manipulate the row */ + _fnCallbackFire( oSettings, 'aoRowCallback', null, + [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] ); + + anRows.push( nRow ); + iRowCount++; + + /* If there is an open row - and it is attached to this parent - attach it on redraw */ + if ( iOpenRows !== 0 ) + { + for ( var k=0 ; k<iOpenRows ; k++ ) + { + if ( nRow == oSettings.aoOpenRows[k].nParent ) + { + anRows.push( oSettings.aoOpenRows[k].nTr ); + break; + } + } + } + } + } + else + { + /* Table is empty - create a row with an empty message in it */ + anRows[ 0 ] = document.createElement( 'tr' ); + + if ( oSettings.asStripeClasses[0] ) + { + anRows[ 0 ].className = oSettings.asStripeClasses[0]; + } + + var oLang = oSettings.oLanguage; + var sZero = oLang.sZeroRecords; + if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) + { + sZero = oLang.sLoadingRecords; + } + else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) + { + sZero = oLang.sEmptyTable; + } + + var nTd = document.createElement( 'td' ); + nTd.setAttribute( 'valign', "top" ); + nTd.colSpan = _fnVisbleColumns( oSettings ); + nTd.className = oSettings.oClasses.sRowEmpty; + nTd.innerHTML = _fnInfoMacros( oSettings, sZero ); + + anRows[ iRowCount ].appendChild( nTd ); + } + + /* Header and footer callbacks */ + _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], + _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); + + _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], + _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); + + /* + * Need to remove any old row from the display - note we can't just empty the tbody using + * $().html('') since this will unbind the jQuery event handlers (even although the node + * still exists!) - equally we can't use innerHTML, since IE throws an exception. + */ + var + nAddFrag = document.createDocumentFragment(), + nRemoveFrag = document.createDocumentFragment(), + nBodyPar, nTrs; + + if ( oSettings.nTBody ) + { + nBodyPar = oSettings.nTBody.parentNode; + nRemoveFrag.appendChild( oSettings.nTBody ); + + /* When doing infinite scrolling, only remove child rows when sorting, filtering or start + * up. When not infinite scroll, always do it. + */ + if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete || + oSettings.bSorted || oSettings.bFiltered ) + { + while( (n = oSettings.nTBody.firstChild) ) + { + oSettings.nTBody.removeChild( n ); + } + } + + /* Put the draw table into the dom */ + for ( i=0, iLen=anRows.length ; i<iLen ; i++ ) + { + nAddFrag.appendChild( anRows[i] ); + } + + oSettings.nTBody.appendChild( nAddFrag ); + if ( nBodyPar !== null ) + { + nBodyPar.appendChild( oSettings.nTBody ); + } + } + + /* Call all required callback functions for the end of a draw */ + _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); + + /* Draw is complete, sorting and filtering must be as well */ + oSettings.bSorted = false; + oSettings.bFiltered = false; + oSettings.bDrawing = false; + + if ( oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + if ( !oSettings._bInitComplete ) + { + _fnInitComplete( oSettings ); + } + } + } + + + /** + * Redraw the table - taking account of the various features which are enabled + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnReDraw( oSettings ) + { + if ( oSettings.oFeatures.bSort ) + { + /* Sorting will refilter and draw for us */ + _fnSort( oSettings, oSettings.oPreviousSearch ); + } + else if ( oSettings.oFeatures.bFilter ) + { + /* Filtering will redraw for us */ + _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); + } + else + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + + + /** + * Add the options to the page HTML for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAddOptionsHtml ( oSettings ) + { + /* + * Create a temporary, empty, div which we can later on replace with what we have generated + * we do it this way to rendering the 'options' html offline - speed :-) + */ + var nHolding = $('<div></div>')[0]; + oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable ); + + /* + * All DataTables are wrapped in a div + */ + oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0]; + oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; + + /* Track where we want to insert the option */ + var nInsertNode = oSettings.nTableWrapper; + + /* Loop over the user set positioning and place the elements as needed */ + var aDom = oSettings.sDom.split(''); + var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j; + for ( var i=0 ; i<aDom.length ; i++ ) + { + iPushFeature = 0; + cOption = aDom[i]; + + if ( cOption == '<' ) + { + /* New container div */ + nNewNode = $('<div></div>')[0]; + + /* Check to see if we should append an id and/or a class name to the container */ + cNext = aDom[i+1]; + if ( cNext == "'" || cNext == '"' ) + { + sAttr = ""; + j = 2; + while ( aDom[i+j] != cNext ) + { + sAttr += aDom[i+j]; + j++; + } + + /* Replace jQuery UI constants */ + if ( sAttr == "H" ) + { + sAttr = oSettings.oClasses.sJUIHeader; + } + else if ( sAttr == "F" ) + { + sAttr = oSettings.oClasses.sJUIFooter; + } + + /* The attribute can be in the format of "#id.class", "#id" or "class" This logic + * breaks the string into parts and applies them as needed + */ + if ( sAttr.indexOf('.') != -1 ) + { + var aSplit = sAttr.split('.'); + nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); + nNewNode.className = aSplit[1]; + } + else if ( sAttr.charAt(0) == "#" ) + { + nNewNode.id = sAttr.substr(1, sAttr.length-1); + } + else + { + nNewNode.className = sAttr; + } + + i += j; /* Move along the position array */ + } + + nInsertNode.appendChild( nNewNode ); + nInsertNode = nNewNode; + } + else if ( cOption == '>' ) + { + /* End container div */ + nInsertNode = nInsertNode.parentNode; + } + else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange ) + { + /* Length */ + nTmp = _fnFeatureHtmlLength( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'f' && oSettings.oFeatures.bFilter ) + { + /* Filter */ + nTmp = _fnFeatureHtmlFilter( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'r' && oSettings.oFeatures.bProcessing ) + { + /* pRocessing */ + nTmp = _fnFeatureHtmlProcessing( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 't' ) + { + /* Table */ + nTmp = _fnFeatureHtmlTable( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'i' && oSettings.oFeatures.bInfo ) + { + /* Info */ + nTmp = _fnFeatureHtmlInfo( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'p' && oSettings.oFeatures.bPaginate ) + { + /* Pagination */ + nTmp = _fnFeatureHtmlPaginate( oSettings ); + iPushFeature = 1; + } + else if ( DataTable.ext.aoFeatures.length !== 0 ) + { + /* Plug-in features */ + var aoFeatures = DataTable.ext.aoFeatures; + for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) + { + if ( cOption == aoFeatures[k].cFeature ) + { + nTmp = aoFeatures[k].fnInit( oSettings ); + if ( nTmp ) + { + iPushFeature = 1; + } + break; + } + } + } + + /* Add to the 2D features array */ + if ( iPushFeature == 1 && nTmp !== null ) + { + if ( typeof oSettings.aanFeatures[cOption] !== 'object' ) + { + oSettings.aanFeatures[cOption] = []; + } + oSettings.aanFeatures[cOption].push( nTmp ); + nInsertNode.appendChild( nTmp ); + } + } + + /* Built our DOM structure - replace the holding div with what we want */ + nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding ); + } + + + /** + * Use the DOM source to create up an array of header cells. The idea here is to + * create a layout grid (array) of rows x columns, which contains a reference + * to the cell that that point in the grid (regardless of col/rowspan), such that + * any column / row could be removed and the new grid constructed + * @param array {object} aLayout Array to store the calculated layout in + * @param {node} nThead The header/footer element for the table + * @memberof DataTable#oApi + */ + function _fnDetectHeader ( aLayout, nThead ) + { + var nTrs = $(nThead).children('tr'); + var nTr, nCell; + var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; + var bUnique; + var fnShiftCol = function ( a, i, j ) { + var k = a[i]; + while ( k[j] ) { + j++; + } + return j; + }; + + aLayout.splice( 0, aLayout.length ); + + /* We know how many rows there are in the layout - so prep it */ + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + aLayout.push( [] ); + } + + /* Calculate a layout array */ + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + nTr = nTrs[i]; + iColumn = 0; + + /* For every cell in the row... */ + nCell = nTr.firstChild; + while ( nCell ) { + if ( nCell.nodeName.toUpperCase() == "TD" || + nCell.nodeName.toUpperCase() == "TH" ) + { + /* Get the col and rowspan attributes from the DOM and sanitise them */ + iColspan = nCell.getAttribute('colspan') * 1; + iRowspan = nCell.getAttribute('rowspan') * 1; + iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; + iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; + + /* There might be colspan cells already in this row, so shift our target + * accordingly + */ + iColShifted = fnShiftCol( aLayout, i, iColumn ); + + /* Cache calculation for unique columns */ + bUnique = iColspan === 1 ? true : false; + + /* If there is col / rowspan, copy the information into the layout grid */ + for ( l=0 ; l<iColspan ; l++ ) + { + for ( k=0 ; k<iRowspan ; k++ ) + { + aLayout[i+k][iColShifted+l] = { + "cell": nCell, + "unique": bUnique + }; + aLayout[i+k].nTr = nTr; + } + } + } + nCell = nCell.nextSibling; + } + } + } + + + /** + * Get an array of unique th elements, one for each column + * @param {object} oSettings dataTables settings object + * @param {node} nHeader automatically detect the layout from this node - optional + * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional + * @returns array {node} aReturn list of unique th's + * @memberof DataTable#oApi + */ + function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) + { + var aReturn = []; + if ( !aLayout ) + { + aLayout = oSettings.aoHeader; + if ( nHeader ) + { + aLayout = []; + _fnDetectHeader( aLayout, nHeader ); + } + } + + for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) + { + for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) + { + if ( aLayout[i][j].unique && + (!aReturn[j] || !oSettings.bSortCellsTop) ) + { + aReturn[j] = aLayout[i][j].cell; + } + } + } + + return aReturn; + } + + + + /** + * Update the table using an Ajax call + * @param {object} oSettings dataTables settings object + * @returns {boolean} Block the table drawing or not + * @memberof DataTable#oApi + */ + function _fnAjaxUpdate( oSettings ) + { + if ( oSettings.bAjaxDataGet ) + { + oSettings.iDraw++; + _fnProcessingDisplay( oSettings, true ); + var iColumns = oSettings.aoColumns.length; + var aoData = _fnAjaxParameters( oSettings ); + _fnServerParams( oSettings, aoData ); + + oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, + function(json) { + _fnAjaxUpdateDraw( oSettings, json ); + }, oSettings ); + return false; + } + else + { + return true; + } + } + + + /** + * Build up the parameters in an object needed for a server-side processing request + * @param {object} oSettings dataTables settings object + * @returns {bool} block the table drawing or not + * @memberof DataTable#oApi + */ + function _fnAjaxParameters( oSettings ) + { + var iColumns = oSettings.aoColumns.length; + var aoData = [], mDataProp, aaSort, aDataSort; + var i, j; + + aoData.push( { "name": "sEcho", "value": oSettings.iDraw } ); + aoData.push( { "name": "iColumns", "value": iColumns } ); + aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } ); + aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } ); + aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ? + oSettings._iDisplayLength : -1 } ); + + for ( i=0 ; i<iColumns ; i++ ) + { + mDataProp = oSettings.aoColumns[i].mData; + aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } ); + } + + /* Filtering */ + if ( oSettings.oFeatures.bFilter !== false ) + { + aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } ); + aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } ); + for ( i=0 ; i<iColumns ; i++ ) + { + aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } ); + aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } ); + aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } ); + } + } + + /* Sorting */ + if ( oSettings.oFeatures.bSort !== false ) + { + var iCounter = 0; + + aaSort = ( oSettings.aaSortingFixed !== null ) ? + oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : + oSettings.aaSorting.slice(); + + for ( i=0 ; i<aaSort.length ; i++ ) + { + aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort; + + for ( j=0 ; j<aDataSort.length ; j++ ) + { + aoData.push( { "name": "iSortCol_"+iCounter, "value": aDataSort[j] } ); + aoData.push( { "name": "sSortDir_"+iCounter, "value": aaSort[i][1] } ); + iCounter++; + } + } + aoData.push( { "name": "iSortingCols", "value": iCounter } ); + + for ( i=0 ; i<iColumns ; i++ ) + { + aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } ); + } + } + + return aoData; + } + + + /** + * Add Ajax parameters from plug-ins + * @param {object} oSettings dataTables settings object + * @param array {objects} aoData name/value pairs to send to the server + * @memberof DataTable#oApi + */ + function _fnServerParams( oSettings, aoData ) + { + _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] ); + } + + + /** + * Data the data from the server (nuking the old) and redraw the table + * @param {object} oSettings dataTables settings object + * @param {object} json json data return from the server. + * @param {string} json.sEcho Tracking flag for DataTables to match requests + * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering + * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering + * @param {array} json.aaData The data to display on this page + * @param {string} [json.sColumns] Column ordering (sName, comma separated) + * @memberof DataTable#oApi + */ + function _fnAjaxUpdateDraw ( oSettings, json ) + { + if ( json.sEcho !== undefined ) + { + /* Protect against old returns over-writing a new one. Possible when you get + * very fast interaction, and later queries are completed much faster + */ + if ( json.sEcho*1 < oSettings.iDraw ) + { + return; + } + else + { + oSettings.iDraw = json.sEcho * 1; + } + } + + if ( !oSettings.oScroll.bInfinite || + (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) ) + { + _fnClearTable( oSettings ); + } + oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10); + oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10); + + /* Determine if reordering is required */ + var sOrdering = _fnColumnOrdering(oSettings); + var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering ); + var aiIndex; + if ( bReOrder ) + { + aiIndex = _fnReOrderIndex( oSettings, json.sColumns ); + } + + var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ); + for ( var i=0, iLen=aData.length ; i<iLen ; i++ ) + { + if ( bReOrder ) + { + /* If we need to re-order, then create a new array with the correct order and add it */ + var aDataSorted = []; + for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ ) + { + aDataSorted.push( aData[i][ aiIndex[j] ] ); + } + _fnAddData( oSettings, aDataSorted ); + } + else + { + /* No re-order required, sever got it "right" - just straight add */ + _fnAddData( oSettings, aData[i] ); + } + } + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + oSettings.bAjaxDataGet = false; + _fnDraw( oSettings ); + oSettings.bAjaxDataGet = true; + _fnProcessingDisplay( oSettings, false ); + } + + + + /** + * Generate the node required for filtering text + * @returns {node} Filter control element + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlFilter ( oSettings ) + { + var oPreviousSearch = oSettings.oPreviousSearch; + + var sSearchStr = oSettings.oLanguage.sSearch; + sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ? + sSearchStr.replace('_INPUT_', '<input type="text" />') : + sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />'; + + var nFilter = document.createElement( 'div' ); + nFilter.className = oSettings.oClasses.sFilter; + nFilter.innerHTML = '<label>'+sSearchStr+'</label>'; + if ( !oSettings.aanFeatures.f ) + { + nFilter.id = oSettings.sTableId+'_filter'; + } + + var jqFilter = $('input[type="text"]', nFilter); + + // Store a reference to the input element, so other input elements could be + // added to the filter wrapper if needed (submit button for example) + nFilter._DT_Input = jqFilter[0]; + + jqFilter.val( oPreviousSearch.sSearch.replace('"','"') ); + jqFilter.bind( 'keyup.DT', function(e) { + /* Update all other filter input elements for the new display */ + var n = oSettings.aanFeatures.f; + var val = this.value==="" ? "" : this.value; // mental IE8 fix :-( + + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + if ( n[i] != $(this).parents('div.dataTables_filter')[0] ) + { + $(n[i]._DT_Input).val( val ); + } + } + + /* Now do the filter */ + if ( val != oPreviousSearch.sSearch ) + { + _fnFilterComplete( oSettings, { + "sSearch": val, + "bRegex": oPreviousSearch.bRegex, + "bSmart": oPreviousSearch.bSmart , + "bCaseInsensitive": oPreviousSearch.bCaseInsensitive + } ); + } + } ); + + jqFilter + .attr('aria-controls', oSettings.sTableId) + .bind( 'keypress.DT', function(e) { + /* Prevent form submission */ + if ( e.keyCode == 13 ) + { + return false; + } + } + ); + + return nFilter; + } + + + /** + * Filter the table using both the global filter and column based filtering + * @param {object} oSettings dataTables settings object + * @param {object} oSearch search information + * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) + * @memberof DataTable#oApi + */ + function _fnFilterComplete ( oSettings, oInput, iForce ) + { + var oPrevSearch = oSettings.oPreviousSearch; + var aoPrevSearch = oSettings.aoPreSearchCols; + var fnSaveFilter = function ( oFilter ) { + /* Save the filtering values */ + oPrevSearch.sSearch = oFilter.sSearch; + oPrevSearch.bRegex = oFilter.bRegex; + oPrevSearch.bSmart = oFilter.bSmart; + oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; + }; + + /* In server-side processing all filtering is done by the server, so no point hanging around here */ + if ( !oSettings.oFeatures.bServerSide ) + { + /* Global filter */ + _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive ); + fnSaveFilter( oInput ); + + /* Now do the individual column filter */ + for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ ) + { + _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex, + aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); + } + + /* Custom filtering */ + _fnFilterCustom( oSettings ); + } + else + { + fnSaveFilter( oInput ); + } + + /* Tell the draw function we have been filtering */ + oSettings.bFiltered = true; + $(oSettings.oInstance).trigger('filter', oSettings); + + /* Redraw the table */ + oSettings._iDisplayStart = 0; + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + + /* Rebuild search array 'offline' */ + _fnBuildSearchArray( oSettings, 0 ); + } + + + /** + * Apply custom filtering functions + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnFilterCustom( oSettings ) + { + var afnFilters = DataTable.ext.afnFiltering; + var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); + + for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ ) + { + var iCorrector = 0; + for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ ) + { + var iDisIndex = oSettings.aiDisplay[j-iCorrector]; + var bTest = afnFilters[i]( + oSettings, + _fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ), + iDisIndex + ); + + /* Check if we should use this row based on the filtering function */ + if ( !bTest ) + { + oSettings.aiDisplay.splice( j-iCorrector, 1 ); + iCorrector++; + } + } + } + } + + + /** + * Filter the table on a per-column basis + * @param {object} oSettings dataTables settings object + * @param {string} sInput string to filter on + * @param {int} iColumn column to filter + * @param {bool} bRegex treat search string as a regular expression or not + * @param {bool} bSmart use smart filtering or not + * @param {bool} bCaseInsensitive Do case insenstive matching or not + * @memberof DataTable#oApi + */ + function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive ) + { + if ( sInput === "" ) + { + return; + } + + var iIndexCorrector = 0; + var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); + + for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- ) + { + var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ), + oSettings.aoColumns[iColumn].sType ); + if ( ! rpSearch.test( sData ) ) + { + oSettings.aiDisplay.splice( i, 1 ); + iIndexCorrector++; + } + } + } + + + /** + * Filter the data table based on user input and draw the table + * @param {object} oSettings dataTables settings object + * @param {string} sInput string to filter on + * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0) + * @param {bool} bRegex treat as a regular expression or not + * @param {bool} bSmart perform smart filtering or not + * @param {bool} bCaseInsensitive Do case insenstive matching or not + * @memberof DataTable#oApi + */ + function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive ) + { + var i; + var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); + var oPrevSearch = oSettings.oPreviousSearch; + + /* Check if we are forcing or not - optional parameter */ + if ( !iForce ) + { + iForce = 0; + } + + /* Need to take account of custom filtering functions - always filter */ + if ( DataTable.ext.afnFiltering.length !== 0 ) + { + iForce = 1; + } + + /* + * If the input is blank - we want the full data set + */ + if ( sInput.length <= 0 ) + { + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + } + else + { + /* + * We are starting a new search or the new search string is smaller + * then the old one (i.e. delete). Search from the master array + */ + if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length || + oPrevSearch.sSearch.length > sInput.length || iForce == 1 || + sInput.indexOf(oPrevSearch.sSearch) !== 0 ) + { + /* Nuke the old display array - we are going to rebuild it */ + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); + + /* Force a rebuild of the search array */ + _fnBuildSearchArray( oSettings, 1 ); + + /* Search through all records to populate the search array + * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 + * mapping + */ + for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ ) + { + if ( rpSearch.test(oSettings.asDataSearch[i]) ) + { + oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] ); + } + } + } + else + { + /* Using old search array - refine it - do it this way for speed + * Don't have to search the whole master array again + */ + var iIndexCorrector = 0; + + /* Search the current results */ + for ( i=0 ; i<oSettings.asDataSearch.length ; i++ ) + { + if ( ! rpSearch.test(oSettings.asDataSearch[i]) ) + { + oSettings.aiDisplay.splice( i-iIndexCorrector, 1 ); + iIndexCorrector++; + } + } + } + } + } + + + /** + * Create an array which can be quickly search through + * @param {object} oSettings dataTables settings object + * @param {int} iMaster use the master data array - optional + * @memberof DataTable#oApi + */ + function _fnBuildSearchArray ( oSettings, iMaster ) + { + if ( !oSettings.oFeatures.bServerSide ) + { + /* Clear out the old data */ + oSettings.asDataSearch = []; + + var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); + var aiIndex = (iMaster===1) ? + oSettings.aiDisplayMaster : + oSettings.aiDisplay; + + for ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ ) + { + oSettings.asDataSearch[i] = _fnBuildSearchRow( + oSettings, + _fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns ) + ); + } + } + } + + + /** + * Create a searchable string from a single data row + * @param {object} oSettings dataTables settings object + * @param {array} aData Row data array to use for the data to search + * @memberof DataTable#oApi + */ + function _fnBuildSearchRow( oSettings, aData ) + { + var sSearch = aData.join(' '); + + /* If it looks like there is an HTML entity in the string, attempt to decode it */ + if ( sSearch.indexOf('&') !== -1 ) + { + sSearch = $('<div>').html(sSearch).text(); + } + + // Strip newline characters + return sSearch.replace( /[\n\r]/g, " " ); + } + + /** + * Build a regular expression object suitable for searching a table + * @param {string} sSearch string to search for + * @param {bool} bRegex treat as a regular expression or not + * @param {bool} bSmart perform smart filtering or not + * @param {bool} bCaseInsensitive Do case insensitive matching or not + * @returns {RegExp} constructed object + * @memberof DataTable#oApi + */ + function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive ) + { + var asSearch, sRegExpString; + + if ( bSmart ) + { + /* Generate the regular expression to use. Something along the lines of: + * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$ + */ + asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' ); + sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$'; + return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" ); + } + else + { + sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch ); + return new RegExp( sSearch, bCaseInsensitive ? "i" : "" ); + } + } + + + /** + * Convert raw data into something that the user can search on + * @param {string} sData data to be modified + * @param {string} sType data type + * @returns {string} search string + * @memberof DataTable#oApi + */ + function _fnDataToSearch ( sData, sType ) + { + if ( typeof DataTable.ext.ofnSearch[sType] === "function" ) + { + return DataTable.ext.ofnSearch[sType]( sData ); + } + else if ( sData === null ) + { + return ''; + } + else if ( sType == "html" ) + { + return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" ); + } + else if ( typeof sData === "string" ) + { + return sData.replace(/[\r\n]/g," "); + } + return sData; + } + + + /** + * scape a string such that it can be used in a regular expression + * @param {string} sVal string to escape + * @returns {string} escaped string + * @memberof DataTable#oApi + */ + function _fnEscapeRegex ( sVal ) + { + var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ]; + var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' ); + return sVal.replace(reReplace, '\\$1'); + } + + + /** + * Generate the node required for the info display + * @param {object} oSettings dataTables settings object + * @returns {node} Information element + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlInfo ( oSettings ) + { + var nInfo = document.createElement( 'div' ); + nInfo.className = oSettings.oClasses.sInfo; + + /* Actions that are to be taken once only for this feature */ + if ( !oSettings.aanFeatures.i ) + { + /* Add draw callback */ + oSettings.aoDrawCallback.push( { + "fn": _fnUpdateInfo, + "sName": "information" + } ); + + /* Add id */ + nInfo.id = oSettings.sTableId+'_info'; + } + oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' ); + + return nInfo; + } + + + /** + * Update the information elements in the display + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnUpdateInfo ( oSettings ) + { + /* Show information about the table */ + if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 ) + { + return; + } + + var + oLang = oSettings.oLanguage, + iStart = oSettings._iDisplayStart+1, + iEnd = oSettings.fnDisplayEnd(), + iMax = oSettings.fnRecordsTotal(), + iTotal = oSettings.fnRecordsDisplay(), + sOut; + + if ( iTotal === 0 ) + { + /* Empty record set */ + sOut = oLang.sInfoEmpty; + } + else { + /* Normal record set */ + sOut = oLang.sInfo; + } + + if ( iTotal != iMax ) + { + /* Record set after filtering */ + sOut += ' ' + oLang.sInfoFiltered; + } + + // Convert the macros + sOut += oLang.sInfoPostFix; + sOut = _fnInfoMacros( oSettings, sOut ); + + if ( oLang.fnInfoCallback !== null ) + { + sOut = oLang.fnInfoCallback.call( oSettings.oInstance, + oSettings, iStart, iEnd, iMax, iTotal, sOut ); + } + + var n = oSettings.aanFeatures.i; + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + $(n[i]).html( sOut ); + } + } + + + function _fnInfoMacros ( oSettings, str ) + { + var + iStart = oSettings._iDisplayStart+1, + sStart = oSettings.fnFormatNumber( iStart ), + iEnd = oSettings.fnDisplayEnd(), + sEnd = oSettings.fnFormatNumber( iEnd ), + iTotal = oSettings.fnRecordsDisplay(), + sTotal = oSettings.fnFormatNumber( iTotal ), + iMax = oSettings.fnRecordsTotal(), + sMax = oSettings.fnFormatNumber( iMax ); + + // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only + // internally + if ( oSettings.oScroll.bInfinite ) + { + sStart = oSettings.fnFormatNumber( 1 ); + } + + return str. + replace(/_START_/g, sStart). + replace(/_END_/g, sEnd). + replace(/_TOTAL_/g, sTotal). + replace(/_MAX_/g, sMax); + } + + + + /** + * Draw the table for the first time, adding all required features + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnInitialise ( oSettings ) + { + var i, iLen, iAjaxStart=oSettings.iInitDisplayStart; + + /* Ensure that the table data is fully initialised */ + if ( oSettings.bInitialised === false ) + { + setTimeout( function(){ _fnInitialise( oSettings ); }, 200 ); + return; + } + + /* Show the display HTML options */ + _fnAddOptionsHtml( oSettings ); + + /* Build and draw the header / footer for the table */ + _fnBuildHead( oSettings ); + _fnDrawHead( oSettings, oSettings.aoHeader ); + if ( oSettings.nTFoot ) + { + _fnDrawHead( oSettings, oSettings.aoFooter ); + } + + /* Okay to show that something is going on now */ + _fnProcessingDisplay( oSettings, true ); + + /* Calculate sizes for columns */ + if ( oSettings.oFeatures.bAutoWidth ) + { + _fnCalculateColumnWidths( oSettings ); + } + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( oSettings.aoColumns[i].sWidth !== null ) + { + oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth ); + } + } + + /* If there is default sorting required - let's do it. The sort function will do the + * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows + * the table to look initialised for Ajax sourcing data (show 'loading' message possibly) + */ + if ( oSettings.oFeatures.bSort ) + { + _fnSort( oSettings ); + } + else if ( oSettings.oFeatures.bFilter ) + { + _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + /* if there is an ajax source load the data */ + if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) + { + var aoData = []; + _fnServerParams( oSettings, aoData ); + oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) { + var aData = (oSettings.sAjaxDataProp !== "") ? + _fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json; + + /* Got the data - add it to the table */ + for ( i=0 ; i<aData.length ; i++ ) + { + _fnAddData( oSettings, aData[i] ); + } + + /* Reset the init display for cookie saving. We've already done a filter, and + * therefore cleared it before. So we need to make it appear 'fresh' + */ + oSettings.iInitDisplayStart = iAjaxStart; + + if ( oSettings.oFeatures.bSort ) + { + _fnSort( oSettings ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + _fnProcessingDisplay( oSettings, false ); + _fnInitComplete( oSettings, json ); + }, oSettings ); + return; + } + + /* Server-side processing initialisation complete is done at the end of _fnDraw */ + if ( !oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + _fnInitComplete( oSettings ); + } + } + + + /** + * Draw the table for the first time, adding all required features + * @param {object} oSettings dataTables settings object + * @param {object} [json] JSON from the server that completed the table, if using Ajax source + * with client-side processing (optional) + * @memberof DataTable#oApi + */ + function _fnInitComplete ( oSettings, json ) + { + oSettings._bInitComplete = true; + _fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] ); + } + + + /** + * Language compatibility - when certain options are given, and others aren't, we + * need to duplicate the values over, in order to provide backwards compatibility + * with older language files. + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnLanguageCompat( oLanguage ) + { + var oDefaults = DataTable.defaults.oLanguage; + + /* Backwards compatibility - if there is no sEmptyTable given, then use the same as + * sZeroRecords - assuming that is given. + */ + if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords && + oDefaults.sEmptyTable === "No data available in table" ) + { + _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' ); + } + + /* Likewise with loading records */ + if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords && + oDefaults.sLoadingRecords === "Loading..." ) + { + _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' ); + } + } + + + + /** + * Generate the node required for user display length changing + * @param {object} oSettings dataTables settings object + * @returns {node} Display length feature node + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlLength ( oSettings ) + { + if ( oSettings.oScroll.bInfinite ) + { + return null; + } + + /* This can be overruled by not using the _MENU_ var/macro in the language variable */ + var sName = 'name="'+oSettings.sTableId+'_length"'; + var sStdMenu = '<select size="1" '+sName+'>'; + var i, iLen; + var aLengthMenu = oSettings.aLengthMenu; + + if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' && + typeof aLengthMenu[1] === 'object' ) + { + for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ ) + { + sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>'; + } + } + else + { + for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ ) + { + sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>'; + } + } + sStdMenu += '</select>'; + + var nLength = document.createElement( 'div' ); + if ( !oSettings.aanFeatures.l ) + { + nLength.id = oSettings.sTableId+'_length'; + } + nLength.className = oSettings.oClasses.sLength; + nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>'; + + /* + * Set the length to the current display length - thanks to Andrea Pavlovic for this fix, + * and Stefan Skopnik for fixing the fix! + */ + $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true); + + $('select', nLength).bind( 'change.DT', function(e) { + var iVal = $(this).val(); + + /* Update all other length options for the new display */ + var n = oSettings.aanFeatures.l; + for ( i=0, iLen=n.length ; i<iLen ; i++ ) + { + if ( n[i] != this.parentNode ) + { + $('select', n[i]).val( iVal ); + } + } + + /* Redraw the table */ + oSettings._iDisplayLength = parseInt(iVal, 10); + _fnCalculateEnd( oSettings ); + + /* If we have space to show extra rows (backing up from the end point - then do so */ + if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength; + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + + if ( oSettings._iDisplayLength == -1 ) + { + oSettings._iDisplayStart = 0; + } + + _fnDraw( oSettings ); + } ); + + + $('select', nLength).attr('aria-controls', oSettings.sTableId); + + return nLength; + } + + + /** + * Recalculate the end point based on the start point + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnCalculateEnd( oSettings ) + { + if ( oSettings.oFeatures.bPaginate === false ) + { + oSettings._iDisplayEnd = oSettings.aiDisplay.length; + } + else + { + /* Set the end point of the display - based on how many elements there are + * still to display + */ + if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length || + oSettings._iDisplayLength == -1 ) + { + oSettings._iDisplayEnd = oSettings.aiDisplay.length; + } + else + { + oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength; + } + } + } + + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Note that most of the paging logic is done in + * DataTable.ext.oPagination + */ + + /** + * Generate the node required for default pagination + * @param {object} oSettings dataTables settings object + * @returns {node} Pagination feature node + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlPaginate ( oSettings ) + { + if ( oSettings.oScroll.bInfinite ) + { + return null; + } + + var nPaginate = document.createElement( 'div' ); + nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType; + + DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate, + function( oSettings ) { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + ); + + /* Add a draw callback for the pagination on first instance, to update the paging display */ + if ( !oSettings.aanFeatures.p ) + { + oSettings.aoDrawCallback.push( { + "fn": function( oSettings ) { + DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } ); + }, + "sName": "pagination" + } ); + } + return nPaginate; + } + + + /** + * Alter the display settings to change the page + * @param {object} oSettings dataTables settings object + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer) + * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1 + * @memberof DataTable#oApi + */ + function _fnPageChange ( oSettings, mAction ) + { + var iOldStart = oSettings._iDisplayStart; + + if ( typeof mAction === "number" ) + { + oSettings._iDisplayStart = mAction * oSettings._iDisplayLength; + if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "first" ) + { + oSettings._iDisplayStart = 0; + } + else if ( mAction == "previous" ) + { + oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ? + oSettings._iDisplayStart - oSettings._iDisplayLength : + 0; + + /* Correct for under-run */ + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "next" ) + { + if ( oSettings._iDisplayLength >= 0 ) + { + /* Make sure we are not over running the display array */ + if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart += oSettings._iDisplayLength; + } + } + else + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "last" ) + { + if ( oSettings._iDisplayLength >= 0 ) + { + var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1; + oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength; + } + else + { + oSettings._iDisplayStart = 0; + } + } + else + { + _fnLog( oSettings, 0, "Unknown paging action: "+mAction ); + } + $(oSettings.oInstance).trigger('page', oSettings); + + return iOldStart != oSettings._iDisplayStart; + } + + + + /** + * Generate the node required for the processing node + * @param {object} oSettings dataTables settings object + * @returns {node} Processing element + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlProcessing ( oSettings ) + { + var nProcessing = document.createElement( 'div' ); + + if ( !oSettings.aanFeatures.r ) + { + nProcessing.id = oSettings.sTableId+'_processing'; + } + nProcessing.innerHTML = oSettings.oLanguage.sProcessing; + nProcessing.className = oSettings.oClasses.sProcessing; + oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable ); + + return nProcessing; + } + + + /** + * Display or hide the processing indicator + * @param {object} oSettings dataTables settings object + * @param {bool} bShow Show the processing indicator (true) or not (false) + * @memberof DataTable#oApi + */ + function _fnProcessingDisplay ( oSettings, bShow ) + { + if ( oSettings.oFeatures.bProcessing ) + { + var an = oSettings.aanFeatures.r; + for ( var i=0, iLen=an.length ; i<iLen ; i++ ) + { + an[i].style.visibility = bShow ? "visible" : "hidden"; + } + } + + $(oSettings.oInstance).trigger('processing', [oSettings, bShow]); + } + + /** + * Add any control elements for the table - specifically scrolling + * @param {object} oSettings dataTables settings object + * @returns {node} Node to add to the DOM + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlTable ( oSettings ) + { + /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */ + if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) + { + return oSettings.nTable; + } + + /* + * The HTML structure that we want to generate in this function is: + * div - nScroller + * div - nScrollHead + * div - nScrollHeadInner + * table - nScrollHeadTable + * thead - nThead + * div - nScrollBody + * table - oSettings.nTable + * thead - nTheadSize + * tbody - nTbody + * div - nScrollFoot + * div - nScrollFootInner + * table - nScrollFootTable + * tfoot - nTfoot + */ + var + nScroller = document.createElement('div'), + nScrollHead = document.createElement('div'), + nScrollHeadInner = document.createElement('div'), + nScrollBody = document.createElement('div'), + nScrollFoot = document.createElement('div'), + nScrollFootInner = document.createElement('div'), + nScrollHeadTable = oSettings.nTable.cloneNode(false), + nScrollFootTable = oSettings.nTable.cloneNode(false), + nThead = oSettings.nTable.getElementsByTagName('thead')[0], + nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null : + oSettings.nTable.getElementsByTagName('tfoot')[0], + oClasses = oSettings.oClasses; + + nScrollHead.appendChild( nScrollHeadInner ); + nScrollFoot.appendChild( nScrollFootInner ); + nScrollBody.appendChild( oSettings.nTable ); + nScroller.appendChild( nScrollHead ); + nScroller.appendChild( nScrollBody ); + nScrollHeadInner.appendChild( nScrollHeadTable ); + nScrollHeadTable.appendChild( nThead ); + if ( nTfoot !== null ) + { + nScroller.appendChild( nScrollFoot ); + nScrollFootInner.appendChild( nScrollFootTable ); + nScrollFootTable.appendChild( nTfoot ); + } + + nScroller.className = oClasses.sScrollWrapper; + nScrollHead.className = oClasses.sScrollHead; + nScrollHeadInner.className = oClasses.sScrollHeadInner; + nScrollBody.className = oClasses.sScrollBody; + nScrollFoot.className = oClasses.sScrollFoot; + nScrollFootInner.className = oClasses.sScrollFootInner; + + if ( oSettings.oScroll.bAutoCss ) + { + nScrollHead.style.overflow = "hidden"; + nScrollHead.style.position = "relative"; + nScrollFoot.style.overflow = "hidden"; + nScrollBody.style.overflow = "auto"; + } + + nScrollHead.style.border = "0"; + nScrollHead.style.width = "100%"; + nScrollFoot.style.border = "0"; + nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ? + oSettings.oScroll.sXInner : "100%"; /* will be overwritten */ + + /* Modify attributes to respect the clones */ + nScrollHeadTable.removeAttribute('id'); + nScrollHeadTable.style.marginLeft = "0"; + oSettings.nTable.style.marginLeft = "0"; + if ( nTfoot !== null ) + { + nScrollFootTable.removeAttribute('id'); + nScrollFootTable.style.marginLeft = "0"; + } + + /* Move caption elements from the body to the header, footer or leave where it is + * depending on the configuration. Note that the DTD says there can be only one caption */ + var nCaption = $(oSettings.nTable).children('caption'); + if ( nCaption.length > 0 ) + { + nCaption = nCaption[0]; + if ( nCaption._captionSide === "top" ) + { + nScrollHeadTable.appendChild( nCaption ); + } + else if ( nCaption._captionSide === "bottom" && nTfoot ) + { + nScrollFootTable.appendChild( nCaption ); + } + } + + /* + * Sizing + */ + /* When x-scrolling add the width and a scroller to move the header with the body */ + if ( oSettings.oScroll.sX !== "" ) + { + nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX ); + nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX ); + + if ( nTfoot !== null ) + { + nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX ); + } + + /* When the body is scrolled, then we also want to scroll the headers */ + $(nScrollBody).scroll( function (e) { + nScrollHead.scrollLeft = this.scrollLeft; + + if ( nTfoot !== null ) + { + nScrollFoot.scrollLeft = this.scrollLeft; + } + } ); + } + + /* When yscrolling, add the height */ + if ( oSettings.oScroll.sY !== "" ) + { + nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY ); + } + + /* Redraw - align columns across the tables */ + oSettings.aoDrawCallback.push( { + "fn": _fnScrollDraw, + "sName": "scrolling" + } ); + + /* Infinite scrolling event handlers */ + if ( oSettings.oScroll.bInfinite ) + { + $(nScrollBody).scroll( function() { + /* Use a blocker to stop scrolling from loading more data while other data is still loading */ + if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 ) + { + /* Check if we should load the next data set */ + if ( $(this).scrollTop() + $(this).height() > + $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap ) + { + /* Only do the redraw if we have to - we might be at the end of the data */ + if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() ) + { + _fnPageChange( oSettings, 'next' ); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + } + } ); + } + + oSettings.nScrollHead = nScrollHead; + oSettings.nScrollFoot = nScrollFoot; + + return nScroller; + } + + + /** + * Update the various tables for resizing. It's a bit of a pig this function, but + * basically the idea to: + * 1. Re-create the table inside the scrolling div + * 2. Take live measurements from the DOM + * 3. Apply the measurements + * 4. Clean up + * @param {object} o dataTables settings object + * @returns {node} Node to add to the DOM + * @memberof DataTable#oApi + */ + function _fnScrollDraw ( o ) + { + var + nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0], + nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0], + nScrollBody = o.nTable.parentNode, + i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis, + nTheadSize, nTfootSize, + iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth, + nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null, + nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null, + ie67 = o.oBrowser.bScrollOversize, + zeroOut = function(nSizer) { + oStyle = nSizer.style; + oStyle.paddingTop = "0"; + oStyle.paddingBottom = "0"; + oStyle.borderTopWidth = "0"; + oStyle.borderBottomWidth = "0"; + oStyle.height = 0; + }; + + /* + * 1. Re-create the table inside the scrolling div + */ + + /* Remove the old minimised thead and tfoot elements in the inner table */ + $(o.nTable).children('thead, tfoot').remove(); + + /* Clone the current header and footer elements and then place it into the inner table */ + nTheadSize = $(o.nTHead).clone()[0]; + o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] ); + anHeadToSize = o.nTHead.getElementsByTagName('tr'); + anHeadSizers = nTheadSize.getElementsByTagName('tr'); + + if ( o.nTFoot !== null ) + { + nTfootSize = $(o.nTFoot).clone()[0]; + o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] ); + anFootToSize = o.nTFoot.getElementsByTagName('tr'); + anFootSizers = nTfootSize.getElementsByTagName('tr'); + } + + /* + * 2. Take live measurements from the DOM - do not alter the DOM itself! + */ + + /* Remove old sizing and apply the calculated column widths + * Get the unique column headers in the newly created (cloned) header. We want to apply the + * calculated sizes to this header + */ + if ( o.oScroll.sX === "" ) + { + nScrollBody.style.width = '100%'; + nScrollHeadInner.parentNode.style.width = '100%'; + } + + var nThs = _fnGetUniqueThs( o, nTheadSize ); + for ( i=0, iLen=nThs.length ; i<iLen ; i++ ) + { + iVis = _fnVisibleToColumnIndex( o, i ); + nThs[i].style.width = o.aoColumns[iVis].sWidth; + } + + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( function(n) { + n.style.width = ""; + }, anFootSizers ); + } + + // If scroll collapse is enabled, when we put the headers back into the body for sizing, we + // will end up forcing the scrollbar to appear, making our measurements wrong for when we + // then hide it (end of this function), so add the header height to the body scroller. + if ( o.oScroll.bCollapse && o.oScroll.sY !== "" ) + { + nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px"; + } + + /* Size the table as a whole */ + iSanityWidth = $(o.nTable).outerWidth(); + if ( o.oScroll.sX === "" ) + { + /* No x scrolling */ + o.nTable.style.width = "100%"; + + /* I know this is rubbish - but IE7 will make the width of the table when 100% include + * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this + * into account. + */ + if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight || + $(nScrollBody).css('overflow-y') == "scroll") ) + { + o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth); + } + } + else + { + if ( o.oScroll.sXInner !== "" ) + { + /* x scroll inner has been given - use it */ + o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner); + } + else if ( iSanityWidth == $(nScrollBody).width() && + $(nScrollBody).height() < $(o.nTable).height() ) + { + /* There is y-scrolling - try to take account of the y scroll bar */ + o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth ); + if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth ) + { + /* Not possible to take account of it */ + o.nTable.style.width = _fnStringToCss( iSanityWidth ); + } + } + else + { + /* All else fails */ + o.nTable.style.width = _fnStringToCss( iSanityWidth ); + } + } + + /* Recalculate the sanity width - now that we've applied the required width, before it was + * a temporary variable. This is required because the column width calculation is done + * before this table DOM is created. + */ + iSanityWidth = $(o.nTable).outerWidth(); + + /* We want the hidden header to have zero height, so remove padding and borders. Then + * set the width based on the real headers + */ + + // Apply all styles in one pass. Invalidates layout only once because we don't read any + // DOM properties. + _fnApplyToChildren( zeroOut, anHeadSizers ); + + // Read all widths in next pass. Forces layout only once because we do not change + // any DOM properties. + _fnApplyToChildren( function(nSizer) { + aApplied.push( _fnStringToCss( $(nSizer).width() ) ); + }, anHeadSizers ); + + // Apply all widths in final pass. Invalidates layout only once because we do not + // read any DOM properties. + _fnApplyToChildren( function(nToSize, i) { + nToSize.style.width = aApplied[i]; + }, anHeadToSize ); + + $(anHeadSizers).height(0); + + /* Same again with the footer if we have one */ + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( zeroOut, anFootSizers ); + + _fnApplyToChildren( function(nSizer) { + aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) ); + }, anFootSizers ); + + _fnApplyToChildren( function(nToSize, i) { + nToSize.style.width = aAppliedFooter[i]; + }, anFootToSize ); + + $(anFootSizers).height(0); + } + + /* + * 3. Apply the measurements + */ + + /* "Hide" the header and footer that we used for the sizing. We want to also fix their width + * to what they currently are + */ + _fnApplyToChildren( function(nSizer, i) { + nSizer.innerHTML = ""; + nSizer.style.width = aApplied[i]; + }, anHeadSizers ); + + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( function(nSizer, i) { + nSizer.innerHTML = ""; + nSizer.style.width = aAppliedFooter[i]; + }, anFootSizers ); + } + + /* Sanity check that the table is of a sensible width. If not then we are going to get + * misalignment - try to prevent this by not allowing the table to shrink below its min width + */ + if ( $(o.nTable).outerWidth() < iSanityWidth ) + { + /* The min width depends upon if we have a vertical scrollbar visible or not */ + var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight || + $(nScrollBody).css('overflow-y') == "scroll")) ? + iSanityWidth+o.oScroll.iBarWidth : iSanityWidth; + + /* IE6/7 are a law unto themselves... */ + if ( ie67 && (nScrollBody.scrollHeight > + nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") ) + { + o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth ); + } + + /* Apply the calculated minimum width to the table wrappers */ + nScrollBody.style.width = _fnStringToCss( iCorrection ); + o.nScrollHead.style.width = _fnStringToCss( iCorrection ); + + if ( o.nTFoot !== null ) + { + o.nScrollFoot.style.width = _fnStringToCss( iCorrection ); + } + + /* And give the user a warning that we've stopped the table getting too small */ + if ( o.oScroll.sX === "" ) + { + _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ + " misalignment. The table has been drawn at its minimum possible width." ); + } + else if ( o.oScroll.sXInner !== "" ) + { + _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ + " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+ + " calculation" ); + } + } + else + { + nScrollBody.style.width = _fnStringToCss( '100%' ); + o.nScrollHead.style.width = _fnStringToCss( '100%' ); + + if ( o.nTFoot !== null ) + { + o.nScrollFoot.style.width = _fnStringToCss( '100%' ); + } + } + + + /* + * 4. Clean up + */ + if ( o.oScroll.sY === "" ) + { + /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting + * the scrollbar height from the visible display, rather than adding it on. We need to + * set the height in order to sort this. Don't want to do it in any other browsers. + */ + if ( ie67 ) + { + nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth ); + } + } + + if ( o.oScroll.sY !== "" && o.oScroll.bCollapse ) + { + nScrollBody.style.height = _fnStringToCss( o.oScroll.sY ); + + var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ? + o.oScroll.iBarWidth : 0; + if ( o.nTable.offsetHeight < nScrollBody.offsetHeight ) + { + nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra ); + } + } + + /* Finally set the width's of the header and footer tables */ + var iOuterWidth = $(o.nTable).outerWidth(); + nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth ); + nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth ); + + // Figure out if there are scrollbar present - if so then we need a the header and footer to + // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) + var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll"; + nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; + + if ( o.nTFoot !== null ) + { + nScrollFootTable.style.width = _fnStringToCss( iOuterWidth ); + nScrollFootInner.style.width = _fnStringToCss( iOuterWidth ); + nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; + } + + /* Adjust the position of the header in case we loose the y-scrollbar */ + $(nScrollBody).scroll(); + + /* If sorting or filtering has occurred, jump the scrolling back to the top */ + if ( o.bSorted || o.bFiltered ) + { + nScrollBody.scrollTop = 0; + } + } + + + /** + * Apply a given function to the display child nodes of an element array (typically + * TD children of TR rows + * @param {function} fn Method to apply to the objects + * @param array {nodes} an1 List of elements to look through for display children + * @param array {nodes} an2 Another list (identical structure to the first) - optional + * @memberof DataTable#oApi + */ + function _fnApplyToChildren( fn, an1, an2 ) + { + var index=0, i=0, iLen=an1.length; + var nNode1, nNode2; + + while ( i < iLen ) + { + nNode1 = an1[i].firstChild; + nNode2 = an2 ? an2[i].firstChild : null; + while ( nNode1 ) + { + if ( nNode1.nodeType === 1 ) + { + if ( an2 ) + { + fn( nNode1, nNode2, index ); + } + else + { + fn( nNode1, index ); + } + index++; + } + nNode1 = nNode1.nextSibling; + nNode2 = an2 ? nNode2.nextSibling : null; + } + i++; + } + } + + /** + * Convert a CSS unit width to pixels (e.g. 2em) + * @param {string} sWidth width to be converted + * @param {node} nParent parent to get the with for (required for relative widths) - optional + * @returns {int} iWidth width in pixels + * @memberof DataTable#oApi + */ + function _fnConvertToWidth ( sWidth, nParent ) + { + if ( !sWidth || sWidth === null || sWidth === '' ) + { + return 0; + } + + if ( !nParent ) + { + nParent = document.body; + } + + var iWidth; + var nTmp = document.createElement( "div" ); + nTmp.style.width = _fnStringToCss( sWidth ); + + nParent.appendChild( nTmp ); + iWidth = nTmp.offsetWidth; + nParent.removeChild( nTmp ); + + return ( iWidth ); + } + + + /** + * Calculate the width of columns for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnCalculateColumnWidths ( oSettings ) + { + var iTableWidth = oSettings.nTable.offsetWidth; + var iUserInputs = 0; + var iTmpWidth; + var iVisibleColumns = 0; + var iColums = oSettings.aoColumns.length; + var i, iIndex, iCorrector, iWidth; + var oHeaders = $('th', oSettings.nTHead); + var widthAttr = oSettings.nTable.getAttribute('width'); + var nWrapper = oSettings.nTable.parentNode; + + /* Convert any user input sizes into pixel sizes */ + for ( i=0 ; i<iColums ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + iVisibleColumns++; + + if ( oSettings.aoColumns[i].sWidth !== null ) + { + iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, + nWrapper ); + if ( iTmpWidth !== null ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); + } + + iUserInputs++; + } + } + } + + /* If the number of columns in the DOM equals the number that we have to process in + * DataTables, then we can use the offsets that are created by the web-browser. No custom + * sizes can be set in order for this to happen, nor scrolling used + */ + if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums && + oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) + { + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + iTmpWidth = $(oHeaders[i]).width(); + if ( iTmpWidth !== null ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); + } + } + } + else + { + /* Otherwise we are going to have to do some calculations to get the width of each column. + * Construct a 1 row table with the widest node in the data, and any user defined widths, + * then insert it into the DOM and allow the browser to do all the hard work of + * calculating table widths. + */ + var + nCalcTmp = oSettings.nTable.cloneNode( false ), + nTheadClone = oSettings.nTHead.cloneNode(true), + nBody = document.createElement( 'tbody' ), + nTr = document.createElement( 'tr' ), + nDivSizing; + + nCalcTmp.removeAttribute( "id" ); + nCalcTmp.appendChild( nTheadClone ); + if ( oSettings.nTFoot !== null ) + { + nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) ); + _fnApplyToChildren( function(n) { + n.style.width = ""; + }, nCalcTmp.getElementsByTagName('tr') ); + } + + nCalcTmp.appendChild( nBody ); + nBody.appendChild( nTr ); + + /* Remove any sizing that was previously applied by the styles */ + var jqColSizing = $('thead th', nCalcTmp); + if ( jqColSizing.length === 0 ) + { + jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp); + } + + /* Apply custom sizing to the cloned header */ + var nThs = _fnGetUniqueThs( oSettings, nTheadClone ); + iCorrector = 0; + for ( i=0 ; i<iColums ; i++ ) + { + var oColumn = oSettings.aoColumns[i]; + if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" ) + { + nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig ); + } + else if ( oColumn.bVisible ) + { + nThs[i-iCorrector].style.width = ""; + } + else + { + iCorrector++; + } + } + + /* Find the biggest td for each column and put it into the table */ + for ( i=0 ; i<iColums ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + var nTd = _fnGetWidestNode( oSettings, i ); + if ( nTd !== null ) + { + nTd = nTd.cloneNode(true); + if ( oSettings.aoColumns[i].sContentPadding !== "" ) + { + nTd.innerHTML += oSettings.aoColumns[i].sContentPadding; + } + nTr.appendChild( nTd ); + } + } + } + + /* Build the table and 'display' it */ + nWrapper.appendChild( nCalcTmp ); + + /* When scrolling (X or Y) we want to set the width of the table as appropriate. However, + * when not scrolling leave the table width as it is. This results in slightly different, + * but I think correct behaviour + */ + if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" ) + { + nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner); + } + else if ( oSettings.oScroll.sX !== "" ) + { + nCalcTmp.style.width = ""; + if ( $(nCalcTmp).width() < nWrapper.offsetWidth ) + { + nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); + } + } + else if ( oSettings.oScroll.sY !== "" ) + { + nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); + } + else if ( widthAttr ) + { + nCalcTmp.style.width = _fnStringToCss( widthAttr ); + } + nCalcTmp.style.visibility = "hidden"; + + /* Scrolling considerations */ + _fnScrollingWidthAdjust( oSettings, nCalcTmp ); + + /* Read the width's calculated by the browser and store them for use by the caller. We + * first of all try to use the elements in the body, but it is possible that there are + * no elements there, under which circumstances we use the header elements + */ + var oNodes = $("tbody tr:eq(0)", nCalcTmp).children(); + if ( oNodes.length === 0 ) + { + oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] ); + } + + /* Browsers need a bit of a hand when a width is assigned to any columns when + * x-scrolling as they tend to collapse the table to the min-width, even if + * we sent the column widths. So we need to keep track of what the table width + * should be by summing the user given values, and the automatic values + */ + if ( oSettings.oScroll.sX !== "" ) + { + var iTotal = 0; + iCorrector = 0; + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + if ( oSettings.aoColumns[i].sWidthOrig === null ) + { + iTotal += $(oNodes[iCorrector]).outerWidth(); + } + else + { + iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) + + ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width()); + } + iCorrector++; + } + } + + nCalcTmp.style.width = _fnStringToCss( iTotal ); + oSettings.nTable.style.width = _fnStringToCss( iTotal ); + } + + iCorrector = 0; + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + iWidth = $(oNodes[iCorrector]).width(); + if ( iWidth !== null && iWidth > 0 ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth ); + } + iCorrector++; + } + } + + var cssWidth = $(nCalcTmp).css('width'); + oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ? + cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() ); + nCalcTmp.parentNode.removeChild( nCalcTmp ); + } + + if ( widthAttr ) + { + oSettings.nTable.style.width = _fnStringToCss( widthAttr ); + } + } + + + /** + * Adjust a table's width to take account of scrolling + * @param {object} oSettings dataTables settings object + * @param {node} n table node + * @memberof DataTable#oApi + */ + function _fnScrollingWidthAdjust ( oSettings, n ) + { + if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" ) + { + /* When y-scrolling only, we want to remove the width of the scroll bar so the table + * + scroll bar will fit into the area avaialble. + */ + var iOrigWidth = $(n).width(); + n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth ); + } + else if ( oSettings.oScroll.sX !== "" ) + { + /* When x-scrolling both ways, fix the table at it's current size, without adjusting */ + n.style.width = _fnStringToCss( $(n).outerWidth() ); + } + } + + + /** + * Get the widest node + * @param {object} oSettings dataTables settings object + * @param {int} iCol column of interest + * @returns {node} widest table node + * @memberof DataTable#oApi + */ + function _fnGetWidestNode( oSettings, iCol ) + { + var iMaxIndex = _fnGetMaxLenString( oSettings, iCol ); + if ( iMaxIndex < 0 ) + { + return null; + } + + if ( oSettings.aoData[iMaxIndex].nTr === null ) + { + var n = document.createElement('td'); + n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' ); + return n; + } + return _fnGetTdNodes(oSettings, iMaxIndex)[iCol]; + } + + + /** + * Get the maximum strlen for each data column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column of interest + * @returns {string} max string length for each column + * @memberof DataTable#oApi + */ + function _fnGetMaxLenString( oSettings, iCol ) + { + var iMax = -1; + var iMaxIndex = -1; + + for ( var i=0 ; i<oSettings.aoData.length ; i++ ) + { + var s = _fnGetCellData( oSettings, i, iCol, 'display' )+""; + s = s.replace( /<.*?>/g, "" ); + if ( s.length > iMax ) + { + iMax = s.length; + iMaxIndex = i; + } + } + + return iMaxIndex; + } + + + /** + * Append a CSS unit (only if required) to a string + * @param {array} aArray1 first array + * @param {array} aArray2 second array + * @returns {int} 0 if match, 1 if length is different, 2 if no match + * @memberof DataTable#oApi + */ + function _fnStringToCss( s ) + { + if ( s === null ) + { + return "0px"; + } + + if ( typeof s == 'number' ) + { + if ( s < 0 ) + { + return "0px"; + } + return s+"px"; + } + + /* Check if the last character is not 0-9 */ + var c = s.charCodeAt( s.length-1 ); + if (c < 0x30 || c > 0x39) + { + return s; + } + return s+"px"; + } + + + /** + * Get the width of a scroll bar in this browser being used + * @returns {int} width in pixels + * @memberof DataTable#oApi + */ + function _fnScrollBarWidth () + { + var inner = document.createElement('p'); + var style = inner.style; + style.width = "100%"; + style.height = "200px"; + style.padding = "0px"; + + var outer = document.createElement('div'); + style = outer.style; + style.position = "absolute"; + style.top = "0px"; + style.left = "0px"; + style.visibility = "hidden"; + style.width = "200px"; + style.height = "150px"; + style.padding = "0px"; + style.overflow = "hidden"; + outer.appendChild(inner); + + document.body.appendChild(outer); + var w1 = inner.offsetWidth; + outer.style.overflow = 'scroll'; + var w2 = inner.offsetWidth; + if ( w1 == w2 ) + { + w2 = outer.clientWidth; + } + + document.body.removeChild(outer); + return (w1 - w2); + } + + /** + * Change the order of the table + * @param {object} oSettings dataTables settings object + * @param {bool} bApplyClasses optional - should we apply classes or not + * @memberof DataTable#oApi + */ + function _fnSort ( oSettings, bApplyClasses ) + { + var + i, iLen, j, jLen, k, kLen, + sDataType, nTh, + aaSort = [], + aiOrig = [], + oSort = DataTable.ext.oSort, + aoData = oSettings.aoData, + aoColumns = oSettings.aoColumns, + oAria = oSettings.oLanguage.oAria; + + /* No sorting required if server-side or no sorting array */ + if ( !oSettings.oFeatures.bServerSide && + (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) ) + { + aaSort = ( oSettings.aaSortingFixed !== null ) ? + oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : + oSettings.aaSorting.slice(); + + /* If there is a sorting data type, and a function belonging to it, then we need to + * get the data from the developer's function and apply it for this column + */ + for ( i=0 ; i<aaSort.length ; i++ ) + { + var iColumn = aaSort[i][0]; + var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn ); + sDataType = oSettings.aoColumns[ iColumn ].sSortDataType; + if ( DataTable.ext.afnSortData[sDataType] ) + { + var aData = DataTable.ext.afnSortData[sDataType].call( + oSettings.oInstance, oSettings, iColumn, iVisColumn + ); + if ( aData.length === aoData.length ) + { + for ( j=0, jLen=aoData.length ; j<jLen ; j++ ) + { + _fnSetCellData( oSettings, j, iColumn, aData[j] ); + } + } + else + { + _fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" ); + } + } + } + + /* Create a value - key array of the current row positions such that we can use their + * current position during the sort, if values match, in order to perform stable sorting + */ + for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ ) + { + aiOrig[ oSettings.aiDisplayMaster[i] ] = i; + } + + /* Build an internal data array which is specific to the sort, so we can get and prep + * the data to be sorted only once, rather than needing to do it every time the sorting + * function runs. This make the sorting function a very simple comparison + */ + var iSortLen = aaSort.length; + var fnSortFormat, aDataSort; + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + for ( j=0 ; j<iSortLen ; j++ ) + { + aDataSort = aoColumns[ aaSort[j][0] ].aDataSort; + + for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) + { + sDataType = aoColumns[ aDataSort[k] ].sType; + fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ]; + + aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ? + fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) : + _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ); + } + } + } + + /* Do the sort - here we want multi-column sorting based on a given data source (column) + * and sorting function (from oSort) in a certain direction. It's reasonably complex to + * follow on it's own, but this is what we want (example two column sorting): + * fnLocalSorting = function(a,b){ + * var iTest; + * iTest = oSort['string-asc']('data11', 'data12'); + * if (iTest !== 0) + * return iTest; + * iTest = oSort['numeric-desc']('data21', 'data22'); + * if (iTest !== 0) + * return iTest; + * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); + * } + * Basically we have a test for each sorting column, if the data in that column is equal, + * test the next column. If all columns match, then we use a numeric sort on the row + * positions in the original data array to provide a stable sort. + */ + oSettings.aiDisplayMaster.sort( function ( a, b ) { + var k, l, lLen, iTest, aDataSort, sDataType; + for ( k=0 ; k<iSortLen ; k++ ) + { + aDataSort = aoColumns[ aaSort[k][0] ].aDataSort; + + for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ ) + { + sDataType = aoColumns[ aDataSort[l] ].sType; + + iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ]( + aoData[a]._aSortData[ aDataSort[l] ], + aoData[b]._aSortData[ aDataSort[l] ] + ); + + if ( iTest !== 0 ) + { + return iTest; + } + } + } + + return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); + } ); + } + + /* Alter the sorting classes to take account of the changes */ + if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender ) + { + _fnSortingClasses( oSettings ); + } + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" ); + nTh = aoColumns[i].nTh; + nTh.removeAttribute('aria-sort'); + nTh.removeAttribute('aria-label'); + + /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ + if ( aoColumns[i].bSortable ) + { + if ( aaSort.length > 0 && aaSort[0][0] == i ) + { + nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" ); + + var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ? + aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0]; + nTh.setAttribute('aria-label', sTitle+ + (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); + } + else + { + nTh.setAttribute('aria-label', sTitle+ + (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); + } + } + else + { + nTh.setAttribute('aria-label', sTitle); + } + } + + /* Tell the draw function that we have sorted the data */ + oSettings.bSorted = true; + $(oSettings.oInstance).trigger('sort', oSettings); + + /* Copy the master data into the draw array and re-draw */ + if ( oSettings.oFeatures.bFilter ) + { + /* _fnFilter() will redraw the table for us */ + _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + oSettings._iDisplayStart = 0; /* reset display back to page 0 */ + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + + + /** + * Attach a sort handler (click) to a node + * @param {object} oSettings dataTables settings object + * @param {node} nNode node to attach the handler to + * @param {int} iDataIndex column sorting index + * @param {function} [fnCallback] callback function + * @memberof DataTable#oApi + */ + function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback ) + { + _fnBindAction( nNode, {}, function (e) { + /* If the column is not sortable - don't to anything */ + if ( oSettings.aoColumns[iDataIndex].bSortable === false ) + { + return; + } + + /* + * This is a little bit odd I admit... I declare a temporary function inside the scope of + * _fnBuildHead and the click handler in order that the code presented here can be used + * twice - once for when bProcessing is enabled, and another time for when it is + * disabled, as we need to perform slightly different actions. + * Basically the issue here is that the Javascript engine in modern browsers don't + * appear to allow the rendering engine to update the display while it is still executing + * it's thread (well - it does but only after long intervals). This means that the + * 'processing' display doesn't appear for a table sort. To break the js thread up a bit + * I force an execution break by using setTimeout - but this breaks the expected + * thread continuation for the end-developer's point of view (their code would execute + * too early), so we only do it when we absolutely have to. + */ + var fnInnerSorting = function () { + var iColumn, iNextSort; + + /* If the shift key is pressed then we are multiple column sorting */ + if ( e.shiftKey ) + { + /* Are we already doing some kind of sort on this column? */ + var bFound = false; + for ( var i=0 ; i<oSettings.aaSorting.length ; i++ ) + { + if ( oSettings.aaSorting[i][0] == iDataIndex ) + { + bFound = true; + iColumn = oSettings.aaSorting[i][0]; + iNextSort = oSettings.aaSorting[i][2]+1; + + if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) + { + /* Reached the end of the sorting options, remove from multi-col sort */ + oSettings.aaSorting.splice( i, 1 ); + } + else + { + /* Move onto next sorting direction */ + oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; + oSettings.aaSorting[i][2] = iNextSort; + } + break; + } + } + + /* No sort yet - add it in */ + if ( bFound === false ) + { + oSettings.aaSorting.push( [ iDataIndex, + oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); + } + } + else + { + /* If no shift key then single column sort */ + if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex ) + { + iColumn = oSettings.aaSorting[0][0]; + iNextSort = oSettings.aaSorting[0][2]+1; + if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) + { + iNextSort = 0; + } + oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; + oSettings.aaSorting[0][2] = iNextSort; + } + else + { + oSettings.aaSorting.splice( 0, oSettings.aaSorting.length ); + oSettings.aaSorting.push( [ iDataIndex, + oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); + } + } + + /* Run the sort */ + _fnSort( oSettings ); + }; /* /fnInnerSorting */ + + if ( !oSettings.oFeatures.bProcessing ) + { + fnInnerSorting(); + } + else + { + _fnProcessingDisplay( oSettings, true ); + setTimeout( function() { + fnInnerSorting(); + if ( !oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + } + }, 0 ); + } + + /* Call the user specified callback function - used for async user interaction */ + if ( typeof fnCallback == 'function' ) + { + fnCallback( oSettings ); + } + } ); + } + + + /** + * Set the sorting classes on the header, Note: it is safe to call this function + * when bSort and bSortClasses are false + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnSortingClasses( oSettings ) + { + var i, iLen, j, jLen, iFound; + var aaSort, sClass; + var iColumns = oSettings.aoColumns.length; + var oClasses = oSettings.oClasses; + + for ( i=0 ; i<iColumns ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable ) + { + $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc + + " "+ oSettings.aoColumns[i].sSortingClass ); + } + } + + if ( oSettings.aaSortingFixed !== null ) + { + aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting ); + } + else + { + aaSort = oSettings.aaSorting.slice(); + } + + /* Apply the required classes to the header */ + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable ) + { + sClass = oSettings.aoColumns[i].sSortingClass; + iFound = -1; + for ( j=0 ; j<aaSort.length ; j++ ) + { + if ( aaSort[j][0] == i ) + { + sClass = ( aaSort[j][1] == "asc" ) ? + oClasses.sSortAsc : oClasses.sSortDesc; + iFound = j; + break; + } + } + $(oSettings.aoColumns[i].nTh).addClass( sClass ); + + if ( oSettings.bJUI ) + { + /* jQuery UI uses extra markup */ + var jqSpan = $("span."+oClasses.sSortIcon, oSettings.aoColumns[i].nTh); + jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+ + oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed ); + + var sSpanClass; + if ( iFound == -1 ) + { + sSpanClass = oSettings.aoColumns[i].sSortingClassJUI; + } + else if ( aaSort[iFound][1] == "asc" ) + { + sSpanClass = oClasses.sSortJUIAsc; + } + else + { + sSpanClass = oClasses.sSortJUIDesc; + } + + jqSpan.addClass( sSpanClass ); + } + } + else + { + /* No sorting on this column, so add the base class. This will have been assigned by + * _fnAddColumn + */ + $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass ); + } + } + + /* + * Apply the required classes to the table body + * Note that this is given as a feature switch since it can significantly slow down a sort + * on large data sets (adding and removing of classes is always slow at the best of times..) + * Further to this, note that this code is admittedly fairly ugly. It could be made a lot + * simpler using jQuery selectors and add/removeClass, but that is significantly slower + * (on the order of 5 times slower) - hence the direct DOM manipulation here. + * Note that for deferred drawing we do use jQuery - the reason being that taking the first + * row found to see if the whole column needs processed can miss classes since the first + * column might be new. + */ + sClass = oClasses.sSortColumn; + + if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses ) + { + var nTds = _fnGetTdNodes( oSettings ); + + /* Determine what the sorting class for each column should be */ + var iClass, iTargetCol; + var asClasses = []; + for (i = 0; i < iColumns; i++) + { + asClasses.push(""); + } + for (i = 0, iClass = 1; i < aaSort.length; i++) + { + iTargetCol = parseInt( aaSort[i][0], 10 ); + asClasses[iTargetCol] = sClass + iClass; + + if ( iClass < 3 ) + { + iClass++; + } + } + + /* Make changes to the classes for each cell as needed */ + var reClass = new RegExp(sClass + "[123]"); + var sTmpClass, sCurrentClass, sNewClass; + for ( i=0, iLen=nTds.length; i<iLen; i++ ) + { + /* Determine which column we're looking at */ + iTargetCol = i % iColumns; + + /* What is the full list of classes now */ + sCurrentClass = nTds[i].className; + /* What sorting class should be applied? */ + sNewClass = asClasses[iTargetCol]; + /* What would the new full list be if we did a replacement? */ + sTmpClass = sCurrentClass.replace(reClass, sNewClass); + + if ( sTmpClass != sCurrentClass ) + { + /* We changed something */ + nTds[i].className = $.trim( sTmpClass ); + } + else if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 ) + { + /* We need to add a class */ + nTds[i].className = sCurrentClass + " " + sNewClass; + } + } + } + } + + + + /** + * Save the state of a table in a cookie such that the page can be reloaded + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnSaveState ( oSettings ) + { + if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying ) + { + return; + } + + /* Store the interesting variables */ + var i, iLen, bInfinite=oSettings.oScroll.bInfinite; + var oState = { + "iCreate": new Date().getTime(), + "iStart": (bInfinite ? 0 : oSettings._iDisplayStart), + "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd), + "iLength": oSettings._iDisplayLength, + "aaSorting": $.extend( true, [], oSettings.aaSorting ), + "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ), + "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ), + "abVisCols": [] + }; + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oState.abVisCols.push( oSettings.aoColumns[i].bVisible ); + } + + _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] ); + + oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState ); + } + + + /** + * Attempt to load a saved table state from a cookie + * @param {object} oSettings dataTables settings object + * @param {object} oInit DataTables init object so we can override settings + * @memberof DataTable#oApi + */ + function _fnLoadState ( oSettings, oInit ) + { + if ( !oSettings.oFeatures.bStateSave ) + { + return; + } + + var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings ); + if ( !oData ) + { + return; + } + + /* Allow custom and plug-in manipulation functions to alter the saved data set and + * cancelling of loading by returning false + */ + var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] ); + if ( $.inArray( false, abStateLoad ) !== -1 ) + { + return; + } + + /* Store the saved state so it might be accessed at any time */ + oSettings.oLoadedState = $.extend( true, {}, oData ); + + /* Restore key features */ + oSettings._iDisplayStart = oData.iStart; + oSettings.iInitDisplayStart = oData.iStart; + oSettings._iDisplayEnd = oData.iEnd; + oSettings._iDisplayLength = oData.iLength; + oSettings.aaSorting = oData.aaSorting.slice(); + oSettings.saved_aaSorting = oData.aaSorting.slice(); + + /* Search filtering */ + $.extend( oSettings.oPreviousSearch, oData.oSearch ); + $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols ); + + /* Column visibility state + * Pass back visibility settings to the init handler, but to do not here override + * the init object that the user might have passed in + */ + oInit.saved_aoColumns = []; + for ( var i=0 ; i<oData.abVisCols.length ; i++ ) + { + oInit.saved_aoColumns[i] = {}; + oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i]; + } + + _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] ); + } + + + /** + * Create a new cookie with a value to store the state of a table + * @param {string} sName name of the cookie to create + * @param {string} sValue the value the cookie should take + * @param {int} iSecs duration of the cookie + * @param {string} sBaseName sName is made up of the base + file name - this is the base + * @param {function} fnCallback User definable function to modify the cookie + * @memberof DataTable#oApi + */ + function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback ) + { + var date = new Date(); + date.setTime( date.getTime()+(iSecs*1000) ); + + /* + * Shocking but true - it would appear IE has major issues with having the path not having + * a trailing slash on it. We need the cookie to be available based on the path, so we + * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the + * patch to use at least some of the path + */ + var aParts = window.location.pathname.split('/'); + var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase(); + var sFullCookie, oData; + + if ( fnCallback !== null ) + { + oData = (typeof $.parseJSON === 'function') ? + $.parseJSON( sValue ) : eval( '('+sValue+')' ); + sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(), + aParts.join('/')+"/" ); + } + else + { + sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) + + "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/"; + } + + /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies + * belonging to DataTables. + */ + var + aCookies =document.cookie.split(';'), + iNewCookieLen = sFullCookie.split(';')[0].length, + aOldCookies = []; + + if ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */ + { + for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ ) + { + if ( aCookies[i].indexOf( sBaseName ) != -1 ) + { + /* It's a DataTables cookie, so eval it and check the time stamp */ + var aSplitCookie = aCookies[i].split('='); + try { + oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' ); + + if ( oData && oData.iCreate ) + { + aOldCookies.push( { + "name": aSplitCookie[0], + "time": oData.iCreate + } ); + } + } + catch( e ) {} + } + } + + // Make sure we delete the oldest ones first + aOldCookies.sort( function (a, b) { + return b.time - a.time; + } ); + + // Eliminate as many old DataTables cookies as we need to + while ( iNewCookieLen + document.cookie.length + 10 > 4096 ) { + if ( aOldCookies.length === 0 ) { + // Deleted all DT cookies and still not enough space. Can't state save + return; + } + + var old = aOldCookies.pop(); + document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+ + aParts.join('/') + "/"; + } + } + + document.cookie = sFullCookie; + } + + + /** + * Read an old cookie to get a cookie with an old table state + * @param {string} sName name of the cookie to read + * @returns {string} contents of the cookie - or null if no cookie with that name found + * @memberof DataTable#oApi + */ + function _fnReadCookie ( sName ) + { + var + aParts = window.location.pathname.split('/'), + sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=', + sCookieContents = document.cookie.split(';'); + + for( var i=0 ; i<sCookieContents.length ; i++ ) + { + var c = sCookieContents[i]; + + while (c.charAt(0)==' ') + { + c = c.substring(1,c.length); + } + + if (c.indexOf(sNameEQ) === 0) + { + return decodeURIComponent( c.substring(sNameEQ.length,c.length) ); + } + } + return null; + } + + + /** + * Return the settings object for a particular table + * @param {node} nTable table we are using as a dataTable + * @returns {object} Settings object - or null if not found + * @memberof DataTable#oApi + */ + function _fnSettingsFromNode ( nTable ) + { + for ( var i=0 ; i<DataTable.settings.length ; i++ ) + { + if ( DataTable.settings[i].nTable === nTable ) + { + return DataTable.settings[i]; + } + } + + return null; + } + + + /** + * Return an array with the TR nodes for the table + * @param {object} oSettings dataTables settings object + * @returns {array} TR array + * @memberof DataTable#oApi + */ + function _fnGetTrNodes ( oSettings ) + { + var aNodes = []; + var aoData = oSettings.aoData; + for ( var i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + aNodes.push( aoData[i].nTr ); + } + } + return aNodes; + } + + + /** + * Return an flat array with all TD nodes for the table, or row + * @param {object} oSettings dataTables settings object + * @param {int} [iIndividualRow] aoData index to get the nodes for - optional + * if not given then the return array will contain all nodes for the table + * @returns {array} TD array + * @memberof DataTable#oApi + */ + function _fnGetTdNodes ( oSettings, iIndividualRow ) + { + var anReturn = []; + var iCorrector; + var anTds, nTd; + var iRow, iRows=oSettings.aoData.length, + iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows; + + /* Allow the collection to be limited to just one row */ + if ( iIndividualRow !== undefined ) + { + iStart = iIndividualRow; + iEnd = iIndividualRow+1; + } + + for ( iRow=iStart ; iRow<iEnd ; iRow++ ) + { + oData = oSettings.aoData[iRow]; + if ( oData.nTr !== null ) + { + /* get the TD child nodes - taking into account text etc nodes */ + anTds = []; + nTd = oData.nTr.firstChild; + while ( nTd ) + { + sNodeName = nTd.nodeName.toLowerCase(); + if ( sNodeName == 'td' || sNodeName == 'th' ) + { + anTds.push( nTd ); + } + nTd = nTd.nextSibling; + } + + iCorrector = 0; + for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) + { + if ( oSettings.aoColumns[iColumn].bVisible ) + { + anReturn.push( anTds[iColumn-iCorrector] ); + } + else + { + anReturn.push( oData._anHidden[iColumn] ); + iCorrector++; + } + } + } + } + + return anReturn; + } + + + /** + * Log an error message + * @param {object} oSettings dataTables settings object + * @param {int} iLevel log error messages, or display them to the user + * @param {string} sMesg error message + * @memberof DataTable#oApi + */ + function _fnLog( oSettings, iLevel, sMesg ) + { + var sAlert = (oSettings===null) ? + "DataTables warning: "+sMesg : + "DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg; + + if ( iLevel === 0 ) + { + if ( DataTable.ext.sErrMode == 'alert' ) + { + alert( sAlert ); + } + else + { + throw new Error(sAlert); + } + return; + } + else if ( window.console && console.log ) + { + console.log( sAlert ); + } + } + + + /** + * See if a property is defined on one object, if so assign it to the other object + * @param {object} oRet target object + * @param {object} oSrc source object + * @param {string} sName property + * @param {string} [sMappedName] name to map too - optional, sName used if not given + * @memberof DataTable#oApi + */ + function _fnMap( oRet, oSrc, sName, sMappedName ) + { + if ( sMappedName === undefined ) + { + sMappedName = sName; + } + if ( oSrc[sName] !== undefined ) + { + oRet[sMappedName] = oSrc[sName]; + } + } + + + /** + * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow + * copy arrays. The reason we need to do this, is that we don't want to deep copy array + * init values (such as aaSorting) since the dev wouldn't be able to override them, but + * we do want to deep copy arrays. + * @param {object} oOut Object to extend + * @param {object} oExtender Object from which the properties will be applied to oOut + * @returns {object} oOut Reference, just for convenience - oOut === the return. + * @memberof DataTable#oApi + * @todo This doesn't take account of arrays inside the deep copied objects. + */ + function _fnExtend( oOut, oExtender ) + { + var val; + + for ( var prop in oExtender ) + { + if ( oExtender.hasOwnProperty(prop) ) + { + val = oExtender[prop]; + + if ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false ) + { + $.extend( true, oOut[prop], val ); + } + else + { + oOut[prop] = val; + } + } + } + + return oOut; + } + + + /** + * Bind an event handers to allow a click or return key to activate the callback. + * This is good for accessibility since a return on the keyboard will have the + * same effect as a click, if the element has focus. + * @param {element} n Element to bind the action to + * @param {object} oData Data object to pass to the triggered function + * @param {function} fn Callback function for when the event is triggered + * @memberof DataTable#oApi + */ + function _fnBindAction( n, oData, fn ) + { + $(n) + .bind( 'click.DT', oData, function (e) { + n.blur(); // Remove focus outline for mouse users + fn(e); + } ) + .bind( 'keypress.DT', oData, function (e){ + if ( e.which === 13 ) { + fn(e); + } } ) + .bind( 'selectstart.DT', function () { + /* Take the brutal approach to cancelling text selection */ + return false; + } ); + } + + + /** + * Register a callback function. Easily allows a callback function to be added to + * an array store of callback functions that can then all be called together. + * @param {object} oSettings dataTables settings object + * @param {string} sStore Name of the array storage for the callbacks in oSettings + * @param {function} fn Function to be called back + * @param {string} sName Identifying name for the callback (i.e. a label) + * @memberof DataTable#oApi + */ + function _fnCallbackReg( oSettings, sStore, fn, sName ) + { + if ( fn ) + { + oSettings[sStore].push( { + "fn": fn, + "sName": sName + } ); + } + } + + + /** + * Fire callback functions and trigger events. Note that the loop over the callback + * array store is done backwards! Further note that you do not want to fire off triggers + * in time sensitive applications (for example cell creation) as its slow. + * @param {object} oSettings dataTables settings object + * @param {string} sStore Name of the array storage for the callbacks in oSettings + * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger + * is fired + * @param {array} aArgs Array of arguments to pass to the callback function / trigger + * @memberof DataTable#oApi + */ + function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs ) + { + var aoStore = oSettings[sStore]; + var aRet =[]; + + for ( var i=aoStore.length-1 ; i>=0 ; i-- ) + { + aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) ); + } + + if ( sTrigger !== null ) + { + $(oSettings.oInstance).trigger(sTrigger, aArgs); + } + + return aRet; + } + + + /** + * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other + * library, then we use that as it is fast, safe and accurate. If the function isn't + * available then we need to built it ourselves - the inspiration for this function comes + * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is + * not perfect and absolutely should not be used as a replacement to json2.js - but it does + * do what we need, without requiring a dependency for DataTables. + * @param {object} o JSON object to be converted + * @returns {string} JSON string + * @memberof DataTable#oApi + */ + var _fnJsonString = (window.JSON) ? JSON.stringify : function( o ) + { + /* Not an object or array */ + var sType = typeof o; + if (sType !== "object" || o === null) + { + // simple data type + if (sType === "string") + { + o = '"'+o+'"'; + } + return o+""; + } + + /* If object or array, need to recurse over it */ + var + sProp, mValue, + json = [], + bArr = $.isArray(o); + + for (sProp in o) + { + mValue = o[sProp]; + sType = typeof mValue; + + if (sType === "string") + { + mValue = '"'+mValue+'"'; + } + else if (sType === "object" && mValue !== null) + { + mValue = _fnJsonString(mValue); + } + + json.push((bArr ? "" : '"'+sProp+'":') + mValue); + } + + return (bArr ? "[" : "{") + json + (bArr ? "]" : "}"); + }; + + + /** + * From some browsers (specifically IE6/7) we need special handling to work around browser + * bugs - this function is used to detect when these workarounds are needed. + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnBrowserDetect( oSettings ) + { + /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the + * width of the scrollbar, while other browsers ensure the inner element is contained + * without forcing scrolling + */ + var n = $( + '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">'+ + '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">'+ + '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>'+ + '</div>'+ + '</div>')[0]; + + document.body.appendChild( n ); + oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false; + document.body.removeChild( n ); + } + + + /** + * Perform a jQuery selector action on the table's TR elements (from the tbody) and + * return the resulting jQuery object. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter + * criterion ("applied") or all TR elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {object} jQuery object, filtered by the given selector. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Highlight every second row + * oTable.$('tr:odd').css('backgroundColor', 'blue'); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to rows with 'Webkit' in them, add a background colour and then + * // remove the filter, thus highlighting the 'Webkit' rows only. + * oTable.fnFilter('Webkit'); + * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue'); + * oTable.fnFilter(''); + * } ); + */ + this.$ = function ( sSelector, oOpts ) + { + var i, iLen, a = [], tr; + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var aoData = oSettings.aoData; + var aiDisplay = oSettings.aiDisplay; + var aiDisplayMaster = oSettings.aiDisplayMaster; + + if ( !oOpts ) + { + oOpts = {}; + } + + oOpts = $.extend( {}, { + "filter": "none", // applied + "order": "current", // "original" + "page": "all" // current + }, oOpts ); + + // Current page implies that order=current and fitler=applied, since it is fairly + // senseless otherwise + if ( oOpts.page == 'current' ) + { + for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplay[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "current" && oOpts.filter == "none" ) + { + for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplayMaster[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "current" && oOpts.filter == "applied" ) + { + for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplay[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "original" && oOpts.filter == "none" ) + { + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + tr = aoData[ i ].nTr ; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "original" && oOpts.filter == "applied" ) + { + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + tr = aoData[ i ].nTr; + if ( $.inArray( i, aiDisplay ) !== -1 && tr ) + { + a.push( tr ); + } + } + } + else + { + _fnLog( oSettings, 1, "Unknown selection options" ); + } + + /* We need to filter on the TR elements and also 'find' in their descendants + * to make the selector act like it would in a full table - so we need + * to build both results and then combine them together + */ + var jqA = $(a); + var jqTRs = jqA.filter( sSelector ); + var jqDescendants = jqA.find( sSelector ); + + return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) ); + }; + + + /** + * Almost identical to $ in operation, but in this case returns the data for the matched + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes + * rather than any descendants, so the data can be obtained for the row/cell. If matching + * rows are found, the data returned is the original data array/object that was used to + * create the row (or a generated array if from a DOM source). + * + * This method is often useful in-combination with $ where both functions are given the + * same parameters and the array indexes will match identically. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select elements that meet the current filter + * criterion ("applied") or all elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the data in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {array} Data for the matched elements. If any elements, as a result of the + * selector, were not TR, TD or TH elements in the DataTable, they will have a null + * entry in the array. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the data from the first row in the table + * var data = oTable._('tr:first'); + * + * // Do something useful with the data + * alert( "First cell is: "+data[0] ); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to 'Webkit' and get all data for + * oTable.fnFilter('Webkit'); + * var data = oTable._('tr', {"filter": "applied"}); + * + * // Do something with the data + * alert( data.length+" rows matched the filter" ); + * } ); + */ + this._ = function ( sSelector, oOpts ) + { + var aOut = []; + var i, iLen, iIndex; + var aTrs = this.$( sSelector, oOpts ); + + for ( i=0, iLen=aTrs.length ; i<iLen ; i++ ) + { + aOut.push( this.fnGetData(aTrs[i]) ); + } + + return aOut; + }; + + + /** + * Add a single new row or multiple rows of data to the table. Please note + * that this is suitable for client-side processing only - if you are using + * server-side processing (i.e. "bServerSide": true), then to add data, you + * must add it to the data source, i.e. the server-side, through an Ajax call. + * @param {array|object} mData The data to be added to the table. This can be: + * <ul> + * <li>1D array of data - add a single row with the data provided</li> + * <li>2D array of arrays - add multiple rows in a single call</li> + * <li>object - data object when using <i>mData</i></li> + * <li>array of objects - multiple data objects when using <i>mData</i></li> + * </ul> + * @param {bool} [bRedraw=true] redraw the table or not + * @returns {array} An array of integers, representing the list of indexes in + * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to + * the table. + * @dtopt API + * + * @example + * // Global var for counter + * var giCount = 2; + * + * $(document).ready(function() { + * $('#example').dataTable(); + * } ); + * + * function fnClickAddRow() { + * $('#example').dataTable().fnAddData( [ + * giCount+".1", + * giCount+".2", + * giCount+".3", + * giCount+".4" ] + * ); + * + * giCount++; + * } + */ + this.fnAddData = function( mData, bRedraw ) + { + if ( mData.length === 0 ) + { + return []; + } + + var aiReturn = []; + var iTest; + + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + /* Check if we want to add multiple rows or not */ + if ( typeof mData[0] === "object" && mData[0] !== null ) + { + for ( var i=0 ; i<mData.length ; i++ ) + { + iTest = _fnAddData( oSettings, mData[i] ); + if ( iTest == -1 ) + { + return aiReturn; + } + aiReturn.push( iTest ); + } + } + else + { + iTest = _fnAddData( oSettings, mData ); + if ( iTest == -1 ) + { + return aiReturn; + } + aiReturn.push( iTest ); + } + + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + if ( bRedraw === undefined || bRedraw ) + { + _fnReDraw( oSettings ); + } + return aiReturn; + }; + + + /** + * This function will make DataTables recalculate the column sizes, based on the data + * contained in the table and the sizes applied to the columns (in the DOM, CSS or + * through the sWidth parameter). This can be useful when the width of the table's + * parent element changes (for example a window resize). + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * $(window).bind('resize', function () { + * oTable.fnAdjustColumnSizing(); + * } ); + * } ); + */ + this.fnAdjustColumnSizing = function ( bRedraw ) + { + var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]); + _fnAdjustColumnSizing( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + this.fnDraw( false ); + } + else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) + { + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ + this.oApi._fnScrollDraw(oSettings); + } + }; + + + /** + * Quickly and simply clear a table + * @param {bool} [bRedraw=true] redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) + * oTable.fnClearTable(); + * } ); + */ + this.fnClearTable = function( bRedraw ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + _fnClearTable( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + _fnDraw( oSettings ); + } + }; + + + /** + * The exact opposite of 'opening' a row, this function will close any rows which + * are currently 'open'. + * @param {node} nTr the table row to 'close' + * @returns {int} 0 on success, or 1 if failed (can't find the row) + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnClose = function( nTr ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) + { + if ( oSettings.aoOpenRows[i].nParent == nTr ) + { + var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode; + if ( nTrParent ) + { + /* Remove it if it is currently on display */ + nTrParent.removeChild( oSettings.aoOpenRows[i].nTr ); + } + oSettings.aoOpenRows.splice( i, 1 ); + return 0; + } + } + return 1; + }; + + + /** + * Remove a row for the table + * @param {mixed} mTarget The index of the row from aoData to be deleted, or + * the TR element you want to delete + * @param {function|null} [fnCallBack] Callback function + * @param {bool} [bRedraw=true] Redraw the table or not + * @returns {array} The row that was deleted + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately remove the first row + * oTable.fnDeleteRow( 0 ); + * } ); + */ + this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen, iAODataIndex; + + iAODataIndex = (typeof mTarget === 'object') ? + _fnNodeToDataIndex(oSettings, mTarget) : mTarget; + + /* Return the data array from this row */ + var oData = oSettings.aoData.splice( iAODataIndex, 1 ); + + /* Update the _DT_RowIndex parameter */ + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + if ( oSettings.aoData[i].nTr !== null ) + { + oSettings.aoData[i].nTr._DT_RowIndex = i; + } + } + + /* Remove the target row from the search array */ + var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay ); + oSettings.asDataSearch.splice( iDisplayIndex, 1 ); + + /* Delete from the display arrays */ + _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex ); + _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex ); + + /* If there is a user callback function - call it */ + if ( typeof fnCallBack === "function" ) + { + fnCallBack.call( this, oSettings, oData ); + } + + /* Check for an 'overflow' they case for displaying the table */ + if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart -= oSettings._iDisplayLength; + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + + if ( bRedraw === undefined || bRedraw ) + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + return oData; + }; + + + /** + * Restore the table to it's original state in the DOM by removing all of DataTables + * enhancements, alterations to the DOM structure of the table and event listeners. + * @param {boolean} [bRemove=false] Completely remove the table from the DOM + * @dtopt API + * + * @example + * $(document).ready(function() { + * // This example is fairly pointless in reality, but shows how fnDestroy can be used + * var oTable = $('#example').dataTable(); + * oTable.fnDestroy(); + * } ); + */ + this.fnDestroy = function ( bRemove ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var nOrig = oSettings.nTableWrapper.parentNode; + var nBody = oSettings.nTBody; + var i, iLen; + + bRemove = (bRemove===undefined) ? false : bRemove; + + /* Flag to note that the table is currently being destroyed - no action should be taken */ + oSettings.bDestroying = true; + + /* Fire off the destroy callbacks for plug-ins etc */ + _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] ); + + /* If the table is not being removed, restore the hidden columns */ + if ( !bRemove ) + { + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible === false ) + { + this.fnSetColumnVis( i, true ); + } + } + } + + /* Blitz all DT events */ + $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT'); + + /* If there is an 'empty' indicator row, remove it */ + $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove(); + + /* When scrolling we had to break the table up - restore it */ + if ( oSettings.nTable != oSettings.nTHead.parentNode ) + { + $(oSettings.nTable).children('thead').remove(); + oSettings.nTable.appendChild( oSettings.nTHead ); + } + + if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode ) + { + $(oSettings.nTable).children('tfoot').remove(); + oSettings.nTable.appendChild( oSettings.nTFoot ); + } + + /* Remove the DataTables generated nodes, events and classes */ + oSettings.nTable.parentNode.removeChild( oSettings.nTable ); + $(oSettings.nTableWrapper).remove(); + + oSettings.aaSorting = []; + oSettings.aaSortingFixed = []; + _fnSortingClasses( oSettings ); + + $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') ); + + $('th, td', oSettings.nTHead).removeClass( [ + oSettings.oClasses.sSortable, + oSettings.oClasses.sSortableAsc, + oSettings.oClasses.sSortableDesc, + oSettings.oClasses.sSortableNone ].join(' ') + ); + if ( oSettings.bJUI ) + { + $('th span.'+oSettings.oClasses.sSortIcon + + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove(); + + $('th, td', oSettings.nTHead).each( function () { + var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this); + var kids = jqWrapper.contents(); + $(this).append( kids ); + jqWrapper.remove(); + } ); + } + + /* Add the TR elements back into the table in their original order */ + if ( !bRemove && oSettings.nTableReinsertBefore ) + { + nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore ); + } + else if ( !bRemove ) + { + nOrig.appendChild( oSettings.nTable ); + } + + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + if ( oSettings.aoData[i].nTr !== null ) + { + nBody.appendChild( oSettings.aoData[i].nTr ); + } + } + + /* Restore the width of the original table */ + if ( oSettings.oFeatures.bAutoWidth === true ) + { + oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth); + } + + /* If the were originally stripe classes - then we add them back here. Note + * this is not fool proof (for example if not all rows had stripe classes - but + * it's a good effort without getting carried away + */ + iLen = oSettings.asDestroyStripes.length; + if (iLen) + { + var anRows = $(nBody).children('tr'); + for ( i=0 ; i<iLen ; i++ ) + { + anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] ); + } + } + + /* Remove the settings object from the settings array */ + for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) + { + if ( DataTable.settings[i] == oSettings ) + { + DataTable.settings.splice( i, 1 ); + } + } + + /* End it all */ + oSettings = null; + oInit = null; + }; + + + /** + * Redraw the table + * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) + * oTable.fnDraw(); + * } ); + */ + this.fnDraw = function( bComplete ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + if ( bComplete === false ) + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + else + { + _fnReDraw( oSettings ); + } + }; + + + /** + * Filter the input based on data + * @param {string} sInput String to filter the table on + * @param {int|null} [iColumn] Column to limit filtering to + * @param {bool} [bRegex=false] Treat as regular expression or not + * @param {bool} [bSmart=true] Perform smart filtering or not + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sometime later - filter... + * oTable.fnFilter( 'test string' ); + * } ); + */ + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( !oSettings.oFeatures.bFilter ) + { + return; + } + + if ( bRegex === undefined || bRegex === null ) + { + bRegex = false; + } + + if ( bSmart === undefined || bSmart === null ) + { + bSmart = true; + } + + if ( bShowGlobal === undefined || bShowGlobal === null ) + { + bShowGlobal = true; + } + + if ( bCaseInsensitive === undefined || bCaseInsensitive === null ) + { + bCaseInsensitive = true; + } + + if ( iColumn === undefined || iColumn === null ) + { + /* Global filter */ + _fnFilterComplete( oSettings, { + "sSearch":sInput+"", + "bRegex": bRegex, + "bSmart": bSmart, + "bCaseInsensitive": bCaseInsensitive + }, 1 ); + + if ( bShowGlobal && oSettings.aanFeatures.f ) + { + var n = oSettings.aanFeatures.f; + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + // IE9 throws an 'unknown error' if document.activeElement is used + // inside an iframe or frame... + try { + if ( n[i]._DT_Input != document.activeElement ) + { + $(n[i]._DT_Input).val( sInput ); + } + } + catch ( e ) { + $(n[i]._DT_Input).val( sInput ); + } + } + } + } + else + { + /* Single column filter */ + $.extend( oSettings.aoPreSearchCols[ iColumn ], { + "sSearch": sInput+"", + "bRegex": bRegex, + "bSmart": bSmart, + "bCaseInsensitive": bCaseInsensitive + } ); + _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); + } + }; + + + /** + * Get the data for the whole table, an individual row or an individual cell based on the + * provided parameters. + * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as + * a TR node then the data source for the whole row will be returned. If given as a + * TD/TH cell node then iCol will be automatically calculated and the data for the + * cell returned. If given as an integer, then this is treated as the aoData internal + * data index for the row (see fnGetPosition) and the data for that row used. + * @param {int} [iCol] Optional column index that you want the data of. + * @returns {array|object|string} If mRow is undefined, then the data for all rows is + * returned. If mRow is defined, just data for that row, and is iCol is + * defined, only data for the designated cell is returned. + * @dtopt API + * + * @example + * // Row data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('tr').click( function () { + * var data = oTable.fnGetData( this ); + * // ... do something with the array / object of data for the row + * } ); + * } ); + * + * @example + * // Individual cell data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('td').click( function () { + * var sData = oTable.fnGetData( this ); + * alert( 'The cell clicked on had the value of '+sData ); + * } ); + * } ); + */ + this.fnGetData = function( mRow, iCol ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( mRow !== undefined ) + { + var iRow = mRow; + if ( typeof mRow === 'object' ) + { + var sNode = mRow.nodeName.toLowerCase(); + if (sNode === "tr" ) + { + iRow = _fnNodeToDataIndex(oSettings, mRow); + } + else if ( sNode === "td" ) + { + iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode); + iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow ); + } + } + + if ( iCol !== undefined ) + { + return _fnGetCellData( oSettings, iRow, iCol, '' ); + } + return (oSettings.aoData[iRow]!==undefined) ? + oSettings.aoData[iRow]._aData : null; + } + return _fnGetDataMaster( oSettings ); + }; + + + /** + * Get an array of the TR nodes that are used in the table's body. Note that you will + * typically want to use the '$' API method in preference to this as it is more + * flexible. + * @param {int} [iRow] Optional row index for the TR element you want + * @returns {array|node} If iRow is undefined, returns an array of all TR elements + * in the table's body, or iRow is defined, just the TR element requested. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the nodes from the table + * var nNodes = oTable.fnGetNodes( ); + * } ); + */ + this.fnGetNodes = function( iRow ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( iRow !== undefined ) { + return (oSettings.aoData[iRow]!==undefined) ? + oSettings.aoData[iRow].nTr : null; + } + return _fnGetTrNodes( oSettings ); + }; + + + /** + * Get the array indexes of a particular cell from it's DOM element + * and column index including hidden columns + * @param {node} nNode this can either be a TR, TD or TH in the table's body + * @returns {int} If nNode is given as a TR, then a single index is returned, or + * if given as a cell, an array of [row index, column index (visible), + * column index (all)] is given. + * @dtopt API + * + * @example + * $(document).ready(function() { + * $('#example tbody td').click( function () { + * // Get the position of the current data from the node + * var aPos = oTable.fnGetPosition( this ); + * + * // Get the data array for this row + * var aData = oTable.fnGetData( aPos[0] ); + * + * // Update the data array and return the value + * aData[ aPos[1] ] = 'clicked'; + * this.innerHTML = 'clicked'; + * } ); + * + * // Init DataTables + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnGetPosition = function( nNode ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var sNodeName = nNode.nodeName.toUpperCase(); + + if ( sNodeName == "TR" ) + { + return _fnNodeToDataIndex(oSettings, nNode); + } + else if ( sNodeName == "TD" || sNodeName == "TH" ) + { + var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode ); + var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode ); + return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ]; + } + return null; + }; + + + /** + * Check to see if a row is 'open' or not. + * @param {node} nTr the table row to check + * @returns {boolean} true if the row is currently open, false otherwise + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnIsOpen = function( nTr ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var aoOpenRows = oSettings.aoOpenRows; + + for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) + { + if ( oSettings.aoOpenRows[i].nParent == nTr ) + { + return true; + } + } + return false; + }; + + + /** + * This function will place a new row directly after a row which is currently + * on display on the page, with the HTML contents that is passed into the + * function. This can be used, for example, to ask for confirmation that a + * particular record should be deleted. + * @param {node} nTr The table row to 'open' + * @param {string|node|jQuery} mHtml The HTML to put into the row + * @param {string} sClass Class to give the new TD cell + * @returns {node} The row opened. Note that if the table row passed in as the + * first parameter, is not found in the table, this method will silently + * return. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnOpen = function( nTr, mHtml, sClass ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + /* Check that the row given is in the table */ + var nTableRows = _fnGetTrNodes( oSettings ); + if ( $.inArray(nTr, nTableRows) === -1 ) + { + return; + } + + /* the old open one if there is one */ + this.fnClose( nTr ); + + var nNewRow = document.createElement("tr"); + var nNewCell = document.createElement("td"); + nNewRow.appendChild( nNewCell ); + nNewCell.className = sClass; + nNewCell.colSpan = _fnVisbleColumns( oSettings ); + + if (typeof mHtml === "string") + { + nNewCell.innerHTML = mHtml; + } + else + { + $(nNewCell).html( mHtml ); + } + + /* If the nTr isn't on the page at the moment - then we don't insert at the moment */ + var nTrs = $('tr', oSettings.nTBody); + if ( $.inArray(nTr, nTrs) != -1 ) + { + $(nNewRow).insertAfter(nTr); + } + + oSettings.aoOpenRows.push( { + "nTr": nNewRow, + "nParent": nTr + } ); + + return nNewRow; + }; + + + /** + * Change the pagination - provides the internal logic for pagination in a simple API + * function. With this function you can have a DataTables table go to the next, + * previous, first or last pages. + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer), note that page 0 is the first page. + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnPageChange( 'next' ); + * } ); + */ + this.fnPageChange = function ( mAction, bRedraw ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + _fnPageChange( oSettings, mAction ); + _fnCalculateEnd( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + _fnDraw( oSettings ); + } + }; + + + /** + * Show a particular column + * @param {int} iCol The column whose display should be changed + * @param {bool} bShow Show (true) or hide (false) the column + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Hide the second column after initialisation + * oTable.fnSetColumnVis( 1, false ); + * } ); + */ + this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen; + var aoColumns = oSettings.aoColumns; + var aoData = oSettings.aoData; + var nTd, bAppend, iBefore; + + /* No point in doing anything if we are requesting what is already true */ + if ( aoColumns[iCol].bVisible == bShow ) + { + return; + } + + /* Show the column */ + if ( bShow ) + { + var iInsert = 0; + for ( i=0 ; i<iCol ; i++ ) + { + if ( aoColumns[i].bVisible ) + { + iInsert++; + } + } + + /* Need to decide if we should use appendChild or insertBefore */ + bAppend = (iInsert >= _fnVisbleColumns( oSettings )); + + /* Which coloumn should we be inserting before? */ + if ( !bAppend ) + { + for ( i=iCol ; i<aoColumns.length ; i++ ) + { + if ( aoColumns[i].bVisible ) + { + iBefore = i; + break; + } + } + } + + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + if ( bAppend ) + { + aoData[i].nTr.appendChild( + aoData[i]._anHidden[iCol] + ); + } + else + { + aoData[i].nTr.insertBefore( + aoData[i]._anHidden[iCol], + _fnGetTdNodes( oSettings, i )[iBefore] ); + } + } + } + } + else + { + /* Remove a column from display */ + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + nTd = _fnGetTdNodes( oSettings, i )[iCol]; + aoData[i]._anHidden[iCol] = nTd; + nTd.parentNode.removeChild( nTd ); + } + } + } + + /* Clear to set the visible flag */ + aoColumns[iCol].bVisible = bShow; + + /* Redraw the header and footer based on the new column visibility */ + _fnDrawHead( oSettings, oSettings.aoHeader ); + if ( oSettings.nTFoot ) + { + _fnDrawHead( oSettings, oSettings.aoFooter ); + } + + /* If there are any 'open' rows, then we need to alter the colspan for this col change */ + for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ ) + { + oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings ); + } + + /* Do a redraw incase anything depending on the table columns needs it + * (built-in: scrolling) + */ + if ( bRedraw === undefined || bRedraw ) + { + _fnAdjustColumnSizing( oSettings ); + _fnDraw( oSettings ); + } + + _fnSaveState( oSettings ); + }; + + + /** + * Get the settings for a particular table for external manipulation + * @returns {object} DataTables settings object. See + * {@link DataTable.models.oSettings} + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * var oSettings = oTable.fnSettings(); + * + * // Show an example parameter from the settings + * alert( oSettings._iDisplayStart ); + * } ); + */ + this.fnSettings = function() + { + return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + }; + + + /** + * Sort the table by a particular column + * @param {int} iCol the data index to sort on. Note that this will not match the + * 'display index' if you have hidden data entries + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort immediately with columns 0 and 1 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); + * } ); + */ + this.fnSort = function( aaSort ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + oSettings.aaSorting = aaSort; + _fnSort( oSettings ); + }; + + + /** + * Attach a sort listener to an element for a given column + * @param {node} nNode the element to attach the sort listener to + * @param {int} iColumn the column that a click on this node will sort on + * @param {function} [fnCallback] callback function when sort is run + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort on column 1, when 'sorter' is clicked on + * oTable.fnSortListener( document.getElementById('sorter'), 1 ); + * } ); + */ + this.fnSortListener = function( nNode, iColumn, fnCallback ) + { + _fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn, + fnCallback ); + }; + + + /** + * Update a table cell or row - this method will accept either a single value to + * update the cell with, an array of values with one element for each column or + * an object in the same format as the original data source. The function is + * self-referencing in order to make the multi column updates easier. + * @param {object|array|string} mData Data to update the cell/row with + * @param {node|int} mRow TR element you want to update or the aoData index + * @param {int} [iColumn] The column to update (not used of mData is an array or object) + * @param {bool} [bRedraw=true] Redraw the table or not + * @param {bool} [bAction=true] Perform pre-draw actions or not + * @returns {int} 0 on success, 1 on error + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row + * } ); + */ + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen, sDisplay; + var iRow = (typeof mRow === 'object') ? + _fnNodeToDataIndex(oSettings, mRow) : mRow; + + if ( $.isArray(mData) && iColumn === undefined ) + { + /* Array update - update the whole row */ + oSettings.aoData[iRow]._aData = mData.slice(); + + /* Flag to the function that we are recursing */ + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); + } + } + else if ( $.isPlainObject(mData) && iColumn === undefined ) + { + /* Object update - update the whole row - assume the developer gets the object right */ + oSettings.aoData[iRow]._aData = $.extend( true, {}, mData ); + + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); + } + } + else + { + /* Individual cell update */ + _fnSetCellData( oSettings, iRow, iColumn, mData ); + sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + + var oCol = oSettings.aoColumns[iColumn]; + if ( oCol.fnRender !== null ) + { + sDisplay = _fnRender( oSettings, iRow, iColumn ); + if ( oCol.bUseRendered ) + { + _fnSetCellData( oSettings, iRow, iColumn, sDisplay ); + } + } + + if ( oSettings.aoData[iRow].nTr !== null ) + { + /* Do the actual HTML update */ + _fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay; + } + } + + /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw + * will rebuild the search array - however, the redraw might be disabled by the user) + */ + var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay ); + oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( + oSettings, + _fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) ) + ); + + /* Perform pre-draw actions */ + if ( bAction === undefined || bAction ) + { + _fnAdjustColumnSizing( oSettings ); + } + + /* Redraw the table */ + if ( bRedraw === undefined || bRedraw ) + { + _fnReDraw( oSettings ); + } + return 0; + }; + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @method + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + this.fnVersionCheck = DataTable.ext.fnVersionCheck; + + + /* + * This is really a good bit rubbish this method of exposing the internal methods + * publicly... - To be fixed in 2.0 using methods on the prototype + */ + + + /** + * Create a wrapper function for exporting an internal functions to an external API. + * @param {string} sFunc API function name + * @returns {function} wrapped function + * @memberof DataTable#oApi + */ + function _fnExternApiFunc (sFunc) + { + return function() { + var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat( + Array.prototype.slice.call(arguments) ); + return DataTable.ext.oApi[sFunc].apply( this, aArgs ); + }; + } + + + /** + * Reference to internal functions for use by plug-in developers. Note that these + * methods are references to internal functions and are considered to be private. + * If you use these methods, be aware that they are liable to change between versions + * (check the upgrade notes). + * @namespace + */ + this.oApi = { + "_fnExternApiFunc": _fnExternApiFunc, + "_fnInitialise": _fnInitialise, + "_fnInitComplete": _fnInitComplete, + "_fnLanguageCompat": _fnLanguageCompat, + "_fnAddColumn": _fnAddColumn, + "_fnColumnOptions": _fnColumnOptions, + "_fnAddData": _fnAddData, + "_fnCreateTr": _fnCreateTr, + "_fnGatherData": _fnGatherData, + "_fnBuildHead": _fnBuildHead, + "_fnDrawHead": _fnDrawHead, + "_fnDraw": _fnDraw, + "_fnReDraw": _fnReDraw, + "_fnAjaxUpdate": _fnAjaxUpdate, + "_fnAjaxParameters": _fnAjaxParameters, + "_fnAjaxUpdateDraw": _fnAjaxUpdateDraw, + "_fnServerParams": _fnServerParams, + "_fnAddOptionsHtml": _fnAddOptionsHtml, + "_fnFeatureHtmlTable": _fnFeatureHtmlTable, + "_fnScrollDraw": _fnScrollDraw, + "_fnAdjustColumnSizing": _fnAdjustColumnSizing, + "_fnFeatureHtmlFilter": _fnFeatureHtmlFilter, + "_fnFilterComplete": _fnFilterComplete, + "_fnFilterCustom": _fnFilterCustom, + "_fnFilterColumn": _fnFilterColumn, + "_fnFilter": _fnFilter, + "_fnBuildSearchArray": _fnBuildSearchArray, + "_fnBuildSearchRow": _fnBuildSearchRow, + "_fnFilterCreateSearch": _fnFilterCreateSearch, + "_fnDataToSearch": _fnDataToSearch, + "_fnSort": _fnSort, + "_fnSortAttachListener": _fnSortAttachListener, + "_fnSortingClasses": _fnSortingClasses, + "_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate, + "_fnPageChange": _fnPageChange, + "_fnFeatureHtmlInfo": _fnFeatureHtmlInfo, + "_fnUpdateInfo": _fnUpdateInfo, + "_fnFeatureHtmlLength": _fnFeatureHtmlLength, + "_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing, + "_fnProcessingDisplay": _fnProcessingDisplay, + "_fnVisibleToColumnIndex": _fnVisibleToColumnIndex, + "_fnColumnIndexToVisible": _fnColumnIndexToVisible, + "_fnNodeToDataIndex": _fnNodeToDataIndex, + "_fnVisbleColumns": _fnVisbleColumns, + "_fnCalculateEnd": _fnCalculateEnd, + "_fnConvertToWidth": _fnConvertToWidth, + "_fnCalculateColumnWidths": _fnCalculateColumnWidths, + "_fnScrollingWidthAdjust": _fnScrollingWidthAdjust, + "_fnGetWidestNode": _fnGetWidestNode, + "_fnGetMaxLenString": _fnGetMaxLenString, + "_fnStringToCss": _fnStringToCss, + "_fnDetectType": _fnDetectType, + "_fnSettingsFromNode": _fnSettingsFromNode, + "_fnGetDataMaster": _fnGetDataMaster, + "_fnGetTrNodes": _fnGetTrNodes, + "_fnGetTdNodes": _fnGetTdNodes, + "_fnEscapeRegex": _fnEscapeRegex, + "_fnDeleteIndex": _fnDeleteIndex, + "_fnReOrderIndex": _fnReOrderIndex, + "_fnColumnOrdering": _fnColumnOrdering, + "_fnLog": _fnLog, + "_fnClearTable": _fnClearTable, + "_fnSaveState": _fnSaveState, + "_fnLoadState": _fnLoadState, + "_fnCreateCookie": _fnCreateCookie, + "_fnReadCookie": _fnReadCookie, + "_fnDetectHeader": _fnDetectHeader, + "_fnGetUniqueThs": _fnGetUniqueThs, + "_fnScrollBarWidth": _fnScrollBarWidth, + "_fnApplyToChildren": _fnApplyToChildren, + "_fnMap": _fnMap, + "_fnGetRowData": _fnGetRowData, + "_fnGetCellData": _fnGetCellData, + "_fnSetCellData": _fnSetCellData, + "_fnGetObjectDataFn": _fnGetObjectDataFn, + "_fnSetObjectDataFn": _fnSetObjectDataFn, + "_fnApplyColumnDefs": _fnApplyColumnDefs, + "_fnBindAction": _fnBindAction, + "_fnExtend": _fnExtend, + "_fnCallbackReg": _fnCallbackReg, + "_fnCallbackFire": _fnCallbackFire, + "_fnJsonString": _fnJsonString, + "_fnRender": _fnRender, + "_fnNodeToColumnIndex": _fnNodeToColumnIndex, + "_fnInfoMacros": _fnInfoMacros, + "_fnBrowserDetect": _fnBrowserDetect, + "_fnGetColumns": _fnGetColumns + }; + + $.extend( DataTable.ext.oApi, this.oApi ); + + for ( var sFunc in DataTable.ext.oApi ) + { + if ( sFunc ) + { + this[sFunc] = _fnExternApiFunc(sFunc); + } + } + + + var _that = this; + this.each(function() { + var i=0, iLen, j, jLen, k, kLen; + var sId = this.getAttribute( 'id' ); + var bInitHandedOff = false; + var bUsePassedData = false; + + + /* Sanity check */ + if ( this.nodeName.toLowerCase() != 'table' ) + { + _fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+ + "table: "+this.nodeName ); + return; + } + + /* Check to see if we are re-initialising a table */ + for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) + { + /* Base check on table node */ + if ( DataTable.settings[i].nTable == this ) + { + if ( oInit === undefined || oInit.bRetrieve ) + { + return DataTable.settings[i].oInstance; + } + else if ( oInit.bDestroy ) + { + DataTable.settings[i].oInstance.fnDestroy(); + break; + } + else + { + _fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+ + "To retrieve the DataTables object for this table, pass no arguments or see "+ + "the docs for bRetrieve and bDestroy" ); + return; + } + } + + /* If the element we are initialising has the same ID as a table which was previously + * initialised, but the table nodes don't match (from before) then we destroy the old + * instance by simply deleting it. This is under the assumption that the table has been + * destroyed by other methods. Anyone using non-id selectors will need to do this manually + */ + if ( DataTable.settings[i].sTableId == this.id ) + { + DataTable.settings.splice( i, 1 ); + break; + } + } + + /* Ensure the table has an ID - required for accessibility */ + if ( sId === null || sId === "" ) + { + sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++); + this.id = sId; + } + + /* Create the settings object for this table and set some of the default parameters */ + var oSettings = $.extend( true, {}, DataTable.models.oSettings, { + "nTable": this, + "oApi": _that.oApi, + "oInit": oInit, + "sDestroyWidth": $(this).width(), + "sInstance": sId, + "sTableId": sId + } ); + DataTable.settings.push( oSettings ); + + // Need to add the instance after the instance after the settings object has been added + // to the settings array, so we can self reference the table instance if more than one + oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable(); + + /* Setting up the initialisation object */ + if ( !oInit ) + { + oInit = {}; + } + + // Backwards compatibility, before we apply all the defaults + if ( oInit.oLanguage ) + { + _fnLanguageCompat( oInit.oLanguage ); + } + + oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit ); + + // Map the initialisation options onto the settings object + _fnMap( oSettings.oFeatures, oInit, "bPaginate" ); + _fnMap( oSettings.oFeatures, oInit, "bLengthChange" ); + _fnMap( oSettings.oFeatures, oInit, "bFilter" ); + _fnMap( oSettings.oFeatures, oInit, "bSort" ); + _fnMap( oSettings.oFeatures, oInit, "bInfo" ); + _fnMap( oSettings.oFeatures, oInit, "bProcessing" ); + _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" ); + _fnMap( oSettings.oFeatures, oInit, "bSortClasses" ); + _fnMap( oSettings.oFeatures, oInit, "bServerSide" ); + _fnMap( oSettings.oFeatures, oInit, "bDeferRender" ); + _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" ); + _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" ); + _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" ); + _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" ); + _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" ); + _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" ); + _fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" ); + _fnMap( oSettings, oInit, "asStripeClasses" ); + _fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy + _fnMap( oSettings, oInit, "fnServerData" ); + _fnMap( oSettings, oInit, "fnFormatNumber" ); + _fnMap( oSettings, oInit, "sServerMethod" ); + _fnMap( oSettings, oInit, "aaSorting" ); + _fnMap( oSettings, oInit, "aaSortingFixed" ); + _fnMap( oSettings, oInit, "aLengthMenu" ); + _fnMap( oSettings, oInit, "sPaginationType" ); + _fnMap( oSettings, oInit, "sAjaxSource" ); + _fnMap( oSettings, oInit, "sAjaxDataProp" ); + _fnMap( oSettings, oInit, "iCookieDuration" ); + _fnMap( oSettings, oInit, "sCookiePrefix" ); + _fnMap( oSettings, oInit, "sDom" ); + _fnMap( oSettings, oInit, "bSortCellsTop" ); + _fnMap( oSettings, oInit, "iTabIndex" ); + _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" ); + _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" ); + _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" ); + _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" ); + _fnMap( oSettings, oInit, "fnCookieCallback" ); + _fnMap( oSettings, oInit, "fnStateLoad" ); + _fnMap( oSettings, oInit, "fnStateSave" ); + _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); + + /* Callback functions which are array driven */ + _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); + _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); + _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); + + if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort && + oSettings.oFeatures.bSortClasses ) + { + /* Enable sort classes for server-side processing. Safe to do it here, since server-side + * processing must be enabled by the developer + */ + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' ); + } + else if ( oSettings.oFeatures.bDeferRender ) + { + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' ); + } + + if ( oInit.bJQueryUI ) + { + /* Use the JUI classes object for display. You could clone the oStdClasses object if + * you want to have multiple tables with multiple independent classes + */ + $.extend( oSettings.oClasses, DataTable.ext.oJUIClasses ); + + if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" ) + { + /* Set the DOM to use a layout suitable for jQuery UI's theming */ + oSettings.sDom = '<"H"lfr>t<"F"ip>'; + } + } + else + { + $.extend( oSettings.oClasses, DataTable.ext.oStdClasses ); + } + $(this).addClass( oSettings.oClasses.sTable ); + + /* Calculate the scroll bar width and cache it for use later on */ + if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) + { + oSettings.oScroll.iBarWidth = _fnScrollBarWidth(); + } + + if ( oSettings.iInitDisplayStart === undefined ) + { + /* Display start point, taking into account the save saving */ + oSettings.iInitDisplayStart = oInit.iDisplayStart; + oSettings._iDisplayStart = oInit.iDisplayStart; + } + + /* Must be done after everything which can be overridden by a cookie! */ + if ( oInit.bStateSave ) + { + oSettings.oFeatures.bStateSave = true; + _fnLoadState( oSettings, oInit ); + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); + } + + if ( oInit.iDeferLoading !== null ) + { + oSettings.bDeferLoading = true; + var tmp = $.isArray( oInit.iDeferLoading ); + oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; + oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; + } + + if ( oInit.aaData !== null ) + { + bUsePassedData = true; + } + + /* Language definitions */ + if ( oInit.oLanguage.sUrl !== "" ) + { + /* Get the language definitions from a file - because this Ajax call makes the language + * get async to the remainder of this function we use bInitHandedOff to indicate that + * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor + */ + oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl; + $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) { + _fnLanguageCompat( json ); + $.extend( true, oSettings.oLanguage, oInit.oLanguage, json ); + _fnInitialise( oSettings ); + } ); + bInitHandedOff = true; + } + else + { + $.extend( true, oSettings.oLanguage, oInit.oLanguage ); + } + + + /* + * Stripes + */ + if ( oInit.asStripeClasses === null ) + { + oSettings.asStripeClasses =[ + oSettings.oClasses.sStripeOdd, + oSettings.oClasses.sStripeEven + ]; + } + + /* Remove row stripe classes if they are already on the table row */ + iLen=oSettings.asStripeClasses.length; + oSettings.asDestroyStripes = []; + if (iLen) + { + var bStripeRemove = false; + var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')'); + for ( i=0 ; i<iLen ; i++ ) + { + if ( anRows.hasClass( oSettings.asStripeClasses[i] ) ) + { + bStripeRemove = true; + + /* Store the classes which we are about to remove so they can be re-added on destroy */ + oSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] ); + } + } + + if ( bStripeRemove ) + { + anRows.removeClass( oSettings.asStripeClasses.join(' ') ); + } + } + + /* + * Columns + * See if we should load columns automatically or use defined ones + */ + var anThs = []; + var aoColumnsInit; + var nThead = this.getElementsByTagName('thead'); + if ( nThead.length !== 0 ) + { + _fnDetectHeader( oSettings.aoHeader, nThead[0] ); + anThs = _fnGetUniqueThs( oSettings ); + } + + /* If not given a column array, generate one with nulls */ + if ( oInit.aoColumns === null ) + { + aoColumnsInit = []; + for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) + { + aoColumnsInit.push( null ); + } + } + else + { + aoColumnsInit = oInit.aoColumns; + } + + /* Add the columns */ + for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) + { + /* Short cut - use the loop to check if we have column visibility state to restore */ + if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen ) + { + if ( aoColumnsInit[i] === null ) + { + aoColumnsInit[i] = {}; + } + aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible; + } + + _fnAddColumn( oSettings, anThs ? anThs[i] : null ); + } + + /* Apply the column definitions */ + _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { + _fnColumnOptions( oSettings, iCol, oDef ); + } ); + + + /* + * Sorting + * Check the aaSorting array + */ + for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ ) + { + if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length ) + { + oSettings.aaSorting[i][0] = 0; + } + var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ]; + + /* Add a default sorting index */ + if ( oSettings.aaSorting[i][2] === undefined ) + { + oSettings.aaSorting[i][2] = 0; + } + + /* If aaSorting is not defined, then we use the first indicator in asSorting */ + if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined ) + { + oSettings.aaSorting[i][1] = oColumn.asSorting[0]; + } + + /* Set the current sorting index based on aoColumns.asSorting */ + for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ ) + { + if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] ) + { + oSettings.aaSorting[i][2] = j; + break; + } + } + } + + /* Do a first pass on the sorting classes (allows any size changes to be taken into + * account, and also will apply sorting disabled classes if disabled + */ + _fnSortingClasses( oSettings ); + + + /* + * Final init + * Cache the header, body and footer as required, creating them if needed + */ + + /* Browser support detection */ + _fnBrowserDetect( oSettings ); + + // Work around for Webkit bug 83867 - store the caption-side before removing from doc + var captions = $(this).children('caption').each( function () { + this._captionSide = $(this).css('caption-side'); + } ); + + var thead = $(this).children('thead'); + if ( thead.length === 0 ) + { + thead = [ document.createElement( 'thead' ) ]; + this.appendChild( thead[0] ); + } + oSettings.nTHead = thead[0]; + + var tbody = $(this).children('tbody'); + if ( tbody.length === 0 ) + { + tbody = [ document.createElement( 'tbody' ) ]; + this.appendChild( tbody[0] ); + } + oSettings.nTBody = tbody[0]; + oSettings.nTBody.setAttribute( "role", "alert" ); + oSettings.nTBody.setAttribute( "aria-live", "polite" ); + oSettings.nTBody.setAttribute( "aria-relevant", "all" ); + + var tfoot = $(this).children('tfoot'); + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) + { + // If we are a scrolling table, and no footer has been given, then we need to create + // a tfoot element for the caption element to be appended to + tfoot = [ document.createElement( 'tfoot' ) ]; + this.appendChild( tfoot[0] ); + } + + if ( tfoot.length > 0 ) + { + oSettings.nTFoot = tfoot[0]; + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); + } + + /* Check if there is data passing into the constructor */ + if ( bUsePassedData ) + { + for ( i=0 ; i<oInit.aaData.length ; i++ ) + { + _fnAddData( oSettings, oInit.aaData[ i ] ); + } + } + else + { + /* Grab the data from the page */ + _fnGatherData( oSettings ); + } + + /* Copy the data index array */ + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + /* Initialisation complete - table can be drawn */ + oSettings.bInitialised = true; + + /* Check if we need to initialise the table (it might not have been handed off to the + * language processor) + */ + if ( bInitHandedOff === false ) + { + _fnInitialise( oSettings ); + } + } ); + _that = null; + return this; + }; + + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @static + * @dtopt API-Static + * + * @example + * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) ); + */ + DataTable.fnVersionCheck = function( sVersion ) + { + /* This is cheap, but effective */ + var fnZPad = function (Zpad, count) + { + while(Zpad.length < count) { + Zpad += '0'; + } + return Zpad; + }; + var aThis = DataTable.ext.sVersion.split('.'); + var aThat = sVersion.split('.'); + var sThis = '', sThat = ''; + + for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) + { + sThis += fnZPad( aThis[i], 3 ); + sThat += fnZPad( aThat[i], 3 ); + } + + return parseInt(sThis, 10) >= parseInt(sThat, 10); + }; + + + /** + * Check if a TABLE node is a DataTable table already or not. + * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other + * node types can be passed in, but will always return false). + * @returns {boolean} true the table given is a DataTable, or false otherwise + * @static + * @dtopt API-Static + * + * @example + * var ex = document.getElementById('example'); + * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) { + * $(ex).dataTable(); + * } + */ + DataTable.fnIsDataTable = function ( nTable ) + { + var o = DataTable.settings; + + for ( var i=0 ; i<o.length ; i++ ) + { + if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable ) + { + return true; + } + } + + return false; + }; + + + /** + * Get all DataTable tables that have been initialised - optionally you can select to + * get only currently visible tables. + * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or + * visible tables only. + * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables + * @static + * @dtopt API-Static + * + * @example + * var table = $.fn.dataTable.fnTables(true); + * if ( table.length > 0 ) { + * $(table).dataTable().fnAdjustColumnSizing(); + * } + */ + DataTable.fnTables = function ( bVisible ) + { + var out = []; + + jQuery.each( DataTable.settings, function (i, o) { + if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) ) + { + out.push( o.nTable ); + } + } ); + + return out; + }; + + + /** + * Version string for plug-ins to check compatibility. Allowed format is + * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and + * e are optional + * @member + * @type string + * @default Version number + */ + DataTable.version = "1.9.4"; + + /** + * Private data store, containing all of the settings objects that are created for the + * tables on a given page. + * + * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i> + * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>. + * @member + * @type array + * @default [] + * @private + */ + DataTable.settings = []; + + /** + * Object models container, for the various models that DataTables has available + * to it. These models define the objects that are used to hold the active state + * and configuration of the table. + * @namespace + */ + DataTable.models = {}; + + + /** + * DataTables extension options and plug-ins. This namespace acts as a collection "area" + * for plug-ins that can be used to extend the default DataTables behaviour - indeed many + * of the build in methods use this method to provide their own capabilities (sorting methods + * for example). + * + * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed + * and modified by plug-ins. + * @namespace + */ + DataTable.models.ext = { + /** + * Plug-in filtering functions - this method of filtering is complimentary to the default + * type based filtering, and a lot more comprehensive as it allows you complete control + * over the filtering logic. Each element in this array is a function (parameters + * described below) that is called for every row in the table, and your logic decides if + * it should be included in the filtered data set or not. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{array|object} Data for the row to be processed (same as the original format + * that was passed in as the data source, or an array from a DOM data source</li> + * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can + * be useful to retrieve the TR element if you need DOM interaction.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li> + * </ul> + * </il> + * </ul> + * @type array + * @default [] + * + * @example + * // The following example shows custom filtering being applied to the fourth column (i.e. + * // the aData[3] index) based on two input values from the end-user, matching the data in + * // a certain range. + * $.fn.dataTableExt.afnFiltering.push( + * function( oSettings, aData, iDataIndex ) { + * var iMin = document.getElementById('min').value * 1; + * var iMax = document.getElementById('max').value * 1; + * var iVersion = aData[3] == "-" ? 0 : aData[3]*1; + * if ( iMin == "" && iMax == "" ) { + * return true; + * } + * else if ( iMin == "" && iVersion < iMax ) { + * return true; + * } + * else if ( iMin < iVersion && "" == iMax ) { + * return true; + * } + * else if ( iMin < iVersion && iVersion < iMax ) { + * return true; + * } + * return false; + * } + * ); + */ + "afnFiltering": [], + + + /** + * Plug-in sorting functions - this method of sorting is complimentary to the default type + * based sorting that DataTables does automatically, allowing much greater control over the + * the data that is being used to sort a column. This is useful if you want to do sorting + * based on live data (for example the contents of an 'input' element) rather than just the + * static string that DataTables knows of. The way these plug-ins work is that you create + * an array of the values you wish to be sorted for the column in question and then return + * that array. Which pre-sorting function is run here depends on the sSortDataType parameter + * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort + * data. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{int} Target column index</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{array} Data for the column to be sorted upon</li> + * </ul> + * </il> + * </ul> + * + * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for + * the different uses that DataTables can put the data to. Specifically <i>mData</i> when + * used as a function will give you a 'type' (sorting, filtering etc) that you can use to + * prepare the data as required for the different types. As such, this method is deprecated. + * @type array + * @default [] + * @deprecated + * + * @example + * // Updating the cached sorting information with user entered values in HTML input elements + * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn ) + * { + * var aData = []; + * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () { + * aData.push( this.value ); + * } ); + * return aData; + * } + */ + "afnSortData": [], + + + /** + * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are + * available to DataTables. These feature plug-ins are accessible through the sDom initialisation + * option. As such, each feature plug-in must describe a function that is used to initialise + * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name + * of the feature (sFeature). Thus the objects attached to this method must provide: + * <ul> + * <li>{function} fnInit Initialisation of the plug-in + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{node|null} The element which contains your feature. Note that the return + * may also be void if your plug-in does not require to inject any DOM elements + * into DataTables control (sDom) - for example this might be useful when + * developing a plug-in which allows table control via keyboard entry.</li> + * </ul> + * </il> + * </ul> + * </li> + * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li> + * <li>{string} sFeature Feature name</li> + * </ul> + * @type array + * @default [] + * + * @example + * // How TableTools initialises itself. + * $.fn.dataTableExt.aoFeatures.push( { + * "fnInit": function( oSettings ) { + * return new TableTools( { "oDTSettings": oSettings } ); + * }, + * "cFeature": "T", + * "sFeature": "TableTools" + * } ); + */ + "aoFeatures": [], + + + /** + * Type detection plug-in functions - DataTables utilises types to define how sorting and + * filtering behave, and types can be either be defined by the developer (sType for the + * column) or they can be automatically detected by the methods in this array. The functions + * defined in the array are quite simple, taking a single parameter (the data to analyse) + * and returning the type if it is a known type, or null otherwise. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data from the column cell to be analysed</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{string|null} Data type detected, or null if unknown (and thus pass it + * on to the other type detection functions.</li> + * </ul> + * </il> + * </ul> + * @type array + * @default [] + * + * @example + * // Currency type detection plug-in: + * jQuery.fn.dataTableExt.aTypes.push( + * function ( sData ) { + * var sValidChars = "0123456789.-"; + * var Char; + * + * // Check the numeric part + * for ( i=1 ; i<sData.length ; i++ ) { + * Char = sData.charAt(i); + * if (sValidChars.indexOf(Char) == -1) { + * return null; + * } + * } + * + * // Check prefixed by currency + * if ( sData.charAt(0) == '$' || sData.charAt(0) == '£' ) { + * return 'currency'; + * } + * return null; + * } + * ); + */ + "aTypes": [], + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, + * in order to ensure compatibility. + * @type function + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note + * that the formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the + * required version, or false if this version of DataTales is not suitable + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + "fnVersionCheck": DataTable.fnVersionCheck, + + + /** + * Index for what 'this' index API functions should use + * @type int + * @default 0 + */ + "iApiIndex": 0, + + + /** + * Pre-processing of filtering data plug-ins - When you assign the sType for a column + * (or have it automatically detected for you by DataTables or a type detection plug-in), + * you will typically be using this for custom sorting, but it can also be used to provide + * custom filtering by allowing you to pre-processing the data and returning the data in + * the format that should be filtered upon. This is done by adding functions this object + * with a parameter name which matches the sType for that target column. This is the + * corollary of <i>afnSortData</i> for filtering data. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data from the column cell to be prepared for filtering</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{string|null} Formatted string that will be used for the filtering.</li> + * </ul> + * </il> + * </ul> + * + * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for + * the different uses that DataTables can put the data to. Specifically <i>mData</i> when + * used as a function will give you a 'type' (sorting, filtering etc) that you can use to + * prepare the data as required for the different types. As such, this method is deprecated. + * @type object + * @default {} + * @deprecated + * + * @example + * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) { + * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" ); + * } + */ + "ofnSearch": {}, + + + /** + * Container for all private functions in DataTables so they can be exposed externally + * @type object + * @default {} + */ + "oApi": {}, + + + /** + * Storage for the various classes that DataTables uses + * @type object + * @default {} + */ + "oStdClasses": {}, + + + /** + * Storage for the various classes that DataTables uses - jQuery UI suitable + * @type object + * @default {} + */ + "oJUIClasses": {}, + + + /** + * Pagination plug-in methods - The style and controls of the pagination can significantly + * impact on how the end user interacts with the data in your table, and DataTables allows + * the addition of pagination controls by extending this object, which can then be enabled + * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that + * is added is an object (the property name of which is what <i>sPaginationType</i> refers + * to) that has two properties, both methods that are used by DataTables to update the + * control's state. + * <ul> + * <li> + * fnInit - Initialisation of the paging controls. Called only during initialisation + * of the table. It is expected that this function will add the required DOM elements + * to the page for the paging controls to work. The element pointer + * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging + * controls (note that this is a 2D array to allow for multiple instances of each + * DataTables DOM element). It is suggested that you add the controls to this element + * as children + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{node} Container into which the pagination controls must be inserted</li> + * <li>{function} Draw callback function - whenever the controls cause a page + * change, this method must be called to redraw the table.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>No return required</li> + * </ul> + * </il> + * </ul> + * </il> + * <li> + * fnInit - This function is called whenever the paging status of the table changes and is + * typically used to update classes and/or text of the paging controls to reflex the new + * status. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{function} Draw callback function - in case you need to redraw the table again + * or attach new event listeners</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>No return required</li> + * </ul> + * </il> + * </ul> + * </il> + * </ul> + * @type object + * @default {} + * + * @example + * $.fn.dataTableExt.oPagination.four_button = { + * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { + * nFirst = document.createElement( 'span' ); + * nPrevious = document.createElement( 'span' ); + * nNext = document.createElement( 'span' ); + * nLast = document.createElement( 'span' ); + * + * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) ); + * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) ); + * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) ); + * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) ); + * + * nFirst.className = "paginate_button first"; + * nPrevious.className = "paginate_button previous"; + * nNext.className="paginate_button next"; + * nLast.className = "paginate_button last"; + * + * nPaging.appendChild( nFirst ); + * nPaging.appendChild( nPrevious ); + * nPaging.appendChild( nNext ); + * nPaging.appendChild( nLast ); + * + * $(nFirst).click( function () { + * oSettings.oApi._fnPageChange( oSettings, "first" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nPrevious).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "previous" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nNext).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "next" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nLast).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "last" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nFirst).bind( 'selectstart', function () { return false; } ); + * $(nPrevious).bind( 'selectstart', function () { return false; } ); + * $(nNext).bind( 'selectstart', function () { return false; } ); + * $(nLast).bind( 'selectstart', function () { return false; } ); + * }, + * + * "fnUpdate": function ( oSettings, fnCallbackDraw ) { + * if ( !oSettings.aanFeatures.p ) { + * return; + * } + * + * // Loop over each instance of the pager + * var an = oSettings.aanFeatures.p; + * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) { + * var buttons = an[i].getElementsByTagName('span'); + * if ( oSettings._iDisplayStart === 0 ) { + * buttons[0].className = "paginate_disabled_previous"; + * buttons[1].className = "paginate_disabled_previous"; + * } + * else { + * buttons[0].className = "paginate_enabled_previous"; + * buttons[1].className = "paginate_enabled_previous"; + * } + * + * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) { + * buttons[2].className = "paginate_disabled_next"; + * buttons[3].className = "paginate_disabled_next"; + * } + * else { + * buttons[2].className = "paginate_enabled_next"; + * buttons[3].className = "paginate_enabled_next"; + * } + * } + * } + * }; + */ + "oPagination": {}, + + + /** + * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the + * data column (you can add your own type detection functions, or override automatic + * detection using sType). With this specific type given to the column, DataTables will + * apply the required sort from the functions in the object. Each sort type must provide + * two mandatory methods, one each for ascending and descending sorting, and can optionally + * provide a pre-formatting method that will help speed up sorting by allowing DataTables + * to pre-format the sort data only once (rather than every time the actual sort functions + * are run). The two sorting functions are typical Javascript sort methods: + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data to compare to the second parameter</li> + * <li>{*} Data to compare to the first parameter</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{int} Sorting match: <0 if first parameter should be sorted lower than + * the second parameter, ===0 if the two parameters are equal and >0 if + * the first parameter should be sorted height than the second parameter.</li> + * </ul> + * </il> + * </ul> + * @type object + * @default {} + * + * @example + * // Case-sensitive string sorting, with no pre-formatting method + * $.extend( $.fn.dataTableExt.oSort, { + * "string-case-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-case-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + * + * @example + * // Case-insensitive string sorting, with pre-formatting + * $.extend( $.fn.dataTableExt.oSort, { + * "string-pre": function(x) { + * return x.toLowerCase(); + * }, + * "string-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + */ + "oSort": {}, + + + /** + * Version string for plug-ins to check compatibility. Allowed format is + * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and + * e are optional + * @type string + * @default Version number + */ + "sVersion": DataTable.version, + + + /** + * How should DataTables report an error. Can take the value 'alert' or 'throw' + * @type string + * @default alert + */ + "sErrMode": "alert", + + + /** + * Store information for DataTables to access globally about other instances + * @namespace + * @private + */ + "_oExternConfig": { + /* int:iNextUnique - next unique number for an instance */ + "iNextUnique": 0 + } + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * search information for the global filter and individual column filters. + * @namespace + */ + DataTable.models.oSearch = { + /** + * Flag to indicate if the filtering should be case insensitive or not + * @type boolean + * @default true + */ + "bCaseInsensitive": true, + + /** + * Applied search term + * @type string + * @default <i>Empty string</i> + */ + "sSearch": "", + + /** + * Flag to indicate if the search term should be interpreted as a + * regular expression (true) or not (false) and therefore and special + * regex characters escaped. + * @type boolean + * @default false + */ + "bRegex": false, + + /** + * Flag to indicate if DataTables is to use its smart filtering or not. + * @type boolean + * @default true + */ + "bSmart": true + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * each individual row. This is the object format used for the settings + * aoData array. + * @namespace + */ + DataTable.models.oRow = { + /** + * TR element for the row + * @type node + * @default null + */ + "nTr": null, + + /** + * Data object from the original data source for the row. This is either + * an array if using the traditional form of DataTables, or an object if + * using mData options. The exact type will depend on the passed in + * data from the data source, or will be an array if using DOM a data + * source. + * @type array|object + * @default [] + */ + "_aData": [], + + /** + * Sorting data cache - this array is ostensibly the same length as the + * number of columns (although each index is generated only as it is + * needed), and holds the data that is used for sorting each column in the + * row. We do this cache generation at the start of the sort in order that + * the formatting of the sort data need be done only once for each cell + * per sort. This array should not be read from or written to by anything + * other than the master sorting methods. + * @type array + * @default [] + * @private + */ + "_aSortData": [], + + /** + * Array of TD elements that are cached for hidden rows, so they can be + * reinserted into the table if a column is made visible again (or to act + * as a store if a column is made hidden). Only hidden columns have a + * reference in the array. For non-hidden columns the value is either + * undefined or null. + * @type array nodes + * @default [] + * @private + */ + "_anHidden": [], + + /** + * Cache of the class name that DataTables has applied to the row, so we + * can quickly look at this variable rather than needing to do a DOM check + * on className for the nTr property. + * @type string + * @default <i>Empty string</i> + * @private + */ + "_sRowStripe": "" + }; + + + + /** + * Template object for the column information object in DataTables. This object + * is held in the settings aoColumns array and contains all the information that + * DataTables needs about each individual column. + * + * Note that this object is related to {@link DataTable.defaults.columns} + * but this one is the internal data store for DataTables's cache of columns. + * It should NOT be manipulated outside of DataTables. Any configuration should + * be done through the initialisation options. + * @namespace + */ + DataTable.models.oColumn = { + /** + * A list of the columns that sorting should occur on when this column + * is sorted. That this property is an array allows multi-column sorting + * to be defined for a column (for example first name / last name columns + * would benefit from this). The values are integers pointing to the + * columns to be sorted on (typically it will be a single integer pointing + * at itself, but that doesn't need to be the case). + * @type array + */ + "aDataSort": null, + + /** + * Define the sorting directions that are applied to the column, in sequence + * as the column is repeatedly sorted upon - i.e. the first value is used + * as the sorting direction when the column if first sorted (clicked on). + * Sort it again (click again) and it will move on to the next index. + * Repeat until loop. + * @type array + */ + "asSorting": null, + + /** + * Flag to indicate if the column is searchable, and thus should be included + * in the filtering or not. + * @type boolean + */ + "bSearchable": null, + + /** + * Flag to indicate if the column is sortable or not. + * @type boolean + */ + "bSortable": null, + + /** + * <code>Deprecated</code> When using fnRender, you have two options for what + * to do with the data, and this property serves as the switch. Firstly, you + * can have the sorting and filtering use the rendered value (true - default), + * or you can have the sorting and filtering us the original value (false). + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @deprecated + */ + "bUseRendered": null, + + /** + * Flag to indicate if the column is currently visible in the table or not + * @type boolean + */ + "bVisible": null, + + /** + * Flag to indicate to the type detection method if the automatic type + * detection should be used, or if a column type (sType) has been specified + * @type boolean + * @default true + * @private + */ + "_bAutoType": true, + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @default null + */ + "fnCreatedCell": null, + + /** + * Function to get data from a cell in a column. You should <b>never</b> + * access data directly through _aData internally in DataTables - always use + * the method attached to this property. It allows mData to function as + * required. This function is automatically assigned by the column + * initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {string} sSpecific The specific data type you want to get - + * 'display', 'type' 'filter' 'sort' + * @returns {*} The data for the cell from the given row's data + * @default null + */ + "fnGetData": null, + + /** + * <code>Deprecated</code> Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @returns {string} The string you which to use in the display + * @default null + * @deprecated + */ + "fnRender": null, + + /** + * Function to set data for a cell in the column. You should <b>never</b> + * set the data directly to _aData internally in DataTables - always use + * this method. It allows mData to function as required. This function + * is automatically assigned by the column initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {*} sValue Value to set + * @default null + */ + "fnSetData": null, + + /** + * Property to read the value for the cells in the column from the data + * source array / object. If null, then the default content is used, if a + * function is given then the return from the function is used. + * @type function|int|string|null + * @default null + */ + "mData": null, + + /** + * Partner property to mData which is used (only when defined) to get + * the data - i.e. it is basically the same as mData, but without the + * 'set' option, and also the data fed to it is the result from mData. + * This is the rendering method to match the data method of mData. + * @type function|int|string|null + * @default null + */ + "mRender": null, + + /** + * Unique header TH/TD element for this column - this is what the sorting + * listener is attached to (if sorting is enabled.) + * @type node + * @default null + */ + "nTh": null, + + /** + * Unique footer TH/TD element for this column (if there is one). Not used + * in DataTables as such, but can be used for plug-ins to reference the + * footer for each column. + * @type node + * @default null + */ + "nTf": null, + + /** + * The class to apply to all TD elements in the table's TBODY for the column + * @type string + * @default null + */ + "sClass": null, + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * @type string + */ + "sContentPadding": null, + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + */ + "sDefaultContent": null, + + /** + * Name for the column, allowing reference to the column by name as well as + * by index (needs a lookup to work by name). + * @type string + */ + "sName": null, + + /** + * Custom sorting data type - defines which of the available plug-ins in + * afnSortData the custom sorting will use - if any is defined. + * @type string + * @default std + */ + "sSortDataType": 'std', + + /** + * Class to be applied to the header element when sorting on this column + * @type string + * @default null + */ + "sSortingClass": null, + + /** + * Class to be applied to the header element when sorting on this column - + * when jQuery UI theming is used. + * @type string + * @default null + */ + "sSortingClassJUI": null, + + /** + * Title of the column - what is seen in the TH element (nTh). + * @type string + */ + "sTitle": null, + + /** + * Column sorting and filtering type + * @type string + * @default null + */ + "sType": null, + + /** + * Width of the column + * @type string + * @default null + */ + "sWidth": null, + + /** + * Width of the column when it was first "encountered" + * @type string + * @default null + */ + "sWidthOrig": null + }; + + + + /** + * Initialisation options that can be given to DataTables at initialisation + * time. + * @namespace + */ + DataTable.defaults = { + /** + * An array of data to use for the table, passed in at initialisation which + * will be used in preference to any data which is already in the DOM. This is + * particularly useful for constructing tables purely in Javascript, for + * example with a custom Ajax call. + * @type array + * @default null + * @dtopt Option + * + * @example + * // Using a 2D array data source + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], + * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], + * ], + * "aoColumns": [ + * { "sTitle": "Engine" }, + * { "sTitle": "Browser" }, + * { "sTitle": "Platform" }, + * { "sTitle": "Version" }, + * { "sTitle": "Grade" } + * ] + * } ); + * } ); + * + * @example + * // Using an array of objects as a data source (mData) + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * { + * "engine": "Trident", + * "browser": "Internet Explorer 4.0", + * "platform": "Win 95+", + * "version": 4, + * "grade": "X" + * }, + * { + * "engine": "Trident", + * "browser": "Internet Explorer 5.0", + * "platform": "Win 95+", + * "version": 5, + * "grade": "C" + * } + * ], + * "aoColumns": [ + * { "sTitle": "Engine", "mData": "engine" }, + * { "sTitle": "Browser", "mData": "browser" }, + * { "sTitle": "Platform", "mData": "platform" }, + * { "sTitle": "Version", "mData": "version" }, + * { "sTitle": "Grade", "mData": "grade" } + * ] + * } ); + * } ); + */ + "aaData": null, + + + /** + * If sorting is enabled, then DataTables will perform a first pass sort on + * initialisation. You can define which column(s) the sort is performed upon, + * and the sorting direction, with this variable. The aaSorting array should + * contain an array for each column to be sorted initially containing the + * column's index and a direction string ('asc' or 'desc'). + * @type array + * @default [[0,'asc']] + * @dtopt Option + * + * @example + * // Sort by 3rd column first, and then 4th column + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [[2,'asc'], [3,'desc']] + * } ); + * } ); + * + * // No initial sorting + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [] + * } ); + * } ); + */ + "aaSorting": [[0,'asc']], + + + /** + * This parameter is basically identical to the aaSorting parameter, but + * cannot be overridden by user interaction with the table. What this means + * is that you could have a column (visible or hidden) which the sorting will + * always be forced on first - any sorting after that (from the user) will + * then be performed as required. This can be useful for grouping rows + * together. + * @type array + * @default null + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSortingFixed": [[0,'asc']] + * } ); + * } ) + */ + "aaSortingFixed": null, + + + /** + * This parameter allows you to readily specify the entries in the length drop + * down menu that DataTables shows when pagination is enabled. It can be + * either a 1D array of options which will be used for both the displayed + * option and the value, or a 2D array which will use the array in the first + * position as the value, and the array in the second position as the + * displayed options (useful for language strings such as 'All'). + * @type array + * @default [ 10, 25, 50, 100 ] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] + * } ); + * } ); + * + * @example + * // Setting the default display length as well as length menu + * // This is likely to be wanted if you remove the '10' option which + * // is the iDisplayLength default. + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 25, + * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]] + * } ); + * } ); + */ + "aLengthMenu": [ 10, 25, 50, 100 ], + + + /** + * The aoColumns option in the initialisation parameter allows you to define + * details about the way individual columns behave. For a full list of + * column options that can be set, please see + * {@link DataTable.defaults.columns}. Note that if you use aoColumns to + * define your columns, you must have an entry in the array for every single + * column that you have in your table (these can be null if you don't which + * to specify any options). + * @member + */ + "aoColumns": null, + + /** + * Very similar to aoColumns, aoColumnDefs allows you to target a specific + * column, multiple columns, or all columns, using the aTargets property of + * each object in the array. This allows great flexibility when creating + * tables, as the aoColumnDefs arrays can be of any length, targeting the + * columns you specifically want. aoColumnDefs may use any of the column + * options available: {@link DataTable.defaults.columns}, but it _must_ + * have aTargets defined in each object in the array. Values in the aTargets + * array may be: + * <ul> + * <li>a string - class name will be matched on the TH for the column</li> + * <li>0 or a positive integer - column index counting from the left</li> + * <li>a negative integer - column index counting from the right</li> + * <li>the string "_all" - all columns (i.e. assign a default)</li> + * </ul> + * @member + */ + "aoColumnDefs": null, + + + /** + * Basically the same as oSearch, this parameter defines the individual column + * filtering state at initialisation time. The array must be of the same size + * as the number of columns, and each element be an object with the parameters + * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also + * accepted and the default will be used. + * @type array + * @default [] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoSearchCols": [ + * null, + * { "sSearch": "My filter" }, + * null, + * { "sSearch": "^[0-9]", "bEscapeRegex": false } + * ] + * } ); + * } ) + */ + "aoSearchCols": [], + + + /** + * An array of CSS classes that should be applied to displayed rows. This + * array may be of any length, and DataTables will apply each class + * sequentially, looping when required. + * @type array + * @default null <i>Will take the values determined by the oClasses.sStripe* + * options</i> + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ] + * } ); + * } ) + */ + "asStripeClasses": null, + + + /** + * Enable or disable automatic column width calculation. This can be disabled + * as an optimisation (it takes some time to calculate the widths) if the + * tables widths are passed in using aoColumns. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bAutoWidth": false + * } ); + * } ); + */ + "bAutoWidth": true, + + + /** + * Deferred rendering can provide DataTables with a huge speed boost when you + * are using an Ajax or JS data source for the table. This option, when set to + * true, will cause DataTables to defer the creation of the table elements for + * each row until they are needed for a draw - saving a significant amount of + * time. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/arrays.txt", + * "bDeferRender": true + * } ); + * } ); + */ + "bDeferRender": false, + + + /** + * Replace a DataTable which matches the given selector and replace it with + * one which has the properties of the new initialisation object passed. If no + * table matches the selector, then the new DataTable will be constructed as + * per normal. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * // Some time later.... + * $('#example').dataTable( { + * "bFilter": false, + * "bDestroy": true + * } ); + * } ); + */ + "bDestroy": false, + + + /** + * Enable or disable filtering of data. Filtering in DataTables is "smart" in + * that it allows the end user to input multiple words (space separated) and + * will match a row containing those words, even if not in the order that was + * specified (this allow matching across multiple columns). Note that if you + * wish to use filtering in DataTables this must remain 'true' - to remove the + * default filtering input box and retain filtering abilities, please use + * {@link DataTable.defaults.sDom}. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bFilter": false + * } ); + * } ); + */ + "bFilter": true, + + + /** + * Enable or disable the table information display. This shows information + * about the data that is currently visible on the page, including information + * about filtered data if that action is being performed. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bInfo": false + * } ); + * } ); + */ + "bInfo": true, + + + /** + * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some + * slightly different and additional mark-up from what DataTables has + * traditionally used). + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bJQueryUI": true + * } ); + * } ); + */ + "bJQueryUI": false, + + + /** + * Allows the end user to select the size of a formatted page from a select + * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate). + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bLengthChange": false + * } ); + * } ); + */ + "bLengthChange": true, + + + /** + * Enable or disable pagination. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bPaginate": false + * } ); + * } ); + */ + "bPaginate": true, + + + /** + * Enable or disable the display of a 'processing' indicator when the table is + * being processed (e.g. a sort). This is particularly useful for tables with + * large amounts of data where it can take a noticeable amount of time to sort + * the entries. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bProcessing": true + * } ); + * } ); + */ + "bProcessing": false, + + + /** + * Retrieve the DataTables object for the given selector. Note that if the + * table has already been initialised, this parameter will cause DataTables + * to simply return the object that has already been set up - it will not take + * account of any changes you might have made to the initialisation object + * passed to DataTables (setting this parameter to true is an acknowledgement + * that you understand this). bDestroy can be used to reinitialise a table if + * you need. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * initTable(); + * tableActions(); + * } ); + * + * function initTable () + * { + * return $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false, + * "bRetrieve": true + * } ); + * } + * + * function tableActions () + * { + * var oTable = initTable(); + * // perform API operations with oTable + * } + */ + "bRetrieve": false, + + + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * @type boolean + * @default true + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollAutoCss": false, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollAutoCss": true, + + + /** + * When vertical (y) scrolling is enabled, DataTables will force the height of + * the table's viewport to the given height at all times (useful for layout). + * However, this can look odd when filtering data down to a small data set, + * and the footer is left "floating" further down. This parameter (when + * enabled) will cause DataTables to collapse the table's viewport down when + * the result set will fit within the given Y height. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200", + * "bScrollCollapse": true + * } ); + * } ); + */ + "bScrollCollapse": false, + + + /** + * Enable infinite scrolling for DataTables (to be used in combination with + * sScrollY). Infinite scrolling means that DataTables will continually load + * data as a user scrolls through a table, which is very useful for large + * dataset. This cannot be used with pagination, which is automatically + * disabled. Note - the Scroller extra for DataTables is recommended in + * in preference to this option. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollInfinite": false, + + + /** + * Configure DataTables to use server-side processing. Note that the + * sAjaxSource parameter must also be given in order to give DataTables a + * source to obtain the required data for each draw. + * @type boolean + * @default false + * @dtopt Features + * @dtopt Server-side + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "xhr.php" + * } ); + * } ); + */ + "bServerSide": false, + + + /** + * Enable or disable sorting of columns. Sorting of individual columns can be + * disabled by the "bSortable" option for each column. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSort": false + * } ); + * } ); + */ + "bSort": true, + + + /** + * Allows control over whether DataTables should use the top (true) unique + * cell that is found for a single column, or the bottom (false - default). + * This is useful when using complex headers. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bSortCellsTop": true + * } ); + * } ); + */ + "bSortCellsTop": false, + + + /** + * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and + * 'sorting_3' to the columns which are currently being sorted on. This is + * presented as a feature switch as it can increase processing time (while + * classes are removed and added) so for large data sets you might want to + * turn this off. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSortClasses": false + * } ); + * } ); + */ + "bSortClasses": true, + + + /** + * Enable or disable state saving. When enabled a cookie will be used to save + * table display information such as pagination information, display length, + * filtering and sorting. As such when the end user reloads the page the + * display display will match what thy had previously set up. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bStateSave": true + * } ); + * } ); + */ + "bStateSave": false, + + + /** + * Customise the cookie and / or the parameters being stored when using + * DataTables with state saving enabled. This function is called whenever + * the cookie is modified, and it expects a fully formed cookie string to be + * returned. Note that the data object passed in is a Javascript object which + * must be converted to a string (JSON.stringify for example). + * @type function + * @param {string} sName Name of the cookie defined by DataTables + * @param {object} oData Data to be stored in the cookie + * @param {string} sExpires Cookie expires string + * @param {string} sPath Path of the cookie to set + * @returns {string} Cookie formatted string (which should be encoded by + * using encodeURIComponent()) + * @dtopt Callbacks + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "fnCookieCallback": function (sName, oData, sExpires, sPath) { + * // Customise oData or sName or whatever else here + * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath; + * } + * } ); + * } ); + */ + "fnCookieCallback": null, + + + /** + * This function is called when a TR element is created (and all TD child + * elements have been inserted), or registered if using a DOM source, allowing + * manipulation of the TR element (adding classes etc). + * @type function + * @param {node} nRow "TR" element for the current row + * @param {array} aData Raw data array for this row + * @param {int} iDataIndex The index of this row in aoData + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnCreatedRow": function( nRow, aData, iDataIndex ) { + * // Bold the grade for all 'A' grade browsers + * if ( aData[4] == "A" ) + * { + * $('td:eq(4)', nRow).html( '<b>A</b>' ); + * } + * } + * } ); + * } ); + */ + "fnCreatedRow": null, + + + /** + * This function is called on every 'draw' event, and allows you to + * dynamically modify any aspect you want about the created DOM. + * @type function + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnDrawCallback": function( oSettings ) { + * alert( 'DataTables has redrawn the table' ); + * } + * } ); + * } ); + */ + "fnDrawCallback": null, + + + /** + * Identical to fnHeaderCallback() but for the table footer this function + * allows you to modify the table footer on every 'draw' even. + * @type function + * @param {node} nFoot "TR" element for the footer + * @param {array} aData Full table data (as derived from the original HTML) + * @param {int} iStart Index for the current display starting point in the + * display array + * @param {int} iEnd Index for the current display ending point in the + * display array + * @param {array int} aiDisplay Index array to translate the visual position + * to the full data array + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) { + * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart; + * } + * } ); + * } ) + */ + "fnFooterCallback": null, + + + /** + * When rendering large numbers in the information element for the table + * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers + * to have a comma separator for the 'thousands' units (e.g. 1 million is + * rendered as "1,000,000") to help readability for the end user. This + * function will override the default method DataTables uses. + * @type function + * @member + * @param {int} iIn number to be formatted + * @returns {string} formatted string for DataTables to show the number + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFormatNumber": function ( iIn ) { + * if ( iIn < 1000 ) { + * return iIn; + * } else { + * var + * s=(iIn+""), + * a=s.split(""), out="", + * iLen=s.length; + * + * for ( var i=0 ; i<iLen ; i++ ) { + * if ( i%3 === 0 && i !== 0 ) { + * out = "'"+out; + * } + * out = a[iLen-i-1]+out; + * } + * } + * return out; + * }; + * } ); + * } ); + */ + "fnFormatNumber": function ( iIn ) { + if ( iIn < 1000 ) + { + // A small optimisation for what is likely to be the majority of use cases + return iIn; + } + + var s=(iIn+""), a=s.split(""), out="", iLen=s.length; + + for ( var i=0 ; i<iLen ; i++ ) + { + if ( i%3 === 0 && i !== 0 ) + { + out = this.oLanguage.sInfoThousands+out; + } + out = a[iLen-i-1]+out; + } + return out; + }, + + + /** + * This function is called on every 'draw' event, and allows you to + * dynamically modify the header row. This can be used to calculate and + * display useful information about the table. + * @type function + * @param {node} nHead "TR" element for the header + * @param {array} aData Full table data (as derived from the original HTML) + * @param {int} iStart Index for the current display starting point in the + * display array + * @param {int} iEnd Index for the current display ending point in the + * display array + * @param {array int} aiDisplay Index array to translate the visual position + * to the full data array + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) { + * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records"; + * } + * } ); + * } ) + */ + "fnHeaderCallback": null, + + + /** + * The information element can be used to convey information about the current + * state of the table. Although the internationalisation options presented by + * DataTables are quite capable of dealing with most customisations, there may + * be times where you wish to customise the string further. This callback + * allows you to do exactly that. + * @type function + * @param {object} oSettings DataTables settings object + * @param {int} iStart Starting position in data for the draw + * @param {int} iEnd End position in data for the draw + * @param {int} iMax Total number of rows in the table (regardless of + * filtering) + * @param {int} iTotal Total number of rows in the data set, after filtering + * @param {string} sPre The string that DataTables has formatted using it's + * own rules + * @returns {string} The string to be displayed in the information element. + * @dtopt Callbacks + * + * @example + * $('#example').dataTable( { + * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { + * return iStart +" to "+ iEnd; + * } + * } ); + */ + "fnInfoCallback": null, + + + /** + * Called when the table has been initialised. Normally DataTables will + * initialise sequentially and there will be no need for this function, + * however, this does not hold true when using external language information + * since that is obtained using an async XHR call. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} json The JSON object request from the server - only + * present if client-side Ajax sourced data is used + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnInitComplete": function(oSettings, json) { + * alert( 'DataTables has finished its initialisation.' ); + * } + * } ); + * } ) + */ + "fnInitComplete": null, + + + /** + * Called at the very start of each table draw and can be used to cancel the + * draw by returning false, any other return (including undefined) results in + * the full draw occurring). + * @type function + * @param {object} oSettings DataTables settings object + * @returns {boolean} False will cancel the draw, anything else (including no + * return) will allow it to complete. + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnPreDrawCallback": function( oSettings ) { + * if ( $('#test').val() == 1 ) { + * return false; + * } + * } + * } ); + * } ); + */ + "fnPreDrawCallback": null, + + + /** + * This function allows you to 'post process' each row after it have been + * generated for each table draw, but before it is rendered on screen. This + * function might be used for setting the row class name etc. + * @type function + * @param {node} nRow "TR" element for the current row + * @param {array} aData Raw data array for this row + * @param {int} iDisplayIndex The display index for the current table draw + * @param {int} iDisplayIndexFull The index of the data in the full list of + * rows (after filtering) + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { + * // Bold the grade for all 'A' grade browsers + * if ( aData[4] == "A" ) + * { + * $('td:eq(4)', nRow).html( '<b>A</b>' ); + * } + * } + * } ); + * } ); + */ + "fnRowCallback": null, + + + /** + * This parameter allows you to override the default function which obtains + * the data from the server ($.getJSON) so something more suitable for your + * application. For example you could use POST data, or pull information from + * a Gears or AIR database. + * @type function + * @member + * @param {string} sSource HTTP source to obtain the data from (sAjaxSource) + * @param {array} aoData A key/value pair object containing the data to send + * to the server + * @param {function} fnCallback to be called on completion of the data get + * process that will draw the data on the page. + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * // POST data to server + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "xhr.php", + * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { + * oSettings.jqXHR = $.ajax( { + * "dataType": 'json', + * "type": "POST", + * "url": sSource, + * "data": aoData, + * "success": fnCallback + * } ); + * } + * } ); + * } ); + */ + "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) { + oSettings.jqXHR = $.ajax( { + "url": sUrl, + "data": aoData, + "success": function (json) { + if ( json.sError ) { + oSettings.oApi._fnLog( oSettings, 0, json.sError ); + } + + $(oSettings.oInstance).trigger('xhr', [oSettings, json]); + fnCallback( json ); + }, + "dataType": "json", + "cache": false, + "type": oSettings.sServerMethod, + "error": function (xhr, error, thrown) { + if ( error == "parsererror" ) { + oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+ + "server could not be parsed. This is caused by a JSON formatting error." ); + } + } + } ); + }, + + + /** + * It is often useful to send extra data to the server when making an Ajax + * request - for example custom filtering information, and this callback + * function makes it trivial to send extra information to the server. The + * passed in parameter is the data set that has been constructed by + * DataTables, and you can add to this or modify it as you require. + * @type function + * @param {array} aoData Data array (array of objects which are name/value + * pairs) that has been constructed by DataTables and will be sent to the + * server. In the case of Ajax sourced data with server-side processing + * this will be an empty array, for server-side processing there will be a + * significant number of parameters! + * @returns {undefined} Ensure that you modify the aoData array passed in, + * as this is passed by reference. + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "fnServerParams": function ( aoData ) { + * aoData.push( { "name": "more_data", "value": "my_value" } ); + * } + * } ); + * } ); + */ + "fnServerParams": null, + + + /** + * Load the table state. With this function you can define from where, and how, the + * state of a table is loaded. By default DataTables will load from its state saving + * cookie, but you might wish to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @return {object} The DataTables state object to be loaded + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoad": function (oSettings) { + * var o; + * + * // Send an Ajax request to the server to get the data. Note that + * // this is a synchronous request. + * $.ajax( { + * "url": "/state_load", + * "async": false, + * "dataType": "json", + * "success": function (json) { + * o = json; + * } + * } ); + * + * return o; + * } + * } ); + * } ); + */ + "fnStateLoad": function ( oSettings ) { + var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance ); + var oData; + + try { + oData = (typeof $.parseJSON === 'function') ? + $.parseJSON(sData) : eval( '('+sData+')' ); + } catch (e) { + oData = null; + } + + return oData; + }, + + + /** + * Callback which allows modification of the saved state prior to loading that state. + * This callback is called when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state. Note that for + * plug-in authors, you should use the 'stateLoadParams' event to load parameters for + * a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that is to be loaded + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never loaded + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + * + * @example + * // Disallow state loading by returning false + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * return false; + * } + * } ); + * } ); + */ + "fnStateLoadParams": null, + + + /** + * Callback that is called when the state has been loaded from the state saving method + * and the DataTables settings object has been modified as a result of the loaded state. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that was loaded + * @dtopt Callbacks + * + * @example + * // Show an alert with the filtering value that was saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoaded": function (oSettings, oData) { + * alert( 'Saved filter was: '+oData.oSearch.sSearch ); + * } + * } ); + * } ); + */ + "fnStateLoaded": null, + + + /** + * Save the table state. This function allows you to define where and how the state + * information for the table is stored - by default it will use a cookie, but you + * might want to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSave": function (oSettings, oData) { + * // Send an Ajax request to the server with the state object + * $.ajax( { + * "url": "/state_save", + * "data": oData, + * "dataType": "json", + * "method": "POST" + * "success": function () {} + * } ); + * } + * } ); + * } ); + */ + "fnStateSave": function ( oSettings, oData ) { + this.oApi._fnCreateCookie( + oSettings.sCookiePrefix+oSettings.sInstance, + this.oApi._fnJsonString(oData), + oSettings.iCookieDuration, + oSettings.sCookiePrefix, + oSettings.fnCookieCallback + ); + }, + + + /** + * Callback which allows modification of the state to be saved. Called when the table + * has changed state a new state save is required. This method allows modification of + * the state saving object prior to actually doing the save, including addition or + * other state properties or modification. Note that for plug-in authors, you should + * use the 'stateSaveParams' event to save parameters for a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSaveParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + */ + "fnStateSaveParams": null, + + + /** + * Duration of the cookie which is used for storing session information. This + * value is given in seconds. + * @type int + * @default 7200 <i>(2 hours)</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iCookieDuration": 60*60*24; // 1 day + * } ); + * } ) + */ + "iCookieDuration": 7200, + + + /** + * When enabled DataTables will not make a request to the server for the first + * page draw - rather it will use the data already on the page (no sorting etc + * will be applied to it), thus saving on an XHR at load time. iDeferLoading + * is used to indicate that deferred loading is required, but it is also used + * to tell DataTables how many records there are in the full table (allowing + * the information element and pagination to be displayed correctly). In the case + * where a filtering is applied to the table on initial load, this can be + * indicated by giving the parameter as an array, where the first element is + * the number of records available after filtering and the second element is the + * number of records without filtering (allowing the table information element + * to be shown correctly). + * @type int | array + * @default null + * @dtopt Options + * + * @example + * // 57 records available in the table, no filtering applied + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": 57 + * } ); + * } ); + * + * @example + * // 57 records after filtering, 100 without filtering (an initial filter applied) + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": [ 57, 100 ], + * "oSearch": { + * "sSearch": "my_filter" + * } + * } ); + * } ); + */ + "iDeferLoading": null, + + + /** + * Number of rows to display on a single page when using pagination. If + * feature enabled (bLengthChange) then the end user will be able to override + * this to a custom setting using a pop-up menu. + * @type int + * @default 10 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 50 + * } ); + * } ) + */ + "iDisplayLength": 10, + + + /** + * Define the starting point for data display when using DataTables with + * pagination. Note that this parameter is the number of records, rather than + * the page number, so if you have 10 records per page and want to start on + * the third page, it should be "20". + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayStart": 20 + * } ); + * } ) + */ + "iDisplayStart": 0, + + + /** + * The scroll gap is the amount of scrolling that is left to go before + * DataTables will load the next 'page' of data automatically. You typically + * want a gap which is big enough that the scrolling will be smooth for the + * user, while not so large that it will load more data than need. + * @type int + * @default 100 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px", + * "iScrollLoadGap": 50 + * } ); + * } ); + */ + "iScrollLoadGap": 100, + + + /** + * By default DataTables allows keyboard navigation of the table (sorting, paging, + * and filtering) by adding a tabindex attribute to the required elements. This + * allows you to tab through the controls and press the enter key to activate them. + * The tabindex is default 0, meaning that the tab follows the flow of the document. + * You can overrule this using this parameter if you wish. Use a value of -1 to + * disable built-in keyboard navigation. + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iTabIndex": 1 + * } ); + * } ); + */ + "iTabIndex": 0, + + + /** + * All strings that DataTables uses in the user interface that it creates + * are defined in this object, allowing you to modified them individually or + * completely replace them all as required. + * @namespace + */ + "oLanguage": { + /** + * Strings that are used for WAI-ARIA labels and controls only (these are not + * actually visible on the page, but will be read by screenreaders, and thus + * must be internationalised as well). + * @namespace + */ + "oAria": { + /** + * ARIA label that is added to the table headers when the column may be + * sorted ascending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortAscending": " - click/return to sort ascending" + * } + * } + * } ); + * } ); + */ + "sSortAscending": ": activate to sort column ascending", + + /** + * ARIA label that is added to the table headers when the column may be + * sorted descending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortDescending": " - click/return to sort descending" + * } + * } + * } ); + * } ); + */ + "sSortDescending": ": activate to sort column descending" + }, + + /** + * Pagination string used by DataTables for the two built-in pagination + * control types ("two_button" and "full_numbers") + * @namespace + */ + "oPaginate": { + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the first page. + * @type string + * @default First + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sFirst": "First page" + * } + * } + * } ); + * } ); + */ + "sFirst": "First", + + + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the last page. + * @type string + * @default Last + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sLast": "Last page" + * } + * } + * } ); + * } ); + */ + "sLast": "Last", + + + /** + * Text to use for the 'next' pagination button (to take the user to the + * next page). + * @type string + * @default Next + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sNext": "Next page" + * } + * } + * } ); + * } ); + */ + "sNext": "Next", + + + /** + * Text to use for the 'previous' pagination button (to take the user to + * the previous page). + * @type string + * @default Previous + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sPrevious": "Previous page" + * } + * } + * } ); + * } ); + */ + "sPrevious": "Previous" + }, + + /** + * This string is shown in preference to sZeroRecords when the table is + * empty of data (regardless of filtering). Note that this is an optional + * parameter - if it is not given, the value of sZeroRecords will be used + * instead (either the default or given value). + * @type string + * @default No data available in table + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sEmptyTable": "No data available in table" + * } + * } ); + * } ); + */ + "sEmptyTable": "No data available in table", + + + /** + * This string gives information to the end user about the information that + * is current on display on the page. The _START_, _END_ and _TOTAL_ + * variables are all dynamically replaced as the table display updates, and + * can be freely moved or removed as the language requirements change. + * @type string + * @default Showing _START_ to _END_ of _TOTAL_ entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)" + * } + * } ); + * } ); + */ + "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", + + + /** + * Display information string for when the table is empty. Typically the + * format of this string should match sInfo. + * @type string + * @default Showing 0 to 0 of 0 entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoEmpty": "No entries to show" + * } + * } ); + * } ); + */ + "sInfoEmpty": "Showing 0 to 0 of 0 entries", + + + /** + * When a user filters the information in a table, this string is appended + * to the information (sInfo) to give an idea of how strong the filtering + * is. The variable _MAX_ is dynamically updated. + * @type string + * @default (filtered from _MAX_ total entries) + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoFiltered": " - filtering from _MAX_ records" + * } + * } ); + * } ); + */ + "sInfoFiltered": "(filtered from _MAX_ total entries)", + + + /** + * If can be useful to append extra information to the info string at times, + * and this variable does exactly that. This information will be appended to + * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are + * being used) at all times. + * @type string + * @default <i>Empty string</i> + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoPostFix": "All records shown are derived from real information." + * } + * } ); + * } ); + */ + "sInfoPostFix": "", + + + /** + * DataTables has a build in number formatter (fnFormatNumber) which is used + * to format large numbers that are used in the table information. By + * default a comma is used, but this can be trivially changed to any + * character you wish with this parameter. + * @type string + * @default , + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoThousands": "'" + * } + * } ); + * } ); + */ + "sInfoThousands": ",", + + + /** + * Detail the action that will be taken when the drop down menu for the + * pagination length option is changed. The '_MENU_' variable is replaced + * with a default select list of 10, 25, 50 and 100, and can be replaced + * with a custom select box if required. + * @type string + * @default Show _MENU_ entries + * @dtopt Language + * + * @example + * // Language change only + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": "Display _MENU_ records" + * } + * } ); + * } ); + * + * @example + * // Language and options change + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": 'Display <select>'+ + * '<option value="10">10</option>'+ + * '<option value="20">20</option>'+ + * '<option value="30">30</option>'+ + * '<option value="40">40</option>'+ + * '<option value="50">50</option>'+ + * '<option value="-1">All</option>'+ + * '</select> records' + * } + * } ); + * } ); + */ + "sLengthMenu": "Show _MENU_ entries", + + + /** + * When using Ajax sourced data and during the first draw when DataTables is + * gathering the data, this message is shown in an empty row in the table to + * indicate to the end user the the data is being loaded. Note that this + * parameter is not used when loading data by server-side processing, just + * Ajax sourced data with client-side processing. + * @type string + * @default Loading... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLoadingRecords": "Please wait - loading..." + * } + * } ); + * } ); + */ + "sLoadingRecords": "Loading...", + + + /** + * Text which is displayed when the table is processing a user action + * (usually a sort command or similar). + * @type string + * @default Processing... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sProcessing": "DataTables is currently busy" + * } + * } ); + * } ); + */ + "sProcessing": "Processing...", + + + /** + * Details the actions that will be taken when the user types into the + * filtering input text box. The variable "_INPUT_", if used in the string, + * is replaced with the HTML text box for the filtering input allowing + * control over where it appears in the string. If "_INPUT_" is not given + * then the input box is appended to the string automatically. + * @type string + * @default Search: + * @dtopt Language + * + * @example + * // Input text box will be appended at the end automatically + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Filter records:" + * } + * } ); + * } ); + * + * @example + * // Specify where the filter should appear + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Apply filter _INPUT_ to table" + * } + * } ); + * } ); + */ + "sSearch": "Search:", + + + /** + * All of the language information can be stored in a file on the + * server-side, which DataTables will look up if this parameter is passed. + * It must store the URL of the language file, which is in a JSON format, + * and the object has the same properties as the oLanguage object in the + * initialiser object (i.e. the above parameters). Please refer to one of + * the example language files to see how this works in action. + * @type string + * @default <i>Empty string - i.e. disabled</i> + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt" + * } + * } ); + * } ); + */ + "sUrl": "", + + + /** + * Text shown inside the table records when the is no information to be + * displayed after filtering. sEmptyTable is shown when there is simply no + * information in the table at all (regardless of filtering). + * @type string + * @default No matching records found + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sZeroRecords": "No records to display" + * } + * } ); + * } ); + */ + "sZeroRecords": "No matching records found" + }, + + + /** + * This parameter allows you to have define the global filtering state at + * initialisation time. As an object the "sSearch" parameter must be + * defined, but all other parameters are optional. When "bRegex" is true, + * the search string will be treated as a regular expression, when false + * (default) it will be treated as a straight string. When "bSmart" + * DataTables will use it's smart filtering methods (to word match at + * any point in the data), when false this will not be done. + * @namespace + * @extends DataTable.models.oSearch + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oSearch": {"sSearch": "Initial search"} + * } ); + * } ) + */ + "oSearch": $.extend( {}, DataTable.models.oSearch ), + + + /** + * By default DataTables will look for the property 'aaData' when obtaining + * data from an Ajax source or for server-side processing - this parameter + * allows that property to be changed. You can use Javascript dotted object + * notation to get a data source for multiple levels of nesting. + * @type string + * @default aaData + * @dtopt Options + * @dtopt Server-side + * + * @example + * // Get data from { "data": [...] } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data" + * } ); + * } ); + * + * @example + * // Get data from { "data": { "inner": [...] } } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data.inner" + * } ); + * } ); + */ + "sAjaxDataProp": "aaData", + + + /** + * You can instruct DataTables to load data from an external source using this + * parameter (use aData if you want to pass data in you already have). Simply + * provide a url a JSON object can be obtained from. This object must include + * the parameter 'aaData' which is the data source for the table. + * @type string + * @default null + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php" + * } ); + * } ) + */ + "sAjaxSource": null, + + + /** + * This parameter can be used to override the default prefix that DataTables + * assigns to a cookie when state saving is enabled. + * @type string + * @default SpryMedia_DataTables_ + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sCookiePrefix": "my_datatable_", + * } ); + * } ); + */ + "sCookiePrefix": "SpryMedia_DataTables_", + + + /** + * This initialisation variable allows you to specify exactly where in the + * DOM you want DataTables to inject the various controls it adds to the page + * (for example you might want the pagination controls at the top of the + * table). DIV elements (with or without a custom class) can also be added to + * aid styling. The follow syntax is used: + * <ul> + * <li>The following options are allowed: + * <ul> + * <li>'l' - Length changing</li + * <li>'f' - Filtering input</li> + * <li>'t' - The table!</li> + * <li>'i' - Information</li> + * <li>'p' - Pagination</li> + * <li>'r' - pRocessing</li> + * </ul> + * </li> + * <li>The following constants are allowed: + * <ul> + * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> + * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> + * </ul> + * </li> + * <li>The following syntax is expected: + * <ul> + * <li>'<' and '>' - div elements</li> + * <li>'<"class" and '>' - div with a class</li> + * <li>'<"#id" and '>' - div with an ID</li> + * </ul> + * </li> + * <li>Examples: + * <ul> + * <li>'<"wrapper"flipt>'</li> + * <li>'<lf<t>ip>'</li> + * </ul> + * </li> + * </ul> + * @type string + * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b> + * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sDom": '<"top"i>rt<"bottom"flp><"clear">' + * } ); + * } ); + */ + "sDom": "lfrtip", + + + /** + * DataTables features two different built-in pagination interaction methods + * ('two_button' or 'full_numbers') which present different page controls to + * the end user. Further methods can be added using the API (see below). + * @type string + * @default two_button + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sPaginationType": "full_numbers" + * } ); + * } ) + */ + "sPaginationType": "two_button", + + + /** + * Enable horizontal scrolling. When a table is too wide to fit into a certain + * layout, or you have a large number of columns in the table, you can enable + * x-scrolling to show the table in a viewport, which can be scrolled. This + * property can be any CSS unit, or a number (in which case it will be treated + * as a pixel measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "bScrollCollapse": true + * } ); + * } ); + */ + "sScrollX": "", + + + /** + * This property can be used to force a DataTable to use more width than it + * might otherwise do when x-scrolling is enabled. For example if you have a + * table which requires to be well spaced, this parameter is useful for + * "over-sizing" the table, and thus forcing scrolling. This property can by + * any CSS unit, or a number (in which case it will be treated as a pixel + * measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "sScrollXInner": "110%" + * } ); + * } ); + */ + "sScrollXInner": "", + + + /** + * Enable vertical scrolling. Vertical scrolling will constrain the DataTable + * to the given height, and enable scrolling for any data which overflows the + * current viewport. This can be used as an alternative to paging to display + * a lot of data in a small area (although paging and scrolling can both be + * enabled at the same time). This property can be any CSS unit, or a number + * (in which case it will be treated as a pixel measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * } ); + */ + "sScrollY": "", + + + /** + * Set the HTTP method that is used to make the Ajax call for server-side + * processing or Ajax sourced data. + * @type string + * @default GET + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/post.php", + * "sServerMethod": "POST" + * } ); + * } ); + */ + "sServerMethod": "GET" + }; + + + + /** + * Column options that can be given to DataTables at initialisation time. + * @namespace + */ + DataTable.defaults.columns = { + /** + * Allows a column's sorting to take multiple columns into account when + * doing a sort. For example first name / last name columns make sense to + * do a multi-column sort over the two columns. + * @type array + * @default null <i>Takes the value of the column index automatically</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] }, + * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] }, + * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "aDataSort": [ 0, 1 ] }, + * { "aDataSort": [ 1, 0 ] }, + * { "aDataSort": [ 2, 3, 4 ] }, + * null, + * null + * ] + * } ); + * } ); + */ + "aDataSort": null, + + + /** + * You can control the default sorting direction, and even alter the behaviour + * of the sort handler (i.e. only allow ascending sorting etc) using this + * parameter. + * @type array + * @default [ 'asc', 'desc' ] + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "asSorting": [ "asc" ], "aTargets": [ 1 ] }, + * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] }, + * { "asSorting": [ "desc" ], "aTargets": [ 3 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * { "asSorting": [ "asc" ] }, + * { "asSorting": [ "desc", "asc", "asc" ] }, + * { "asSorting": [ "desc" ] }, + * null + * ] + * } ); + * } ); + */ + "asSorting": [ 'asc', 'desc' ], + + + /** + * Enable or disable filtering on the data in this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSearchable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSearchable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSearchable": true, + + + /** + * Enable or disable sorting on this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSortable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSortable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSortable": true, + + + /** + * <code>Deprecated</code> When using fnRender() for a column, you may wish + * to use the original data (before rendering) for sorting and filtering + * (the default is to used the rendered data that the user can see). This + * may be useful for dates etc. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @default true + * @dtopt Columns + * @deprecated + */ + "bUseRendered": true, + + + /** + * Enable or disable the display of this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bVisible": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bVisible": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bVisible": true, + + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @param {int} iCol The column index for aoColumns + * @dtopt Columns + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [3], + * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) { + * if ( sData == "1.7" ) { + * $(nTd).css('color', 'blue') + * } + * } + * } ] + * }); + * } ); + */ + "fnCreatedCell": null, + + + /** + * <code>Deprecated</code> Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @param {object} o.mDataProp The data property used for this column + * @param {*} val The current cell value + * @returns {string} The string you which to use in the display + * @dtopt Columns + * @deprecated + */ + "fnRender": null, + + + /** + * The column index (starting from 0!) that you wish a sort to be performed + * upon when this column is selected for sorting. This can be used for sorting + * on hidden columns for example. + * @type int + * @default -1 <i>Use automatically calculated column index</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "iDataSort": 1, "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "iDataSort": 1 }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "iDataSort": -1, + + + /** + * This parameter has been replaced by mData in DataTables to ensure naming + * consistency. mDataProp can still be used, as there is backwards compatibility + * in DataTables for this option, but it is strongly recommended that you use + * mData in preference to mDataProp. + * @name DataTable.defaults.columns.mDataProp + */ + + + /** + * This property can be used to read data from any JSON data source property, + * including deeply nested objects / properties. mData can be given in a + * number of different ways which effect its behaviour: + * <ul> + * <li>integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).</li> + * <li>string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source.</li> + * <li>null - the sDefaultContent option will be used for the cell (null + * by default, so you will need to specify the default content you want - + * typically an empty string). This can be useful on generated columns such + * as edit / delete action columns.</li> + * <li>function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + * <ul> + * <li>{array|object} The data source for the row</li> + * <li>{string} The type call data requested - this will be 'set' when + * setting data or 'filter', 'display', 'type', 'sort' or undefined when + * gathering data. Note that when <i>undefined</i> is given for the type + * DataTables expects to get the raw data for the object back</li> + * <li>{*} Data to set when the second parameter is 'set'.</li> + * </ul> + * The return value from the function is not required when 'set' is the type + * of call, but otherwise the return is what will be used for the data + * requested.</li> + * </ul> + * + * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change + * reflects the flexibility of this property and is consistent with the naming of + * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as + * it automatically maps the old name to the new if required. + * @type string|int|function|null + * @default null <i>Use automatically calculated column index</i> + * @dtopt Columns + * + * @example + * // Read table data from objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { "mData": "platform.inner" }, + * { "mData": "platform.details.0" }, + * { "mData": "platform.details.1" } + * ] + * } ); + * } ); + * + * @example + * // Using mData as a function to provide different information for + * // sorting, filtering and display. In this case, currency (price) + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "mData": function ( source, type, val ) { + * if (type === 'set') { + * source.price = val; + * // Store the computed dislay and filter values for efficiency + * source.price_display = val=="" ? "" : "$"+numberFormat(val); + * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; + * return; + * } + * else if (type === 'display') { + * return source.price_display; + * } + * else if (type === 'filter') { + * return source.price_filter; + * } + * // 'sort', 'type' and undefined all just use the integer + * return source.price; + * } + * } ] + * } ); + * } ); + */ + "mData": null, + + + /** + * This property is the rendering partner to mData and it is suggested that + * when you want to manipulate data for display (including filtering, sorting etc) + * but not altering the underlying data for the table, use this property. mData + * can actually do everything this property can and more, but this parameter is + * easier to use since there is no 'set' option. Like mData is can be given + * in a number of different ways to effect its behaviour, with the addition of + * supporting array syntax for easy outputting of arrays (including arrays of + * objects): + * <ul> + * <li>integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).</li> + * <li>string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source and also array brackets to indicate that the data reader should + * loop over the data source array. When characters are given between the array + * brackets, these characters are used to join the data source array together. + * For example: "accounts[, ].name" would result in a comma separated list with + * the 'name' value from the 'accounts' array of objects.</li> + * <li>function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + * <ul> + * <li>{array|object} The data source for the row (based on mData)</li> + * <li>{string} The type call data requested - this will be 'filter', 'display', + * 'type' or 'sort'.</li> + * <li>{array|object} The full data source for the row (not based on mData)</li> + * </ul> + * The return value from the function is what will be used for the data + * requested.</li> + * </ul> + * @type string|int|function|null + * @default null <i>Use mData</i> + * @dtopt Columns + * + * @example + * // Create a comma separated list from an array of objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { + * "mData": "platform", + * "mRender": "[, ].name" + * } + * ] + * } ); + * } ); + * + * @example + * // Use as a function to create a link from the data source + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "aTargets": [ 0 ], + * "mData": "download_link", + * "mRender": function ( data, type, full ) { + * return '<a href="'+data+'">Download</a>'; + * } + * ] + * } ); + * } ); + */ + "mRender": null, + + + /** + * Change the cell type created for the column - either TD cells or TH cells. This + * can be useful as TH cells have semantic meaning in the table body, allowing them + * to act as a header for a row (you may wish to add scope='row' to the TH elements). + * @type string + * @default td + * @dtopt Columns + * + * @example + * // Make the first column use TH cells + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "sCellType": "th" + * } ] + * } ); + * } ); + */ + "sCellType": "td", + + + /** + * Class to give to each cell in this column. + * @type string + * @default <i>Empty string</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sClass": "my_class", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sClass": "my_class" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sClass": "", + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * Generally you shouldn't need this, and it is not documented on the + * general DataTables.net documentation + * @type string + * @default <i>Empty string<i> + * @dtopt Columns + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "sContentPadding": "mmm" + * } + * ] + * } ); + * } ); + */ + "sContentPadding": "", + + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "mData": null, + * "sDefaultContent": "Edit", + * "aTargets": [ -1 ] + * } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "mData": null, + * "sDefaultContent": "Edit" + * } + * ] + * } ); + * } ); + */ + "sDefaultContent": null, + + + /** + * This parameter is only used in DataTables' server-side processing. It can + * be exceptionally useful to know what columns are being displayed on the + * client side, and to map these to database fields. When defined, the names + * also allow DataTables to reorder information from the server if it comes + * back in an unexpected order (i.e. if you switch your columns around on the + * client-side, your server-side code does not also need updating). + * @type string + * @default <i>Empty string</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sName": "engine", "aTargets": [ 0 ] }, + * { "sName": "browser", "aTargets": [ 1 ] }, + * { "sName": "platform", "aTargets": [ 2 ] }, + * { "sName": "version", "aTargets": [ 3 ] }, + * { "sName": "grade", "aTargets": [ 4 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sName": "engine" }, + * { "sName": "browser" }, + * { "sName": "platform" }, + * { "sName": "version" }, + * { "sName": "grade" } + * ] + * } ); + * } ); + */ + "sName": "", + + + /** + * Defines a data source type for the sorting which can be used to read + * real-time information from the table (updating the internally cached + * version) prior to sorting. This allows sorting to occur on user editable + * elements such as form inputs. + * @type string + * @default std + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] }, + * { "sType": "numeric", "aTargets": [ 3 ] }, + * { "sSortDataType": "dom-select", "aTargets": [ 4 ] }, + * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * { "sSortDataType": "dom-text" }, + * { "sSortDataType": "dom-text", "sType": "numeric" }, + * { "sSortDataType": "dom-select" }, + * { "sSortDataType": "dom-checkbox" } + * ] + * } ); + * } ); + */ + "sSortDataType": "std", + + + /** + * The title of this column. + * @type string + * @default null <i>Derived from the 'TH' value for this column in the + * original HTML table.</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sTitle": "My column title", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sTitle": "My column title" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sTitle": null, + + + /** + * The type allows you to specify how the data for this column will be sorted. + * Four types (string, numeric, date and html (which will strip HTML tags + * before sorting)) are currently available. Note that only date formats + * understood by Javascript's Date() object will be accepted as type date. For + * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric', + * 'date' or 'html' (by default). Further types can be adding through + * plug-ins. + * @type string + * @default null <i>Auto-detected from raw data</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sType": "html", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sType": "html" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sType": null, + + + /** + * Defining the width of the column, this parameter may take any CSS value + * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not + * been given a specific width through this interface ensuring that the table + * remains readable. + * @type string + * @default null <i>Automatic</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sWidth": "20%", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sWidth": "20%" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sWidth": null + }; + + + + /** + * DataTables settings object - this holds all the information needed for a + * given table, including configuration, data and current application of the + * table options. DataTables does not have a single instance for each DataTable + * with the settings attached to that instance, but rather instances of the + * DataTable "class" are created on-the-fly as needed (typically by a + * $().dataTable() call) and the settings object is then applied to that + * instance. + * + * Note that this object is related to {@link DataTable.defaults} but this + * one is the internal data store for DataTables's cache of columns. It should + * NOT be manipulated outside of DataTables. Any configuration should be done + * through the initialisation options. + * @namespace + * @todo Really should attach the settings object to individual instances so we + * don't need to create new instances on each $().dataTable() call (if the + * table already exists). It would also save passing oSettings around and + * into every single function. However, this is a very significant + * architecture change for DataTables and will almost certainly break + * backwards compatibility with older installations. This is something that + * will be done in 2.0. + */ + DataTable.models.oSettings = { + /** + * Primary features of DataTables and their enablement state. + * @namespace + */ + "oFeatures": { + + /** + * Flag to say if DataTables should automatically try to calculate the + * optimum table and columns widths (true) or not (false). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoWidth": null, + + /** + * Delay the creation of TR and TD elements until they are actually + * needed by a driven page draw. This can give a significant speed + * increase for Ajax source and Javascript source data, but makes no + * difference at all fro DOM and server-side processing tables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bDeferRender": null, + + /** + * Enable filtering on the table or not. Note that if this is disabled + * then there is no filtering at all on the table, including fnFilter. + * To just remove the filtering input use sDom and remove the 'f' option. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bFilter": null, + + /** + * Table information element (the 'Showing x of y records' div) enable + * flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfo": null, + + /** + * Present a user control allowing the end user to change the page size + * when pagination is enabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bLengthChange": null, + + /** + * Pagination enabled or not. Note that if this is disabled then length + * changing must also be disabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bPaginate": null, + + /** + * Processing indicator enable flag whenever DataTables is enacting a + * user request - typically an Ajax request for server-side processing. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bProcessing": null, + + /** + * Server-side processing enabled flag - when enabled DataTables will + * get all data from the server for every draw - there is no filtering, + * sorting or paging done on the client-side. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bServerSide": null, + + /** + * Sorting enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSort": null, + + /** + * Apply a class to the columns which are being sorted to provide a + * visual highlight or not. This can slow things down when enabled since + * there is a lot of DOM interaction. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortClasses": null, + + /** + * State saving enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bStateSave": null + }, + + + /** + * Scrolling settings for a table. + * @namespace + */ + "oScroll": { + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoCss": null, + + /** + * When the table is shorter in height than sScrollY, collapse the + * table container down to the height of the table (when true). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bCollapse": null, + + /** + * Infinite scrolling enablement flag. Now deprecated in favour of + * using the Scroller plug-in. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfinite": null, + + /** + * Width of the scrollbar for the web-browser's platform. Calculated + * during table initialisation. + * @type int + * @default 0 + */ + "iBarWidth": 0, + + /** + * Space (in pixels) between the bottom of the scrolling container and + * the bottom of the scrolling viewport before the next page is loaded + * when using infinite scrolling. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + */ + "iLoadGap": null, + + /** + * Viewport width for horizontal scrolling. Horizontal scrolling is + * disabled if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sX": null, + + /** + * Width to expand the table to when using x-scrolling. Typically you + * should not need to use this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @deprecated + */ + "sXInner": null, + + /** + * Viewport height for vertical scrolling. Vertical scrolling is disabled + * if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sY": null + }, + + /** + * Language information for the table. + * @namespace + * @extends DataTable.defaults.oLanguage + */ + "oLanguage": { + /** + * Information callback function. See + * {@link DataTable.defaults.fnInfoCallback} + * @type function + * @default null + */ + "fnInfoCallback": null + }, + + /** + * Browser support parameters + * @namespace + */ + "oBrowser": { + /** + * Indicate if the browser incorrectly calculates width:100% inside a + * scrolling element (IE6/7) + * @type boolean + * @default false + */ + "bScrollOversize": false + }, + + /** + * Array referencing the nodes which are used for the features. The + * parameters of this object match what is allowed by sDom - i.e. + * <ul> + * <li>'l' - Length changing</li> + * <li>'f' - Filtering input</li> + * <li>'t' - The table!</li> + * <li>'i' - Information</li> + * <li>'p' - Pagination</li> + * <li>'r' - pRocessing</li> + * </ul> + * @type array + * @default [] + */ + "aanFeatures": [], + + /** + * Store data information - see {@link DataTable.models.oRow} for detailed + * information. + * @type array + * @default [] + */ + "aoData": [], + + /** + * Array of indexes which are in the current display (after filtering etc) + * @type array + * @default [] + */ + "aiDisplay": [], + + /** + * Array of indexes for display - no filtering + * @type array + * @default [] + */ + "aiDisplayMaster": [], + + /** + * Store information about each column that is in use + * @type array + * @default [] + */ + "aoColumns": [], + + /** + * Store information about the table's header + * @type array + * @default [] + */ + "aoHeader": [], + + /** + * Store information about the table's footer + * @type array + * @default [] + */ + "aoFooter": [], + + /** + * Search data array for regular expression searching + * @type array + * @default [] + */ + "asDataSearch": [], + + /** + * Store the applied global search information in case we want to force a + * research or compare the old search to a new one. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @namespace + * @extends DataTable.models.oSearch + */ + "oPreviousSearch": {}, + + /** + * Store the applied search for each column - see + * {@link DataTable.models.oSearch} for the format that is used for the + * filtering information for each column. + * @type array + * @default [] + */ + "aoPreSearchCols": [], + + /** + * Sorting that is applied to the table. Note that the inner arrays are + * used in the following manner: + * <ul> + * <li>Index 0 - column number</li> + * <li>Index 1 - current sorting direction</li> + * <li>Index 2 - index of asSorting for this column</li> + * </ul> + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @todo These inner arrays should really be objects + */ + "aaSorting": null, + + /** + * Sorting that is always applied to the table (i.e. prefixed in front of + * aaSorting). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array|null + * @default null + */ + "aaSortingFixed": null, + + /** + * Classes to use for the striping of a table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "asStripeClasses": null, + + /** + * If restoring a table - we should restore its striping classes as well + * @type array + * @default [] + */ + "asDestroyStripes": [], + + /** + * If restoring a table - we should restore its width + * @type int + * @default 0 + */ + "sDestroyWidth": 0, + + /** + * Callback functions array for every time a row is inserted (i.e. on a draw). + * @type array + * @default [] + */ + "aoRowCallback": [], + + /** + * Callback functions for the header on each draw. + * @type array + * @default [] + */ + "aoHeaderCallback": [], + + /** + * Callback function for the footer on each draw. + * @type array + * @default [] + */ + "aoFooterCallback": [], + + /** + * Array of callback functions for draw callback functions + * @type array + * @default [] + */ + "aoDrawCallback": [], + + /** + * Array of callback functions for row created function + * @type array + * @default [] + */ + "aoRowCreatedCallback": [], + + /** + * Callback functions for just before the table is redrawn. A return of + * false will be used to cancel the draw. + * @type array + * @default [] + */ + "aoPreDrawCallback": [], + + /** + * Callback functions for when the table has been initialised. + * @type array + * @default [] + */ + "aoInitComplete": [], + + + /** + * Callbacks for modifying the settings to be stored for state saving, prior to + * saving state. + * @type array + * @default [] + */ + "aoStateSaveParams": [], + + /** + * Callbacks for modifying the settings that have been stored for state saving + * prior to using the stored values to restore the state. + * @type array + * @default [] + */ + "aoStateLoadParams": [], + + /** + * Callbacks for operating on the settings object once the saved state has been + * loaded + * @type array + * @default [] + */ + "aoStateLoaded": [], + + /** + * Cache the table ID for quick access + * @type string + * @default <i>Empty string</i> + */ + "sTableId": "", + + /** + * The TABLE node for the main table + * @type node + * @default null + */ + "nTable": null, + + /** + * Permanent ref to the thead element + * @type node + * @default null + */ + "nTHead": null, + + /** + * Permanent ref to the tfoot element - if it exists + * @type node + * @default null + */ + "nTFoot": null, + + /** + * Permanent ref to the tbody element + * @type node + * @default null + */ + "nTBody": null, + + /** + * Cache the wrapper node (contains all DataTables controlled elements) + * @type node + * @default null + */ + "nTableWrapper": null, + + /** + * Indicate if when using server-side processing the loading of data + * should be deferred until the second draw. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + * @default false + */ + "bDeferLoading": false, + + /** + * Indicate if all required information has been read in + * @type boolean + * @default false + */ + "bInitialised": false, + + /** + * Information about open rows. Each object in the array has the parameters + * 'nTr' and 'nParent' + * @type array + * @default [] + */ + "aoOpenRows": [], + + /** + * Dictate the positioning of DataTables' control elements - see + * {@link DataTable.model.oInit.sDom}. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sDom": null, + + /** + * Which type of pagination should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default two_button + */ + "sPaginationType": "two_button", + + /** + * The cookie duration (for bStateSave) in seconds. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + * @default 0 + */ + "iCookieDuration": 0, + + /** + * The cookie name prefix. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default <i>Empty string</i> + */ + "sCookiePrefix": "", + + /** + * Callback function for cookie creation. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + * @default null + */ + "fnCookieCallback": null, + + /** + * Array of callback functions for state saving. Each array element is an + * object with the following parameters: + * <ul> + * <li>function:fn - function to call. Takes two parameters, oSettings + * and the JSON string to save that has been thus far created. Returns + * a JSON string to be inserted into a json object + * (i.e. '"param": [ 0, 1, 2]')</li> + * <li>string:sName - name of callback</li> + * </ul> + * @type array + * @default [] + */ + "aoStateSave": [], + + /** + * Array of callback functions for state loading. Each array element is an + * object with the following parameters: + * <ul> + * <li>function:fn - function to call. Takes two parameters, oSettings + * and the object stored. May return false to cancel state loading</li> + * <li>string:sName - name of callback</li> + * </ul> + * @type array + * @default [] + */ + "aoStateLoad": [], + + /** + * State that was loaded from the cookie. Useful for back reference + * @type object + * @default null + */ + "oLoadedState": null, + + /** + * Source url for AJAX data for the table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sAjaxSource": null, + + /** + * Property from a given object from which to read the table data from. This + * can be an empty string (when not server-side processing), in which case + * it is assumed an an array is given directly. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sAjaxDataProp": null, + + /** + * Note if draw should be blocked while getting data + * @type boolean + * @default true + */ + "bAjaxDataGet": true, + + /** + * The last jQuery XHR object that was used for server-side data gathering. + * This can be used for working with the XHR information in one of the + * callbacks + * @type object + * @default null + */ + "jqXHR": null, + + /** + * Function to get the server-side data. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnServerData": null, + + /** + * Functions which are called prior to sending an Ajax request so extra + * parameters can easily be sent to the server + * @type array + * @default [] + */ + "aoServerParams": [], + + /** + * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if + * required). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sServerMethod": null, + + /** + * Format numbers for display. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnFormatNumber": null, + + /** + * List of options that can be used for the user selectable length menu. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "aLengthMenu": null, + + /** + * Counter for the draws that the table does. Also used as a tracker for + * server-side processing + * @type int + * @default 0 + */ + "iDraw": 0, + + /** + * Indicate if a redraw is being done - useful for Ajax + * @type boolean + * @default false + */ + "bDrawing": false, + + /** + * Draw index (iDraw) of the last error when parsing the returned data + * @type int + * @default -1 + */ + "iDrawError": -1, + + /** + * Paging display length + * @type int + * @default 10 + */ + "_iDisplayLength": 10, + + /** + * Paging start point - aiDisplay index + * @type int + * @default 0 + */ + "_iDisplayStart": 0, + + /** + * Paging end point - aiDisplay index. Use fnDisplayEnd rather than + * this property to get the end point + * @type int + * @default 10 + * @private + */ + "_iDisplayEnd": 10, + + /** + * Server-side processing - number of records in the result set + * (i.e. before filtering), Use fnRecordsTotal rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type int + * @default 0 + * @private + */ + "_iRecordsTotal": 0, + + /** + * Server-side processing - number of records in the current display set + * (i.e. after filtering). Use fnRecordsDisplay rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type boolean + * @default 0 + * @private + */ + "_iRecordsDisplay": 0, + + /** + * Flag to indicate if jQuery UI marking and classes should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bJUI": null, + + /** + * The classes to use for the table + * @type object + * @default {} + */ + "oClasses": {}, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if filtering has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bFiltered": false, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if sorting has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bSorted": false, + + /** + * Indicate that if multiple rows are in the header and there is more than + * one unique cell per column, if the top one (true) or bottom one (false) + * should be used for sorting / title by DataTables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortCellsTop": null, + + /** + * Initialisation object that is used for the table + * @type object + * @default null + */ + "oInit": null, + + /** + * Destroy callback functions - for plug-ins to attach themselves to the + * destroy so they can clean up markup and events. + * @type array + * @default [] + */ + "aoDestroyCallback": [], + + + /** + * Get the number of records in the current record set, before filtering + * @type function + */ + "fnRecordsTotal": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsTotal, 10); + } else { + return this.aiDisplayMaster.length; + } + }, + + /** + * Get the number of records in the current record set, after filtering + * @type function + */ + "fnRecordsDisplay": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsDisplay, 10); + } else { + return this.aiDisplay.length; + } + }, + + /** + * Set the display end point - aiDisplay index + * @type function + * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here + */ + "fnDisplayEnd": function () + { + if ( this.oFeatures.bServerSide ) { + if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) { + return this._iDisplayStart+this.aiDisplay.length; + } else { + return Math.min( this._iDisplayStart+this._iDisplayLength, + this._iRecordsDisplay ); + } + } else { + return this._iDisplayEnd; + } + }, + + /** + * The DataTables object for this table + * @type object + * @default null + */ + "oInstance": null, + + /** + * Unique identifier for each instance of the DataTables object. If there + * is an ID on the table node, then it takes that value, otherwise an + * incrementing internal counter is used. + * @type string + * @default null + */ + "sInstance": null, + + /** + * tabindex attribute value that is added to DataTables control elements, allowing + * keyboard navigation of the table and its controls. + */ + "iTabIndex": 0, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollHead": null, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollFoot": null + }; + + /** + * Extension object for DataTables that is used to provide all extension options. + * + * Note that the <i>DataTable.ext</i> object is available through + * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is + * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons. + * @namespace + * @extends DataTable.models.ext + */ + DataTable.ext = $.extend( true, {}, DataTable.models.ext ); + + $.extend( DataTable.ext.oStdClasses, { + "sTable": "dataTable", + + /* Two buttons buttons */ + "sPagePrevEnabled": "paginate_enabled_previous", + "sPagePrevDisabled": "paginate_disabled_previous", + "sPageNextEnabled": "paginate_enabled_next", + "sPageNextDisabled": "paginate_disabled_next", + "sPageJUINext": "", + "sPageJUIPrev": "", + + /* Full numbers paging buttons */ + "sPageButton": "paginate_button", + "sPageButtonActive": "paginate_active", + "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled", + "sPageFirst": "first", + "sPagePrevious": "previous", + "sPageNext": "next", + "sPageLast": "last", + + /* Striping classes */ + "sStripeOdd": "odd", + "sStripeEven": "even", + + /* Empty row */ + "sRowEmpty": "dataTables_empty", + + /* Features */ + "sWrapper": "dataTables_wrapper", + "sFilter": "dataTables_filter", + "sInfo": "dataTables_info", + "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ + "sLength": "dataTables_length", + "sProcessing": "dataTables_processing", + + /* Sorting */ + "sSortAsc": "sorting_asc", + "sSortDesc": "sorting_desc", + "sSortable": "sorting", /* Sortable in both directions */ + "sSortableAsc": "sorting_asc_disabled", + "sSortableDesc": "sorting_desc_disabled", + "sSortableNone": "sorting_disabled", + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ + "sSortJUIAsc": "", + "sSortJUIDesc": "", + "sSortJUI": "", + "sSortJUIAscAllowed": "", + "sSortJUIDescAllowed": "", + "sSortJUIWrapper": "", + "sSortIcon": "", + + /* Scrolling */ + "sScrollWrapper": "dataTables_scroll", + "sScrollHead": "dataTables_scrollHead", + "sScrollHeadInner": "dataTables_scrollHeadInner", + "sScrollBody": "dataTables_scrollBody", + "sScrollFoot": "dataTables_scrollFoot", + "sScrollFootInner": "dataTables_scrollFootInner", + + /* Misc */ + "sFooterTH": "", + "sJUIHeader": "", + "sJUIFooter": "" + } ); + + + $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, { + /* Two buttons buttons */ + "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left", + "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled", + "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right", + "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled", + "sPageJUINext": "ui-icon ui-icon-circle-arrow-e", + "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w", + + /* Full numbers paging buttons */ + "sPageButton": "fg-button ui-button ui-state-default", + "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageFirst": "first ui-corner-tl ui-corner-bl", + "sPageLast": "last ui-corner-tr ui-corner-br", + + /* Features */ + "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ + "ui-buttonset-multi paging_", /* Note that the type is postfixed */ + + /* Sorting */ + "sSortAsc": "ui-state-default", + "sSortDesc": "ui-state-default", + "sSortable": "ui-state-default", + "sSortableAsc": "ui-state-default", + "sSortableDesc": "ui-state-default", + "sSortableNone": "ui-state-default", + "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n", + "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s", + "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s", + "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n", + "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s", + "sSortJUIWrapper": "DataTables_sort_wrapper", + "sSortIcon": "DataTables_sort_icon", + + /* Scrolling */ + "sScrollHead": "dataTables_scrollHead ui-state-default", + "sScrollFoot": "dataTables_scrollFoot ui-state-default", + + /* Misc */ + "sFooterTH": "ui-state-default", + "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix", + "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix" + } ); + + /* + * Variable: oPagination + * Purpose: + * Scope: jQuery.fn.dataTableExt + */ + $.extend( DataTable.ext.oPagination, { + /* + * Variable: two_button + * Purpose: Standard two button (forward/back) pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "two_button": { + /* + * Function: oPagination.two_button.fnInit + * Purpose: Initialise dom elements required for pagination with forward/back buttons only + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var oLang = oSettings.oLanguage.oPaginate; + var oClasses = oSettings.oClasses; + var fnClickHandler = function ( e ) { + if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) + { + fnCallbackDraw( oSettings ); + } + }; + + var sAppend = (!oSettings.bJUI) ? + '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+ + '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>' + : + '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+ + '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>'; + $(nPaging).append( sAppend ); + + var els = $('a', nPaging); + var nPrevious = els[0], + nNext = els[1]; + + oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nPrevious.id = oSettings.sTableId+'_previous'; + nNext.id = oSettings.sTableId+'_next'; + + nPrevious.setAttribute('aria-controls', oSettings.sTableId); + nNext.setAttribute('aria-controls', oSettings.sTableId); + } + }, + + /* + * Function: oPagination.two_button.fnUpdate + * Purpose: Update the two button pagination at the end of the draw + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var oClasses = oSettings.oClasses; + var an = oSettings.aanFeatures.p; + var nNode; + + /* Loop over each instance of the pager */ + for ( var i=0, iLen=an.length ; i<iLen ; i++ ) + { + nNode = an[i].firstChild; + if ( nNode ) + { + /* Previous page */ + nNode.className = ( oSettings._iDisplayStart === 0 ) ? + oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled; + + /* Next page */ + nNode = nNode.nextSibling; + nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ? + oClasses.sPageNextDisabled : oClasses.sPageNextEnabled; + } + } + } + }, + + + /* + * Variable: iFullNumbersShowPages + * Purpose: Change the number of pages which can be seen + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "iFullNumbersShowPages": 5, + + /* + * Variable: full_numbers + * Purpose: Full numbers pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "full_numbers": { + /* + * Function: oPagination.full_numbers.fnInit + * Purpose: Initialise dom elements required for pagination with a list of the pages + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var oLang = oSettings.oLanguage.oPaginate; + var oClasses = oSettings.oClasses; + var fnClickHandler = function ( e ) { + if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) + { + fnCallbackDraw( oSettings ); + } + }; + + $(nPaging).append( + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+ + '<span></span>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>' + ); + var els = $('a', nPaging); + var nFirst = els[0], + nPrev = els[1], + nNext = els[2], + nLast = els[3]; + + oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nFirst.id =oSettings.sTableId+'_first'; + nPrev.id =oSettings.sTableId+'_previous'; + nNext.id =oSettings.sTableId+'_next'; + nLast.id =oSettings.sTableId+'_last'; + } + }, + + /* + * Function: oPagination.full_numbers.fnUpdate + * Purpose: Update the list of page buttons shows + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages; + var iPageCountHalf = Math.floor(iPageCount / 2); + var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength); + var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; + var sList = ""; + var iStartButton, iEndButton, i, iLen; + var oClasses = oSettings.oClasses; + var anButtons, anStatic, nPaginateList, nNode; + var an = oSettings.aanFeatures.p; + var fnBind = function (j) { + oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) { + /* Use the information in the element to jump to the required page */ + oSettings.oApi._fnPageChange( oSettings, e.data.page ); + fnCallbackDraw( oSettings ); + e.preventDefault(); + } ); + }; + + /* Pages calculation */ + if ( oSettings._iDisplayLength === -1 ) + { + iStartButton = 1; + iEndButton = 1; + iCurrentPage = 1; + } + else if (iPages < iPageCount) + { + iStartButton = 1; + iEndButton = iPages; + } + else if (iCurrentPage <= iPageCountHalf) + { + iStartButton = 1; + iEndButton = iPageCount; + } + else if (iCurrentPage >= (iPages - iPageCountHalf)) + { + iStartButton = iPages - iPageCount + 1; + iEndButton = iPages; + } + else + { + iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1; + iEndButton = iStartButton + iPageCount - 1; + } + + + /* Build the dynamic list */ + for ( i=iStartButton ; i<=iEndButton ; i++ ) + { + sList += (iCurrentPage !== i) ? + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' : + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>'; + } + + /* Loop over each instance of the pager */ + for ( i=0, iLen=an.length ; i<iLen ; i++ ) + { + nNode = an[i]; + if ( !nNode.hasChildNodes() ) + { + continue; + } + + /* Build up the dynamic list first - html and listeners */ + $('span:eq(0)', nNode) + .html( sList ) + .children('a').each( fnBind ); + + /* Update the permanent button's classes */ + anButtons = nNode.getElementsByTagName('a'); + anStatic = [ + anButtons[0], anButtons[1], + anButtons[anButtons.length-2], anButtons[anButtons.length-1] + ]; + + $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled ); + $([anStatic[0], anStatic[1]]).addClass( + (iCurrentPage==1) ? + oClasses.sPageButtonStaticDisabled : + oClasses.sPageButton + ); + $([anStatic[2], anStatic[3]]).addClass( + (iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ? + oClasses.sPageButtonStaticDisabled : + oClasses.sPageButton + ); + } + } + } + } ); + + $.extend( DataTable.ext.oSort, { + /* + * text sorting + */ + "string-pre": function ( a ) + { + if ( typeof a != 'string' ) { + a = (a !== null && a.toString) ? a.toString() : ''; + } + return a.toLowerCase(); + }, + + "string-asc": function ( x, y ) + { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "string-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * html sorting (ignore html tags) + */ + "html-pre": function ( a ) + { + return a.replace( /<.*?>/g, "" ).toLowerCase(); + }, + + "html-asc": function ( x, y ) + { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "html-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * date sorting + */ + "date-pre": function ( a ) + { + var x = Date.parse( a ); + + if ( isNaN(x) || x==="" ) + { + x = Date.parse( "01/01/1970 00:00:00" ); + } + return x; + }, + + "date-asc": function ( x, y ) + { + return x - y; + }, + + "date-desc": function ( x, y ) + { + return y - x; + }, + + + /* + * numerical sorting + */ + "numeric-pre": function ( a ) + { + return (a=="-" || a==="") ? 0 : a*1; + }, + + "numeric-asc": function ( x, y ) + { + return x - y; + }, + + "numeric-desc": function ( x, y ) + { + return y - x; + } + } ); + + + $.extend( DataTable.ext.aTypes, [ + /* + * Function: - + * Purpose: Check to see if a string is numeric + * Returns: string:'numeric' or null + * Inputs: mixed:sText - string to check + */ + function ( sData ) + { + /* Allow zero length strings as a number */ + if ( typeof sData === 'number' ) + { + return 'numeric'; + } + else if ( typeof sData !== 'string' ) + { + return null; + } + + var sValidFirstChars = "0123456789-"; + var sValidChars = "0123456789."; + var Char; + var bDecimal = false; + + /* Check for a valid first char (no period and allow negatives) */ + Char = sData.charAt(0); + if (sValidFirstChars.indexOf(Char) == -1) + { + return null; + } + + /* Check all the other characters are valid */ + for ( var i=1 ; i<sData.length ; i++ ) + { + Char = sData.charAt(i); + if (sValidChars.indexOf(Char) == -1) + { + return null; + } + + /* Only allowed one decimal place... */ + if ( Char == "." ) + { + if ( bDecimal ) + { + return null; + } + bDecimal = true; + } + } + + return 'numeric'; + }, + + /* + * Function: - + * Purpose: Check to see if a string is actually a formatted date + * Returns: string:'date' or null + * Inputs: string:sText - string to check + */ + function ( sData ) + { + var iParse = Date.parse(sData); + if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) ) + { + return 'date'; + } + return null; + }, + + /* + * Function: - + * Purpose: Check to see if a string should be treated as an HTML string + * Returns: string:'html' or null + * Inputs: string:sText - string to check + */ + function ( sData ) + { + if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 ) + { + return 'html'; + } + return null; + } + ] ); + + + // jQuery aliases + $.fn.DataTable = DataTable; + $.fn.dataTable = DataTable; + $.fn.dataTableSettings = DataTable.settings; + $.fn.dataTableExt = DataTable.ext; + + + // Information about events fired by DataTables - for documentation. + /** + * Draw event, fired whenever the table is redrawn on the page, at the same point as + * fnDrawCallback. This may be useful for binding events or performing calculations when + * the table is altered at all. + * @name DataTable#draw + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Filter event, fired when the filtering applied to the table (using the build in global + * global filter, or column filters) is altered. + * @name DataTable#filter + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Page change event, fired when the paging of the table is altered. + * @name DataTable#page + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Sort event, fired when the sorting applied to the table is altered. + * @name DataTable#sort + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * DataTables initialisation complete event, fired when the table is fully drawn, + * including Ajax data loaded, if Ajax data is required. + * @name DataTable#init + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The JSON object request from the server - only + * present if client-side Ajax sourced data is used</li></ol> + */ + + /** + * State save event, fired when the table has changed state a new state save is required. + * This method allows modification of the state saving object prior to actually doing the + * save, including addition or other state properties (for plug-ins) or modification + * of a DataTables core property. + * @name DataTable#stateSaveParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The state information to be saved + */ + + /** + * State load event, fired when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state - allowing modification + * of the saved state is required or loading of state for a plug-in. + * @name DataTable#stateLoadParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * State loaded event, fired when state has been loaded from stored data and the settings + * object has been modified by the loaded data. + * @name DataTable#stateLoaded + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * Processing event, fired when DataTables is doing some kind of processing (be it, + * sort, filter or anything else). Can be used to indicate to the end user that + * there is something happening, or that something has finished. + * @name DataTable#processing + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {boolean} bShow Flag for if DataTables is doing processing or not + */ + + /** + * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to + * made to the server for new data (note that this trigger is called in fnServerData, + * if you override fnServerData and which to use this event, you need to trigger it in + * you success function). + * @name DataTable#xhr + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + * @param {object} json JSON returned from the server + */ + + /** + * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing + * the bDestroy:true parameter in the initialisation object. This can be used to remove + * bound events, added DOM nodes, etc. + * @name DataTable#destroy + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ +})); + +}(window, document)); + diff --git a/themes/default/js/plugins/jquery.jgrowl.css b/themes/default/js/plugins/jquery.jgrowl.css new file mode 100644 index 000000000..376d224c2 --- /dev/null +++ b/themes/default/js/plugins/jquery.jgrowl.css @@ -0,0 +1,158 @@ +div.jGrowl { + z-index: 9999; + color: #fff; + font-size: 12px; +} + +div.jGrowl-notification.success>div, +div.jGrowl-notification.error>div, +div.jGrowl-notification.warning>div{ + margin-left:45px; +} +div.jGrowl-notification.success { + background: url(jgrowl-check.png) no-repeat 5px 5px; +} +div.jGrowl-notification.error { + background: url(jgrowl-error.png) no-repeat 5px 5px; +} +div.jGrowl-notification.warning { + background: url(jgrowl-alert.png) no-repeat 5px 5px; +} +div.jGrowl-notification.warning:before { + content:none; +} + +/** Cross Browser Styling **/ +div.center div.jGrowl-notification, div.center div.jGrowl-closer { + margin-left: auto; + margin-right: auto; +} + +div.jGrowl div.jGrowl-notification, div.jGrowl div.jGrowl-closer { + background-color: #000; + opacity: .85; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)"; + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85); + zoom: 1; + width: 300px; + padding: 5px; + margin-top: 5px; + margin-bottom: 5px; + font-family: Tahoma, Arial, Helvetica, sans-serif; + font-size: 1em; + text-align: left; + display: none; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +div.jGrowl div.jGrowl-notification { + min-height: 40px; +} + +div.jGrowl div.jGrowl-notification, +div.jGrowl div.jGrowl-closer { + margin: 8px; +} + +div.jGrowl div.jGrowl-notification div.jGrowl-header { + font-weight: bold; + font-size: 1em; +} + +div.jGrowl div.jGrowl-notification div.jGrowl-message { + font-size: 0.9em; +} + +div.jGrowl div.jGrowl-notification div.jGrowl-close { + z-index: 99; + float: right; + font-weight: bold; + font-size: 1em; + cursor: pointer; +} + +div.jGrowl div.jGrowl-closer { + padding-top: 4px; + padding-bottom: 4px; + cursor: pointer; + font-size: .9em; + font-weight: bold; + text-align: center; +} + +/** Hide jGrowl when printing **/ +@media print { + div.jGrowl { + display: none; + } +} + +/** Special IE6 Style Positioning **/ +div.ie6 { + position: absolute; +} + +div.ie6.top-right { + right: auto; + bottom: auto; + left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.top-left { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.bottom-right { + left: expression( ( 0 - jGrowl.offsetWidth + ( document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth ) + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.bottom-left { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 - jGrowl.offsetHeight + ( document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); +} + +div.ie6.center { + left: expression( ( 0 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' ); + top: expression( ( 0 + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ) ) + 'px' ); + width: 100%; +} + +/** Normal Style Positions **/ +div.jGrowl { + position: absolute; +} + +body > div.jGrowl { + position: fixed; +} + +div.jGrowl.top-left { + left: 0px; + top: 0px; +} + +div.jGrowl.top-right { + right: 0px; + top: 0px; +} + +div.jGrowl.bottom-left { + left: 0px; + bottom: 0px; +} + +div.jGrowl.bottom-right { + right: 0px; + bottom: 0px; +} + +div.jGrowl.center { + top: 0px; + width: 50%; + left: 25%; +}
\ No newline at end of file diff --git a/themes/default/js/plugins/jquery.jgrowl_minimized.js b/themes/default/js/plugins/jquery.jgrowl_minimized.js index 02503a0db..4aca192d7 100644 --- a/themes/default/js/plugins/jquery.jgrowl_minimized.js +++ b/themes/default/js/plugins/jquery.jgrowl_minimized.js @@ -1,9 +1,4 @@ -(function($){$.jGrowl=function(m,o){if($('#jGrowl').size()==0) -$('<div id="jGrowl"></div>').addClass($.jGrowl.defaults.position).appendTo('body');$('#jGrowl').jGrowl(m,o);};$.fn.jGrowl=function(m,o){if($.isFunction(this.each)){var args=arguments;return this.each(function(){var self=this;if($(this).data('jGrowl.instance')==undefined){$(this).data('jGrowl.instance',$.extend(new $.fn.jGrowl(),{notifications:[],element:null,interval:null}));$(this).data('jGrowl.instance').startup(this);} -if($.isFunction($(this).data('jGrowl.instance')[m])){$(this).data('jGrowl.instance')[m].apply($(this).data('jGrowl.instance'),$.makeArray(args).slice(1));}else{$(this).data('jGrowl.instance').create(m,o);}});};};$.extend($.fn.jGrowl.prototype,{defaults:{pool:0,header:'',group:'',sticky:false,position:'top-right',glue:'after',theme:'default',corners:'10px',check:250,life:3000,speed:'normal',easing:'swing',closer:true,closeTemplate:'×',closerTemplate:'<div>[ close all ]</div>',log:function(e,m,o){},beforeOpen:function(e,m,o){},open:function(e,m,o){},beforeClose:function(e,m,o){},close:function(e,m,o){},animateOpen:{opacity:'show'},animateClose:{opacity:'hide'}},notifications:[],element:null,interval:null,create:function(message,o){var o=$.extend({},this.defaults,o);this.notifications.push({message:message,options:o});o.log.apply(this.element,[this.element,message,o]);},render:function(notification){var self=this;var message=notification.message;var o=notification.options;var notification=$('<div class="jGrowl-notification ui-state-highlight ui-corner-all'+ -((o.group!=undefined&&o.group!='')?' '+o.group:'')+'">'+'<div class="close">'+o.closeTemplate+'</div>'+'<div class="header">'+o.header+'</div>'+'<div class="message">'+message+'</div></div>').data("jGrowl",o).addClass(o.theme).children('div.close').bind("click.jGrowl",function(){$(this).parent().trigger('jGrowl.close');}).parent();$(notification).bind("mouseover.jGrowl",function(){$('div.jGrowl-notification',self.element).data("jGrowl.pause",true);}).bind("mouseout.jGrowl",function(){$('div.jGrowl-notification',self.element).data("jGrowl.pause",false);}).bind('jGrowl.beforeOpen',function(){if(o.beforeOpen.apply(notification,[notification,message,o,self.element])!=false){$(this).trigger('jGrowl.open');}}).bind('jGrowl.open',function(){if(o.open.apply(notification,[notification,message,o,self.element])!=false){if(o.glue=='after'){$('div.jGrowl-notification:last',self.element).after(notification);}else{$('div.jGrowl-notification:first',self.element).before(notification);} -$(this).animate(o.animateOpen,o.speed,o.easing,function(){if($.browser.msie&&(parseInt($(this).css('opacity'),10)===1||parseInt($(this).css('opacity'),10)===0)) -this.style.removeAttribute('filter');$(this).data("jGrowl").created=new Date();});}}).bind('jGrowl.beforeClose',function(){if(o.beforeClose.apply(notification,[notification,message,o,self.element])!=false) -$(this).trigger('jGrowl.close');}).bind('jGrowl.close',function(){$(this).data('jGrowl.pause',true);$(this).animate(o.animateClose,o.speed,o.easing,function(){$(this).remove();var close=o.close.apply(notification,[notification,message,o,self.element]);if($.isFunction(close)) -close.apply(notification,[notification,message,o,self.element]);});}).trigger('jGrowl.beforeOpen');if($.fn.corner!=undefined)$(notification).corner(o.corners);if($('div.jGrowl-notification:parent',self.element).size()>1&&$('div.jGrowl-closer',self.element).size()==0&&this.defaults.closer!=false){$(this.defaults.closerTemplate).addClass('jGrowl-closer ui-state-highlight ui-corner-all').addClass(this.defaults.theme).appendTo(self.element).animate(this.defaults.animateOpen,this.defaults.speed,this.defaults.easing).bind("click.jGrowl",function(){$(this).siblings().children('div.close').trigger("click.jGrowl");if($.isFunction(self.defaults.closer)){self.defaults.closer.apply($(this).parent()[0],[$(this).parent()[0]]);}});};},update:function(){$(this.element).find('div.jGrowl-notification:parent').each(function(){if($(this).data("jGrowl")!=undefined&&$(this).data("jGrowl").created!=undefined&&($(this).data("jGrowl").created.getTime()+$(this).data("jGrowl").life)<(new Date()).getTime()&&$(this).data("jGrowl").sticky!=true&&($(this).data("jGrowl.pause")==undefined||$(this).data("jGrowl.pause")!=true)){$(this).trigger('jGrowl.beforeClose');}});if(this.notifications.length>0&&(this.defaults.pool==0||$(this.element).find('div.jGrowl-notification:parent').size()<this.defaults.pool)) -this.render(this.notifications.shift());if($(this.element).find('div.jGrowl-notification:parent').size()<2){$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose,this.defaults.speed,this.defaults.easing,function(){$(this).remove();});}},startup:function(e){this.element=$(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');this.interval=setInterval(function(){$(e).data('jGrowl.instance').update();},this.defaults.check);if($.browser.msie&&parseInt($.browser.version)<7&&!window["XMLHttpRequest"]){$(this.element).addClass('ie6');}},shutdown:function(){$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();clearInterval(this.interval);},close:function(){$(this.element).find('div.jGrowl-notification').each(function(){$(this).trigger('jGrowl.beforeClose');});}});$.jGrowl.defaults=$.fn.jGrowl.prototype.defaults;})(jQuery);
\ No newline at end of file +(function(e){var t=function(){return!1===e.support.boxModel&&e.support.objectAll&&e.support.leadingWhitespace}();e.jGrowl=function(t,i){0==e("#jGrowl").size()&&e('<div id="jGrowl"></div>').addClass(i&&i.position?i.position:e.jGrowl.defaults.position).appendTo("body"),e("#jGrowl").jGrowl(t,i)},e.fn.jGrowl=function(t,i){if(e.isFunction(this.each)){var o=arguments;return this.each(function(){void 0==e(this).data("jGrowl.instance")&&(e(this).data("jGrowl.instance",e.extend(new e.fn.jGrowl,{notifications:[],element:null,interval:null})),e(this).data("jGrowl.instance").startup(this)),e.isFunction(e(this).data("jGrowl.instance")[t])?e(this).data("jGrowl.instance")[t].apply(e(this).data("jGrowl.instance"),e.makeArray(o).slice(1)):e(this).data("jGrowl.instance").create(t,i)})}},e.extend(e.fn.jGrowl.prototype,{defaults:{pool:0,header:"",group:"",sticky:!1,position:"top-right",glue:"after",theme:"default",themeState:"highlight",corners:"10px",check:250,life:3e3,closeDuration:"normal",openDuration:"normal",easing:"swing",closer:!0,closeTemplate:"×",closerTemplate:"<div>[ close all ]</div>",log:function(){},beforeOpen:function(){},afterOpen:function(){},open:function(){},beforeClose:function(){},close:function(){},animateOpen:{opacity:"show"},animateClose:{opacity:"hide"}},notifications:[],element:null,interval:null,create:function(t,i){var i=e.extend({},this.defaults,i);i.speed!==void 0&&(i.openDuration=i.speed,i.closeDuration=i.speed),this.notifications.push({message:t,options:i}),i.log.apply(this.element,[this.element,t,i])},render:function(t){var i=this,o=t.message,n=t.options;n.themeState=""==n.themeState?"":"ui-state-"+n.themeState;var t=e("<div/>").addClass("jGrowl-notification "+n.themeState+" ui-corner-all"+(void 0!=n.group&&""!=n.group?" "+n.group:"")).append(e("<div/>").addClass("jGrowl-close").html(n.closeTemplate)).append(e("<div/>").addClass("jGrowl-header").html(n.header)).append(e("<div/>").addClass("jGrowl-message").html(o)).data("jGrowl",n).addClass(n.theme).children("div.jGrowl-close").bind("click.jGrowl",function(){e(this).parent().trigger("jGrowl.beforeClose")}).parent();e(t).bind("mouseover.jGrowl",function(){e("div.jGrowl-notification",i.element).data("jGrowl.pause",!0)}).bind("mouseout.jGrowl",function(){e("div.jGrowl-notification",i.element).data("jGrowl.pause",!1)}).bind("jGrowl.beforeOpen",function(){n.beforeOpen.apply(t,[t,o,n,i.element])!==!1&&e(this).trigger("jGrowl.open")}).bind("jGrowl.open",function(){n.open.apply(t,[t,o,n,i.element])!==!1&&("after"==n.glue?e("div.jGrowl-notification:last",i.element).after(t):e("div.jGrowl-notification:first",i.element).before(t),e(this).animate(n.animateOpen,n.openDuration,n.easing,function(){e.support.opacity===!1&&this.style.removeAttribute("filter"),null!==e(this).data("jGrowl")&&(e(this).data("jGrowl").created=new Date),e(this).trigger("jGrowl.afterOpen")}))}).bind("jGrowl.afterOpen",function(){n.afterOpen.apply(t,[t,o,n,i.element])}).bind("jGrowl.beforeClose",function(){n.beforeClose.apply(t,[t,o,n,i.element])!==!1&&e(this).trigger("jGrowl.close")}).bind("jGrowl.close",function(){e(this).data("jGrowl.pause",!0),e(this).animate(n.animateClose,n.closeDuration,n.easing,function(){e.isFunction(n.close)?n.close.apply(t,[t,o,n,i.element])!==!1&&e(this).remove():e(this).remove()})}).trigger("jGrowl.beforeOpen"),""!=n.corners&&void 0!=e.fn.corner&&e(t).corner(n.corners),e("div.jGrowl-notification:parent",i.element).size()>1&&0==e("div.jGrowl-closer",i.element).size()&&this.defaults.closer!==!1&&e(this.defaults.closerTemplate).addClass("jGrowl-closer "+this.defaults.themeState+" ui-corner-all").addClass(this.defaults.theme).appendTo(i.element).animate(this.defaults.animateOpen,this.defaults.speed,this.defaults.easing).bind("click.jGrowl",function(){e(this).siblings().trigger("jGrowl.beforeClose"),e.isFunction(i.defaults.closer)&&i.defaults.closer.apply(e(this).parent()[0],[e(this).parent()[0]])})},update:function(){e(this.element).find("div.jGrowl-notification:parent").each(function(){void 0!=e(this).data("jGrowl")&&void 0!==e(this).data("jGrowl").created&&e(this).data("jGrowl").created.getTime()+parseInt(e(this).data("jGrowl").life)<(new Date).getTime()&&e(this).data("jGrowl").sticky!==!0&&(void 0==e(this).data("jGrowl.pause")||e(this).data("jGrowl.pause")!==!0)&&e(this).trigger("jGrowl.beforeClose")}),this.notifications.length>0&&(0==this.defaults.pool||e(this.element).find("div.jGrowl-notification:parent").size()<this.defaults.pool)&&this.render(this.notifications.shift()),2>e(this.element).find("div.jGrowl-notification:parent").size()&&e(this.element).find("div.jGrowl-closer").animate(this.defaults.animateClose,this.defaults.speed,this.defaults.easing,function(){e(this).remove()})},startup:function(i){this.element=e(i).addClass("jGrowl").append('<div class="jGrowl-notification"></div>'),this.interval=setInterval(function(){e(i).data("jGrowl.instance").update()},parseInt(this.defaults.check)),t&&e(this.element).addClass("ie6")},shutdown:function(){e(this.element).removeClass("jGrowl").find("div.jGrowl-notification").trigger("jGrowl.close").parent().empty()},close:function(){e(this.element).find("div.jGrowl-notification").each(function(){e(this).trigger("jGrowl.beforeClose")})}}),e.jGrowl.defaults=e.fn.jGrowl.prototype.defaults})(jQuery); +/* +//@ sourceMappingURL=jquery.jgrowl.map +*/
\ No newline at end of file diff --git a/themes/default/js/plugins/jquery.tokeninput.css b/themes/default/js/plugins/jquery.tokeninput.css new file mode 100644 index 000000000..6eb101b2a --- /dev/null +++ b/themes/default/js/plugins/jquery.tokeninput.css @@ -0,0 +1,16 @@ +/* TokenInput (with Facebook style) */ +ul.token-input-list {overflow: hidden; height: auto !important; height: 1%;width: 400px;border: 1px solid #8496ba;cursor: text;font-size: 12px;font-family: Verdana;min-height: 1px;z-index: 999;margin: 0;padding: 0;background-color: #fff;list-style-type: none;clear: left;} +ul.token-input-list li input {border: 0;width: 100px;padding: 3px 8px;background-color: white;margin: 2px 0;-webkit-appearance: caret;color: black;} +li.token-input-token {overflow: hidden; height: auto !important; height: 15px;margin: 3px;padding: 1px 3px;background-color: #eff2f7;color: #000;cursor: default;border: 1px solid #ccd5e4;font-size: 11px;border-radius: 5px;-moz-border-radius: 5px;-webkit-border-radius: 5px;float: left;white-space: nowrap;} +li.token-input-token p {display: inline;padding: 0;margin: 0;} +li.token-input-token span {color: #a6b3cf;margin-left: 5px;font-weight: bold;cursor: pointer;} +li.token-input-selected-token {background-color: #5670a6;border: 1px solid #3b5998;color: #fff;} +li.token-input-input-token {float: left;margin: 0;padding: 0;list-style-type: none;width:10px;} +div.token-input-dropdown {position: absolute;width: 400px;background-color: #fff;overflow: hidden;border-left: 1px solid #ccc;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;cursor: default;font-size: 11px;font-family: Verdana;z-index: 1;} +div.token-input-dropdown p {margin: 0;padding: 5px;font-weight: bold;color: #777;} +div.token-input-dropdown ul {margin: 0;padding: 0;} +div.token-input-dropdown ul li {background-color: #fff;padding: 3px;margin: 0;list-style-type: none;} +div.token-input-dropdown ul li.token-input-dropdown-item {background-color: #fff;} +div.token-input-dropdown ul li.token-input-dropdown-item2 {background-color: #fff;} +div.token-input-dropdown ul li em {font-weight: bold;font-style: normal;} +div.token-input-dropdown ul li.token-input-selected-dropdown-item {background-color: #3b5998;color: #fff;}
\ No newline at end of file diff --git a/themes/default/js/plugins/jquery.tokeninput.js b/themes/default/js/plugins/jquery.tokeninput.js index 0c8662b3b..7348639ae 100644 --- a/themes/default/js/plugins/jquery.tokeninput.js +++ b/themes/default/js/plugins/jquery.tokeninput.js @@ -1,50 +1,85 @@ -/** - DON'T MAKE AUTOMATIC UPGRADE - This is a merged version of : - + https://github.com/gr2m/jquery-tokeninput/ - + https://github.com/mistic100/jquery-tokeninput/ -*/ - /* * jQuery Plugin: Tokenizing Autocomplete Text Entry - * Version 1.4.2 + * Version 1.6.1 * * Copyright (c) 2009 James Smith (http://loopj.com) * Licensed jointly under the GPL and MIT licenses, * choose which one suits your project best! * + * https://github.com/mistic100/jquery-tokeninput */ (function ($) { // Default settings var DEFAULT_SETTINGS = { - hintText: "Type in a search term", - noResultsText: "No results", - searchingText: "Searching...", - newText: "(new)", - deleteText: "×", + // Search settings + method: "GET", + queryParam: "q", searchDelay: 300, minChars: 1, - tokenLimit: null, + propertyToSearch: "name", jsonContainer: null, - method: "GET", contentType: "json", - queryParam: "q", - tokenDelimiter: ",", - preventDuplicates: false, + + // Prepopulation settings prePopulate: null, processPrePopulate: false, + + // Display settings + hintText: "Type in a search term", + noResultsText: "No results", + searchingText: "Searching...", + deleteText: "×", + newText: " (new)", animateDropdown: true, + placeholder: null, + theme: null, + zindex: 999, + resultsLimit: null, + + enableHTML: false, + + resultsFormatter: function(item) { + var string = item[this.propertyToSearch]; + return "<li>" + (this.enableHTML ? string : _escapeHTML(string)) + "</li>"; + }, + + tokenFormatter: function(item) { + var string = item[this.propertyToSearch]; + return "<li><p>" + (this.enableHTML ? string : _escapeHTML(string)) + "</p></li>"; + }, + + // Tokenization settings + tokenLimit: null, + tokenDelimiter: ",", + preventDuplicates: false, + tokenValue: "id", + + // Behavioral settings + allowFreeTagging: false, + freeTaggingHint: true, + allowTabOut: false, + + // Callbacks onResult: null, + onCachedResult: null, onAdd: null, + onFreeTaggingAdd: null, onDelete: null, - allowCreation: false + onReady: null, + + // Other settings + idPrefix: "token-input-", + + // Keep track if the input is currently in disabled mode + disabled: false }; // Default classes to use when theming var DEFAULT_CLASSES = { tokenList: "token-input-list", token: "token-input-token", + tokenReadOnly: "token-input-token-readonly", tokenDelete: "token-input-delete-token", selectedToken: "token-input-selected-token", highlightedToken: "token-input-highlighted-token", @@ -52,7 +87,9 @@ var DEFAULT_CLASSES = { dropdownItem: "token-input-dropdown-item", dropdownItem2: "token-input-dropdown-item2", selectedDropdownItem: "token-input-selected-dropdown-item", - inputToken: "token-input-input-token" + inputToken: "token-input-input-token", + focused: "token-input-focused", + disabled: "token-input-disabled" }; // Input box position "enum" @@ -81,16 +118,82 @@ var KEY = { COMMA: 188 }; +var HTML_ESCAPES = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' +}; -// Expose the .tokenInput function to jQuery as a plugin -$.fn.tokenInput = function (url_or_data, options) { - var settings = $.extend({}, DEFAULT_SETTINGS, options || {}); +var HTML_ESCAPE_CHARS = /[&<>"'\/]/g; + +function coerceToString(val) { + return String((val === null || val === undefined) ? '' : val); +} + +function _escapeHTML(text) { + return coerceToString(text).replace(HTML_ESCAPE_CHARS, function(match) { + return HTML_ESCAPES[match]; + }); +} + +// Additional public (exposed) methods +var methods = { + init: function(url_or_data_or_function, options) { + var settings = $.extend({}, DEFAULT_SETTINGS, options || {}); - return this.each(function () { - new $.TokenList(this, url_or_data, settings); - }); + return this.each(function () { + $(this).data("settings", settings); + $(this).data("tokenInputObject", new $.TokenList(this, url_or_data_or_function, settings)); + }); + }, + clear: function() { + this.data("tokenInputObject").clear(); + return this; + }, + add: function(item) { + this.data("tokenInputObject").add(item); + return this; + }, + remove: function(item) { + this.data("tokenInputObject").remove(item); + return this; + }, + get: function() { + return this.data("tokenInputObject").getTokens(); + }, + toggleDisabled: function(disable) { + this.data("tokenInputObject").toggleDisabled(disable); + return this; + }, + setOptions: function(options){ + $(this).data("settings", $.extend({}, $(this).data("settings"), options || {})); + return this; + }, + destroy: function () { + if(this.data("tokenInputObject")){ + this.data("tokenInputObject").clear(); + var tmpInput = this; + var closest = this.parent(); + closest.empty(); + tmpInput.show(); + closest.append(tmpInput); + return tmpInput; + } + } }; +// Expose the .tokenInput function to jQuery as a plugin +$.fn.tokenInput = function (method) { + // Method calling and initialization logic + if(methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else { + return methods.init.apply(this, arguments); + } +}; // TokenList class for each input $.TokenList = function (input, url_or_data, settings) { @@ -99,35 +202,38 @@ $.TokenList = function (input, url_or_data, settings) { // // Configure the data source - if(typeof(url_or_data) === "string") { + if($.type(url_or_data) === "string" || $.type(url_or_data) === "function") { // Set the url to query against - settings.url = url_or_data; + $(input).data("settings").url = url_or_data; + + // If the URL is a function, evaluate it here to do our initalization work + var url = computeURL(); // Make a smart guess about cross-domain if it wasn't explicitly specified - if(settings.crossDomain === undefined) { - if(settings.url.indexOf("://") === -1) { - settings.crossDomain = false; + if($(input).data("settings").crossDomain === undefined && typeof url === "string") { + if(url.indexOf("://") === -1) { + $(input).data("settings").crossDomain = false; } else { - settings.crossDomain = (location.href.split(/\/+/g)[1] !== settings.url.split(/\/+/g)[1]); + $(input).data("settings").crossDomain = (location.href.split(/\/+/g)[1] !== url.split(/\/+/g)[1]); } } } else if(typeof(url_or_data) === "object") { // Set the local data to search through - settings.local_data = url_or_data; + $(input).data("settings").local_data = url_or_data; } // Build class names - if(settings.classes) { + if($(input).data("settings").classes) { // Use custom class names - settings.classes = $.extend({}, DEFAULT_CLASSES, settings.classes); - } else if(settings.theme) { + $(input).data("settings").classes = $.extend({}, DEFAULT_CLASSES, $(input).data("settings").classes); + } else if($(input).data("settings").theme) { // Use theme-suffixed default class names - settings.classes = {}; + $(input).data("settings").classes = {}; $.each(DEFAULT_CLASSES, function(key, value) { - settings.classes[key] = value + "-" + settings.theme; + $(input).data("settings").classes[key] = value + "-" + $(input).data("settings").theme; }); } else { - settings.classes = DEFAULT_CLASSES; + $(input).data("settings").classes = DEFAULT_CLASSES; } @@ -145,17 +251,29 @@ $.TokenList = function (input, url_or_data, settings) { var input_val; // Create a new text input an attach keyup events - var input_box = $("<input type=\"text\" autocomplete=\"off\">") + var input_box = $("<input type=\"text\" autocomplete=\"off\" autocapitalize=\"off\">") .css({ outline: "none" }) + .attr("id", $(input).data("settings").idPrefix + input.id) .focus(function () { - if (settings.tokenLimit === null || settings.tokenLimit !== token_count) { + if ($(input).data("settings").disabled) { + return false; + } else + if ($(input).data("settings").tokenLimit === null || $(input).data("settings").tokenLimit !== token_count) { show_dropdown_hint(); } + token_list.addClass($(input).data("settings").classes.focused); }) .blur(function () { hide_dropdown(); + + if ($(input).data("settings").allowFreeTagging) { + add_freetagging_tokens(); + } + + $(this).val(""); + token_list.removeClass($(input).data("settings").classes.focused); }) .bind("keyup keydown blur update", resize_input) .keydown(function (event) { @@ -197,8 +315,8 @@ $.TokenList = function (input, url_or_data, settings) { if(dropdown_item.length) { select_dropdown_item(dropdown_item); } - return false; } + return false; break; case KEY.BACKSPACE: @@ -207,6 +325,7 @@ $.TokenList = function (input, url_or_data, settings) { if(!$(this).val().length) { if(selected_token) { delete_token($(selected_token)); + hidden_input.change(); } else if(previous_token.length) { select_token($(previous_token.get(0))); } @@ -225,10 +344,25 @@ $.TokenList = function (input, url_or_data, settings) { case KEY.NUMPAD_ENTER: case KEY.COMMA: if(selected_dropdown_item) { - add_token($(selected_dropdown_item)); - return false; + add_token($(selected_dropdown_item).data("tokeninput")); + hidden_input.change(); + } else { + if ($(input).data("settings").allowFreeTagging) { + if($(input).data("settings").allowTabOut && $(this).val() === "") { + return true; + } else { + add_freetagging_tokens(); + } + } else { + $(this).val(""); + if($(input).data("settings").allowTabOut) { + return true; + } + } + event.stopPropagation(); + event.preventDefault(); } - break; + return false; case KEY.ESCAPE: hide_dropdown(); @@ -243,29 +377,52 @@ $.TokenList = function (input, url_or_data, settings) { } }); + // Keep reference for placeholder + if (settings.placeholder) + input_box.attr("placeholder", settings.placeholder) + if ($(input).get(0).tagName == 'SELECT') { - // Create a new input to store selected tokens, original will be delete later - var hidden_input = $("<input type=\"text\" name=\"" + $(input).attr('name') + "\" autocomplete=\"off\">") - .hide() - .val("") - .focus(function () { - input_box.focus(); - }) - .blur(function () { - input_box.blur(); - }) - .insertBefore(input); + // Create a new input to store selected tokens, original will be removed later + var hidden_input = $("<input type=\"text\" name=\"" + $(input).attr('name') + "\" autocomplete=\"off\">") + .hide() + .val("") + .focus(function () { + focus_with_timeout(input_box); + }) + .blur(function () { + input_box.blur(); + return hidden_input; + }) + .insertBefore(input); + + // get prepopulate options and store them in hidden_input + var select_data = []; + $(input).children('option').each(function () { + var item = {}; + item[$(input).data("settings").tokenValue] = $(this).attr('value'); + item[$(input).data("settings").propertyToSearch] = $(this).text(); + select_data[ select_data.length ] = item; + }); + hidden_input.data("pre", select_data); + + // remove the SELECT object + hidden_input.data("settings", $(input).data("settings")); + $(input).remove(); + input = hidden_input[0]; + } else { - // Keep a reference to the original input box - var hidden_input = $(input) - .hide() - .val("") - .focus(function () { - input_box.focus(); - }) - .blur(function () { - input_box.blur(); - }); + // Keep a reference to the original input box + var hidden_input = $(input) + .hide() + .val("") + .focus(function () { + focus_with_timeout(input_box); + }) + .blur(function () { + input_box.blur(); + //return the object to this can be referenced in the callback functions. + return hidden_input; + }); } // Keep a reference to the selected token and dropdown item @@ -275,7 +432,7 @@ $.TokenList = function (input, url_or_data, settings) { // The list to store the token items in var token_list = $("<ul />") - .addClass(settings.classes.tokenList) + .addClass($(input).data("settings").classes.tokenList) .click(function (event) { var li = $(event.target).closest("li"); if(li && li.get(0) && $.data(li.get(0), "tokeninput")) { @@ -287,32 +444,32 @@ $.TokenList = function (input, url_or_data, settings) { } // Focus input box - input_box.focus(); + focus_with_timeout(input_box); } }) .mouseover(function (event) { var li = $(event.target).closest("li"); if(li && selected_token !== this) { - li.addClass(settings.classes.highlightedToken); + li.addClass($(input).data("settings").classes.highlightedToken); } }) .mouseout(function (event) { var li = $(event.target).closest("li"); if(li && selected_token !== this) { - li.removeClass(settings.classes.highlightedToken); + li.removeClass($(input).data("settings").classes.highlightedToken); } }) .insertBefore(hidden_input); // The token holding the input box var input_token = $("<li />") - .addClass(settings.classes.inputToken) + .addClass($(input).data("settings").classes.inputToken) .appendTo(token_list) .append(input_box); // The list to store the dropdown items in var dropdown = $("<div>") - .addClass(settings.classes.dropdown) + .addClass($(input).data("settings").classes.dropdown) .appendTo("body") .hide(); @@ -333,36 +490,116 @@ $.TokenList = function (input, url_or_data, settings) { // Pre-populate list if items exist hidden_input.val(""); - var li_data = settings.prePopulate || hidden_input.data("pre"); - if(settings.processPrePopulate && $.isFunction(settings.onResult)) { - li_data = settings.onResult.call(hidden_input, li_data); - } + var li_data = $(input).data("settings").prePopulate || hidden_input.data("pre"); + if($(input).data("settings").processPrePopulate && $.isFunction($(input).data("settings").onResult)) { + li_data = $(input).data("settings").onResult.call(hidden_input, li_data); + } if(li_data && li_data.length) { $.each(li_data, function (index, value) { - insert_token(value.id, value.name); + insert_token(value); + checkTokenLimit(); + input_box.attr("placeholder", null) }); } - - // Pre-populate from SELECT options - if ($(input).get(0).tagName == 'SELECT') { - $(input).children('option').each(function () { - insert_token($(this).attr('value'), $(this).text()); - }); + + // Check if widget should initialize as disabled + if ($(input).data("settings").disabled) { + toggleDisabled(true); } + // Initialization is done + if($.isFunction($(input).data("settings").onReady)) { + $(input).data("settings").onReady.call(); + } + + // + // Public functions + // + + this.clear = function() { + token_list.children("li").each(function() { + if ($(this).children("input").length === 0) { + delete_token($(this)); + } + }); + }; + + this.add = function(item) { + add_token(item); + }; + + this.remove = function(item) { + token_list.children("li").each(function() { + if ($(this).children("input").length === 0) { + var currToken = $(this).data("tokeninput"); + var match = true; + for (var prop in item) { + if (item[prop] !== currToken[prop]) { + match = false; + break; + } + } + if (match) { + delete_token($(this)); + } + } + }); + }; + + this.getTokens = function() { + return saved_tokens; + }; + + this.toggleDisabled = function(disable) { + toggleDisabled(disable); + }; + // Resize input to maximum width so the placeholder can be seen + resize_input(); // // Private functions // + function escapeHTML(text) { + return $(input).data("settings").enableHTML ? text : _escapeHTML(text); + } + + // Toggles the widget between enabled and disabled state, or according + // to the [disable] parameter. + function toggleDisabled(disable) { + if (typeof disable === 'boolean') { + $(input).data("settings").disabled = disable + } else { + $(input).data("settings").disabled = !$(input).data("settings").disabled; + } + input_box.attr('disabled', $(input).data("settings").disabled); + token_list.toggleClass($(input).data("settings").classes.disabled, $(input).data("settings").disabled); + // if there is any token selected we deselect it + if(selected_token) { + deselect_token($(selected_token), POSITION.END); + } + hidden_input.attr('disabled', $(input).data("settings").disabled); + } + + function checkTokenLimit() { + if($(input).data("settings").tokenLimit !== null && token_count >= $(input).data("settings").tokenLimit) { + input_box.hide(); + hide_dropdown(); + return; + } + } + function resize_input() { if(input_val === (input_val = input_box.val())) {return;} + // Get width left on the current line + var width_left = token_list.width() - input_box.offset().left - token_list.offset().left; // Enter new content into resizer and resize input accordingly - var escaped = input_val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>'); - input_resizer.html(escaped); - input_box.width(input_resizer.width() + 30); + input_resizer.html(_escapeHTML(input_val)); + // Get maximum width, minimum the size of input and maximum the widget's width + input_box.width(Math.min(token_list.width(), + Math.max(width_left, input_resizer.width() + 30))); } function is_printable_character(keycode) { @@ -372,52 +609,79 @@ $.TokenList = function (input, url_or_data, settings) { (keycode >= 219 && keycode <= 222)); // ( \ ) ' } + function add_freetagging_tokens() { + var value = $.trim(input_box.val()); + var tokens = value.split($(input).data("settings").tokenDelimiter); + $.each(tokens, function(i, token) { + if (!token) { + return; + } + + if ($.isFunction($(input).data("settings").onFreeTaggingAdd)) { + token = $(input).data("settings").onFreeTaggingAdd.call(hidden_input, token); + } + var object = {}; + object[$(input).data("settings").tokenValue] = object[$(input).data("settings").propertyToSearch] = token; + add_token(object); + }); + } + // Inner function to a token to the list - function insert_token(id, value) { - var this_token = $("<li><p>"+ value +"</p></li>") - .addClass(settings.classes.token) - .insertBefore(input_token); + function insert_token(item) { + var $this_token = $($(input).data("settings").tokenFormatter(item)); + var readonly = item.readonly === true ? true : false; + + if(readonly) $this_token.addClass($(input).data("settings").classes.tokenReadOnly); + + $this_token.addClass($(input).data("settings").classes.token).insertBefore(input_token); // The 'delete token' button - $("<span>" + settings.deleteText + "</span>") - .addClass(settings.classes.tokenDelete) - .appendTo(this_token) - .click(function () { - delete_token($(this).parent()); - return false; - }); + if(!readonly) { + $("<span>" + $(input).data("settings").deleteText + "</span>") + .addClass($(input).data("settings").classes.tokenDelete) + .appendTo($this_token) + .click(function () { + if (!$(input).data("settings").disabled) { + delete_token($(this).parent()); + hidden_input.change(); + return false; + } + }); + } // Store data on the token - var token_data = {"id": id, "name": value}; - $.data(this_token.get(0), "tokeninput", token_data); + var token_data = item; + $.data($this_token.get(0), "tokeninput", item); // Save this token for duplicate checking saved_tokens = saved_tokens.slice(0,selected_token_index).concat([token_data]).concat(saved_tokens.slice(selected_token_index)); selected_token_index++; // Update the hidden input - var token_ids = $.map(saved_tokens, function (el) { - return el.id; - }); - hidden_input.val(token_ids.join(settings.tokenDelimiter)); + update_hidden_input(saved_tokens, hidden_input); token_count += 1; - return this_token; + // Check the token limit + if($(input).data("settings").tokenLimit !== null && token_count >= $(input).data("settings").tokenLimit) { + input_box.hide(); + hide_dropdown(); + } + + return $this_token; } // Add a token to the token list based on user input function add_token (item) { - var li_data = $.data(item.get(0), "tokeninput"); - var callback = settings.onAdd; + var callback = $(input).data("settings").onAdd; // See if the token already exists and select it if we don't want duplicates - if(token_count > 0 && settings.preventDuplicates) { + if(token_count > 0 && $(input).data("settings").preventDuplicates) { var found_existing_token = null; token_list.children().each(function () { var existing_token = $(this); var existing_data = $.data(existing_token.get(0), "tokeninput"); - if(existing_data && existing_data.id === li_data.id) { + if(existing_data && existing_data[settings.tokenValue] === item[settings.tokenValue]) { found_existing_token = existing_token; return false; } @@ -426,21 +690,20 @@ $.TokenList = function (input, url_or_data, settings) { if(found_existing_token) { select_token(found_existing_token); input_token.insertAfter(found_existing_token); - input_box.focus(); + focus_with_timeout(input_box); return; } } - // Insert the new tokens - insert_token(li_data.id, li_data.name); + // Squeeze input_box so we force no unnecessary line break + input_box.width(0); - // Check the token limit - if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) { - input_box.hide(); - hide_dropdown(); - return; - } else { - input_box.focus(); + // Insert the new tokens + if($(input).data("settings").tokenLimit == null || token_count < $(input).data("settings").tokenLimit) { + insert_token(item); + // Remove the placeholder so it's not seen after you've added a token + input_box.attr("placeholder", null) + checkTokenLimit(); } // Clear input box @@ -451,25 +714,27 @@ $.TokenList = function (input, url_or_data, settings) { // Execute the onAdd callback if defined if($.isFunction(callback)) { - callback.call(hidden_input,li_data); + callback.call(hidden_input,item); } } // Select a token in the token list function select_token (token) { - token.addClass(settings.classes.selectedToken); - selected_token = token.get(0); + if (!$(input).data("settings").disabled) { + token.addClass($(input).data("settings").classes.selectedToken); + selected_token = token.get(0); - // Hide input box - input_box.val(""); + // Hide input box + input_box.val(""); - // Hide dropdown if it is visible (eg if we clicked to select token) - hide_dropdown(); + // Hide dropdown if it is visible (eg if we clicked to select token) + hide_dropdown(); + } } // Deselect a token in the token list function deselect_token (token, position) { - token.removeClass(settings.classes.selectedToken); + token.removeClass($(input).data("settings").classes.selectedToken); selected_token = null; if(position === POSITION.BEFORE) { @@ -484,7 +749,7 @@ $.TokenList = function (input, url_or_data, settings) { } // Show the input box and give it focus again - input_box.focus(); + focus_with_timeout(input_box); } // Toggle selection of a token in the token list @@ -506,7 +771,7 @@ $.TokenList = function (input, url_or_data, settings) { function delete_token (token) { // Remove the id from the saved list var token_data = $.data(token.get(0), "tokeninput"); - var callback = settings.onDelete; + var callback = $(input).data("settings").onDelete; var index = token.prevAll().length; if(index > selected_token_index) index--; @@ -516,25 +781,25 @@ $.TokenList = function (input, url_or_data, settings) { selected_token = null; // Show the input box and give it focus again - input_box.focus(); + focus_with_timeout(input_box); // Remove this token from the saved list saved_tokens = saved_tokens.slice(0,index).concat(saved_tokens.slice(index+1)); + if (saved_tokens.length == 0) { + input_box.attr("placeholder", settings.placeholder) + } if(index < selected_token_index) selected_token_index--; // Update the hidden input - var token_ids = $.map(saved_tokens, function (el) { - return el.id; - }); - hidden_input.val(token_ids.join(settings.tokenDelimiter)); + update_hidden_input(saved_tokens, hidden_input); token_count -= 1; - if(settings.tokenLimit !== null) { + if($(input).data("settings").tokenLimit !== null) { input_box .show() - .val("") - .focus(); + .val(""); + focus_with_timeout(input_box); } // Execute the onDelete callback if defined @@ -543,6 +808,18 @@ $.TokenList = function (input, url_or_data, settings) { } } + // Update the hidden input box value + function update_hidden_input(saved_tokens, hidden_input) { + var token_values = $.map(saved_tokens, function (el) { + if(typeof $(input).data("settings").tokenValue == 'function') + return $(input).data("settings").tokenValue.call(this, el); + + return el[$(input).data("settings").tokenValue]; + }); + hidden_input.val(token_values.join($(input).data("settings").tokenDelimiter)); + + } + // Hide and clear the results dropdown function hide_dropdown () { dropdown.hide().empty(); @@ -553,30 +830,47 @@ $.TokenList = function (input, url_or_data, settings) { dropdown .css({ position: "absolute", - top: $(token_list).offset().top + $(token_list).outerHeight(), - left: $(token_list).offset().left, - zindex: 999 + top: token_list.offset().top + token_list.outerHeight(), + left: token_list.offset().left, + width: token_list.width(), + 'z-index': $(input).data("settings").zindex }) .show(); } function show_dropdown_searching () { - if(settings.searchingText) { - dropdown.html("<p>"+settings.searchingText+"</p>"); + if($(input).data("settings").searchingText) { + dropdown.html("<p>" + escapeHTML($(input).data("settings").searchingText) + "</p>"); show_dropdown(); } } function show_dropdown_hint () { - if(settings.hintText) { - dropdown.html("<p>"+settings.hintText+"</p>"); + if($(input).data("settings").hintText) { + dropdown.html("<p>" + escapeHTML($(input).data("settings").hintText) + "</p>"); show_dropdown(); } } + var regexp_special_chars = new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g'); + function regexp_escape(term) { + return term.replace(regexp_special_chars, '\\$&'); + } + // Highlight the query part of the search term function highlight_term(value, term) { - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>"); + return value.replace( + new RegExp( + "(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(term) + ")(?![^<>]*>)(?![^&;]+;)", + "gi" + ), function(match, p1) { + return "<b>" + escapeHTML(p1) + "</b>"; + } + ); + } + + function find_value_and_highlight_term(template, value, term) { + return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(value) + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term)); } // Populate the results dropdown with some results @@ -589,38 +883,46 @@ $.TokenList = function (input, url_or_data, settings) { select_dropdown_item($(event.target).closest("li")); }) .mousedown(function (event) { - add_token($(event.target).closest("li")); + add_token($(event.target).closest("li").data("tokeninput")); + hidden_input.change(); return false; }) .hide(); + if ($(input).data("settings").resultsLimit && results.length > $(input).data("settings").resultsLimit) { + results = results.slice(0, $(input).data("settings").resultsLimit); + } + $.each(results, function(index, value) { - var this_li = $("<li>" + highlight_term(value.name, query) + "</li>") - .appendTo(dropdown_ul); + var this_li = $(input).data("settings").resultsFormatter(value); + + this_li = find_value_and_highlight_term(this_li ,value[$(input).data("settings").propertyToSearch], query); + + this_li = $(this_li).appendTo(dropdown_ul); if(index % 2) { - this_li.addClass(settings.classes.dropdownItem); + this_li.addClass($(input).data("settings").classes.dropdownItem); } else { - this_li.addClass(settings.classes.dropdownItem2); + this_li.addClass($(input).data("settings").classes.dropdownItem2); } if(index === 0) { select_dropdown_item(this_li); } - $.data(this_li.get(0), "tokeninput", {"id": value.id, "name": value.name}); + $.data(this_li.get(0), "tokeninput", value); }); show_dropdown(); - if(settings.animateDropdown) { + if($(input).data("settings").animateDropdown) { dropdown_ul.slideDown("fast"); } else { dropdown_ul.show(); } } else { - if(settings.noResultsText) { - dropdown.html("<p>"+settings.noResultsText+"</p>"); + if($(input).data("settings").noResultsText) { + dropdown.html("<p>" + escapeHTML($(input).data("settings").noResultsText) + "</p>"); show_dropdown(); } } @@ -633,34 +935,34 @@ $.TokenList = function (input, url_or_data, settings) { deselect_dropdown_item($(selected_dropdown_item)); } - item.addClass(settings.classes.selectedDropdownItem); + item.addClass($(input).data("settings").classes.selectedDropdownItem); selected_dropdown_item = item.get(0); } } // Remove highlighting from an item in the results dropdown function deselect_dropdown_item (item) { - item.removeClass(settings.classes.selectedDropdownItem); + item.removeClass($(input).data("settings").classes.selectedDropdownItem); selected_dropdown_item = null; } // Do a search and show the "searching" dropdown if the input is longer - // than settings.minChars + // than $(input).data("settings").minChars function do_search() { - var query = input_box.val().toLowerCase(); + var query = input_box.val(); if(query && query.length) { if(selected_token) { deselect_token($(selected_token), POSITION.AFTER); } - if(query.length >= settings.minChars) { + if(query.length >= $(input).data("settings").minChars) { show_dropdown_searching(); clearTimeout(timeout); timeout = setTimeout(function(){ run_search(query); - }, settings.searchDelay); + }, $(input).data("settings").searchDelay); } else { hide_dropdown(); } @@ -669,17 +971,22 @@ $.TokenList = function (input, url_or_data, settings) { // Do the actual search function run_search(query) { - var cached_results = cache.get(query); + var cache_key = query + computeURL(); + var cached_results = cache.get(cache_key); if(cached_results) { + if ($.isFunction($(input).data("settings").onCachedResult)) { + cached_results = $(input).data("settings").onCachedResult.call(hidden_input, cached_results); + } populate_dropdown(query, cached_results); } else { // Are we doing an ajax search or local data search? - if(settings.url) { + if($(input).data("settings").url) { + var url = computeURL(); // Extract exisiting get params var ajax_params = {}; ajax_params.data = {}; - if(settings.url.indexOf("?") > -1) { - var parts = settings.url.split("?"); + if(url.indexOf("?") > -1) { + var parts = url.split("?"); ajax_params.url = parts[0]; var param_array = parts[1].split("&"); @@ -688,60 +995,73 @@ $.TokenList = function (input, url_or_data, settings) { ajax_params.data[kv[0]] = kv[1]; }); } else { - ajax_params.url = settings.url; + ajax_params.url = url; } // Prepare the request - ajax_params.data[settings.queryParam] = query; - ajax_params.type = settings.method; - ajax_params.dataType = settings.contentType; - if(settings.crossDomain) { + ajax_params.data[$(input).data("settings").queryParam] = query; + ajax_params.type = $(input).data("settings").method; + ajax_params.dataType = $(input).data("settings").contentType; + if($(input).data("settings").crossDomain) { ajax_params.dataType = "jsonp"; } // Attach the success callback ajax_params.success = function(results) { - if($.isFunction(settings.onResult)) { - results = settings.onResult.call(hidden_input, results); + cache.add(cache_key, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results); + if($.isFunction($(input).data("settings").onResult)) { + results = $(input).data("settings").onResult.call(hidden_input, results); } - if(settings.allowCreation) { - results.push({name: input_box.val() + settings.newText, id: input_box.val()}); + if($(input).data("settings").allowFreeTagging && $(input).data("settings").freeTaggingHint) { + results.push({name: input_box.val() + $(input).data("settings").newText, id: input_box.val()}); } - cache.add(query, settings.jsonContainer ? results[settings.jsonContainer] : results); // only populate the dropdown if the results are associated with the active search query - if(input_box.val().toLowerCase() === query) { - populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results); + if(input_box.val() === query) { + populate_dropdown(query, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results); } }; // Make the request $.ajax(ajax_params); - } else if(settings.local_data) { + } else if($(input).data("settings").local_data) { // Do the search through local data - var results = $.grep(settings.local_data, function (row) { - return row.name.toLowerCase().indexOf(query.toLowerCase()) > -1; + var results = $.grep($(input).data("settings").local_data, function (row) { + return row[$(input).data("settings").propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1; }); - - if($.isFunction(settings.onResult)) { - results = settings.onResult.call(hidden_input, results); - } - if(settings.allowCreation) { - results.push({name: input_box.val() + settings.newText, id: input_box.val()}); + if($(input).data("settings").allowFreeTagging && $(input).data("settings").freeTaggingHint) { + results.push({name: input_box.val() + $(input).data("settings").newText, id: input_box.val()}); + } + + cache.add(cache_key, results); + if($.isFunction($(input).data("settings").onResult)) { + results = $(input).data("settings").onResult.call(hidden_input, results); } - - cache.add(query, results); - populate_dropdown(query, results); } } } - - if ($(input).get(0).tagName == 'SELECT') { - $(input).remove(); + + // compute the dynamic URL + function computeURL() { + var url = $(input).data("settings").url; + if(typeof $(input).data("settings").url == 'function') { + url = $(input).data("settings").url.call($(input).data("settings")); + } + return url; } + + // Bring browser focus to the specified object. + // Use of setTimeout is to get around an IE bug. + // (See, e.g., http://stackoverflow.com/questions/2600186/focus-doesnt-work-in-ie) + // + // obj: a jQuery object to focus() + function focus_with_timeout(obj) { + setTimeout(function() { obj.focus(); }, 50); + } + }; // Really basic cache for the results @@ -775,3 +1095,4 @@ $.TokenList.Cache = function (options) { }; }; }(jQuery)); + diff --git a/themes/default/js/plugins/underscore.js b/themes/default/js/plugins/underscore.js new file mode 100644 index 000000000..b50115df5 --- /dev/null +++ b/themes/default/js/plugins/underscore.js @@ -0,0 +1,1276 @@ +// Underscore.js 1.5.2 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.5.2'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, length = obj.length; i < length; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? void 0 : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed > result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sample **n** random values from an array. + // If **n** is not specified, returns a single random element from the array. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (arguments.length < 2 || guard) { + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, value, context) { + var result = {}; + var iterator = value == null ? _.identity : lookupIterator(value); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n == null) || guard ? array[0] : slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) { + return array[array.length - 1]; + } else { + return slice.call(array, Math.max(array.length - n, 0)); + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, "length").concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error("bindAll must be passed function names"); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + return function() { + context = this; + args = arguments; + timestamp = new Date(); + var later = function() { + var last = (new Date()) - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) result = func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); diff --git a/themes/default/js/raphael.js b/themes/default/js/raphael.js deleted file mode 100644 index 9b1a60ef0..000000000 --- a/themes/default/js/raphael.js +++ /dev/null @@ -1,5501 +0,0 @@ -// ┌────────────────────────────────────────────────────────────────────┐ \\ -// │ Raphaël 2.0.2 - JavaScript Vector Library │ \\ -// ├────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ -// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\ -// ├────────────────────────────────────────────────────────────────────┤ \\ -// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\ -// └────────────────────────────────────────────────────────────────────┘ \\ -// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\ -// │ Eve 0.3.4 - JavaScript Events Library │ \\ -// ├──────────────────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ -// │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\ -// └──────────────────────────────────────────────────────────────────────────────────────┘ \\ - -(function (glob) { - var version = "0.3.4", - has = "hasOwnProperty", - separator = /[\.\/]/, - wildcard = "*", - fun = function () {}, - numsort = function (a, b) { - return a - b; - }, - current_event, - stop, - events = {n: {}}, - - eve = function (name, scope) { - var e = events, - oldstop = stop, - args = Array.prototype.slice.call(arguments, 2), - listeners = eve.listeners(name), - z = 0, - f = false, - l, - indexed = [], - queue = {}, - out = [], - ce = current_event, - errors = []; - current_event = name; - stop = 0; - for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) { - indexed.push(listeners[i].zIndex); - if (listeners[i].zIndex < 0) { - queue[listeners[i].zIndex] = listeners[i]; - } - } - indexed.sort(numsort); - while (indexed[z] < 0) { - l = queue[indexed[z++]]; - out.push(l.apply(scope, args)); - if (stop) { - stop = oldstop; - return out; - } - } - for (i = 0; i < ii; i++) { - l = listeners[i]; - if ("zIndex" in l) { - if (l.zIndex == indexed[z]) { - out.push(l.apply(scope, args)); - if (stop) { - break; - } - do { - z++; - l = queue[indexed[z]]; - l && out.push(l.apply(scope, args)); - if (stop) { - break; - } - } while (l) - } else { - queue[l.zIndex] = l; - } - } else { - out.push(l.apply(scope, args)); - if (stop) { - break; - } - } - } - stop = oldstop; - current_event = ce; - return out.length ? out : null; - }; - - eve.listeners = function (name) { - var names = name.split(separator), - e = events, - item, - items, - k, - i, - ii, - j, - jj, - nes, - es = [e], - out = []; - for (i = 0, ii = names.length; i < ii; i++) { - nes = []; - for (j = 0, jj = es.length; j < jj; j++) { - e = es[j].n; - items = [e[names[i]], e[wildcard]]; - k = 2; - while (k--) { - item = items[k]; - if (item) { - nes.push(item); - out = out.concat(item.f || []); - } - } - } - es = nes; - } - return out; - }; - - - eve.on = function (name, f) { - var names = name.split(separator), - e = events; - for (var i = 0, ii = names.length; i < ii; i++) { - e = e.n; - !e[names[i]] && (e[names[i]] = {n: {}}); - e = e[names[i]]; - } - e.f = e.f || []; - for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { - return fun; - } - e.f.push(f); - return function (zIndex) { - if (+zIndex == +zIndex) { - f.zIndex = +zIndex; - } - }; - }; - - eve.stop = function () { - stop = 1; - }; - - eve.nt = function (subname) { - if (subname) { - return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event); - } - return current_event; - }; - - - eve.off = eve.unbind = function (name, f) { - var names = name.split(separator), - e, - key, - splice, - i, ii, j, jj, - cur = [events]; - for (i = 0, ii = names.length; i < ii; i++) { - for (j = 0; j < cur.length; j += splice.length - 2) { - splice = [j, 1]; - e = cur[j].n; - if (names[i] != wildcard) { - if (e[names[i]]) { - splice.push(e[names[i]]); - } - } else { - for (key in e) if (e[has](key)) { - splice.push(e[key]); - } - } - cur.splice.apply(cur, splice); - } - } - for (i = 0, ii = cur.length; i < ii; i++) { - e = cur[i]; - while (e.n) { - if (f) { - if (e.f) { - for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) { - e.f.splice(j, 1); - break; - } - !e.f.length && delete e.f; - } - for (key in e.n) if (e.n[has](key) && e.n[key].f) { - var funcs = e.n[key].f; - for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) { - funcs.splice(j, 1); - break; - } - !funcs.length && delete e.n[key].f; - } - } else { - delete e.f; - for (key in e.n) if (e.n[has](key) && e.n[key].f) { - delete e.n[key].f; - } - } - e = e.n; - } - } - }; - - eve.once = function (name, f) { - var f2 = function () { - var res = f.apply(this, arguments); - eve.unbind(name, f2); - return res; - }; - return eve.on(name, f2); - }; - - eve.version = version; - eve.toString = function () { - return "You are running Eve " + version; - }; - (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (typeof define != "undefined" ? (define("eve", [], function() { return eve; })) : (glob.eve = eve)); -})(this); - - -// ┌─────────────────────────────────────────────────────────────────────┐ \\ -// │ "Raphaël 2.0.2" - JavaScript Vector Library │ \\ -// ├─────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ -// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ -// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ -// └─────────────────────────────────────────────────────────────────────┘ \\ -(function () { - - function R(first) { - if (R.is(first, "function")) { - return loaded ? first() : eve.on("DOMload", first); - } else if (R.is(first, array)) { - return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first); - } else { - var args = Array.prototype.slice.call(arguments, 0); - if (R.is(args[args.length - 1], "function")) { - var f = args.pop(); - return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("DOMload", function () { - f.call(R._engine.create[apply](R, args)); - }); - } else { - return R._engine.create[apply](R, arguments); - } - } - } - R.version = "2.0.2"; - R.eve = eve; - var loaded, - separator = /[, ]+/, - elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, - formatrg = /\{(\d+)\}/g, - proto = "prototype", - has = "hasOwnProperty", - g = { - doc: document, - win: window - }, - oldRaphael = { - was: Object.prototype[has].call(g.win, "Raphael"), - is: g.win.Raphael - }, - Paper = function () { - - - this.ca = this.customAttributes = {}; - }, - paperproto, - appendChild = "appendChild", - apply = "apply", - concat = "concat", - supportsTouch = "createTouch" in g.doc, - E = "", - S = " ", - Str = String, - split = "split", - events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S), - touchMap = { - mousedown: "touchstart", - mousemove: "touchmove", - mouseup: "touchend" - }, - lowerCase = Str.prototype.toLowerCase, - math = Math, - mmax = math.max, - mmin = math.min, - abs = math.abs, - pow = math.pow, - PI = math.PI, - nu = "number", - string = "string", - array = "array", - toString = "toString", - fillString = "fill", - objectToString = Object.prototype.toString, - paper = {}, - push = "push", - ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, - colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, - isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, - bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, - round = math.round, - setAttribute = "setAttribute", - toFloat = parseFloat, - toInt = parseInt, - upperCase = Str.prototype.toUpperCase, - availableAttrs = R._availableAttrs = { - "arrow-end": "none", - "arrow-start": "none", - blur: 0, - "clip-rect": "0 0 1e9 1e9", - cursor: "default", - cx: 0, - cy: 0, - fill: "#fff", - "fill-opacity": 1, - font: '10px "Arial"', - "font-family": '"Arial"', - "font-size": "10", - "font-style": "normal", - "font-weight": 400, - gradient: 0, - height: 0, - href: "http://raphaeljs.com/", - "letter-spacing": 0, - opacity: 1, - path: "M0,0", - r: 0, - rx: 0, - ry: 0, - src: "", - stroke: "#000", - "stroke-dasharray": "", - "stroke-linecap": "butt", - "stroke-linejoin": "butt", - "stroke-miterlimit": 0, - "stroke-opacity": 1, - "stroke-width": 1, - target: "_blank", - "text-anchor": "middle", - title: "Raphael", - transform: "", - width: 0, - x: 0, - y: 0 - }, - availableAnimAttrs = R._availableAnimAttrs = { - blur: nu, - "clip-rect": "csv", - cx: nu, - cy: nu, - fill: "colour", - "fill-opacity": nu, - "font-size": nu, - height: nu, - opacity: nu, - path: "path", - r: nu, - rx: nu, - ry: nu, - stroke: "colour", - "stroke-opacity": nu, - "stroke-width": nu, - transform: "transform", - width: nu, - x: nu, - y: nu - }, - whitespace = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g, - commaSpaces = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/, - hsrg = {hs: 1, rg: 1}, - p2s = /,?([achlmqrstvxz]),?/gi, - pathCommand = /([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig, - tCommand = /([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig, - pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig, - radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/, - eldata = {}, - sortByKey = function (a, b) { - return a.key - b.key; - }, - sortByNumber = function (a, b) { - return toFloat(a) - toFloat(b); - }, - fun = function () {}, - pipe = function (x) { - return x; - }, - rectPath = R._rectPath = function (x, y, w, h, r) { - if (r) { - return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; - } - return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; - }, - ellipsePath = function (x, y, rx, ry) { - if (ry == null) { - ry = rx; - } - return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; - }, - getPath = R._getPath = { - path: function (el) { - return el.attr("path"); - }, - circle: function (el) { - var a = el.attrs; - return ellipsePath(a.cx, a.cy, a.r); - }, - ellipse: function (el) { - var a = el.attrs; - return ellipsePath(a.cx, a.cy, a.rx, a.ry); - }, - rect: function (el) { - var a = el.attrs; - return rectPath(a.x, a.y, a.width, a.height, a.r); - }, - image: function (el) { - var a = el.attrs; - return rectPath(a.x, a.y, a.width, a.height); - }, - text: function (el) { - var bbox = el._getBBox(); - return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); - } - }, - mapPath = R.mapPath = function (path, matrix) { - if (!matrix) { - return path; - } - var x, y, i, j, ii, jj, pathi; - path = path2curve(path); - for (i = 0, ii = path.length; i < ii; i++) { - pathi = path[i]; - for (j = 1, jj = pathi.length; j < jj; j += 2) { - x = matrix.x(pathi[j], pathi[j + 1]); - y = matrix.y(pathi[j], pathi[j + 1]); - pathi[j] = x; - pathi[j + 1] = y; - } - } - return path; - }; - - R._g = g; - - R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); - if (R.type == "VML") { - var d = g.doc.createElement("div"), - b; - d.innerHTML = '<v:shape adj="1"/>'; - b = d.firstChild; - b.style.behavior = "url(#default#VML)"; - if (!(b && typeof b.adj == "object")) { - return (R.type = E); - } - d = null; - } - - - R.svg = !(R.vml = R.type == "VML"); - R._Paper = Paper; - - R.fn = paperproto = Paper.prototype = R.prototype; - R._id = 0; - R._oid = 0; - - R.is = function (o, type) { - type = lowerCase.call(type); - if (type == "finite") { - return !isnan[has](+o); - } - if (type == "array") { - return o instanceof Array; - } - return (type == "null" && o === null) || - (type == typeof o && o !== null) || - (type == "object" && o === Object(o)) || - (type == "array" && Array.isArray && Array.isArray(o)) || - objectToString.call(o).slice(8, -1).toLowerCase() == type; - }; - - R.angle = function (x1, y1, x2, y2, x3, y3) { - if (x3 == null) { - var x = x1 - x2, - y = y1 - y2; - if (!x && !y) { - return 0; - } - return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; - } else { - return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); - } - }; - - R.rad = function (deg) { - return deg % 360 * PI / 180; - }; - - R.deg = function (rad) { - return rad * 180 / PI % 360; - }; - - R.snapTo = function (values, value, tolerance) { - tolerance = R.is(tolerance, "finite") ? tolerance : 10; - if (R.is(values, array)) { - var i = values.length; - while (i--) if (abs(values[i] - value) <= tolerance) { - return values[i]; - } - } else { - values = +values; - var rem = value % values; - if (rem < tolerance) { - return value - rem; - } - if (rem > values - tolerance) { - return value - rem + values; - } - } - return value; - }; - - - var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) { - return function () { - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); - }; - })(/[xy]/g, function (c) { - var r = math.random() * 16 | 0, - v = c == "x" ? r : (r & 3 | 8); - return v.toString(16); - }); - - - R.setWindow = function (newwin) { - eve("setWindow", R, g.win, newwin); - g.win = newwin; - g.doc = g.win.document; - if (R._engine.initWin) { - R._engine.initWin(g.win); - } - }; - var toHex = function (color) { - if (R.vml) { - // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ - var trim = /^\s+|\s+$/g; - var bod; - try { - var docum = new ActiveXObject("htmlfile"); - docum.write("<body>"); - docum.close(); - bod = docum.body; - } catch(e) { - bod = createPopup().document.body; - } - var range = bod.createTextRange(); - toHex = cacher(function (color) { - try { - bod.style.color = Str(color).replace(trim, E); - var value = range.queryCommandValue("ForeColor"); - value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); - return "#" + ("000000" + value.toString(16)).slice(-6); - } catch(e) { - return "none"; - } - }); - } else { - var i = g.doc.createElement("i"); - i.title = "Rapha\xebl Colour Picker"; - i.style.display = "none"; - g.doc.body.appendChild(i); - toHex = cacher(function (color) { - i.style.color = color; - return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); - }); - } - return toHex(color); - }, - hsbtoString = function () { - return "hsb(" + [this.h, this.s, this.b] + ")"; - }, - hsltoString = function () { - return "hsl(" + [this.h, this.s, this.l] + ")"; - }, - rgbtoString = function () { - return this.hex; - }, - prepareRGB = function (r, g, b) { - if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { - b = r.b; - g = r.g; - r = r.r; - } - if (g == null && R.is(r, string)) { - var clr = R.getRGB(r); - r = clr.r; - g = clr.g; - b = clr.b; - } - if (r > 1 || g > 1 || b > 1) { - r /= 255; - g /= 255; - b /= 255; - } - - return [r, g, b]; - }, - packageRGB = function (r, g, b, o) { - r *= 255; - g *= 255; - b *= 255; - var rgb = { - r: r, - g: g, - b: b, - hex: R.rgb(r, g, b), - toString: rgbtoString - }; - R.is(o, "finite") && (rgb.opacity = o); - return rgb; - }; - - - R.color = function (clr) { - var rgb; - if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { - rgb = R.hsb2rgb(clr); - clr.r = rgb.r; - clr.g = rgb.g; - clr.b = rgb.b; - clr.hex = rgb.hex; - } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { - rgb = R.hsl2rgb(clr); - clr.r = rgb.r; - clr.g = rgb.g; - clr.b = rgb.b; - clr.hex = rgb.hex; - } else { - if (R.is(clr, "string")) { - clr = R.getRGB(clr); - } - if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) { - rgb = R.rgb2hsl(clr); - clr.h = rgb.h; - clr.s = rgb.s; - clr.l = rgb.l; - rgb = R.rgb2hsb(clr); - clr.v = rgb.b; - } else { - clr = {hex: "none"}; - clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; - } - } - clr.toString = rgbtoString; - return clr; - }; - - R.hsb2rgb = function (h, s, v, o) { - if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { - v = h.b; - s = h.s; - h = h.h; - o = h.o; - } - h *= 360; - var R, G, B, X, C; - h = (h % 360) / 60; - C = v * s; - X = C * (1 - abs(h % 2 - 1)); - R = G = B = v - C; - - h = ~~h; - R += [C, X, 0, 0, X, C][h]; - G += [X, C, C, X, 0, 0][h]; - B += [0, 0, X, C, C, X][h]; - return packageRGB(R, G, B, o); - }; - - R.hsl2rgb = function (h, s, l, o) { - if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { - l = h.l; - s = h.s; - h = h.h; - } - if (h > 1 || s > 1 || l > 1) { - h /= 360; - s /= 100; - l /= 100; - } - h *= 360; - var R, G, B, X, C; - h = (h % 360) / 60; - C = 2 * s * (l < .5 ? l : 1 - l); - X = C * (1 - abs(h % 2 - 1)); - R = G = B = l - C / 2; - - h = ~~h; - R += [C, X, 0, 0, X, C][h]; - G += [X, C, C, X, 0, 0][h]; - B += [0, 0, X, C, C, X][h]; - return packageRGB(R, G, B, o); - }; - - R.rgb2hsb = function (r, g, b) { - b = prepareRGB(r, g, b); - r = b[0]; - g = b[1]; - b = b[2]; - - var H, S, V, C; - V = mmax(r, g, b); - C = V - mmin(r, g, b); - H = (C == 0 ? null : - V == r ? (g - b) / C : - V == g ? (b - r) / C + 2 : - (r - g) / C + 4 - ); - H = ((H + 360) % 6) * 60 / 360; - S = C == 0 ? 0 : C / V; - return {h: H, s: S, b: V, toString: hsbtoString}; - }; - - R.rgb2hsl = function (r, g, b) { - b = prepareRGB(r, g, b); - r = b[0]; - g = b[1]; - b = b[2]; - - var H, S, L, M, m, C; - M = mmax(r, g, b); - m = mmin(r, g, b); - C = M - m; - H = (C == 0 ? null : - M == r ? (g - b) / C : - M == g ? (b - r) / C + 2 : - (r - g) / C + 4); - H = ((H + 360) % 6) * 60 / 360; - L = (M + m) / 2; - S = (C == 0 ? 0 : - L < .5 ? C / (2 * L) : - C / (2 - 2 * L)); - return {h: H, s: S, l: L, toString: hsltoString}; - }; - R._path2string = function () { - return this.join(",").replace(p2s, "$1"); - }; - function repush(array, item) { - for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { - return array.push(array.splice(i, 1)[0]); - } - } - function cacher(f, scope, postprocessor) { - function newf() { - var arg = Array.prototype.slice.call(arguments, 0), - args = arg.join("\u2400"), - cache = newf.cache = newf.cache || {}, - count = newf.count = newf.count || []; - if (cache[has](args)) { - repush(count, args); - return postprocessor ? postprocessor(cache[args]) : cache[args]; - } - count.length >= 1e3 && delete cache[count.shift()]; - count.push(args); - cache[args] = f[apply](scope, arg); - return postprocessor ? postprocessor(cache[args]) : cache[args]; - } - return newf; - } - - var preload = R._preload = function (src, f) { - var img = g.doc.createElement("img"); - img.style.cssText = "position:absolute;left:-9999em;top:-9999em"; - img.onload = function () { - f.call(this); - this.onload = null; - g.doc.body.removeChild(this); - }; - img.onerror = function () { - g.doc.body.removeChild(this); - }; - g.doc.body.appendChild(img); - img.src = src; - }; - - function clrToString() { - return this.hex; - } - - - R.getRGB = cacher(function (colour) { - if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { - return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; - } - if (colour == "none") { - return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString}; - } - !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); - var res, - red, - green, - blue, - opacity, - t, - values, - rgb = colour.match(colourRegExp); - if (rgb) { - if (rgb[2]) { - blue = toInt(rgb[2].substring(5), 16); - green = toInt(rgb[2].substring(3, 5), 16); - red = toInt(rgb[2].substring(1, 3), 16); - } - if (rgb[3]) { - blue = toInt((t = rgb[3].charAt(3)) + t, 16); - green = toInt((t = rgb[3].charAt(2)) + t, 16); - red = toInt((t = rgb[3].charAt(1)) + t, 16); - } - if (rgb[4]) { - values = rgb[4][split](commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red *= 2.55); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green *= 2.55); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue *= 2.55); - rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - } - if (rgb[5]) { - values = rgb[5][split](commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red *= 2.55); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green *= 2.55); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue *= 2.55); - (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); - rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - return R.hsb2rgb(red, green, blue, opacity); - } - if (rgb[6]) { - values = rgb[6][split](commaSpaces); - red = toFloat(values[0]); - values[0].slice(-1) == "%" && (red *= 2.55); - green = toFloat(values[1]); - values[1].slice(-1) == "%" && (green *= 2.55); - blue = toFloat(values[2]); - values[2].slice(-1) == "%" && (blue *= 2.55); - (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); - rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); - values[3] && values[3].slice(-1) == "%" && (opacity /= 100); - return R.hsl2rgb(red, green, blue, opacity); - } - rgb = {r: red, g: green, b: blue, toString: clrToString}; - rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); - R.is(opacity, "finite") && (rgb.opacity = opacity); - return rgb; - } - return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; - }, R); - - R.hsb = cacher(function (h, s, b) { - return R.hsb2rgb(h, s, b).hex; - }); - - R.hsl = cacher(function (h, s, l) { - return R.hsl2rgb(h, s, l).hex; - }); - - R.rgb = cacher(function (r, g, b) { - return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); - }); - - R.getColor = function (value) { - var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, - rgb = this.hsb2rgb(start.h, start.s, start.b); - start.h += .075; - if (start.h > 1) { - start.h = 0; - start.s -= .2; - start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); - } - return rgb.hex; - }; - - R.getColor.reset = function () { - delete this.start; - }; - - // http://schepers.cc/getting-to-the-point - function catmullRom2bezier(crp, z) { - var d = []; - for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) { - var p = [ - {x: +crp[i - 2], y: +crp[i - 1]}, - {x: +crp[i], y: +crp[i + 1]}, - {x: +crp[i + 2], y: +crp[i + 3]}, - {x: +crp[i + 4], y: +crp[i + 5]} - ]; - if (z) { - if (!i) { - p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]}; - } else if (iLen - 4 == i) { - p[3] = {x: +crp[0], y: +crp[1]}; - } else if (iLen - 2 == i) { - p[2] = {x: +crp[0], y: +crp[1]}; - p[3] = {x: +crp[2], y: +crp[3]}; - } - } else { - if (iLen - 4 == i) { - p[3] = p[2]; - } else if (!i) { - p[0] = {x: +crp[i], y: +crp[i + 1]}; - } - } - d.push(["C", - (-p[0].x + 6 * p[1].x + p[2].x) / 6, - (-p[0].y + 6 * p[1].y + p[2].y) / 6, - (p[1].x + 6 * p[2].x - p[3].x) / 6, - (p[1].y + 6*p[2].y - p[3].y) / 6, - p[2].x, - p[2].y - ]); - } - - return d; - } - - R.parsePathString = cacher(function (pathString) { - if (!pathString) { - return null; - } - var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0}, - data = []; - if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption - data = pathClone(pathString); - } - if (!data.length) { - Str(pathString).replace(pathCommand, function (a, b, c) { - var params = [], - name = b.toLowerCase(); - c.replace(pathValues, function (a, b) { - b && params.push(+b); - }); - if (name == "m" && params.length > 2) { - data.push([b][concat](params.splice(0, 2))); - name = "l"; - b = b == "m" ? "l" : "L"; - } - if (name == "r") { - data.push([b][concat](params)); - } else while (params.length >= paramCounts[name]) { - data.push([b][concat](params.splice(0, paramCounts[name]))); - if (!paramCounts[name]) { - break; - } - } - }); - } - data.toString = R._path2string; - return data; - }); - - R.parseTransformString = cacher(function (TString) { - if (!TString) { - return null; - } - var paramCounts = {r: 3, s: 4, t: 2, m: 6}, - data = []; - if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption - data = pathClone(TString); - } - if (!data.length) { - Str(TString).replace(tCommand, function (a, b, c) { - var params = [], - name = lowerCase.call(b); - c.replace(pathValues, function (a, b) { - b && params.push(+b); - }); - data.push([b][concat](params)); - }); - } - data.toString = R._path2string; - return data; - }); - - R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { - var t1 = 1 - t, - t13 = pow(t1, 3), - t12 = pow(t1, 2), - t2 = t * t, - t3 = t2 * t, - x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, - y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, - mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), - my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), - nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), - ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), - ax = t1 * p1x + t * c1x, - ay = t1 * p1y + t * c1y, - cx = t1 * c2x + t * p2x, - cy = t1 * c2y + t * p2y, - alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); - (mx > nx || my < ny) && (alpha += 180); - return { - x: x, - y: y, - m: {x: mx, y: my}, - n: {x: nx, y: ny}, - start: {x: ax, y: ay}, - end: {x: cx, y: cy}, - alpha: alpha - }; - }; - R._removedFactory = function (methodname) { - return function () { - throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object"); - }; - }; - var pathDimensions = cacher(function (path) { - if (!path) { - return {x: 0, y: 0, width: 0, height: 0}; - } - path = path2curve(path); - var x = 0, - y = 0, - X = [], - Y = [], - p; - for (var i = 0, ii = path.length; i < ii; i++) { - p = path[i]; - if (p[0] == "M") { - x = p[1]; - y = p[2]; - X.push(x); - Y.push(y); - } else { - var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); - X = X[concat](dim.min.x, dim.max.x); - Y = Y[concat](dim.min.y, dim.max.y); - x = p[5]; - y = p[6]; - } - } - var xmin = mmin[apply](0, X), - ymin = mmin[apply](0, Y); - return { - x: xmin, - y: ymin, - width: mmax[apply](0, X) - xmin, - height: mmax[apply](0, Y) - ymin - }; - }, null, function (o) { - return { - x: o.x, - y: o.y, - width: o.width, - height: o.height - }; - }), - pathClone = function (pathArray) { - var res = []; - if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption - pathArray = R.parsePathString(pathArray); - } - for (var i = 0, ii = pathArray.length; i < ii; i++) { - res[i] = []; - for (var j = 0, jj = pathArray[i].length; j < jj; j++) { - res[i][j] = pathArray[i][j]; - } - } - res.toString = R._path2string; - return res; - }, - pathToRelative = R._pathToRelative = cacher(function (pathArray) { - if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption - pathArray = R.parsePathString(pathArray); - } - var res = [], - x = 0, - y = 0, - mx = 0, - my = 0, - start = 0; - if (pathArray[0][0] == "M") { - x = pathArray[0][1]; - y = pathArray[0][2]; - mx = x; - my = y; - start++; - res.push(["M", x, y]); - } - for (var i = start, ii = pathArray.length; i < ii; i++) { - var r = res[i] = [], - pa = pathArray[i]; - if (pa[0] != lowerCase.call(pa[0])) { - r[0] = lowerCase.call(pa[0]); - switch (r[0]) { - case "a": - r[1] = pa[1]; - r[2] = pa[2]; - r[3] = pa[3]; - r[4] = pa[4]; - r[5] = pa[5]; - r[6] = +(pa[6] - x).toFixed(3); - r[7] = +(pa[7] - y).toFixed(3); - break; - case "v": - r[1] = +(pa[1] - y).toFixed(3); - break; - case "m": - mx = pa[1]; - my = pa[2]; - default: - for (var j = 1, jj = pa.length; j < jj; j++) { - r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); - } - } - } else { - r = res[i] = []; - if (pa[0] == "m") { - mx = pa[1] + x; - my = pa[2] + y; - } - for (var k = 0, kk = pa.length; k < kk; k++) { - res[i][k] = pa[k]; - } - } - var len = res[i].length; - switch (res[i][0]) { - case "z": - x = mx; - y = my; - break; - case "h": - x += +res[i][len - 1]; - break; - case "v": - y += +res[i][len - 1]; - break; - default: - x += +res[i][len - 2]; - y += +res[i][len - 1]; - } - } - res.toString = R._path2string; - return res; - }, 0, pathClone), - pathToAbsolute = R._pathToAbsolute = cacher(function (pathArray) { - if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption - pathArray = R.parsePathString(pathArray); - } - if (!pathArray || !pathArray.length) { - return [["M", 0, 0]]; - } - var res = [], - x = 0, - y = 0, - mx = 0, - my = 0, - start = 0; - if (pathArray[0][0] == "M") { - x = +pathArray[0][1]; - y = +pathArray[0][2]; - mx = x; - my = y; - start++; - res[0] = ["M", x, y]; - } - var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z"; - for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { - res.push(r = []); - pa = pathArray[i]; - if (pa[0] != upperCase.call(pa[0])) { - r[0] = upperCase.call(pa[0]); - switch (r[0]) { - case "A": - r[1] = pa[1]; - r[2] = pa[2]; - r[3] = pa[3]; - r[4] = pa[4]; - r[5] = pa[5]; - r[6] = +(pa[6] + x); - r[7] = +(pa[7] + y); - break; - case "V": - r[1] = +pa[1] + y; - break; - case "H": - r[1] = +pa[1] + x; - break; - case "R": - var dots = [x, y][concat](pa.slice(1)); - for (var j = 2, jj = dots.length; j < jj; j++) { - dots[j] = +dots[j] + x; - dots[++j] = +dots[j] + y; - } - res.pop(); - res = res[concat](catmullRom2bezier(dots, crz)); - break; - case "M": - mx = +pa[1] + x; - my = +pa[2] + y; - default: - for (j = 1, jj = pa.length; j < jj; j++) { - r[j] = +pa[j] + ((j % 2) ? x : y); - } - } - } else if (pa[0] == "R") { - dots = [x, y][concat](pa.slice(1)); - res.pop(); - res = res[concat](catmullRom2bezier(dots, crz)); - r = ["R"][concat](pa.slice(-2)); - } else { - for (var k = 0, kk = pa.length; k < kk; k++) { - r[k] = pa[k]; - } - } - switch (r[0]) { - case "Z": - x = mx; - y = my; - break; - case "H": - x = r[1]; - break; - case "V": - y = r[1]; - break; - case "M": - mx = r[r.length - 2]; - my = r[r.length - 1]; - default: - x = r[r.length - 2]; - y = r[r.length - 1]; - } - } - res.toString = R._path2string; - return res; - }, null, pathClone), - l2c = function (x1, y1, x2, y2) { - return [x1, y1, x2, y2, x2, y2]; - }, - q2c = function (x1, y1, ax, ay, x2, y2) { - var _13 = 1 / 3, - _23 = 2 / 3; - return [ - _13 * x1 + _23 * ax, - _13 * y1 + _23 * ay, - _13 * x2 + _23 * ax, - _13 * y2 + _23 * ay, - x2, - y2 - ]; - }, - a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { - // for more information of where this math came from visit: - // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes - var _120 = PI * 120 / 180, - rad = PI / 180 * (+angle || 0), - res = [], - xy, - rotate = cacher(function (x, y, rad) { - var X = x * math.cos(rad) - y * math.sin(rad), - Y = x * math.sin(rad) + y * math.cos(rad); - return {x: X, y: Y}; - }); - if (!recursive) { - xy = rotate(x1, y1, -rad); - x1 = xy.x; - y1 = xy.y; - xy = rotate(x2, y2, -rad); - x2 = xy.x; - y2 = xy.y; - var cos = math.cos(PI / 180 * angle), - sin = math.sin(PI / 180 * angle), - x = (x1 - x2) / 2, - y = (y1 - y2) / 2; - var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); - if (h > 1) { - h = math.sqrt(h); - rx = h * rx; - ry = h * ry; - } - var rx2 = rx * rx, - ry2 = ry * ry, - k = (large_arc_flag == sweep_flag ? -1 : 1) * - math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), - cx = k * rx * y / ry + (x1 + x2) / 2, - cy = k * -ry * x / rx + (y1 + y2) / 2, - f1 = math.asin(((y1 - cy) / ry).toFixed(9)), - f2 = math.asin(((y2 - cy) / ry).toFixed(9)); - - f1 = x1 < cx ? PI - f1 : f1; - f2 = x2 < cx ? PI - f2 : f2; - f1 < 0 && (f1 = PI * 2 + f1); - f2 < 0 && (f2 = PI * 2 + f2); - if (sweep_flag && f1 > f2) { - f1 = f1 - PI * 2; - } - if (!sweep_flag && f2 > f1) { - f2 = f2 - PI * 2; - } - } else { - f1 = recursive[0]; - f2 = recursive[1]; - cx = recursive[2]; - cy = recursive[3]; - } - var df = f2 - f1; - if (abs(df) > _120) { - var f2old = f2, - x2old = x2, - y2old = y2; - f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); - x2 = cx + rx * math.cos(f2); - y2 = cy + ry * math.sin(f2); - res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); - } - df = f2 - f1; - var c1 = math.cos(f1), - s1 = math.sin(f1), - c2 = math.cos(f2), - s2 = math.sin(f2), - t = math.tan(df / 4), - hx = 4 / 3 * rx * t, - hy = 4 / 3 * ry * t, - m1 = [x1, y1], - m2 = [x1 + hx * s1, y1 - hy * c1], - m3 = [x2 + hx * s2, y2 - hy * c2], - m4 = [x2, y2]; - m2[0] = 2 * m1[0] - m2[0]; - m2[1] = 2 * m1[1] - m2[1]; - if (recursive) { - return [m2, m3, m4][concat](res); - } else { - res = [m2, m3, m4][concat](res).join()[split](","); - var newres = []; - for (var i = 0, ii = res.length; i < ii; i++) { - newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; - } - return newres; - } - }, - findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { - var t1 = 1 - t; - return { - x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, - y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y - }; - }, - curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { - var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x), - b = 2 * (c1x - p1x) - 2 * (c2x - c1x), - c = p1x - c1x, - t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a, - t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a, - y = [p1y, p2y], - x = [p1x, p2x], - dot; - abs(t1) > "1e12" && (t1 = .5); - abs(t2) > "1e12" && (t2 = .5); - if (t1 > 0 && t1 < 1) { - dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); - x.push(dot.x); - y.push(dot.y); - } - if (t2 > 0 && t2 < 1) { - dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); - x.push(dot.x); - y.push(dot.y); - } - a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y); - b = 2 * (c1y - p1y) - 2 * (c2y - c1y); - c = p1y - c1y; - t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a; - t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a; - abs(t1) > "1e12" && (t1 = .5); - abs(t2) > "1e12" && (t2 = .5); - if (t1 > 0 && t1 < 1) { - dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); - x.push(dot.x); - y.push(dot.y); - } - if (t2 > 0 && t2 < 1) { - dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); - x.push(dot.x); - y.push(dot.y); - } - return { - min: {x: mmin[apply](0, x), y: mmin[apply](0, y)}, - max: {x: mmax[apply](0, x), y: mmax[apply](0, y)} - }; - }), - path2curve = R._path2curve = cacher(function (path, path2) { - var p = pathToAbsolute(path), - p2 = path2 && pathToAbsolute(path2), - attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, - attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, - processPath = function (path, d) { - var nx, ny; - if (!path) { - return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; - } - !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null); - switch (path[0]) { - case "M": - d.X = path[1]; - d.Y = path[2]; - break; - case "A": - path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1)))); - break; - case "S": - nx = d.x + (d.x - (d.bx || d.x)); - ny = d.y + (d.y - (d.by || d.y)); - path = ["C", nx, ny][concat](path.slice(1)); - break; - case "T": - d.qx = d.x + (d.x - (d.qx || d.x)); - d.qy = d.y + (d.y - (d.qy || d.y)); - path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); - break; - case "Q": - d.qx = path[1]; - d.qy = path[2]; - path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4])); - break; - case "L": - path = ["C"][concat](l2c(d.x, d.y, path[1], path[2])); - break; - case "H": - path = ["C"][concat](l2c(d.x, d.y, path[1], d.y)); - break; - case "V": - path = ["C"][concat](l2c(d.x, d.y, d.x, path[1])); - break; - case "Z": - path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y)); - break; - } - return path; - }, - fixArc = function (pp, i) { - if (pp[i].length > 7) { - pp[i].shift(); - var pi = pp[i]; - while (pi.length) { - pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6))); - } - pp.splice(i, 1); - ii = mmax(p.length, p2 && p2.length || 0); - } - }, - fixM = function (path1, path2, a1, a2, i) { - if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { - path2.splice(i, 0, ["M", a2.x, a2.y]); - a1.bx = 0; - a1.by = 0; - a1.x = path1[i][1]; - a1.y = path1[i][2]; - ii = mmax(p.length, p2 && p2.length || 0); - } - }; - for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { - p[i] = processPath(p[i], attrs); - fixArc(p, i); - p2 && (p2[i] = processPath(p2[i], attrs2)); - p2 && fixArc(p2, i); - fixM(p, p2, attrs, attrs2, i); - fixM(p2, p, attrs2, attrs, i); - var seg = p[i], - seg2 = p2 && p2[i], - seglen = seg.length, - seg2len = p2 && seg2.length; - attrs.x = seg[seglen - 2]; - attrs.y = seg[seglen - 1]; - attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; - attrs.by = toFloat(seg[seglen - 3]) || attrs.y; - attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); - attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); - attrs2.x = p2 && seg2[seg2len - 2]; - attrs2.y = p2 && seg2[seg2len - 1]; - } - return p2 ? [p, p2] : p; - }, null, pathClone), - parseDots = R._parseDots = cacher(function (gradient) { - var dots = []; - for (var i = 0, ii = gradient.length; i < ii; i++) { - var dot = {}, - par = gradient[i].match(/^([^:]*):?([\d\.]*)/); - dot.color = R.getRGB(par[1]); - if (dot.color.error) { - return null; - } - dot.color = dot.color.hex; - par[2] && (dot.offset = par[2] + "%"); - dots.push(dot); - } - for (i = 1, ii = dots.length - 1; i < ii; i++) { - if (!dots[i].offset) { - var start = toFloat(dots[i - 1].offset || 0), - end = 0; - for (var j = i + 1; j < ii; j++) { - if (dots[j].offset) { - end = dots[j].offset; - break; - } - } - if (!end) { - end = 100; - j = ii; - } - end = toFloat(end); - var d = (end - start) / (j - i + 1); - for (; i < j; i++) { - start += d; - dots[i].offset = start + "%"; - } - } - } - return dots; - }), - tear = R._tear = function (el, paper) { - el == paper.top && (paper.top = el.prev); - el == paper.bottom && (paper.bottom = el.next); - el.next && (el.next.prev = el.prev); - el.prev && (el.prev.next = el.next); - }, - tofront = R._tofront = function (el, paper) { - if (paper.top === el) { - return; - } - tear(el, paper); - el.next = null; - el.prev = paper.top; - paper.top.next = el; - paper.top = el; - }, - toback = R._toback = function (el, paper) { - if (paper.bottom === el) { - return; - } - tear(el, paper); - el.next = paper.bottom; - el.prev = null; - paper.bottom.prev = el; - paper.bottom = el; - }, - insertafter = R._insertafter = function (el, el2, paper) { - tear(el, paper); - el2 == paper.top && (paper.top = el); - el2.next && (el2.next.prev = el); - el.next = el2.next; - el.prev = el2; - el2.next = el; - }, - insertbefore = R._insertbefore = function (el, el2, paper) { - tear(el, paper); - el2 == paper.bottom && (paper.bottom = el); - el2.prev && (el2.prev.next = el); - el.prev = el2.prev; - el2.prev = el; - el.next = el2; - }, - extractTransform = R._extractTransform = function (el, tstr) { - if (tstr == null) { - return el._.transform; - } - tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); - var tdata = R.parseTransformString(tstr), - deg = 0, - dx = 0, - dy = 0, - sx = 1, - sy = 1, - _ = el._, - m = new Matrix; - _.transform = tdata || []; - if (tdata) { - for (var i = 0, ii = tdata.length; i < ii; i++) { - var t = tdata[i], - tlen = t.length, - command = Str(t[0]).toLowerCase(), - absolute = t[0] != command, - inver = absolute ? m.invert() : 0, - x1, - y1, - x2, - y2, - bb; - if (command == "t" && tlen == 3) { - if (absolute) { - x1 = inver.x(0, 0); - y1 = inver.y(0, 0); - x2 = inver.x(t[1], t[2]); - y2 = inver.y(t[1], t[2]); - m.translate(x2 - x1, y2 - y1); - } else { - m.translate(t[1], t[2]); - } - } else if (command == "r") { - if (tlen == 2) { - bb = bb || el.getBBox(1); - m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); - deg += t[1]; - } else if (tlen == 4) { - if (absolute) { - x2 = inver.x(t[2], t[3]); - y2 = inver.y(t[2], t[3]); - m.rotate(t[1], x2, y2); - } else { - m.rotate(t[1], t[2], t[3]); - } - deg += t[1]; - } - } else if (command == "s") { - if (tlen == 2 || tlen == 3) { - bb = bb || el.getBBox(1); - m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); - sx *= t[1]; - sy *= t[tlen - 1]; - } else if (tlen == 5) { - if (absolute) { - x2 = inver.x(t[3], t[4]); - y2 = inver.y(t[3], t[4]); - m.scale(t[1], t[2], x2, y2); - } else { - m.scale(t[1], t[2], t[3], t[4]); - } - sx *= t[1]; - sy *= t[2]; - } - } else if (command == "m" && tlen == 7) { - m.add(t[1], t[2], t[3], t[4], t[5], t[6]); - } - _.dirtyT = 1; - el.matrix = m; - } - } - - el.matrix = m; - - _.sx = sx; - _.sy = sy; - _.deg = deg; - _.dx = dx = m.e; - _.dy = dy = m.f; - - if (sx == 1 && sy == 1 && !deg && _.bbox) { - _.bbox.x += +dx; - _.bbox.y += +dy; - } else { - _.dirtyT = 1; - } - }, - getEmpty = function (item) { - var l = item[0]; - switch (l.toLowerCase()) { - case "t": return [l, 0, 0]; - case "m": return [l, 1, 0, 0, 1, 0, 0]; - case "r": if (item.length == 4) { - return [l, 0, item[2], item[3]]; - } else { - return [l, 0]; - } - case "s": if (item.length == 5) { - return [l, 1, 1, item[3], item[4]]; - } else if (item.length == 3) { - return [l, 1, 1]; - } else { - return [l, 1]; - } - } - }, - equaliseTransform = R._equaliseTransform = function (t1, t2) { - t2 = Str(t2).replace(/\.{3}|\u2026/g, t1); - t1 = R.parseTransformString(t1) || []; - t2 = R.parseTransformString(t2) || []; - var maxlength = mmax(t1.length, t2.length), - from = [], - to = [], - i = 0, j, jj, - tt1, tt2; - for (; i < maxlength; i++) { - tt1 = t1[i] || getEmpty(t2[i]); - tt2 = t2[i] || getEmpty(tt1); - if ((tt1[0] != tt2[0]) || - (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || - (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) - ) { - return; - } - from[i] = []; - to[i] = []; - for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) { - j in tt1 && (from[i][j] = tt1[j]); - j in tt2 && (to[i][j] = tt2[j]); - } - } - return { - from: from, - to: to - }; - }; - R._getContainer = function (x, y, w, h) { - var container; - container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x; - if (container == null) { - return; - } - if (container.tagName) { - if (y == null) { - return { - container: container, - width: container.style.pixelWidth || container.offsetWidth, - height: container.style.pixelHeight || container.offsetHeight - }; - } else { - return { - container: container, - width: y, - height: w - }; - } - } - return { - container: 1, - x: x, - y: y, - width: w, - height: h - }; - }; - - R.pathToRelative = pathToRelative; - R._engine = {}; - - R.path2curve = path2curve; - - R.matrix = function (a, b, c, d, e, f) { - return new Matrix(a, b, c, d, e, f); - }; - function Matrix(a, b, c, d, e, f) { - if (a != null) { - this.a = +a; - this.b = +b; - this.c = +c; - this.d = +d; - this.e = +e; - this.f = +f; - } else { - this.a = 1; - this.b = 0; - this.c = 0; - this.d = 1; - this.e = 0; - this.f = 0; - } - } - (function (matrixproto) { - - matrixproto.add = function (a, b, c, d, e, f) { - var out = [[], [], []], - m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]], - matrix = [[a, c, e], [b, d, f], [0, 0, 1]], - x, y, z, res; - - if (a && a instanceof Matrix) { - matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]]; - } - - for (x = 0; x < 3; x++) { - for (y = 0; y < 3; y++) { - res = 0; - for (z = 0; z < 3; z++) { - res += m[x][z] * matrix[z][y]; - } - out[x][y] = res; - } - } - this.a = out[0][0]; - this.b = out[1][0]; - this.c = out[0][1]; - this.d = out[1][1]; - this.e = out[0][2]; - this.f = out[1][2]; - }; - - matrixproto.invert = function () { - var me = this, - x = me.a * me.d - me.b * me.c; - return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x); - }; - - matrixproto.clone = function () { - return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f); - }; - - matrixproto.translate = function (x, y) { - this.add(1, 0, 0, 1, x, y); - }; - - matrixproto.scale = function (x, y, cx, cy) { - y == null && (y = x); - (cx || cy) && this.add(1, 0, 0, 1, cx, cy); - this.add(x, 0, 0, y, 0, 0); - (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy); - }; - - matrixproto.rotate = function (a, x, y) { - a = R.rad(a); - x = x || 0; - y = y || 0; - var cos = +math.cos(a).toFixed(9), - sin = +math.sin(a).toFixed(9); - this.add(cos, sin, -sin, cos, x, y); - this.add(1, 0, 0, 1, -x, -y); - }; - - matrixproto.x = function (x, y) { - return x * this.a + y * this.c + this.e; - }; - - matrixproto.y = function (x, y) { - return x * this.b + y * this.d + this.f; - }; - matrixproto.get = function (i) { - return +this[Str.fromCharCode(97 + i)].toFixed(4); - }; - matrixproto.toString = function () { - return R.svg ? - "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" : - [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join(); - }; - matrixproto.toFilter = function () { - return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) + - ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) + - ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')"; - }; - matrixproto.offset = function () { - return [this.e.toFixed(4), this.f.toFixed(4)]; - }; - function norm(a) { - return a[0] * a[0] + a[1] * a[1]; - } - function normalize(a) { - var mag = math.sqrt(norm(a)); - a[0] && (a[0] /= mag); - a[1] && (a[1] /= mag); - } - - matrixproto.split = function () { - var out = {}; - // translation - out.dx = this.e; - out.dy = this.f; - - // scale and shear - var row = [[this.a, this.c], [this.b, this.d]]; - out.scalex = math.sqrt(norm(row[0])); - normalize(row[0]); - - out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1]; - row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear]; - - out.scaley = math.sqrt(norm(row[1])); - normalize(row[1]); - out.shear /= out.scaley; - - // rotation - var sin = -row[0][1], - cos = row[1][1]; - if (cos < 0) { - out.rotate = R.deg(math.acos(cos)); - if (sin < 0) { - out.rotate = 360 - out.rotate; - } - } else { - out.rotate = R.deg(math.asin(sin)); - } - - out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate); - out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate; - out.noRotation = !+out.shear.toFixed(9) && !out.rotate; - return out; - }; - - matrixproto.toTransformString = function (shorter) { - var s = shorter || this[split](); - if (s.isSimple) { - s.scalex = +s.scalex.toFixed(4); - s.scaley = +s.scaley.toFixed(4); - s.rotate = +s.rotate.toFixed(4); - return (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) + - (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) + - (s.rotate ? "r" + [s.rotate, 0, 0] : E); - } else { - return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)]; - } - }; - })(Matrix.prototype); - - // WebKit rendering bug workaround method - var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); - if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || - (navigator.vendor == "Google Inc." && version && version[1] < 8)) { - - paperproto.safari = function () { - var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); - setTimeout(function () {rect.remove();}); - }; - } else { - paperproto.safari = fun; - } - - var preventDefault = function () { - this.returnValue = false; - }, - preventTouch = function () { - return this.originalEvent.preventDefault(); - }, - stopPropagation = function () { - this.cancelBubble = true; - }, - stopTouch = function () { - return this.originalEvent.stopPropagation(); - }, - addEvent = (function () { - if (g.doc.addEventListener) { - return function (obj, type, fn, element) { - var realName = supportsTouch && touchMap[type] ? touchMap[type] : type, - f = function (e) { - var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, - scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, - x = e.clientX + scrollX, - y = e.clientY + scrollY; - if (supportsTouch && touchMap[has](type)) { - for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { - if (e.targetTouches[i].target == obj) { - var olde = e; - e = e.targetTouches[i]; - e.originalEvent = olde; - e.preventDefault = preventTouch; - e.stopPropagation = stopTouch; - break; - } - } - } - return fn.call(element, e, x, y); - }; - obj.addEventListener(realName, f, false); - return function () { - obj.removeEventListener(realName, f, false); - return true; - }; - }; - } else if (g.doc.attachEvent) { - return function (obj, type, fn, element) { - var f = function (e) { - e = e || g.win.event; - var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, - scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, - x = e.clientX + scrollX, - y = e.clientY + scrollY; - e.preventDefault = e.preventDefault || preventDefault; - e.stopPropagation = e.stopPropagation || stopPropagation; - return fn.call(element, e, x, y); - }; - obj.attachEvent("on" + type, f); - var detacher = function () { - obj.detachEvent("on" + type, f); - return true; - }; - return detacher; - }; - } - })(), - drag = [], - dragMove = function (e) { - var x = e.clientX, - y = e.clientY, - scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, - scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, - dragi, - j = drag.length; - while (j--) { - dragi = drag[j]; - if (supportsTouch) { - var i = e.touches.length, - touch; - while (i--) { - touch = e.touches[i]; - if (touch.identifier == dragi.el._drag.id) { - x = touch.clientX; - y = touch.clientY; - (e.originalEvent ? e.originalEvent : e).preventDefault(); - break; - } - } - } else { - e.preventDefault(); - } - var node = dragi.el.node, - o, - next = node.nextSibling, - parent = node.parentNode, - display = node.style.display; - g.win.opera && parent.removeChild(node); - node.style.display = "none"; - o = dragi.el.paper.getElementByPoint(x, y); - node.style.display = display; - g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); - o && eve("drag.over." + dragi.el.id, dragi.el, o); - x += scrollX; - y += scrollY; - eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); - } - }, - dragUp = function (e) { - R.unmousemove(dragMove).unmouseup(dragUp); - var i = drag.length, - dragi; - while (i--) { - dragi = drag[i]; - dragi.el._drag = {}; - eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); - } - drag = []; - }, - - elproto = R.el = {}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for (var i = events.length; i--;) { - (function (eventName) { - R[eventName] = elproto[eventName] = function (fn, scope) { - if (R.is(fn, "function")) { - this.events = this.events || []; - this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); - } - return this; - }; - R["un" + eventName] = elproto["un" + eventName] = function (fn) { - var events = this.events || [], - l = events.length; - while (l--) if (events[l].name == eventName && events[l].f == fn) { - events[l].unbind(); - events.splice(l, 1); - !events.length && delete this.events; - return this; - } - return this; - }; - })(events[i]); - } - - - elproto.data = function (key, value) { - var data = eldata[this.id] = eldata[this.id] || {}; - if (arguments.length == 1) { - if (R.is(key, "object")) { - for (var i in key) if (key[has](i)) { - this.data(i, key[i]); - } - return this; - } - eve("data.get." + this.id, this, data[key], key); - return data[key]; - } - data[key] = value; - eve("data.set." + this.id, this, value, key); - return this; - }; - - elproto.removeData = function (key) { - if (key == null) { - eldata[this.id] = {}; - } else { - eldata[this.id] && delete eldata[this.id][key]; - } - return this; - }; - - elproto.hover = function (f_in, f_out, scope_in, scope_out) { - return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); - }; - - elproto.unhover = function (f_in, f_out) { - return this.unmouseover(f_in).unmouseout(f_out); - }; - var draggable = []; - - elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { - function start(e) { - (e.originalEvent || e).preventDefault(); - var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, - scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; - this._drag.x = e.clientX + scrollX; - this._drag.y = e.clientY + scrollY; - this._drag.id = e.identifier; - !drag.length && R.mousemove(dragMove).mouseup(dragUp); - drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); - onstart && eve.on("drag.start." + this.id, onstart); - onmove && eve.on("drag.move." + this.id, onmove); - onend && eve.on("drag.end." + this.id, onend); - eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); - } - this._drag = {}; - draggable.push({el: this, start: start}); - this.mousedown(start); - return this; - }; - - elproto.onDragOver = function (f) { - f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id); - }; - - elproto.undrag = function () { - var i = draggable.length; - while (i--) if (draggable[i].el == this) { - this.unmousedown(draggable[i].start); - draggable.splice(i, 1); - eve.unbind("drag.*." + this.id); - } - !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp); - }; - - paperproto.circle = function (x, y, r) { - var out = R._engine.circle(this, x || 0, y || 0, r || 0); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.rect = function (x, y, w, h, r) { - var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.ellipse = function (x, y, rx, ry) { - var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.path = function (pathString) { - pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); - var out = R._engine.path(R.format[apply](R, arguments), this); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.image = function (src, x, y, w, h) { - var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.text = function (x, y, text) { - var out = R._engine.text(this, x || 0, y || 0, Str(text)); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.set = function (itemsArray) { - !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); - var out = new Set(itemsArray); - this.__set__ && this.__set__.push(out); - return out; - }; - - paperproto.setStart = function (set) { - this.__set__ = set || this.set(); - }; - - paperproto.setFinish = function (set) { - var out = this.__set__; - delete this.__set__; - return out; - }; - - paperproto.setSize = function (width, height) { - return R._engine.setSize.call(this, width, height); - }; - - paperproto.setViewBox = function (x, y, w, h, fit) { - return R._engine.setViewBox.call(this, x, y, w, h, fit); - }; - - - paperproto.top = paperproto.bottom = null; - - paperproto.raphael = R; - var getOffset = function (elem) { - var box = elem.getBoundingClientRect(), - doc = elem.ownerDocument, - body = doc.body, - docElem = doc.documentElement, - clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, - top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, - left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; - return { - y: top, - x: left - }; - }; - - paperproto.getElementByPoint = function (x, y) { - var paper = this, - svg = paper.canvas, - target = g.doc.elementFromPoint(x, y); - if (g.win.opera && target.tagName == "svg") { - var so = getOffset(svg), - sr = svg.createSVGRect(); - sr.x = x - so.x; - sr.y = y - so.y; - sr.width = sr.height = 1; - var hits = svg.getIntersectionList(sr, null); - if (hits.length) { - target = hits[hits.length - 1]; - } - } - if (!target) { - return null; - } - while (target.parentNode && target != svg.parentNode && !target.raphael) { - target = target.parentNode; - } - target == paper.canvas.parentNode && (target = svg); - target = target && target.raphael ? paper.getById(target.raphaelid) : null; - return target; - }; - - paperproto.getById = function (id) { - var bot = this.bottom; - while (bot) { - if (bot.id == id) { - return bot; - } - bot = bot.next; - } - return null; - }; - - paperproto.forEach = function (callback, thisArg) { - var bot = this.bottom; - while (bot) { - if (callback.call(thisArg, bot) === false) { - return this; - } - bot = bot.next; - } - return this; - }; - function x_y() { - return this.x + S + this.y; - } - function x_y_w_h() { - return this.x + S + this.y + S + this.width + " \xd7 " + this.height; - } - - elproto.getBBox = function (isWithoutTransform) { - if (this.removed) { - return {}; - } - var _ = this._; - if (isWithoutTransform) { - if (_.dirty || !_.bboxwt) { - this.realPath = getPath[this.type](this); - _.bboxwt = pathDimensions(this.realPath); - _.bboxwt.toString = x_y_w_h; - _.dirty = 0; - } - return _.bboxwt; - } - if (_.dirty || _.dirtyT || !_.bbox) { - if (_.dirty || !this.realPath) { - _.bboxwt = 0; - this.realPath = getPath[this.type](this); - } - _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); - _.bbox.toString = x_y_w_h; - _.dirty = _.dirtyT = 0; - } - return _.bbox; - }; - - elproto.clone = function () { - if (this.removed) { - return null; - } - var out = this.paper[this.type]().attr(this.attr()); - this.__set__ && this.__set__.push(out); - return out; - }; - - elproto.glow = function (glow) { - if (this.type == "text") { - return null; - } - glow = glow || {}; - var s = { - width: (glow.width || 10) + (+this.attr("stroke-width") || 1), - fill: glow.fill || false, - opacity: glow.opacity || .5, - offsetx: glow.offsetx || 0, - offsety: glow.offsety || 0, - color: glow.color || "#000" - }, - c = s.width / 2, - r = this.paper, - out = r.set(), - path = this.realPath || getPath[this.type](this); - path = this.matrix ? mapPath(path, this.matrix) : path; - for (var i = 1; i < c + 1; i++) { - out.push(r.path(path).attr({ - stroke: s.color, - fill: s.fill ? s.color : "none", - "stroke-linejoin": "round", - "stroke-linecap": "round", - "stroke-width": +(s.width / c * i).toFixed(3), - opacity: +(s.opacity / c).toFixed(3) - })); - } - return out.insertBefore(this).translate(s.offsetx, s.offsety); - }; - var curveslengths = {}, - getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { - var len = 0, - precision = 100, - name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(), - cache = curveslengths[name], - old, dot; - !cache && (curveslengths[name] = cache = {data: []}); - cache.timer && clearTimeout(cache.timer); - cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3); - if (length != null && !cache.precision) { - var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); - cache.precision = ~~total * 10; - cache.data = []; - } - precision = cache.precision || precision; - for (var i = 0; i < precision + 1; i++) { - if (cache.data[i * precision]) { - dot = cache.data[i * precision]; - } else { - dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision); - cache.data[i * precision] = dot; - } - i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); - if (length != null && len >= length) { - return dot; - } - old = dot; - } - if (length == null) { - return len; - } - }, - getLengthFactory = function (istotal, subpath) { - return function (path, length, onlystart) { - path = path2curve(path); - var x, y, p, l, sp = "", subpaths = {}, point, - len = 0; - for (var i = 0, ii = path.length; i < ii; i++) { - p = path[i]; - if (p[0] == "M") { - x = +p[1]; - y = +p[2]; - } else { - l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); - if (len + l > length) { - if (subpath && !subpaths.start) { - point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); - sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; - if (onlystart) {return sp;} - subpaths.start = sp; - sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); - len += l; - x = +p[5]; - y = +p[6]; - continue; - } - if (!istotal && !subpath) { - point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); - return {x: point.x, y: point.y, alpha: point.alpha}; - } - } - len += l; - x = +p[5]; - y = +p[6]; - } - sp += p.shift() + p; - } - subpaths.end = sp; - point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); - point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); - return point; - }; - }; - var getTotalLength = getLengthFactory(1), - getPointAtLength = getLengthFactory(), - getSubpathsAtLength = getLengthFactory(0, 1); - - R.getTotalLength = getTotalLength; - - R.getPointAtLength = getPointAtLength; - - R.getSubpath = function (path, from, to) { - if (this.getTotalLength(path) - to < 1e-6) { - return getSubpathsAtLength(path, from).end; - } - var a = getSubpathsAtLength(path, to, 1); - return from ? getSubpathsAtLength(a, from).end : a; - }; - - elproto.getTotalLength = function () { - if (this.type != "path") {return;} - if (this.node.getTotalLength) { - return this.node.getTotalLength(); - } - return getTotalLength(this.attrs.path); - }; - - elproto.getPointAtLength = function (length) { - if (this.type != "path") {return;} - return getPointAtLength(this.attrs.path, length); - }; - - elproto.getSubpath = function (from, to) { - if (this.type != "path") {return;} - return R.getSubpath(this.attrs.path, from, to); - }; - - var ef = R.easing_formulas = { - linear: function (n) { - return n; - }, - "<": function (n) { - return pow(n, 1.7); - }, - ">": function (n) { - return pow(n, .48); - }, - "<>": function (n) { - var q = .48 - n / 1.04, - Q = math.sqrt(.1734 + q * q), - x = Q - q, - X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), - y = -Q - q, - Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), - t = X + Y + .5; - return (1 - t) * 3 * t * t + t * t * t; - }, - backIn: function (n) { - var s = 1.70158; - return n * n * ((s + 1) * n - s); - }, - backOut: function (n) { - n = n - 1; - var s = 1.70158; - return n * n * ((s + 1) * n + s) + 1; - }, - elastic: function (n) { - if (n == !!n) { - return n; - } - return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; - }, - bounce: function (n) { - var s = 7.5625, - p = 2.75, - l; - if (n < (1 / p)) { - l = s * n * n; - } else { - if (n < (2 / p)) { - n -= (1.5 / p); - l = s * n * n + .75; - } else { - if (n < (2.5 / p)) { - n -= (2.25 / p); - l = s * n * n + .9375; - } else { - n -= (2.625 / p); - l = s * n * n + .984375; - } - } - } - return l; - } - }; - ef.easeIn = ef["ease-in"] = ef["<"]; - ef.easeOut = ef["ease-out"] = ef[">"]; - ef.easeInOut = ef["ease-in-out"] = ef["<>"]; - ef["back-in"] = ef.backIn; - ef["back-out"] = ef.backOut; - - var animationElements = [], - requestAnimFrame = window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function (callback) { - setTimeout(callback, 16); - }, - animation = function () { - var Now = +new Date, - l = 0; - for (; l < animationElements.length; l++) { - var e = animationElements[l]; - if (e.el.removed || e.paused) { - continue; - } - var time = Now - e.start, - ms = e.ms, - easing = e.easing, - from = e.from, - diff = e.diff, - to = e.to, - t = e.t, - that = e.el, - set = {}, - now, - init = {}, - key; - if (e.initstatus) { - time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; - e.status = e.initstatus; - delete e.initstatus; - e.stop && animationElements.splice(l--, 1); - } else { - e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; - } - if (time < 0) { - continue; - } - if (time < ms) { - var pos = easing(time / ms); - for (var attr in from) if (from[has](attr)) { - switch (availableAnimAttrs[attr]) { - case nu: - now = +from[attr] + pos * ms * diff[attr]; - break; - case "colour": - now = "rgb(" + [ - upto255(round(from[attr].r + pos * ms * diff[attr].r)), - upto255(round(from[attr].g + pos * ms * diff[attr].g)), - upto255(round(from[attr].b + pos * ms * diff[attr].b)) - ].join(",") + ")"; - break; - case "path": - now = []; - for (var i = 0, ii = from[attr].length; i < ii; i++) { - now[i] = [from[attr][i][0]]; - for (var j = 1, jj = from[attr][i].length; j < jj; j++) { - now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; - } - now[i] = now[i].join(S); - } - now = now.join(S); - break; - case "transform": - if (diff[attr].real) { - now = []; - for (i = 0, ii = from[attr].length; i < ii; i++) { - now[i] = [from[attr][i][0]]; - for (j = 1, jj = from[attr][i].length; j < jj; j++) { - now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; - } - } - } else { - var get = function (i) { - return +from[attr][i] + pos * ms * diff[attr][i]; - }; - // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; - now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; - } - break; - case "csv": - if (attr == "clip-rect") { - now = []; - i = 4; - while (i--) { - now[i] = +from[attr][i] + pos * ms * diff[attr][i]; - } - } - break; - default: - var from2 = [][concat](from[attr]); - now = []; - i = that.paper.customAttributes[attr].length; - while (i--) { - now[i] = +from2[i] + pos * ms * diff[attr][i]; - } - break; - } - set[attr] = now; - } - that.attr(set); - (function (id, that, anim) { - setTimeout(function () { - eve("anim.frame." + id, that, anim); - }); - })(that.id, that, e.anim); - } else { - (function(f, el, a) { - setTimeout(function() { - eve("anim.frame." + el.id, el, a); - eve("anim.finish." + el.id, el, a); - R.is(f, "function") && f.call(el); - }); - })(e.callback, that, e.anim); - that.attr(to); - animationElements.splice(l--, 1); - if (e.repeat > 1 && !e.next) { - for (key in to) if (to[has](key)) { - init[key] = e.totalOrigin[key]; - } - e.el.attr(init); - runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1); - } - if (e.next && !e.stop) { - runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat); - } - } - } - R.svg && that && that.paper && that.paper.safari(); - animationElements.length && requestAnimFrame(animation); - }, - upto255 = function (color) { - return color > 255 ? 255 : color < 0 ? 0 : color; - }; - - elproto.animateWith = function (el, anim, params, ms, easing, callback) { - var element = this; - if (element.removed) { - callback && callback.call(element); - return element; - } - var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback), - x, y; - runAnimation(a, element, a.percents[0], null, element.attr()); - for (var i = 0, ii = animationElements.length; i < ii; i++) { - if (animationElements[i].anim == anim && animationElements[i].el == el) { - animationElements[ii - 1].start = animationElements[i].start; - break; - } - } - return element; - // - // - // var a = params ? R.animation(params, ms, easing, callback) : anim, - // status = element.status(anim); - // return this.animate(a).status(a, status * anim.ms / a.ms); - }; - function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { - var cx = 3 * p1x, - bx = 3 * (p2x - p1x) - cx, - ax = 1 - cx - bx, - cy = 3 * p1y, - by = 3 * (p2y - p1y) - cy, - ay = 1 - cy - by; - function sampleCurveX(t) { - return ((ax * t + bx) * t + cx) * t; - } - function solve(x, epsilon) { - var t = solveCurveX(x, epsilon); - return ((ay * t + by) * t + cy) * t; - } - function solveCurveX(x, epsilon) { - var t0, t1, t2, x2, d2, i; - for(t2 = x, i = 0; i < 8; i++) { - x2 = sampleCurveX(t2) - x; - if (abs(x2) < epsilon) { - return t2; - } - d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; - if (abs(d2) < 1e-6) { - break; - } - t2 = t2 - x2 / d2; - } - t0 = 0; - t1 = 1; - t2 = x; - if (t2 < t0) { - return t0; - } - if (t2 > t1) { - return t1; - } - while (t0 < t1) { - x2 = sampleCurveX(t2); - if (abs(x2 - x) < epsilon) { - return t2; - } - if (x > x2) { - t0 = t2; - } else { - t1 = t2; - } - t2 = (t1 - t0) / 2 + t0; - } - return t2; - } - return solve(t, 1 / (200 * duration)); - } - elproto.onAnimation = function (f) { - f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id); - return this; - }; - function Animation(anim, ms) { - var percents = [], - newAnim = {}; - this.ms = ms; - this.times = 1; - if (anim) { - for (var attr in anim) if (anim[has](attr)) { - newAnim[toFloat(attr)] = anim[attr]; - percents.push(toFloat(attr)); - } - percents.sort(sortByNumber); - } - this.anim = newAnim; - this.top = percents[percents.length - 1]; - this.percents = percents; - } - - Animation.prototype.delay = function (delay) { - var a = new Animation(this.anim, this.ms); - a.times = this.times; - a.del = +delay || 0; - return a; - }; - - Animation.prototype.repeat = function (times) { - var a = new Animation(this.anim, this.ms); - a.del = this.del; - a.times = math.floor(mmax(times, 0)) || 1; - return a; - }; - function runAnimation(anim, element, percent, status, totalOrigin, times) { - percent = toFloat(percent); - var params, - isInAnim, - isInAnimSet, - percents = [], - next, - prev, - timestamp, - ms = anim.ms, - from = {}, - to = {}, - diff = {}; - if (status) { - for (i = 0, ii = animationElements.length; i < ii; i++) { - var e = animationElements[i]; - if (e.el.id == element.id && e.anim == anim) { - if (e.percent != percent) { - animationElements.splice(i, 1); - isInAnimSet = 1; - } else { - isInAnim = e; - } - element.attr(e.totalOrigin); - break; - } - } - } else { - status = +to; // NaN - } - for (var i = 0, ii = anim.percents.length; i < ii; i++) { - if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { - percent = anim.percents[i]; - prev = anim.percents[i - 1] || 0; - ms = ms / anim.top * (percent - prev); - next = anim.percents[i + 1]; - params = anim.anim[percent]; - break; - } else if (status) { - element.attr(anim.anim[anim.percents[i]]); - } - } - if (!params) { - return; - } - if (!isInAnim) { - for (var attr in params) if (params[has](attr)) { - if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { - from[attr] = element.attr(attr); - (from[attr] == null) && (from[attr] = availableAttrs[attr]); - to[attr] = params[attr]; - switch (availableAnimAttrs[attr]) { - case nu: - diff[attr] = (to[attr] - from[attr]) / ms; - break; - case "colour": - from[attr] = R.getRGB(from[attr]); - var toColour = R.getRGB(to[attr]); - diff[attr] = { - r: (toColour.r - from[attr].r) / ms, - g: (toColour.g - from[attr].g) / ms, - b: (toColour.b - from[attr].b) / ms - }; - break; - case "path": - var pathes = path2curve(from[attr], to[attr]), - toPath = pathes[1]; - from[attr] = pathes[0]; - diff[attr] = []; - for (i = 0, ii = from[attr].length; i < ii; i++) { - diff[attr][i] = [0]; - for (var j = 1, jj = from[attr][i].length; j < jj; j++) { - diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; - } - } - break; - case "transform": - var _ = element._, - eq = equaliseTransform(_[attr], to[attr]); - if (eq) { - from[attr] = eq.from; - to[attr] = eq.to; - diff[attr] = []; - diff[attr].real = true; - for (i = 0, ii = from[attr].length; i < ii; i++) { - diff[attr][i] = [from[attr][i][0]]; - for (j = 1, jj = from[attr][i].length; j < jj; j++) { - diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; - } - } - } else { - var m = (element.matrix || new Matrix), - to2 = { - _: {transform: _.transform}, - getBBox: function () { - return element.getBBox(1); - } - }; - from[attr] = [ - m.a, - m.b, - m.c, - m.d, - m.e, - m.f - ]; - extractTransform(to2, to[attr]); - to[attr] = to2._.transform; - diff[attr] = [ - (to2.matrix.a - m.a) / ms, - (to2.matrix.b - m.b) / ms, - (to2.matrix.c - m.c) / ms, - (to2.matrix.d - m.d) / ms, - (to2.matrix.e - m.e) / ms, - (to2.matrix.e - m.f) / ms - ]; - // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; - // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; - // extractTransform(to2, to[attr]); - // diff[attr] = [ - // (to2._.sx - _.sx) / ms, - // (to2._.sy - _.sy) / ms, - // (to2._.deg - _.deg) / ms, - // (to2._.dx - _.dx) / ms, - // (to2._.dy - _.dy) / ms - // ]; - } - break; - case "csv": - var values = Str(params[attr])[split](separator), - from2 = Str(from[attr])[split](separator); - if (attr == "clip-rect") { - from[attr] = from2; - diff[attr] = []; - i = from2.length; - while (i--) { - diff[attr][i] = (values[i] - from[attr][i]) / ms; - } - } - to[attr] = values; - break; - default: - values = [][concat](params[attr]); - from2 = [][concat](from[attr]); - diff[attr] = []; - i = element.paper.customAttributes[attr].length; - while (i--) { - diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; - } - break; - } - } - } - var easing = params.easing, - easyeasy = R.easing_formulas[easing]; - if (!easyeasy) { - easyeasy = Str(easing).match(bezierrg); - if (easyeasy && easyeasy.length == 5) { - var curve = easyeasy; - easyeasy = function (t) { - return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); - }; - } else { - easyeasy = pipe; - } - } - timestamp = params.start || anim.start || +new Date; - e = { - anim: anim, - percent: percent, - timestamp: timestamp, - start: timestamp + (anim.del || 0), - status: 0, - initstatus: status || 0, - stop: false, - ms: ms, - easing: easyeasy, - from: from, - diff: diff, - to: to, - el: element, - callback: params.callback, - prev: prev, - next: next, - repeat: times || anim.times, - origin: element.attr(), - totalOrigin: totalOrigin - }; - animationElements.push(e); - if (status && !isInAnim && !isInAnimSet) { - e.stop = true; - e.start = new Date - ms * status; - if (animationElements.length == 1) { - return animation(); - } - } - if (isInAnimSet) { - e.start = new Date - e.ms * status; - } - animationElements.length == 1 && requestAnimFrame(animation); - } else { - isInAnim.initstatus = status; - isInAnim.start = new Date - isInAnim.ms * status; - } - eve("anim.start." + element.id, element, anim); - } - - R.animation = function (params, ms, easing, callback) { - if (params instanceof Animation) { - return params; - } - if (R.is(easing, "function") || !easing) { - callback = callback || easing || null; - easing = null; - } - params = Object(params); - ms = +ms || 0; - var p = {}, - json, - attr; - for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) { - json = true; - p[attr] = params[attr]; - } - if (!json) { - return new Animation(params, ms); - } else { - easing && (p.easing = easing); - callback && (p.callback = callback); - return new Animation({100: p}, ms); - } - }; - - elproto.animate = function (params, ms, easing, callback) { - var element = this; - if (element.removed) { - callback && callback.call(element); - return element; - } - var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); - runAnimation(anim, element, anim.percents[0], null, element.attr()); - return element; - }; - - elproto.setTime = function (anim, value) { - if (anim && value != null) { - this.status(anim, mmin(value, anim.ms) / anim.ms); - } - return this; - }; - - elproto.status = function (anim, value) { - var out = [], - i = 0, - len, - e; - if (value != null) { - runAnimation(anim, this, -1, mmin(value, 1)); - return this; - } else { - len = animationElements.length; - for (; i < len; i++) { - e = animationElements[i]; - if (e.el.id == this.id && (!anim || e.anim == anim)) { - if (anim) { - return e.status; - } - out.push({ - anim: e.anim, - status: e.status - }); - } - } - if (anim) { - return 0; - } - return out; - } - }; - - elproto.pause = function (anim) { - for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { - if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) { - animationElements[i].paused = true; - } - } - return this; - }; - - elproto.resume = function (anim) { - for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { - var e = animationElements[i]; - if (eve("anim.resume." + this.id, this, e.anim) !== false) { - delete e.paused; - this.status(e.anim, e.status); - } - } - return this; - }; - - elproto.stop = function (anim) { - for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { - if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) { - animationElements.splice(i--, 1); - } - } - return this; - }; - elproto.toString = function () { - return "Rapha\xebl\u2019s object"; - }; - - // Set - var Set = function (items) { - this.items = []; - this.length = 0; - this.type = "set"; - if (items) { - for (var i = 0, ii = items.length; i < ii; i++) { - if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) { - this[this.items.length] = this.items[this.items.length] = items[i]; - this.length++; - } - } - } - }, - setproto = Set.prototype; - - setproto.push = function () { - var item, - len; - for (var i = 0, ii = arguments.length; i < ii; i++) { - item = arguments[i]; - if (item && (item.constructor == elproto.constructor || item.constructor == Set)) { - len = this.items.length; - this[len] = this.items[len] = item; - this.length++; - } - } - return this; - }; - - setproto.pop = function () { - this.length && delete this[this.length--]; - return this.items.pop(); - }; - - setproto.forEach = function (callback, thisArg) { - for (var i = 0, ii = this.items.length; i < ii; i++) { - if (callback.call(thisArg, this.items[i], i) === false) { - return this; - } - } - return this; - }; - for (var method in elproto) if (elproto[has](method)) { - setproto[method] = (function (methodname) { - return function () { - var arg = arguments; - return this.forEach(function (el) { - el[methodname][apply](el, arg); - }); - }; - })(method); - } - setproto.attr = function (name, value) { - if (name && R.is(name, array) && R.is(name[0], "object")) { - for (var j = 0, jj = name.length; j < jj; j++) { - this.items[j].attr(name[j]); - } - } else { - for (var i = 0, ii = this.items.length; i < ii; i++) { - this.items[i].attr(name, value); - } - } - return this; - }; - - setproto.clear = function () { - while (this.length) { - this.pop(); - } - }; - - setproto.splice = function (index, count, insertion) { - index = index < 0 ? mmax(this.length + index, 0) : index; - count = mmax(0, mmin(this.length - index, count)); - var tail = [], - todel = [], - args = [], - i; - for (i = 2; i < arguments.length; i++) { - args.push(arguments[i]); - } - for (i = 0; i < count; i++) { - todel.push(this[index + i]); - } - for (; i < this.length - index; i++) { - tail.push(this[index + i]); - } - var arglen = args.length; - for (i = 0; i < arglen + tail.length; i++) { - this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen]; - } - i = this.items.length = this.length -= count - arglen; - while (this[i]) { - delete this[i++]; - } - return new Set(todel); - }; - - setproto.exclude = function (el) { - for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) { - this.splice(i, 1); - return true; - } - }; - setproto.animate = function (params, ms, easing, callback) { - (R.is(easing, "function") || !easing) && (callback = easing || null); - var len = this.items.length, - i = len, - item, - set = this, - collector; - if (!len) { - return this; - } - callback && (collector = function () { - !--len && callback.call(set); - }); - easing = R.is(easing, string) ? easing : collector; - var anim = R.animation(params, ms, easing, collector); - item = this.items[--i].animate(anim); - while (i--) { - this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim); - } - return this; - }; - setproto.insertAfter = function (el) { - var i = this.items.length; - while (i--) { - this.items[i].insertAfter(el); - } - return this; - }; - setproto.getBBox = function () { - var x = [], - y = [], - w = [], - h = []; - for (var i = this.items.length; i--;) if (!this.items[i].removed) { - var box = this.items[i].getBBox(); - x.push(box.x); - y.push(box.y); - w.push(box.x + box.width); - h.push(box.y + box.height); - } - x = mmin[apply](0, x); - y = mmin[apply](0, y); - return { - x: x, - y: y, - width: mmax[apply](0, w) - x, - height: mmax[apply](0, h) - y - }; - }; - setproto.clone = function (s) { - s = new Set; - for (var i = 0, ii = this.items.length; i < ii; i++) { - s.push(this.items[i].clone()); - } - return s; - }; - setproto.toString = function () { - return "Rapha\xebl\u2018s set"; - }; - - - R.registerFont = function (font) { - if (!font.face) { - return font; - } - this.fonts = this.fonts || {}; - var fontcopy = { - w: font.w, - face: {}, - glyphs: {} - }, - family = font.face["font-family"]; - for (var prop in font.face) if (font.face[has](prop)) { - fontcopy.face[prop] = font.face[prop]; - } - if (this.fonts[family]) { - this.fonts[family].push(fontcopy); - } else { - this.fonts[family] = [fontcopy]; - } - if (!font.svg) { - fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); - for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { - var path = font.glyphs[glyph]; - fontcopy.glyphs[glyph] = { - w: path.w, - k: {}, - d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { - return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; - }) + "z" - }; - if (path.k) { - for (var k in path.k) if (path[has](k)) { - fontcopy.glyphs[glyph].k[k] = path.k[k]; - } - } - } - } - return font; - }; - - paperproto.getFont = function (family, weight, style, stretch) { - stretch = stretch || "normal"; - style = style || "normal"; - weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; - if (!R.fonts) { - return; - } - var font = R.fonts[family]; - if (!font) { - var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); - for (var fontName in R.fonts) if (R.fonts[has](fontName)) { - if (name.test(fontName)) { - font = R.fonts[fontName]; - break; - } - } - } - var thefont; - if (font) { - for (var i = 0, ii = font.length; i < ii; i++) { - thefont = font[i]; - if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { - break; - } - } - } - return thefont; - }; - - paperproto.print = function (x, y, string, font, size, origin, letter_spacing) { - origin = origin || "middle"; // baseline|middle - letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); - var out = this.set(), - letters = Str(string)[split](E), - shift = 0, - path = E, - scale; - R.is(font, string) && (font = this.getFont(font)); - if (font) { - scale = (size || 16) / font.face["units-per-em"]; - var bb = font.face.bbox[split](separator), - top = +bb[0], - height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); - for (var i = 0, ii = letters.length; i < ii; i++) { - var prev = i && font.glyphs[letters[i - 1]] || {}, - curr = font.glyphs[letters[i]]; - shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; - curr && curr.d && out.push(this.path(curr.d).attr({ - fill: "#000", - stroke: "none", - transform: [["t", shift * scale, 0]] - })); - } - out.transform(["...s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]); - } - return out; - }; - - - paperproto.add = function (json) { - if (R.is(json, "array")) { - var res = this.set(), - i = 0, - ii = json.length, - j; - for (; i < ii; i++) { - j = json[i] || {}; - elements[has](j.type) && res.push(this[j.type]().attr(j)); - } - } - return res; - }; - - - R.format = function (token, params) { - var args = R.is(params, array) ? [0][concat](params) : arguments; - token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { - return args[++i] == null ? E : args[i]; - })); - return token || E; - }; - - R.fullfill = (function () { - var tokenRegex = /\{([^\}]+)\}/g, - objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties - replacer = function (all, key, obj) { - var res = obj; - key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { - name = name || quotedName; - if (res) { - if (name in res) { - res = res[name]; - } - typeof res == "function" && isFunc && (res = res()); - } - }); - res = (res == null || res == obj ? all : res) + ""; - return res; - }; - return function (str, obj) { - return String(str).replace(tokenRegex, function (all, key) { - return replacer(all, key, obj); - }); - }; - })(); - - R.ninja = function () { - oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; - return R; - }; - - R.st = setproto; - // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html - (function (doc, loaded, f) { - if (doc.readyState == null && doc.addEventListener){ - doc.addEventListener(loaded, f = function () { - doc.removeEventListener(loaded, f, false); - doc.readyState = "complete"; - }, false); - doc.readyState = "loading"; - } - function isLoaded() { - (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("DOMload"); - } - isLoaded(); - })(document, "DOMContentLoaded"); - - oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); - - eve.on("DOMload", function () { - loaded = true; - }); -})(); - - -// ┌─────────────────────────────────────────────────────────────────────┐ \\ -// │ Raphaël - JavaScript Vector Library │ \\ -// ├─────────────────────────────────────────────────────────────────────┤ \\ -// │ SVG Module │ \\ -// ├─────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ -// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ -// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ -// └─────────────────────────────────────────────────────────────────────┘ \\ -window.Raphael.svg && function (R) { - var has = "hasOwnProperty", - Str = String, - toFloat = parseFloat, - toInt = parseInt, - math = Math, - mmax = math.max, - abs = math.abs, - pow = math.pow, - separator = /[, ]+/, - eve = R.eve, - E = "", - S = " "; - var xlink = "http://www.w3.org/1999/xlink", - markers = { - block: "M5,0 0,2.5 5,5z", - classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z", - diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z", - open: "M6,1 1,3.5 6,6", - oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z" - }, - markerCounter = {}; - R.toString = function () { - return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; - }; - var $ = function (el, attr) { - if (attr) { - if (typeof el == "string") { - el = $(el); - } - for (var key in attr) if (attr[has](key)) { - if (key.substring(0, 6) == "xlink:") { - el.setAttributeNS(xlink, key.substring(6), Str(attr[key])); - } else { - el.setAttribute(key, Str(attr[key])); - } - } - } else { - el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el); - el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"); - } - return el; - }, - addGradientFill = function (element, gradient) { - var type = "linear", - id = element.id + gradient, - fx = .5, fy = .5, - o = element.node, - SVG = element.paper, - s = o.style, - el = R._g.doc.getElementById(id); - if (!el) { - gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) { - type = "radial"; - if (_fx && _fy) { - fx = toFloat(_fx); - fy = toFloat(_fy); - var dir = ((fy > .5) * 2 - 1); - pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && - (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) && - fy != .5 && - (fy = fy.toFixed(5) - 1e-5 * dir); - } - return E; - }); - gradient = gradient.split(/\s*\-\s*/); - if (type == "linear") { - var angle = gradient.shift(); - angle = -toFloat(angle); - if (isNaN(angle)) { - return null; - } - var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))], - max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1); - vector[2] *= max; - vector[3] *= max; - if (vector[2] < 0) { - vector[0] = -vector[2]; - vector[2] = 0; - } - if (vector[3] < 0) { - vector[1] = -vector[3]; - vector[3] = 0; - } - } - var dots = R._parseDots(gradient); - if (!dots) { - return null; - } - id = id.replace(/[\(\)\s,\xb0#]/g, "_"); - - if (element.gradient && id != element.gradient.id) { - SVG.defs.removeChild(element.gradient); - delete element.gradient; - } - - if (!element.gradient) { - el = $(type + "Gradient", {id: id}); - element.gradient = el; - $(el, type == "radial" ? { - fx: fx, - fy: fy - } : { - x1: vector[0], - y1: vector[1], - x2: vector[2], - y2: vector[3], - gradientTransform: element.matrix.invert() - }); - SVG.defs.appendChild(el); - for (var i = 0, ii = dots.length; i < ii; i++) { - el.appendChild($("stop", { - offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%", - "stop-color": dots[i].color || "#fff" - })); - } - } - } - $(o, { - fill: "url(#" + id + ")", - opacity: 1, - "fill-opacity": 1 - }); - s.fill = E; - s.opacity = 1; - s.fillOpacity = 1; - return 1; - }, - updatePosition = function (o) { - var bbox = o.getBBox(1); - $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"}); - }, - addArrow = function (o, value, isEnd) { - if (o.type == "path") { - var values = Str(value).toLowerCase().split("-"), - p = o.paper, - se = isEnd ? "end" : "start", - node = o.node, - attrs = o.attrs, - stroke = attrs["stroke-width"], - i = values.length, - type = "classic", - from, - to, - dx, - refX, - attr, - w = 3, - h = 3, - t = 5; - while (i--) { - switch (values[i]) { - case "block": - case "classic": - case "oval": - case "diamond": - case "open": - case "none": - type = values[i]; - break; - case "wide": h = 5; break; - case "narrow": h = 2; break; - case "long": w = 5; break; - case "short": w = 2; break; - } - } - if (type == "open") { - w += 2; - h += 2; - t += 2; - dx = 1; - refX = isEnd ? 4 : 1; - attr = { - fill: "none", - stroke: attrs.stroke - }; - } else { - refX = dx = w / 2; - attr = { - fill: attrs.stroke, - stroke: "none" - }; - } - if (o._.arrows) { - if (isEnd) { - o._.arrows.endPath && markerCounter[o._.arrows.endPath]--; - o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--; - } else { - o._.arrows.startPath && markerCounter[o._.arrows.startPath]--; - o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--; - } - } else { - o._.arrows = {}; - } - if (type != "none") { - var pathId = "raphael-marker-" + type, - markerId = "raphael-marker-" + se + type + w + h; - if (!R._g.doc.getElementById(pathId)) { - p.defs.appendChild($($("path"), { - "stroke-linecap": "round", - d: markers[type], - id: pathId - })); - markerCounter[pathId] = 1; - } else { - markerCounter[pathId]++; - } - var marker = R._g.doc.getElementById(markerId), - use; - if (!marker) { - marker = $($("marker"), { - id: markerId, - markerHeight: h, - markerWidth: w, - orient: "auto", - refX: refX, - refY: h / 2 - }); - use = $($("use"), { - "xlink:href": "#" + pathId, - transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")", - "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4) - }); - marker.appendChild(use); - p.defs.appendChild(marker); - markerCounter[markerId] = 1; - } else { - markerCounter[markerId]++; - use = marker.getElementsByTagName("use")[0]; - } - $(use, attr); - var delta = dx * (type != "diamond" && type != "oval"); - if (isEnd) { - from = o._.arrows.startdx * stroke || 0; - to = R.getTotalLength(attrs.path) - delta * stroke; - } else { - from = delta * stroke; - to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); - } - attr = {}; - attr["marker-" + se] = "url(#" + markerId + ")"; - if (to || from) { - attr.d = Raphael.getSubpath(attrs.path, from, to); - } - $(node, attr); - o._.arrows[se + "Path"] = pathId; - o._.arrows[se + "Marker"] = markerId; - o._.arrows[se + "dx"] = delta; - o._.arrows[se + "Type"] = type; - o._.arrows[se + "String"] = value; - } else { - if (isEnd) { - from = o._.arrows.startdx * stroke || 0; - to = R.getTotalLength(attrs.path) - from; - } else { - from = 0; - to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); - } - o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)}); - delete o._.arrows[se + "Path"]; - delete o._.arrows[se + "Marker"]; - delete o._.arrows[se + "dx"]; - delete o._.arrows[se + "Type"]; - delete o._.arrows[se + "String"]; - } - for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) { - var item = R._g.doc.getElementById(attr); - item && item.parentNode.removeChild(item); - } - } - }, - dasharray = { - "": [0], - "none": [0], - "-": [3, 1], - ".": [1, 1], - "-.": [3, 1, 1, 1], - "-..": [3, 1, 1, 1, 1, 1], - ". ": [1, 3], - "- ": [4, 3], - "--": [8, 3], - "- .": [4, 3, 1, 3], - "--.": [8, 3, 1, 3], - "--..": [8, 3, 1, 3, 1, 3] - }, - addDashes = function (o, value, params) { - value = dasharray[Str(value).toLowerCase()]; - if (value) { - var width = o.attrs["stroke-width"] || "1", - butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, - dashes = [], - i = value.length; - while (i--) { - dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt; - } - $(o.node, {"stroke-dasharray": dashes.join(",")}); - } - }, - setFillAndStroke = function (o, params) { - var node = o.node, - attrs = o.attrs, - vis = node.style.visibility; - node.style.visibility = "hidden"; - for (var att in params) { - if (params[has](att)) { - if (!R._availableAttrs[has](att)) { - continue; - } - var value = params[att]; - attrs[att] = value; - switch (att) { - case "blur": - o.blur(value); - break; - case "href": - case "title": - case "target": - var pn = node.parentNode; - if (pn.tagName.toLowerCase() != "a") { - var hl = $("a"); - pn.insertBefore(hl, node); - hl.appendChild(node); - pn = hl; - } - if (att == "target") { - pn.setAttributeNS(xlink, "show", value == "blank" ? "new" : value); - } else { - pn.setAttributeNS(xlink, att, value); - } - break; - case "cursor": - node.style.cursor = value; - break; - case "transform": - o.transform(value); - break; - case "arrow-start": - addArrow(o, value); - break; - case "arrow-end": - addArrow(o, value, 1); - break; - case "clip-rect": - var rect = Str(value).split(separator); - if (rect.length == 4) { - o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); - var el = $("clipPath"), - rc = $("rect"); - el.id = R.createUUID(); - $(rc, { - x: rect[0], - y: rect[1], - width: rect[2], - height: rect[3] - }); - el.appendChild(rc); - o.paper.defs.appendChild(el); - $(node, {"clip-path": "url(#" + el.id + ")"}); - o.clip = rc; - } - if (!value) { - var path = node.getAttribute("clip-path"); - if (path) { - var clip = R._g.doc.getElementById(path.replace(/(^url\(#|\)$)/g, E)); - clip && clip.parentNode.removeChild(clip); - $(node, {"clip-path": E}); - delete o.clip; - } - } - break; - case "path": - if (o.type == "path") { - $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"}); - o._.dirty = 1; - if (o._.arrows) { - "startString" in o._.arrows && addArrow(o, o._.arrows.startString); - "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); - } - } - break; - case "width": - node.setAttribute(att, value); - o._.dirty = 1; - if (attrs.fx) { - att = "x"; - value = attrs.x; - } else { - break; - } - case "x": - if (attrs.fx) { - value = -attrs.x - (attrs.width || 0); - } - case "rx": - if (att == "rx" && o.type == "rect") { - break; - } - case "cx": - node.setAttribute(att, value); - o.pattern && updatePosition(o); - o._.dirty = 1; - break; - case "height": - node.setAttribute(att, value); - o._.dirty = 1; - if (attrs.fy) { - att = "y"; - value = attrs.y; - } else { - break; - } - case "y": - if (attrs.fy) { - value = -attrs.y - (attrs.height || 0); - } - case "ry": - if (att == "ry" && o.type == "rect") { - break; - } - case "cy": - node.setAttribute(att, value); - o.pattern && updatePosition(o); - o._.dirty = 1; - break; - case "r": - if (o.type == "rect") { - $(node, {rx: value, ry: value}); - } else { - node.setAttribute(att, value); - } - o._.dirty = 1; - break; - case "src": - if (o.type == "image") { - node.setAttributeNS(xlink, "href", value); - } - break; - case "stroke-width": - if (o._.sx != 1 || o._.sy != 1) { - value /= mmax(abs(o._.sx), abs(o._.sy)) || 1; - } - if (o.paper._vbSize) { - value *= o.paper._vbSize; - } - node.setAttribute(att, value); - if (attrs["stroke-dasharray"]) { - addDashes(o, attrs["stroke-dasharray"], params); - } - if (o._.arrows) { - "startString" in o._.arrows && addArrow(o, o._.arrows.startString); - "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); - } - break; - case "stroke-dasharray": - addDashes(o, value, params); - break; - case "fill": - var isURL = Str(value).match(R._ISURL); - if (isURL) { - el = $("pattern"); - var ig = $("image"); - el.id = R.createUUID(); - $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); - $(ig, {x: 0, y: 0, "xlink:href": isURL[1]}); - el.appendChild(ig); - - (function (el) { - R._preload(isURL[1], function () { - var w = this.offsetWidth, - h = this.offsetHeight; - $(el, {width: w, height: h}); - $(ig, {width: w, height: h}); - o.paper.safari(); - }); - })(el); - o.paper.defs.appendChild(el); - $(node, {fill: "url(#" + el.id + ")"}); - o.pattern = el; - o.pattern && updatePosition(o); - break; - } - var clr = R.getRGB(value); - if (!clr.error) { - delete params.gradient; - delete attrs.gradient; - !R.is(attrs.opacity, "undefined") && - R.is(params.opacity, "undefined") && - $(node, {opacity: attrs.opacity}); - !R.is(attrs["fill-opacity"], "undefined") && - R.is(params["fill-opacity"], "undefined") && - $(node, {"fill-opacity": attrs["fill-opacity"]}); - } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) { - if ("opacity" in attrs || "fill-opacity" in attrs) { - var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); - if (gradient) { - var stops = gradient.getElementsByTagName("stop"); - $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)}); - } - } - attrs.gradient = value; - attrs.fill = "none"; - break; - } - clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); - case "stroke": - clr = R.getRGB(value); - node.setAttribute(att, clr.hex); - att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); - if (att == "stroke" && o._.arrows) { - "startString" in o._.arrows && addArrow(o, o._.arrows.startString); - "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); - } - break; - case "gradient": - (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value); - break; - case "opacity": - if (attrs.gradient && !attrs[has]("stroke-opacity")) { - $(node, {"stroke-opacity": value > 1 ? value / 100 : value}); - } - // fall - case "fill-opacity": - if (attrs.gradient) { - gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); - if (gradient) { - stops = gradient.getElementsByTagName("stop"); - $(stops[stops.length - 1], {"stop-opacity": value}); - } - break; - } - default: - att == "font-size" && (value = toInt(value, 10) + "px"); - var cssrule = att.replace(/(\-.)/g, function (w) { - return w.substring(1).toUpperCase(); - }); - node.style[cssrule] = value; - o._.dirty = 1; - node.setAttribute(att, value); - break; - } - } - } - - tuneText(o, params); - node.style.visibility = vis; - }, - leading = 1.2, - tuneText = function (el, params) { - if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { - return; - } - var a = el.attrs, - node = el.node, - fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10; - - if (params[has]("text")) { - a.text = params.text; - while (node.firstChild) { - node.removeChild(node.firstChild); - } - var texts = Str(params.text).split("\n"), - tspans = [], - tspan; - for (var i = 0, ii = texts.length; i < ii; i++) { - tspan = $("tspan"); - i && $(tspan, {dy: fontSize * leading, x: a.x}); - tspan.appendChild(R._g.doc.createTextNode(texts[i])); - node.appendChild(tspan); - tspans[i] = tspan; - } - } else { - tspans = node.getElementsByTagName("tspan"); - for (i = 0, ii = tspans.length; i < ii; i++) if (i) { - $(tspans[i], {dy: fontSize * leading, x: a.x}); - } else { - $(tspans[0], {dy: 0}); - } - } - $(node, {x: a.x, y: a.y}); - el._.dirty = 1; - var bb = el._getBBox(), - dif = a.y - (bb.y + bb.height / 2); - dif && R.is(dif, "finite") && $(tspans[0], {dy: dif}); - }, - Element = function (node, svg) { - var X = 0, - Y = 0; - - this[0] = this.node = node; - - node.raphael = true; - - this.id = R._oid++; - node.raphaelid = this.id; - this.matrix = R.matrix(); - this.realPath = null; - - this.paper = svg; - this.attrs = this.attrs || {}; - this._ = { - transform: [], - sx: 1, - sy: 1, - deg: 0, - dx: 0, - dy: 0, - dirty: 1 - }; - !svg.bottom && (svg.bottom = this); - - this.prev = svg.top; - svg.top && (svg.top.next = this); - svg.top = this; - - this.next = null; - }, - elproto = R.el; - - Element.prototype = elproto; - elproto.constructor = Element; - - R._engine.path = function (pathString, SVG) { - var el = $("path"); - SVG.canvas && SVG.canvas.appendChild(el); - var p = new Element(el, SVG); - p.type = "path"; - setFillAndStroke(p, { - fill: "none", - stroke: "#000", - path: pathString - }); - return p; - }; - - elproto.rotate = function (deg, cx, cy) { - if (this.removed) { - return this; - } - deg = Str(deg).split(separator); - if (deg.length - 1) { - cx = toFloat(deg[1]); - cy = toFloat(deg[2]); - } - deg = toFloat(deg[0]); - (cy == null) && (cx = cy); - if (cx == null || cy == null) { - var bbox = this.getBBox(1); - cx = bbox.x + bbox.width / 2; - cy = bbox.y + bbox.height / 2; - } - this.transform(this._.transform.concat([["r", deg, cx, cy]])); - return this; - }; - - elproto.scale = function (sx, sy, cx, cy) { - if (this.removed) { - return this; - } - sx = Str(sx).split(separator); - if (sx.length - 1) { - sy = toFloat(sx[1]); - cx = toFloat(sx[2]); - cy = toFloat(sx[3]); - } - sx = toFloat(sx[0]); - (sy == null) && (sy = sx); - (cy == null) && (cx = cy); - if (cx == null || cy == null) { - var bbox = this.getBBox(1); - } - cx = cx == null ? bbox.x + bbox.width / 2 : cx; - cy = cy == null ? bbox.y + bbox.height / 2 : cy; - this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); - return this; - }; - - elproto.translate = function (dx, dy) { - if (this.removed) { - return this; - } - dx = Str(dx).split(separator); - if (dx.length - 1) { - dy = toFloat(dx[1]); - } - dx = toFloat(dx[0]) || 0; - dy = +dy || 0; - this.transform(this._.transform.concat([["t", dx, dy]])); - return this; - }; - - elproto.transform = function (tstr) { - var _ = this._; - if (tstr == null) { - return _.transform; - } - R._extractTransform(this, tstr); - - this.clip && $(this.clip, {transform: this.matrix.invert()}); - this.pattern && updatePosition(this); - this.node && $(this.node, {transform: this.matrix}); - - if (_.sx != 1 || _.sy != 1) { - var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1; - this.attr({"stroke-width": sw}); - } - - return this; - }; - - elproto.hide = function () { - !this.removed && this.paper.safari(this.node.style.display = "none"); - return this; - }; - - elproto.show = function () { - !this.removed && this.paper.safari(this.node.style.display = ""); - return this; - }; - - elproto.remove = function () { - if (this.removed) { - return; - } - var paper = this.paper; - paper.__set__ && paper.__set__.exclude(this); - eve.unbind("*.*." + this.id); - if (this.gradient) { - paper.defs.removeChild(this.gradient); - } - R._tear(this, paper); - if (this.node.parentNode.tagName.toLowerCase() == "a") { - this.node.parentNode.parentNode.removeChild(this.node.parentNode); - } else { - this.node.parentNode.removeChild(this.node); - } - for (var i in this) { - this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; - } - this.removed = true; - }; - elproto._getBBox = function () { - if (this.node.style.display == "none") { - this.show(); - var hide = true; - } - var bbox = {}; - try { - bbox = this.node.getBBox(); - } catch(e) { - // Firefox 3.0.x plays badly here - } finally { - bbox = bbox || {}; - } - hide && this.hide(); - return bbox; - }; - - elproto.attr = function (name, value) { - if (this.removed) { - return this; - } - if (name == null) { - var res = {}; - for (var a in this.attrs) if (this.attrs[has](a)) { - res[a] = this.attrs[a]; - } - res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; - res.transform = this._.transform; - return res; - } - if (value == null && R.is(name, "string")) { - if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) { - return this.attrs.gradient; - } - if (name == "transform") { - return this._.transform; - } - var names = name.split(separator), - out = {}; - for (var i = 0, ii = names.length; i < ii; i++) { - name = names[i]; - if (name in this.attrs) { - out[name] = this.attrs[name]; - } else if (R.is(this.paper.customAttributes[name], "function")) { - out[name] = this.paper.customAttributes[name].def; - } else { - out[name] = R._availableAttrs[name]; - } - } - return ii - 1 ? out : out[names[0]]; - } - if (value == null && R.is(name, "array")) { - out = {}; - for (i = 0, ii = name.length; i < ii; i++) { - out[name[i]] = this.attr(name[i]); - } - return out; - } - if (value != null) { - var params = {}; - params[name] = value; - } else if (name != null && R.is(name, "object")) { - params = name; - } - for (var key in params) { - eve("attr." + key + "." + this.id, this, params[key]); - } - for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { - var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); - this.attrs[key] = params[key]; - for (var subkey in par) if (par[has](subkey)) { - params[subkey] = par[subkey]; - } - } - setFillAndStroke(this, params); - return this; - }; - - elproto.toFront = function () { - if (this.removed) { - return this; - } - if (this.node.parentNode.tagName.toLowerCase() == "a") { - this.node.parentNode.parentNode.appendChild(this.node.parentNode); - } else { - this.node.parentNode.appendChild(this.node); - } - var svg = this.paper; - svg.top != this && R._tofront(this, svg); - return this; - }; - - elproto.toBack = function () { - if (this.removed) { - return this; - } - var parent = this.node.parentNode; - if (parent.tagName.toLowerCase() == "a") { - parent.parentNode.insertBefore(this.node.parentNode, this.node.parentNode.parentNode.firstChild); - } else if (parent.firstChild != this.node) { - parent.insertBefore(this.node, this.node.parentNode.firstChild); - } - R._toback(this, this.paper); - var svg = this.paper; - return this; - }; - - elproto.insertAfter = function (element) { - if (this.removed) { - return this; - } - var node = element.node || element[element.length - 1].node; - if (node.nextSibling) { - node.parentNode.insertBefore(this.node, node.nextSibling); - } else { - node.parentNode.appendChild(this.node); - } - R._insertafter(this, element, this.paper); - return this; - }; - - elproto.insertBefore = function (element) { - if (this.removed) { - return this; - } - var node = element.node || element[0].node; - node.parentNode.insertBefore(this.node, node); - R._insertbefore(this, element, this.paper); - return this; - }; - elproto.blur = function (size) { - // Experimental. No Safari support. Use it on your own risk. - var t = this; - if (+size !== 0) { - var fltr = $("filter"), - blur = $("feGaussianBlur"); - t.attrs.blur = size; - fltr.id = R.createUUID(); - $(blur, {stdDeviation: +size || 1.5}); - fltr.appendChild(blur); - t.paper.defs.appendChild(fltr); - t._blur = fltr; - $(t.node, {filter: "url(#" + fltr.id + ")"}); - } else { - if (t._blur) { - t._blur.parentNode.removeChild(t._blur); - delete t._blur; - delete t.attrs.blur; - } - t.node.removeAttribute("filter"); - } - }; - R._engine.circle = function (svg, x, y, r) { - var el = $("circle"); - svg.canvas && svg.canvas.appendChild(el); - var res = new Element(el, svg); - res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"}; - res.type = "circle"; - $(el, res.attrs); - return res; - }; - R._engine.rect = function (svg, x, y, w, h, r) { - var el = $("rect"); - svg.canvas && svg.canvas.appendChild(el); - var res = new Element(el, svg); - res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"}; - res.type = "rect"; - $(el, res.attrs); - return res; - }; - R._engine.ellipse = function (svg, x, y, rx, ry) { - var el = $("ellipse"); - svg.canvas && svg.canvas.appendChild(el); - var res = new Element(el, svg); - res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"}; - res.type = "ellipse"; - $(el, res.attrs); - return res; - }; - R._engine.image = function (svg, src, x, y, w, h) { - var el = $("image"); - $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"}); - el.setAttributeNS(xlink, "href", src); - svg.canvas && svg.canvas.appendChild(el); - var res = new Element(el, svg); - res.attrs = {x: x, y: y, width: w, height: h, src: src}; - res.type = "image"; - return res; - }; - R._engine.text = function (svg, x, y, text) { - var el = $("text"); - svg.canvas && svg.canvas.appendChild(el); - var res = new Element(el, svg); - res.attrs = { - x: x, - y: y, - "text-anchor": "middle", - text: text, - font: R._availableAttrs.font, - stroke: "none", - fill: "#000" - }; - res.type = "text"; - setFillAndStroke(res, res.attrs); - return res; - }; - R._engine.setSize = function (width, height) { - this.width = width || this.width; - this.height = height || this.height; - this.canvas.setAttribute("width", this.width); - this.canvas.setAttribute("height", this.height); - if (this._viewBox) { - this.setViewBox.apply(this, this._viewBox); - } - return this; - }; - R._engine.create = function () { - var con = R._getContainer.apply(0, arguments), - container = con && con.container, - x = con.x, - y = con.y, - width = con.width, - height = con.height; - if (!container) { - throw new Error("SVG container not found."); - } - var cnvs = $("svg"), - css = "overflow:hidden;", - isFloating; - x = x || 0; - y = y || 0; - width = width || 512; - height = height || 342; - $(cnvs, { - height: height, - version: 1.1, - width: width, - xmlns: "http://www.w3.org/2000/svg" - }); - if (container == 1) { - cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; - R._g.doc.body.appendChild(cnvs); - isFloating = 1; - } else { - cnvs.style.cssText = css + "position:relative"; - if (container.firstChild) { - container.insertBefore(cnvs, container.firstChild); - } else { - container.appendChild(cnvs); - } - } - container = new R._Paper; - container.width = width; - container.height = height; - container.canvas = cnvs; - container.clear(); - container._left = container._top = 0; - isFloating && (container.renderfix = function () {}); - container.renderfix(); - return container; - }; - R._engine.setViewBox = function (x, y, w, h, fit) { - eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); - var size = mmax(w / this.width, h / this.height), - top = this.top, - aspectRatio = fit ? "meet" : "xMinYMin", - vb, - sw; - if (x == null) { - if (this._vbSize) { - size = 1; - } - delete this._vbSize; - vb = "0 0 " + this.width + S + this.height; - } else { - this._vbSize = size; - vb = x + S + y + S + w + S + h; - } - $(this.canvas, { - viewBox: vb, - preserveAspectRatio: aspectRatio - }); - while (size && top) { - sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; - top.attr({"stroke-width": sw}); - top._.dirty = 1; - top._.dirtyT = 1; - top = top.prev; - } - this._viewBox = [x, y, w, h, !!fit]; - return this; - }; - - R.prototype.renderfix = function () { - var cnvs = this.canvas, - s = cnvs.style, - pos; - try { - pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix(); - } catch (e) { - pos = cnvs.createSVGMatrix(); - } - var left = -pos.e % 1, - top = -pos.f % 1; - if (left || top) { - if (left) { - this._left = (this._left + left) % 1; - s.left = this._left + "px"; - } - if (top) { - this._top = (this._top + top) % 1; - s.top = this._top + "px"; - } - } - }; - - R.prototype.clear = function () { - R.eve("clear", this); - var c = this.canvas; - while (c.firstChild) { - c.removeChild(c.firstChild); - } - this.bottom = this.top = null; - (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version)); - c.appendChild(this.desc); - c.appendChild(this.defs = $("defs")); - }; - - R.prototype.remove = function () { - eve("remove", this); - this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); - for (var i in this) { - this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; - } - }; - var setproto = R.st; - for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { - setproto[method] = (function (methodname) { - return function () { - var arg = arguments; - return this.forEach(function (el) { - el[methodname].apply(el, arg); - }); - }; - })(method); - } -}(window.Raphael); - -// ┌─────────────────────────────────────────────────────────────────────┐ \\ -// │ Raphaël - JavaScript Vector Library │ \\ -// ├─────────────────────────────────────────────────────────────────────┤ \\ -// │ VML Module │ \\ -// ├─────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ -// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ -// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ -// └─────────────────────────────────────────────────────────────────────┘ \\ -window.Raphael.vml && function (R) { - var has = "hasOwnProperty", - Str = String, - toFloat = parseFloat, - math = Math, - round = math.round, - mmax = math.max, - mmin = math.min, - abs = math.abs, - fillString = "fill", - separator = /[, ]+/, - eve = R.eve, - ms = " progid:DXImageTransform.Microsoft", - S = " ", - E = "", - map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, - bites = /([clmz]),?([^clmz]*)/gi, - blurregexp = / progid:\S+Blur\([^\)]+\)/g, - val = /-?[^,\s-]+/g, - cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", - zoom = 21600, - pathTypes = {path: 1, rect: 1, image: 1}, - ovalTypes = {circle: 1, ellipse: 1}, - path2vml = function (path) { - var total = /[ahqstv]/ig, - command = R._pathToAbsolute; - Str(path).match(total) && (command = R._path2curve); - total = /[clmz]/g; - if (command == R._pathToAbsolute && !Str(path).match(total)) { - var res = Str(path).replace(bites, function (all, command, args) { - var vals = [], - isMove = command.toLowerCase() == "m", - res = map[command]; - args.replace(val, function (value) { - if (isMove && vals.length == 2) { - res += vals + map[command == "m" ? "l" : "L"]; - vals = []; - } - vals.push(round(value * zoom)); - }); - return res + vals; - }); - return res; - } - var pa = command(path), p, r; - res = []; - for (var i = 0, ii = pa.length; i < ii; i++) { - p = pa[i]; - r = pa[i][0].toLowerCase(); - r == "z" && (r = "x"); - for (var j = 1, jj = p.length; j < jj; j++) { - r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); - } - res.push(r); - } - return res.join(S); - }, - compensation = function (deg, dx, dy) { - var m = R.matrix(); - m.rotate(-deg, .5, .5); - return { - dx: m.x(dx, dy), - dy: m.y(dx, dy) - }; - }, - setCoords = function (p, sx, sy, dx, dy, deg) { - var _ = p._, - m = p.matrix, - fillpos = _.fillpos, - o = p.node, - s = o.style, - y = 1, - flip = "", - dxdy, - kx = zoom / sx, - ky = zoom / sy; - s.visibility = "hidden"; - if (!sx || !sy) { - return; - } - o.coordsize = abs(kx) + S + abs(ky); - s.rotation = deg * (sx * sy < 0 ? -1 : 1); - if (deg) { - var c = compensation(deg, dx, dy); - dx = c.dx; - dy = c.dy; - } - sx < 0 && (flip += "x"); - sy < 0 && (flip += " y") && (y = -1); - s.flip = flip; - o.coordorigin = (dx * -kx) + S + (dy * -ky); - if (fillpos || _.fillsize) { - var fill = o.getElementsByTagName(fillString); - fill = fill && fill[0]; - o.removeChild(fill); - if (fillpos) { - c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); - fill.position = c.dx * y + S + c.dy * y; - } - if (_.fillsize) { - fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); - } - o.appendChild(fill); - } - s.visibility = "visible"; - }; - R.toString = function () { - return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; - }; - var addArrow = function (o, value, isEnd) { - var values = Str(value).toLowerCase().split("-"), - se = isEnd ? "end" : "start", - i = values.length, - type = "classic", - w = "medium", - h = "medium"; - while (i--) { - switch (values[i]) { - case "block": - case "classic": - case "oval": - case "diamond": - case "open": - case "none": - type = values[i]; - break; - case "wide": - case "narrow": h = values[i]; break; - case "long": - case "short": w = values[i]; break; - } - } - var stroke = o.node.getElementsByTagName("stroke")[0]; - stroke[se + "arrow"] = type; - stroke[se + "arrowlength"] = w; - stroke[se + "arrowwidth"] = h; - }, - setFillAndStroke = function (o, params) { - // o.paper.canvas.style.display = "none"; - o.attrs = o.attrs || {}; - var node = o.node, - a = o.attrs, - s = node.style, - xy, - newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r), - isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), - res = o; - - - for (var par in params) if (params[has](par)) { - a[par] = params[par]; - } - if (newpath) { - a.path = R._getPath[o.type](o); - o._.dirty = 1; - } - params.href && (node.href = params.href); - params.title && (node.title = params.title); - params.target && (node.target = params.target); - params.cursor && (s.cursor = params.cursor); - "blur" in params && o.blur(params.blur); - if (params.path && o.type == "path" || newpath) { - node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path); - if (o.type == "image") { - o._.fillpos = [a.x, a.y]; - o._.fillsize = [a.width, a.height]; - setCoords(o, 1, 1, 0, 0, 0); - } - } - "transform" in params && o.transform(params.transform); - if (isOval) { - var cx = +a.cx, - cy = +a.cy, - rx = +a.rx || +a.r || 0, - ry = +a.ry || +a.r || 0; - node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom)); - } - if ("clip-rect" in params) { - var rect = Str(params["clip-rect"]).split(separator); - if (rect.length == 4) { - rect[2] = +rect[2] + (+rect[0]); - rect[3] = +rect[3] + (+rect[1]); - var div = node.clipRect || R._g.doc.createElement("div"), - dstyle = div.style; - dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); - if (!node.clipRect) { - dstyle.position = "absolute"; - dstyle.top = 0; - dstyle.left = 0; - dstyle.width = o.paper.width + "px"; - dstyle.height = o.paper.height + "px"; - node.parentNode.insertBefore(div, node); - div.appendChild(node); - node.clipRect = div; - } - } - if (!params["clip-rect"]) { - node.clipRect && (node.clipRect.style.clip = "auto"); - } - } - if (o.textpath) { - var textpathStyle = o.textpath.style; - params.font && (textpathStyle.font = params.font); - params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); - params["font-size"] && (textpathStyle.fontSize = params["font-size"]); - params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); - params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); - } - if ("arrow-start" in params) { - addArrow(res, params["arrow-start"]); - } - if ("arrow-end" in params) { - addArrow(res, params["arrow-end"], 1); - } - if (params.opacity != null || - params["stroke-width"] != null || - params.fill != null || - params.src != null || - params.stroke != null || - params["stroke-width"] != null || - params["stroke-opacity"] != null || - params["fill-opacity"] != null || - params["stroke-dasharray"] != null || - params["stroke-miterlimit"] != null || - params["stroke-linejoin"] != null || - params["stroke-linecap"] != null) { - var fill = node.getElementsByTagName(fillString), - newfill = false; - fill = fill && fill[0]; - !fill && (newfill = fill = createNode(fillString)); - if (o.type == "image" && params.src) { - fill.src = params.src; - } - params.fill && (fill.on = true); - if (fill.on == null || params.fill == "none" || params.fill === null) { - fill.on = false; - } - if (fill.on && params.fill) { - var isURL = Str(params.fill).match(R._ISURL); - if (isURL) { - fill.parentNode == node && node.removeChild(fill); - fill.rotate = true; - fill.src = isURL[1]; - fill.type = "tile"; - var bbox = o.getBBox(1); - fill.position = bbox.x + S + bbox.y; - o._.fillpos = [bbox.x, bbox.y]; - - R._preload(isURL[1], function () { - o._.fillsize = [this.offsetWidth, this.offsetHeight]; - }); - } else { - fill.color = R.getRGB(params.fill).hex; - fill.src = E; - fill.type = "solid"; - if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { - a.fill = "none"; - a.gradient = params.fill; - fill.rotate = false; - } - } - } - if ("fill-opacity" in params || "opacity" in params) { - var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); - opacity = mmin(mmax(opacity, 0), 1); - fill.opacity = opacity; - if (fill.src) { - fill.color = "none"; - } - } - node.appendChild(fill); - var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), - newstroke = false; - !stroke && (newstroke = stroke = createNode("stroke")); - if ((params.stroke && params.stroke != "none") || - params["stroke-width"] || - params["stroke-opacity"] != null || - params["stroke-dasharray"] || - params["stroke-miterlimit"] || - params["stroke-linejoin"] || - params["stroke-linecap"]) { - stroke.on = true; - } - (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); - var strokeColor = R.getRGB(params.stroke); - stroke.on && params.stroke && (stroke.color = strokeColor.hex); - opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); - var width = (toFloat(params["stroke-width"]) || 1) * .75; - opacity = mmin(mmax(opacity, 0), 1); - params["stroke-width"] == null && (width = a["stroke-width"]); - params["stroke-width"] && (stroke.weight = width); - width && width < 1 && (opacity *= width) && (stroke.weight = 1); - stroke.opacity = opacity; - - params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); - stroke.miterlimit = params["stroke-miterlimit"] || 8; - params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); - if (params["stroke-dasharray"]) { - var dasharray = { - "-": "shortdash", - ".": "shortdot", - "-.": "shortdashdot", - "-..": "shortdashdotdot", - ". ": "dot", - "- ": "dash", - "--": "longdash", - "- .": "dashdot", - "--.": "longdashdot", - "--..": "longdashdotdot" - }; - stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; - } - newstroke && node.appendChild(stroke); - } - if (res.type == "text") { - res.paper.canvas.style.display = E; - var span = res.paper.span, - m = 100, - fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); - s = span.style; - a.font && (s.font = a.font); - a["font-family"] && (s.fontFamily = a["font-family"]); - a["font-weight"] && (s.fontWeight = a["font-weight"]); - a["font-style"] && (s.fontStyle = a["font-style"]); - fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10; - s.fontSize = fontSize * m + "px"; - res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "<").replace(/&/g, "&").replace(/\n/g, "<br>")); - var brect = span.getBoundingClientRect(); - res.W = a.w = (brect.right - brect.left) / m; - res.H = a.h = (brect.bottom - brect.top) / m; - // res.paper.canvas.style.display = "none"; - res.X = a.x; - res.Y = a.y + res.H / 2; - - ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1)); - var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; - for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { - res._.dirty = 1; - break; - } - - // text-anchor emulation - switch (a["text-anchor"]) { - case "start": - res.textpath.style["v-text-align"] = "left"; - res.bbx = res.W / 2; - break; - case "end": - res.textpath.style["v-text-align"] = "right"; - res.bbx = -res.W / 2; - break; - default: - res.textpath.style["v-text-align"] = "center"; - res.bbx = 0; - break; - } - res.textpath.style["v-text-kern"] = true; - } - // res.paper.canvas.style.display = E; - }, - addGradientFill = function (o, gradient, fill) { - o.attrs = o.attrs || {}; - var attrs = o.attrs, - pow = Math.pow, - opacity, - oindex, - type = "linear", - fxfy = ".5 .5"; - o.attrs.gradient = gradient; - gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) { - type = "radial"; - if (fx && fy) { - fx = toFloat(fx); - fy = toFloat(fy); - pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); - fxfy = fx + S + fy; - } - return E; - }); - gradient = gradient.split(/\s*\-\s*/); - if (type == "linear") { - var angle = gradient.shift(); - angle = -toFloat(angle); - if (isNaN(angle)) { - return null; - } - } - var dots = R._parseDots(gradient); - if (!dots) { - return null; - } - o = o.shape || o.node; - if (dots.length) { - o.removeChild(fill); - fill.on = true; - fill.method = "none"; - fill.color = dots[0].color; - fill.color2 = dots[dots.length - 1].color; - var clrs = []; - for (var i = 0, ii = dots.length; i < ii; i++) { - dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); - } - fill.colors = clrs.length ? clrs.join() : "0% " + fill.color; - if (type == "radial") { - fill.type = "gradientTitle"; - fill.focus = "100%"; - fill.focussize = "0 0"; - fill.focusposition = fxfy; - fill.angle = 0; - } else { - // fill.rotate= true; - fill.type = "gradient"; - fill.angle = (270 - angle) % 360; - } - o.appendChild(fill); - } - return 1; - }, - Element = function (node, vml) { - this[0] = this.node = node; - node.raphael = true; - this.id = R._oid++; - node.raphaelid = this.id; - this.X = 0; - this.Y = 0; - this.attrs = {}; - this.paper = vml; - this.matrix = R.matrix(); - this._ = { - transform: [], - sx: 1, - sy: 1, - dx: 0, - dy: 0, - deg: 0, - dirty: 1, - dirtyT: 1 - }; - !vml.bottom && (vml.bottom = this); - this.prev = vml.top; - vml.top && (vml.top.next = this); - vml.top = this; - this.next = null; - }; - var elproto = R.el; - - Element.prototype = elproto; - elproto.constructor = Element; - elproto.transform = function (tstr) { - if (tstr == null) { - return this._.transform; - } - var vbs = this.paper._viewBoxShift, - vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E, - oldt; - if (vbs) { - oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E); - } - R._extractTransform(this, vbt + tstr); - var matrix = this.matrix.clone(), - skew = this.skew, - o = this.node, - split, - isGrad = ~Str(this.attrs.fill).indexOf("-"), - isPatt = !Str(this.attrs.fill).indexOf("url("); - matrix.translate(-.5, -.5); - if (isPatt || isGrad || this.type == "image") { - skew.matrix = "1 0 0 1"; - skew.offset = "0 0"; - split = matrix.split(); - if ((isGrad && split.noRotation) || !split.isSimple) { - o.style.filter = matrix.toFilter(); - var bb = this.getBBox(), - bbt = this.getBBox(1), - dx = bb.x - bbt.x, - dy = bb.y - bbt.y; - o.coordorigin = (dx * -zoom) + S + (dy * -zoom); - setCoords(this, 1, 1, dx, dy, 0); - } else { - o.style.filter = E; - setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate); - } - } else { - o.style.filter = E; - skew.matrix = Str(matrix); - skew.offset = matrix.offset(); - } - oldt && (this._.transform = oldt); - return this; - }; - elproto.rotate = function (deg, cx, cy) { - if (this.removed) { - return this; - } - if (deg == null) { - return; - } - deg = Str(deg).split(separator); - if (deg.length - 1) { - cx = toFloat(deg[1]); - cy = toFloat(deg[2]); - } - deg = toFloat(deg[0]); - (cy == null) && (cx = cy); - if (cx == null || cy == null) { - var bbox = this.getBBox(1); - cx = bbox.x + bbox.width / 2; - cy = bbox.y + bbox.height / 2; - } - this._.dirtyT = 1; - this.transform(this._.transform.concat([["r", deg, cx, cy]])); - return this; - }; - elproto.translate = function (dx, dy) { - if (this.removed) { - return this; - } - dx = Str(dx).split(separator); - if (dx.length - 1) { - dy = toFloat(dx[1]); - } - dx = toFloat(dx[0]) || 0; - dy = +dy || 0; - if (this._.bbox) { - this._.bbox.x += dx; - this._.bbox.y += dy; - } - this.transform(this._.transform.concat([["t", dx, dy]])); - return this; - }; - elproto.scale = function (sx, sy, cx, cy) { - if (this.removed) { - return this; - } - sx = Str(sx).split(separator); - if (sx.length - 1) { - sy = toFloat(sx[1]); - cx = toFloat(sx[2]); - cy = toFloat(sx[3]); - isNaN(cx) && (cx = null); - isNaN(cy) && (cy = null); - } - sx = toFloat(sx[0]); - (sy == null) && (sy = sx); - (cy == null) && (cx = cy); - if (cx == null || cy == null) { - var bbox = this.getBBox(1); - } - cx = cx == null ? bbox.x + bbox.width / 2 : cx; - cy = cy == null ? bbox.y + bbox.height / 2 : cy; - - this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); - this._.dirtyT = 1; - return this; - }; - elproto.hide = function () { - !this.removed && (this.node.style.display = "none"); - return this; - }; - elproto.show = function () { - !this.removed && (this.node.style.display = E); - return this; - }; - elproto._getBBox = function () { - if (this.removed) { - return {}; - } - return { - x: this.X + (this.bbx || 0) - this.W / 2, - y: this.Y - this.H, - width: this.W, - height: this.H - }; - }; - elproto.remove = function () { - if (this.removed) { - return; - } - this.paper.__set__ && this.paper.__set__.exclude(this); - R.eve.unbind("*.*." + this.id); - R._tear(this, this.paper); - this.node.parentNode.removeChild(this.node); - this.shape && this.shape.parentNode.removeChild(this.shape); - for (var i in this) { - this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; - } - this.removed = true; - }; - elproto.attr = function (name, value) { - if (this.removed) { - return this; - } - if (name == null) { - var res = {}; - for (var a in this.attrs) if (this.attrs[has](a)) { - res[a] = this.attrs[a]; - } - res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; - res.transform = this._.transform; - return res; - } - if (value == null && R.is(name, "string")) { - if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { - return this.attrs.gradient; - } - var names = name.split(separator), - out = {}; - for (var i = 0, ii = names.length; i < ii; i++) { - name = names[i]; - if (name in this.attrs) { - out[name] = this.attrs[name]; - } else if (R.is(this.paper.customAttributes[name], "function")) { - out[name] = this.paper.customAttributes[name].def; - } else { - out[name] = R._availableAttrs[name]; - } - } - return ii - 1 ? out : out[names[0]]; - } - if (this.attrs && value == null && R.is(name, "array")) { - out = {}; - for (i = 0, ii = name.length; i < ii; i++) { - out[name[i]] = this.attr(name[i]); - } - return out; - } - var params; - if (value != null) { - params = {}; - params[name] = value; - } - value == null && R.is(name, "object") && (params = name); - for (var key in params) { - eve("attr." + key + "." + this.id, this, params[key]); - } - if (params) { - for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { - var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); - this.attrs[key] = params[key]; - for (var subkey in par) if (par[has](subkey)) { - params[subkey] = par[subkey]; - } - } - // this.paper.canvas.style.display = "none"; - if (params.text && this.type == "text") { - this.textpath.string = params.text; - } - setFillAndStroke(this, params); - // this.paper.canvas.style.display = E; - } - return this; - }; - elproto.toFront = function () { - !this.removed && this.node.parentNode.appendChild(this.node); - this.paper && this.paper.top != this && R._tofront(this, this.paper); - return this; - }; - elproto.toBack = function () { - if (this.removed) { - return this; - } - if (this.node.parentNode.firstChild != this.node) { - this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); - R._toback(this, this.paper); - } - return this; - }; - elproto.insertAfter = function (element) { - if (this.removed) { - return this; - } - if (element.constructor == R.st.constructor) { - element = element[element.length - 1]; - } - if (element.node.nextSibling) { - element.node.parentNode.insertBefore(this.node, element.node.nextSibling); - } else { - element.node.parentNode.appendChild(this.node); - } - R._insertafter(this, element, this.paper); - return this; - }; - elproto.insertBefore = function (element) { - if (this.removed) { - return this; - } - if (element.constructor == R.st.constructor) { - element = element[0]; - } - element.node.parentNode.insertBefore(this.node, element.node); - R._insertbefore(this, element, this.paper); - return this; - }; - elproto.blur = function (size) { - var s = this.node.runtimeStyle, - f = s.filter; - f = f.replace(blurregexp, E); - if (+size !== 0) { - this.attrs.blur = size; - s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; - s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); - } else { - s.filter = f; - s.margin = 0; - delete this.attrs.blur; - } - }; - - R._engine.path = function (pathString, vml) { - var el = createNode("shape"); - el.style.cssText = cssDot; - el.coordsize = zoom + S + zoom; - el.coordorigin = vml.coordorigin; - var p = new Element(el, vml), - attr = {fill: "none", stroke: "#000"}; - pathString && (attr.path = pathString); - p.type = "path"; - p.path = []; - p.Path = E; - setFillAndStroke(p, attr); - vml.canvas.appendChild(el); - var skew = createNode("skew"); - skew.on = true; - el.appendChild(skew); - p.skew = skew; - p.transform(E); - return p; - }; - R._engine.rect = function (vml, x, y, w, h, r) { - var path = R._rectPath(x, y, w, h, r), - res = vml.path(path), - a = res.attrs; - res.X = a.x = x; - res.Y = a.y = y; - res.W = a.width = w; - res.H = a.height = h; - a.r = r; - a.path = path; - res.type = "rect"; - return res; - }; - R._engine.ellipse = function (vml, x, y, rx, ry) { - var res = vml.path(), - a = res.attrs; - res.X = x - rx; - res.Y = y - ry; - res.W = rx * 2; - res.H = ry * 2; - res.type = "ellipse"; - setFillAndStroke(res, { - cx: x, - cy: y, - rx: rx, - ry: ry - }); - return res; - }; - R._engine.circle = function (vml, x, y, r) { - var res = vml.path(), - a = res.attrs; - res.X = x - r; - res.Y = y - r; - res.W = res.H = r * 2; - res.type = "circle"; - setFillAndStroke(res, { - cx: x, - cy: y, - r: r - }); - return res; - }; - R._engine.image = function (vml, src, x, y, w, h) { - var path = R._rectPath(x, y, w, h), - res = vml.path(path).attr({stroke: "none"}), - a = res.attrs, - node = res.node, - fill = node.getElementsByTagName(fillString)[0]; - a.src = src; - res.X = a.x = x; - res.Y = a.y = y; - res.W = a.width = w; - res.H = a.height = h; - a.path = path; - res.type = "image"; - fill.parentNode == node && node.removeChild(fill); - fill.rotate = true; - fill.src = src; - fill.type = "tile"; - res._.fillpos = [x, y]; - res._.fillsize = [w, h]; - node.appendChild(fill); - setCoords(res, 1, 1, 0, 0, 0); - return res; - }; - R._engine.text = function (vml, x, y, text) { - var el = createNode("shape"), - path = createNode("path"), - o = createNode("textpath"); - x = x || 0; - y = y || 0; - text = text || ""; - path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); - path.textpathok = true; - o.string = Str(text); - o.on = true; - el.style.cssText = cssDot; - el.coordsize = zoom + S + zoom; - el.coordorigin = "0 0"; - var p = new Element(el, vml), - attr = { - fill: "#000", - stroke: "none", - font: R._availableAttrs.font, - text: text - }; - p.shape = el; - p.path = path; - p.textpath = o; - p.type = "text"; - p.attrs.text = Str(text); - p.attrs.x = x; - p.attrs.y = y; - p.attrs.w = 1; - p.attrs.h = 1; - setFillAndStroke(p, attr); - el.appendChild(o); - el.appendChild(path); - vml.canvas.appendChild(el); - var skew = createNode("skew"); - skew.on = true; - el.appendChild(skew); - p.skew = skew; - p.transform(E); - return p; - }; - R._engine.setSize = function (width, height) { - var cs = this.canvas.style; - this.width = width; - this.height = height; - width == +width && (width += "px"); - height == +height && (height += "px"); - cs.width = width; - cs.height = height; - cs.clip = "rect(0 " + width + " " + height + " 0)"; - if (this._viewBox) { - R._engine.setViewBox.apply(this, this._viewBox); - } - return this; - }; - R._engine.setViewBox = function (x, y, w, h, fit) { - R.eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); - var width = this.width, - height = this.height, - size = 1 / mmax(w / width, h / height), - H, W; - if (fit) { - H = height / h; - W = width / w; - if (w * H < width) { - x -= (width - w * H) / 2 / H; - } - if (h * W < height) { - y -= (height - h * W) / 2 / W; - } - } - this._viewBox = [x, y, w, h, !!fit]; - this._viewBoxShift = { - dx: -x, - dy: -y, - scale: size - }; - this.forEach(function (el) { - el.transform("..."); - }); - return this; - }; - var createNode; - R._engine.initWin = function (win) { - var doc = win.document; - doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); - try { - !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); - createNode = function (tagName) { - return doc.createElement('<rvml:' + tagName + ' class="rvml">'); - }; - } catch (e) { - createNode = function (tagName) { - return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); - }; - } - }; - R._engine.initWin(R._g.win); - R._engine.create = function () { - var con = R._getContainer.apply(0, arguments), - container = con.container, - height = con.height, - s, - width = con.width, - x = con.x, - y = con.y; - if (!container) { - throw new Error("VML container not found."); - } - var res = new R._Paper, - c = res.canvas = R._g.doc.createElement("div"), - cs = c.style; - x = x || 0; - y = y || 0; - width = width || 512; - height = height || 342; - res.width = width; - res.height = height; - width == +width && (width += "px"); - height == +height && (height += "px"); - res.coordsize = zoom * 1e3 + S + zoom * 1e3; - res.coordorigin = "0 0"; - res.span = R._g.doc.createElement("span"); - res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; - c.appendChild(res.span); - cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height); - if (container == 1) { - R._g.doc.body.appendChild(c); - cs.left = x + "px"; - cs.top = y + "px"; - cs.position = "absolute"; - } else { - if (container.firstChild) { - container.insertBefore(c, container.firstChild); - } else { - container.appendChild(c); - } - } - // plugins.call(res, res, R.fn); - res.renderfix = function () {}; - return res; - }; - R.prototype.clear = function () { - R.eve("clear", this); - this.canvas.innerHTML = E; - this.span = R._g.doc.createElement("span"); - this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; - this.canvas.appendChild(this.span); - this.bottom = this.top = null; - }; - R.prototype.remove = function () { - R.eve("remove", this); - this.canvas.parentNode.removeChild(this.canvas); - for (var i in this) { - this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null; - } - return true; - }; - - var setproto = R.st; - for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { - setproto[method] = (function (methodname) { - return function () { - var arg = arguments; - return this.forEach(function (el) { - el[methodname].apply(el, arg); - }); - }; - })(method); - } -}(window.Raphael);
\ No newline at end of file diff --git a/themes/default/js/switchbox.js b/themes/default/js/switchbox.js new file mode 100644 index 000000000..b20f82d50 --- /dev/null +++ b/themes/default/js/switchbox.js @@ -0,0 +1,23 @@ +(function () { + var sbFunc = function(link, box) { + jQuery(link).click(function() { + var elt = jQuery(box); + elt.css("left", Math.min( jQuery(this).position().left, jQuery(window).width() - elt.outerWidth(true) - 5)) + .css("top", jQuery(this).position().top + jQuery(this).outerHeight(true)) + .toggle(); + return false; + }); + jQuery(box).on("mouseleave click", function() { + jQuery(this).hide(); + }); + }; + + if (window.SwitchBox) { + for (var i=0; i<SwitchBox.length; i+=2) + sbFunc(SwitchBox[i], SwitchBox[i+1]); + } + + SwitchBox = { + push: sbFunc + } +})();
\ No newline at end of file diff --git a/themes/default/s26/outline_005e89.png b/themes/default/s26/outline_005e89.png Binary files differindex ee114abe9..a745c0bc5 100644 --- a/themes/default/s26/outline_005e89.png +++ b/themes/default/s26/outline_005e89.png diff --git a/themes/default/s26/outline_808060.png b/themes/default/s26/outline_808060.png Binary files differindex 351cf4149..1457946f0 100644 --- a/themes/default/s26/outline_808060.png +++ b/themes/default/s26/outline_808060.png diff --git a/themes/default/s26/outline_808080.png b/themes/default/s26/outline_808080.png Binary files differindex c7a89c270..7745175ca 100644 --- a/themes/default/s26/outline_808080.png +++ b/themes/default/s26/outline_808080.png diff --git a/themes/default/s26/outline_ff3363.png b/themes/default/s26/outline_ff3363.png Binary files differindex bb2224f39..4e726eb26 100644 --- a/themes/default/s26/outline_ff3363.png +++ b/themes/default/s26/outline_ff3363.png diff --git a/themes/default/s26/outline_ff7700.png b/themes/default/s26/outline_ff7700.png Binary files differindex 6cbec3fdf..7b63f3a0f 100644 --- a/themes/default/s26/outline_ff7700.png +++ b/themes/default/s26/outline_ff7700.png diff --git a/themes/default/s26/outline_ffff80.png b/themes/default/s26/outline_ffff80.png Binary files differindex 66734159b..17f264db3 100644 --- a/themes/default/s26/outline_ffff80.png +++ b/themes/default/s26/outline_ffff80.png diff --git a/themes/default/s26/outline_ffffff.png b/themes/default/s26/outline_ffffff.png Binary files differindex 86ff920d5..d8490441d 100644 --- a/themes/default/s26/outline_ffffff.png +++ b/themes/default/s26/outline_ffffff.png diff --git a/themes/default/template/comment_list.tpl b/themes/default/template/comment_list.tpl index 433de1ff2..5fe4e2f47 100644 --- a/themes/default/template/comment_list.tpl +++ b/themes/default/template/comment_list.tpl @@ -1,16 +1,16 @@ {if isset($comment_derivative_params)} {strip}{html_style} -.commentElement .illustration{ldelim} - width: {$comment_derivative_params->max_width()+5}px +.commentElement .illustration{ + width:{$comment_derivative_params->max_width()+5}px } -.content .commentElement .description{ldelim} - min-height: {$comment_derivative_params->max_height()+5}px +.content .commentElement .description{ + min-height:{$comment_derivative_params->max_height()+5}px } {/html_style}{/strip} -{/if} {footer_script}var error_icon = "{$ROOT_URL}{$themeconf.icon_dir}/errors_small.png";{/footer_script} <div class="loader"><img src="{$ROOT_URL}{$themeconf.img_dir}/ajax_loader.gif"></div> +{/if} <ul class="commentsList"> {foreach from=$comments item=comment name=comment_loop} <li class="commentElement {if $smarty.foreach.comment_loop.index is odd}odd{else}even{/if}"> @@ -57,7 +57,7 @@ {/if} <span class="commentAuthor">{if $comment.WEBSITE_URL}<a href="{$comment.WEBSITE_URL}" class="external" target="_blank" rel="nofollow">{$comment.AUTHOR}</a>{else}{$comment.AUTHOR}{/if}</span> - {if $comment.EMAIL}- <a href="mailto:{$comment.EMAIL}">{$comment.EMAIL}</a>{/if} + {if isset($comment.EMAIL)}- <a href="mailto:{$comment.EMAIL}">{$comment.EMAIL}</a>{/if} - <span class="commentDate">{$comment.DATE}</span> {if isset($comment.IN_EDIT)} <a name="edit_comment"></a> diff --git a/themes/default/template/index.tpl b/themes/default/template/index.tpl index 3ed52498c..00dccca5e 100644 --- a/themes/default/template/index.tpl +++ b/themes/default/template/index.tpl @@ -1,5 +1,7 @@ +{combine_script id='core.switchbox' load='async' require='jquery' path='themes/default/js/switchbox.js'} {$MENUBAR} + {if isset($errors) or isset($infos)} <div class="content messages{if isset($MENUBAR)} contentWithMenu{/if}"> {include file='infos_errors.tpl'} @@ -12,7 +14,7 @@ <ul class="categoryActions"> {if !empty($image_orders)} <li>{strip}<a id="sortOrderLink" title="{'Sort order'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-sort"> </span><span class="pwg-button-text">{'Sort order'|@translate}</span> + <span class="pwg-icon pwg-icon-sort"></span><span class="pwg-button-text">{'Sort order'|@translate}</span> </a> <div id="sortOrderBox" class="switchBox"> <div class="switchBoxTitle">{'Sort order'|@translate}</div> @@ -24,22 +26,12 @@ {/if} {/foreach} </div> - {footer_script require='jquery'}{literal} -jQuery("#sortOrderLink").click(function() { - var elt = jQuery("#sortOrderBox"); - elt.css("left", Math.min( jQuery(this).offset().left, jQuery(window).width() - elt.outerWidth(true) - 5)) - .css("top", jQuery(this).offset().top + jQuery(this).outerHeight(true)) - .toggle(); -}); -jQuery("#sortOrderBox").on("mouseleave", function() { - jQuery(this).hide(); -}); - {/literal}{/footer_script} + {footer_script}(SwitchBox=window.SwitchBox||[]).push("#sortOrderLink", "#sortOrderBox");{/footer_script} {/strip}</li> {/if} {if !empty($image_derivatives)} <li>{strip}<a id="derivativeSwitchLink" title="{'Photo sizes'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-sizes"> </span><span class="pwg-button-text">{'Photo sizes'|@translate}</span> + <span class="pwg-icon pwg-icon-sizes"></span><span class="pwg-button-text">{'Photo sizes'|@translate}</span> </a> <div id="derivativeSwitchBox" class="switchBox"> <div class="switchBoxTitle">{'Photo sizes'|@translate}</div> @@ -51,66 +43,57 @@ jQuery("#sortOrderBox").on("mouseleave", function() { {/if} {/foreach} </div> - {footer_script require='jquery'}{literal} -jQuery("#derivativeSwitchLink").click(function() { - var elt = jQuery("#derivativeSwitchBox"); - elt.css("left", Math.min( jQuery(this).offset().left, jQuery(window).width() - elt.outerWidth(true) - 5)) - .css("top", jQuery(this).offset().top + jQuery(this).outerHeight(true)) - .toggle(); -}); -jQuery("#derivativeSwitchBox").on("mouseleave", function() { - jQuery(this).hide(); -}); - {/literal}{/footer_script} + {footer_script}(SwitchBox=window.SwitchBox||[]).push("#derivativeSwitchLink", "#derivativeSwitchBox");{/footer_script} {/strip}</li> {/if} {if isset($favorite)} - <li><a href="{$favorite.U_FAVORITE}" title="{'delete all photos from your favorites'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-favorite-del"> </span><span class="pwg-button-text">{'delete all photos from your favorites'|@translate}</span> + <li id="cmdFavorite"><a href="{$favorite.U_FAVORITE}" title="{'delete all photos from your favorites'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> + <span class="pwg-icon pwg-icon-favorite-del"></span><span class="pwg-button-text">{'delete all photos from your favorites'|@translate}</span> </a></li> {/if} {if isset($U_CADDIE)} - <li><a href="{$U_CADDIE}" title="{'Add to caddie'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-caddie-add"> </span><span class="pwg-button-text">{'Caddie'|@translate}</span> + <li id="cmdCaddie"><a href="{$U_CADDIE}" title="{'Add to caddie'|@translate}" class="pwg-state-default pwg-button"> + <span class="pwg-icon pwg-icon-caddie-add"></span><span class="pwg-button-text">{'Caddie'|@translate}</span> </a></li> {/if} {if isset($U_EDIT)} - <li><a href="{$U_EDIT}" title="{'Edit album'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-category-edit"> </span><span class="pwg-button-text">{'Edit'|@translate}</span> + <li id="cmdEditAlbum"><a href="{$U_EDIT}" title="{'Edit album'|@translate}" class="pwg-state-default pwg-button"> + <span class="pwg-icon pwg-icon-category-edit"></span><span class="pwg-button-text">{'Edit'|@translate}</span> </a></li> {/if} {if isset($U_SEARCH_RULES)} {combine_script id='core.scripts' load='async' path='themes/default/js/scripts.js'} <li><a href="{$U_SEARCH_RULES}" onclick="popuphelp(this.href); return false;" title="{'Search rules'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-help"> </span><span class="pwg-button-text">(?)</span> + <span class="pwg-icon pwg-icon-help"></span><span class="pwg-button-text">(?)</span> </a></li> {/if} {if isset($U_SLIDESHOW)} - <li>{strip}<a href="{$U_SLIDESHOW}" title="{'slideshow'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-slideshow"> </span><span class="pwg-button-text">{'slideshow'|@translate}</span> + <li id="cmdSlideshow">{strip}<a href="{$U_SLIDESHOW}" title="{'slideshow'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> + <span class="pwg-icon pwg-icon-slideshow"></span><span class="pwg-button-text">{'slideshow'|@translate}</span> </a>{/strip}</li> {/if} {if isset($U_MODE_FLAT)} <li>{strip}<a href="{$U_MODE_FLAT}" title="{'display all photos in all sub-albums'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-category-view-flat"> </span><span class="pwg-button-text">{'display all photos in all sub-albums'|@translate}</span> + <span class="pwg-icon pwg-icon-category-view-flat"></span><span class="pwg-button-text">{'display all photos in all sub-albums'|@translate}</span> </a>{/strip}</li> {/if} {if isset($U_MODE_NORMAL)} <li>{strip}<a href="{$U_MODE_NORMAL}" title="{'return to normal view mode'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-category-view-normal"> </span><span class="pwg-button-text">{'return to normal view mode'|@translate}</span> + <span class="pwg-icon pwg-icon-category-view-normal"></span><span class="pwg-button-text">{'return to normal view mode'|@translate}</span> </a>{/strip}</li> {/if} {if isset($U_MODE_POSTED)} <li>{strip}<a href="{$U_MODE_POSTED}" title="{'display a calendar by posted date'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-calendar"> </span><span class="pwg-button-text">{'Calendar'|@translate}</span> + <span class="pwg-icon pwg-icon-calendar"></span><span class="pwg-button-text">{'Calendar'|@translate}</span> </a>{/strip}</li> {/if} {if isset($U_MODE_CREATED)} <li>{strip}<a href="{$U_MODE_CREATED}" title="{'display a calendar by creation date'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-camera-calendar"> </span><span class="pwg-button-text">{'Calendar'|@translate}</span> + <span class="pwg-icon pwg-icon-camera-calendar"></span><span class="pwg-button-text">{'Calendar'|@translate}</span> </a>{/strip}</li> {/if} +{if !empty($PLUGIN_INDEX_BUTTONS)}{foreach from=$PLUGIN_INDEX_BUTTONS item=button}<li>{$button}</li>{/foreach}{/if} {if !empty($PLUGIN_INDEX_ACTIONS)}{$PLUGIN_INDEX_ACTIONS}{/if} </ul> @@ -118,26 +101,15 @@ jQuery("#derivativeSwitchBox").on("mouseleave", function() { {if isset($chronology_views)} <div class="calendarViews">{'View'|@translate}: - <a id="calendarViewSwitchLink" href="javascript:toggleCalendarViewsBox()"> + <a id="calendarViewSwitchLink" href="#"> {foreach from=$chronology_views item=view}{if $view.SELECTED}{$view.CONTENT}{/if}{/foreach} - </a> + </a> <div id="calendarViewSwitchBox" class="switchBox"> {foreach from=$chronology_views item=view name=loop}{if !$smarty.foreach.loop.first}<br>{/if} <span{if !$view.SELECTED} style="visibility:hidden"{/if}>✔ </span><a href="{$view.VALUE}">{$view.CONTENT}</a> {/foreach} </div> - {footer_script require='jquery'}{literal} -function toggleCalendarViewsBox() { - var elt = jQuery("#calendarViewSwitchBox") - , ePos = jQuery("#calendarViewSwitchLink"); - elt.css("left", Math.min( ePos.offset().left, jQuery(window).width() - elt.outerWidth(true) - 5)) - .css("top", ePos.offset().top + ePos.outerHeight(true)) - .toggle(); -}; -jQuery("#calendarViewSwitchBox").on("mouseleave", function() { - jQuery(this).hide(); -}); - {/literal}{/footer_script} + {footer_script}(SwitchBox=window.SwitchBox||[]).push("#calendarViewSwitchLink", "#calendarViewSwitchBox");{/footer_script} </div> {/if} @@ -180,7 +152,10 @@ jQuery("#calendarViewSwitchBox").on("mouseleave", function() { </div> {/if} +{if !empty($CONTENT)}{$CONTENT}{/if} + {if !empty($CATEGORIES)}{$CATEGORIES}{/if} + {if !empty($cats_navbar)} {include file='navigation_bar.tpl'|@get_extent:'navbar' navbar=$cats_navbar} {/if} diff --git a/themes/default/template/mail/index.php b/themes/default/template/mail/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/template/mail/index.php +++ b/themes/default/template/mail/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/template/mail/screenshot-clear.png b/themes/default/template/mail/screenshot-clear.png Binary files differnew file mode 100644 index 000000000..ae879604a --- /dev/null +++ b/themes/default/template/mail/screenshot-clear.png diff --git a/themes/default/template/mail/screenshot-dark.png b/themes/default/template/mail/screenshot-dark.png Binary files differnew file mode 100644 index 000000000..2906c4ec8 --- /dev/null +++ b/themes/default/template/mail/screenshot-dark.png diff --git a/themes/default/template/mail/text/html/footer.tpl b/themes/default/template/mail/text/html/footer.tpl index b1f1b9317..da17e4473 100644 --- a/themes/default/template/mail/text/html/footer.tpl +++ b/themes/default/template/mail/text/html/footer.tpl @@ -1,22 +1,23 @@ -</div> <!-- content --> -<div id="copyright"> -<hr> - {'Sent by'|@translate} - <a href="{$GALLERY_URL}">{$GALLERY_TITLE}</a> + {* <!-- end $CONTENT --> *} + </td></tr> - {* Please, do not remove this copyright. If you really want to, - contact us on http://piwigo.org to find a solution on how - to show the origin of the script...*} - - {'Powered by'|@translate} - <a href="http://piwigo.org" class="Piwigo"> - <span class="Piwigo">Piwigo</span></a> - {$VERSION} + <tr><td id="footer"> + {* <!-- begin FOOTER --> *} +{* <!-- Please, do not remove this copyright. If you really want to, +contact us on http://piwigo.org to find a solution on how +to show the origin of the script... --> *} + + {'Sent by'|translate} <a href="{$GALLERY_URL}">{$GALLERY_TITLE}</a> + - {'Powered by'|translate} <a href="{$PHPWG_URL}" class="Piwigo">Piwigo</a> + {if not empty($VERSION)}{$VERSION}{/if} + + - {'Contact'|translate} + <a href="mailto:{$CONTACT_MAIL}?subject={'A comment on your site'|translate|escape:url}">{'Webmaster'|@translate}</a> + {* <!-- end FOOTER --> *} + </td></tr> + </table> - - {'Contact'|@translate} - <a href="mailto:{$MAIL}?subject={$TITLE_MAIL}">{'Webmaster'|@translate}</a> - -</div> <!-- copyright --> -</div> <!-- the_page --> - -</body> -</html> + </td></tr> + </table> + </body> +</html>
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/global-mail-css.tpl b/themes/default/template/mail/text/html/global-mail-css.tpl index 072bcb0be..59a1bde2f 100644 --- a/themes/default/template/mail/text/html/global-mail-css.tpl +++ b/themes/default/template/mail/text/html/global-mail-css.tpl @@ -1,11 +1,105 @@ -/* Global mail css */ - -body {ldelim} font-family: Univers, Helvetica, Optima; font-size:12px; margin:0px; padding:0px; } -#the_page {ldelim} margin:0px; padding:0px; text-align:left;} -#content {ldelim} margin:0px; padding:30px 0px 0px 30px; width:732px;} -hr {ldelim} width:632px; margin-left:0;} -#copyright {ldelim} font-size:10px; margin:0px; padding:48px 0px 32px 62px;} -.PWG {ldelim} font-family:verdana, sans-serif !important; font-size:0.9em; font-weight:normal; letter-spacing:0px;} -h2 {ldelim} padding:7px 15px; width:617px; font-weight:bold;} -img {ldelim} margin:16px; border:16px solid #aaa; -moz-border-radius: 4px; border-radius: 4px 4px; } -img:hover {ldelim} padding: 15px; border: 1px solid yellow; -moz-border-radius: 4px; border-radius: 4px 4px; } +{strip} +/* page */ +body { + font-family:"Verdana", "Helvetica", "Optima", sans-serif; + font-size:12px; + margin:0px; + padding:0px; +} + +html, body, #bodyTable { + width:100%; + height:100%; +} + +/* main block */ +#header { + padding:20px; +} +#header #title { + font-size:26px; + font-weight:bold; +} +#header #subtitle { + font-size:20px; +} +#content { + padding:0 20px 20px 20px; + font-family:"Verdana", "Helvetica", "Optima", sans-serif; + font-size:13px; +} +#footer { + font-size:10px; + padding:5px; +} +#topSpacer { + margin-bottom:20px; +} + +/* images */ +img { + border:none; +} + +h1, h2, h3, h4, h5 { + margin:0.5em 0 0.25em 0; +} +h1 { font-size:26px; } +h2 { font-size:20px; } +h3 { font-size:16px; } +h4 { font-size:12px; } +h5 { font-size:10px; } + +/* paragraphs */ +p { + margin:0.25em 0 0.5em 0; +} +blockquote { + margin-left:10px; + padding-left:10px; + font-family:"Times",serif; + font-size:14px; +} + +/* list */ +ul, ol { + margin:0.5em 0 0.25em 30px; + padding:0; +} +dl { + margin:0.5em 0 0.25em 10px; +} +dt { + margin:0.25em 0 0 0; + font-weight:bold; +} +dd { + margin:0 0 0.25em 10px; +} + +/* tables */ +#content table { + width:100%; + border-spacing:0; + border-collapse:collapse; +} +#content table td { + padding:2px 3px; +} +#content table th { + font-weight:bold; + text-align:center; + padding:4px 0; +} +#content table tfoot td { + font-size:0.8em; +} + +/* line */ +hr { + border-width:0 0 1px 0; + border-color:#ddd; + border-style:solid; + margin:1em; +} +{/strip}
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/header.tpl b/themes/default/template/mail/text/html/header.tpl index e6af4c024..b98f5be18 100644 --- a/themes/default/template/mail/text/html/header.tpl +++ b/themes/default/template/mail/text/html/header.tpl @@ -1,17 +1,29 @@ ------={$BOUNDARY_KEY} -Content-Type: {$CONTENT_TYPE}; charset="{$CONTENT_ENCODING}"; -Content-Transfer-Encoding: 8bit - -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="{$lang_info.code}" dir="{$lang_info.direction}"> -<head> -<title>Piwigo Mail</title> -<meta http-equiv="Content-Type" content="text/html; charset={$CONTENT_ENCODING}"> -<style><!-- /* Mini style for mails */ -{if isset($GLOBAL_MAIL_CSS)}{$GLOBAL_MAIL_CSS}{/if} -{if isset($MAIL_CSS)}{$MAIL_CSS}{/if} ---></style> -</head> -<body> -<div id="the_page"> -<div id="content" class="content"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset={$CONTENT_ENCODING}"/> + <title>Piwigo Mail</title> + + <style type="text/css"> + {if isset($GLOBAL_MAIL_CSS)}{$GLOBAL_MAIL_CSS}{/if} + {if isset($MAIL_CSS)}{$MAIL_CSS}{/if} + </style> + </head> + + <body> + <table id="bodyTable" cellspacing="0" cellpadding="10" border="0"> + <tr><td align="center" valign="top"> + + <table id="contentTable" cellspacing="0" cellpadding="0" border="0"> + <tr><td id="header"> + {* <!-- begin HEADER --> *} + <div id="title">{$MAIL_TITLE}</div> + {if not empty($MAIL_SUBTITLE)}<div id="subtitle">{$MAIL_SUBTITLE}</div>{/if} + {* <!-- end HEADER --> *} + </td></tr> + + <tr><td id="content"> +{* <!-- use an invisible div with a bottom margin to force the browser +to merge the margin with the element bellow (typically h1/h2/...) --> *} + <div id="topSpacer"></div> + {* <!-- begin CONTENT --> *}
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/index.php b/themes/default/template/mail/text/html/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/template/mail/text/html/index.php +++ b/themes/default/template/mail/text/html/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/template/mail/text/html/mail-css-clear.tpl b/themes/default/template/mail/text/html/mail-css-clear.tpl new file mode 100644 index 000000000..98b0337d9 --- /dev/null +++ b/themes/default/template/mail/text/html/mail-css-clear.tpl @@ -0,0 +1,73 @@ +{strip} +/* page */ +body { + color:#111; +} + +html, body, #bodyTable { + background:#fff; +} +#contentTable { + width:600px; +} + +/* main block */ +#header { + background:#eee; + background-image:radial-gradient(ellipse at center, #fefefe, #e5e5e5); + border-top:4px solid #f70; + text-align:center; + text-shadow:1px 1px 0px #fff; +} +#header #subtitle { + color:#e06900; +} +#content { + background:#fefefe; + border-width:1px; + border-style:solid; + border-color:#ddd #eee; + box-shadow:inset 0 0 20px #eee; +} +#footer { + background:#eee; + border-bottom:2px solid #f70; +} + +/* links */ +a { + color:#f70; + text-decoration:none; +} +a:hover { + text-decoration:underline; +} + +/* images */ +img.photo { + border:10px solid #ddd; +} +img.photo:hover { + border-color:#eee; +} + +/* paragraphs */ +blockquote { + border-left:2px solid #aaa; + border-radius:2px; +} + +/* tables */ +#content table td { + border-bottom:1px solid #efefef; +} +#content table th { + background:#aaa; + color:#fff; + border-right:1px solid #ddd; +} +#content table tfoot td { + background:#eee; + border-right:1px solid #fff; +} +{/strip}
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/mail-css-dark.tpl b/themes/default/template/mail/text/html/mail-css-dark.tpl new file mode 100644 index 000000000..390a7dfb6 --- /dev/null +++ b/themes/default/template/mail/text/html/mail-css-dark.tpl @@ -0,0 +1,87 @@ +{strip} +/* page */ +body { + color:#fff; +} + +html, body, #bodyTable { + background:#111; +} +#contentTable { + width:600px; +} + +/* main block */ +#header { + background:#444; + background-image:radial-gradient(ellipse at center, #555, #333); + border:1px solid #000; + border-top:4px solid #f36; + text-align:center; + text-shadow:1px 1px 0px #000; +} +#header #title { + color:#eee; +} +#header #subtitle { + color:#C9224C; +} +#content { + background:#111; + border-width:1px; + border-style:solid; + border-color:#666 #000; + box-shadow:inset 0 0 20px #333; +} +#footer { + background:#333; + border:1px solid #000; + border-bottom:2px solid #f36; +} + +/* links */ +a { + color:#f36; + text-decoration:none; +} +a:hover { + text-decoration:underline; +} + +/* images */ +img.photo { + border:10px solid #666; +} +img.photo:hover { + border-color:#999; +} + +h1, h2, h3, h4, h5 { + color:#bbb; +} + +/* paragraphs */ +blockquote { + border-left:2px solid #aaa; + border-radius:2px; +} + +/* tables */ +#content table td { + border-bottom:1px solid #999; +} +#content table th { + background:#666; + border-right:1px solid #aaa; +} +#content table tfoot td { + background:#444; + color:#aaa; + border-right:1px solid #aaa; +} + +/* line */ +hr { + border-color:#555; +} +{/strip}
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/notification_admin.tpl b/themes/default/template/mail/text/html/notification_admin.tpl new file mode 100644 index 000000000..f236b8ee6 --- /dev/null +++ b/themes/default/template/mail/text/html/notification_admin.tpl @@ -0,0 +1,9 @@ +{$CONTENT} + +{if isset($TECHNICAL)} +<p style="padding-top:10px;font-size:11px;"> +{'Connected user: %s'|translate:$TECHNICAL.username}<br> +{'IP: %s'|translate:$TECHNICAL.ip}<br> +{'Browser: %s'|translate:$TECHNICAL.user_agent} +</p> +{/if}
\ No newline at end of file diff --git a/themes/default/template/mail/text/html/notification_by_mail.tpl b/themes/default/template/mail/text/html/notification_by_mail.tpl index 9989a32c0..df3e431e1 100644 --- a/themes/default/template/mail/text/html/notification_by_mail.tpl +++ b/themes/default/template/mail/text/html/notification_by_mail.tpl @@ -38,13 +38,13 @@ {/if} <p>{'See you soon,'|@translate}</p> <p style="text-align:center">{$SEND_AS_NAME}</p> +<hr> <p> -<br><hr> {'To unsubscribe'|@translate}{', click on'|@translate} <a href="{$UNSUBSCRIBE_LINK}">{$UNSUBSCRIBE_LINK}</a><br> {'To subscribe'|@translate}{', click on'|@translate} <a href="{$SUBSCRIBE_LINK}">{$SUBSCRIBE_LINK}</a><br> {'If you encounter problems or have any question, please send a message to'|@translate} <a href="mailto:{$CONTACT_EMAIL}?subject={'[NBM] Problems or questions'|@translate}">{$CONTACT_EMAIL}</a><br> -<hr><br> </p> +<hr> {if not empty($recent_posts)} </div> <div id="nbm_recent_post"> diff --git a/themes/default/template/mail/text/index.php b/themes/default/template/mail/text/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/template/mail/text/index.php +++ b/themes/default/template/mail/text/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/template/mail/text/plain/footer.tpl b/themes/default/template/mail/text/plain/footer.tpl index 8574697e6..0f9ef273e 100644 --- a/themes/default/template/mail/text/plain/footer.tpl +++ b/themes/default/template/mail/text/plain/footer.tpl @@ -1,5 +1,7 @@ +{literal} --- +{/literal} +---- {'Sent by'|@translate} "{$GALLERY_TITLE}" {$GALLERY_URL} -{'Contact'|@translate} {$MAIL} -{'Powered by'|@translate} Piwigo {$VERSION} +{'Powered by'|@translate} "Piwigo{if not empty($VERSION)} {$VERSION}{/if}" {$PHPWG_URL} +{'Contact'|@translate}: {$CONTACT_MAIL}
\ No newline at end of file diff --git a/themes/default/template/mail/text/plain/header.tpl b/themes/default/template/mail/text/plain/header.tpl index 6fcc863d2..31d7456fb 100644 --- a/themes/default/template/mail/text/plain/header.tpl +++ b/themes/default/template/mail/text/plain/header.tpl @@ -1,5 +1,6 @@ ------={$BOUNDARY_KEY} -Content-Type: {$CONTENT_TYPE}; charset="{$CONTENT_ENCODING}"; -Content-Transfer-Encoding: 8bit{literal} - -{/literal}{*note that there must be an empty line to separate the mime headers*} +{$MAIL_TITLE} +{if not empty($MAIL_SUBTITLE)}{$MAIL_SUBTITLE} +{/if} +---- +{literal} +{/literal}
\ No newline at end of file diff --git a/themes/default/template/mail/text/plain/index.php b/themes/default/template/mail/text/plain/index.php index 41732f2fd..c8de97f60 100644 --- a/themes/default/template/mail/text/plain/index.php +++ b/themes/default/template/mail/text/plain/index.php @@ -2,7 +2,7 @@ // +-----------------------------------------------------------------------+ // | Piwigo - a PHP based photo gallery | // +-----------------------------------------------------------------------+ -// | Copyright(C) 2008-2013 Piwigo Team http://piwigo.org | +// | Copyright(C) 2008-2014 Piwigo Team http://piwigo.org | // | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | // | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | // +-----------------------------------------------------------------------+ diff --git a/themes/default/template/mail/text/plain/notification_admin.tpl b/themes/default/template/mail/text/plain/notification_admin.tpl new file mode 100644 index 000000000..e6970842f --- /dev/null +++ b/themes/default/template/mail/text/plain/notification_admin.tpl @@ -0,0 +1,8 @@ +{$CONTENT} + +{if isset($TECHNICAL)} +----------------------------- +{'Connected user: %s'|translate:$TECHNICAL.username} +{'IP: %s'|translate:$TECHNICAL.ip} +{'Browser: %s'|translate:$TECHNICAL.user_agent} +{/if}
\ No newline at end of file diff --git a/themes/default/template/menubar_categories.tpl b/themes/default/template/menubar_categories.tpl index 65a149cff..c3c5b1c02 100644 --- a/themes/default/template/menubar_categories.tpl +++ b/themes/default/template/menubar_categories.tpl @@ -14,7 +14,7 @@ <ul> {else} </li> - {'</ul></li>'|@str_repeat:$ref_level-$cat.LEVEL} + {'</ul></li>'|@str_repeat:($ref_level-$cat.LEVEL)} {/if} <li {if $cat.SELECTED}class="selected"{/if}> <a href="{$cat.URL}" {if $cat.IS_UPPERCAT}rel="up"{/if} title="{$cat.TITLE}">{$cat.NAME}</a> @@ -28,5 +28,5 @@ {/foreach} {'</li></ul>'|@str_repeat:$ref_level} - <p class="totalImages">{$pwg->l10n_dec('%d photo', '%d photos', $block->data.NB_PICTURE)}</p> + <p class="totalImages">{$block->data.NB_PICTURE|@translate_dec:'%d photo':'%d photos'}</p> </dd> diff --git a/themes/default/template/menubar_menu.tpl b/themes/default/template/menubar_menu.tpl index 29276a48f..2eb2dd3a9 100644 --- a/themes/default/template/menubar_menu.tpl +++ b/themes/default/template/menubar_menu.tpl @@ -11,7 +11,7 @@ <ul>{strip} {foreach from=$block->data item=link} {if is_array($link)} - <li><a href="{$link.URL}" title="{$link.TITLE}"{if isset($link.REL)} {$link.REL}{/if}>{$link.NAME}</a></li> + <li><a href="{$link.URL}" title="{$link.TITLE}"{if isset($link.REL)} {$link.REL}{/if}>{$link.NAME}</a>{if isset($link.COUNTER)} ({$link.COUNTER}){/if}</li> {/if} {/foreach} {/strip}</ul> diff --git a/themes/default/template/menubar_tags.tpl b/themes/default/template/menubar_tags.tpl index 975d7eb09..d1a672837 100644 --- a/themes/default/template/menubar_tags.tpl +++ b/themes/default/template/menubar_tags.tpl @@ -5,7 +5,7 @@ <span>{strip} <a class="tagLevel{$tag.level}" href= {if isset($tag.U_ADD)} - "{$tag.U_ADD}" title="{$pwg->l10n_dec('%d photo is also linked to current tags', '%d photos are also linked to current tags', $tag.counter)}" rel="nofollow">+ + "{$tag.U_ADD}" title="{$tag.counter|@translate_dec:'%d photo is also linked to current tags':'%d photos are also linked to current tags'}" rel="nofollow">+ {else} "{$tag.URL}" title="{'display photos linked to this tag'|@translate}"> {/if} diff --git a/themes/default/template/month_calendar.tpl b/themes/default/template/month_calendar.tpl index 904570a10..ac8fed166 100644 --- a/themes/default/template/month_calendar.tpl +++ b/themes/default/template/month_calendar.tpl @@ -1,31 +1,28 @@ - -{if !empty($chronology_navigation_bars) } +{if !empty($chronology_navigation_bars)} {foreach from=$chronology_navigation_bars item=bar} <div class="calendarBar"> {if isset($bar.previous)} - <div style="float:left">« <a href="{$bar.previous.URL}">{$bar.previous.LABEL}</a></div> + <div style="float:left;margin-right:5px">« <a href="{$bar.previous.URL}">{$bar.previous.LABEL}</a></div> {/if} {if isset($bar.next)} - <div style="float:right"><a href="{$bar.next.URL}">{$bar.next.LABEL}</a> »</div> + <div style="float:right;margin-left:5px"><a href="{$bar.next.URL}">{$bar.next.LABEL}</a> »</div> {/if} {if empty($bar.items)} {else} {foreach from=$bar.items item=item} - <span class="calItem{if !isset($item.URL)}Empty{/if}" {if isset($item.NB_IMAGES)}title="{$pwg->l10n_dec('%d photo', '%d photos', $item.NB_IMAGES)}"{/if}> - {if isset($item.URL)} - <a href="{$item.URL}">{$item.LABEL}</a> + {if !isset($item.URL)} + <span class="calItem">{$item.LABEL}</span> {else} - {$item.LABEL} + <a class="calItem"{if isset($item.NB_IMAGES)} title="{$item.NB_IMAGES|@translate_dec:'%d photo':'%d photos'}"{/if} href="{$item.URL}">{$item.LABEL}</a> {/if} - </span> {/foreach} {/if} </div> {/foreach} {/if} -{if !empty($chronology_calendar.calendar_bars) } +{if !empty($chronology_calendar.calendar_bars)} {foreach from=$chronology_calendar.calendar_bars item=bar} <div class="calendarCalBar"> <span class="calCalHead"><a href="{$bar.U_HEAD}">{$bar.HEAD_LABEL}</a> ({$bar.NB_IMAGES})</span><br> @@ -43,7 +40,7 @@ {/foreach} {/if} -{if isset($chronology_calendar.month_view) } +{if isset($chronology_calendar.month_view)} <table class="calMonth"> <thead> <tr> @@ -52,13 +49,11 @@ {/foreach} </tr> </thead> -{html_head} {*add the style to html head for strict standard compliance*} -<style type="text/css"> -TABLE.calMonth TBODY TD, TABLE.calMonth TBODY TD DIV.calImg {ldelim} - width:{$chronology_calendar.month_view.CELL_WIDTH}px;height:{$chronology_calendar.month_view.CELL_HEIGHT}px; +{html_style} +.calMonth TD, .calMonth .calImg{ + width:{$chronology_calendar.month_view.CELL_WIDTH}px;height:{$chronology_calendar.month_view.CELL_HEIGHT}px } -</style> -{/html_head} +{/html_style} {foreach from=$chronology_calendar.month_view.weeks item=week} <tr> {foreach from=$week item=day} @@ -68,7 +63,7 @@ TABLE.calMonth TBODY TD, TABLE.calMonth TBODY TD DIV.calImg {ldelim} <div class="calBackDate">{$day.DAY}</div><div class="calForeDate">{$day.DAY}</div> <div class="calImg"> <a href="{$day.U_IMG_LINK}"> - <img style="{$day.IMAGE_STYLE}" src="{$day.IMAGE}" alt="{$day.IMAGE_ALT}" title="{$pwg->l10n_dec('%d photo','%d photos', $day.NB_ELEMENTS)}"> + <img src="{$day.IMAGE}" alt="{$day.IMAGE_ALT}" title="{$day.NB_ELEMENTS|@translate_dec:'%d photo':'%d photos'}"> </a> </div> {else} @@ -78,9 +73,9 @@ TABLE.calMonth TBODY TD, TABLE.calMonth TBODY TD DIV.calImg {ldelim} <td> {/if} </td> - {/foreach} {*day in week*} + {/foreach}{*day in week*} </tr> - {/foreach} {*week in month*} + {/foreach}{*week in month*} </table> {/if} diff --git a/themes/default/template/password.tpl b/themes/default/template/password.tpl index 260830cdf..7b6a389ae 100644 --- a/themes/default/template/password.tpl +++ b/themes/default/template/password.tpl @@ -11,6 +11,8 @@ {if $action ne 'none'} <form id="lostPassword" action="{$form_action}?action={$action}{if isset($key)}&key={$key}{/if}" method="post"> +<fieldset> + <legend>{'Forgot your password?'|translate}</legend> <input type="hidden" name="pwg_token" value="{$PWG_TOKEN}"> {if $action eq 'lost'} @@ -44,7 +46,7 @@ <input type="password" name="passwordConf" id="passwordConf" value=""> </label> </p> - +</fieldset> <p class="bottomButtons"><input type="submit" name="submit" value="{'Submit'|@translate}"></p> {/if} diff --git a/themes/default/template/picture.tpl b/themes/default/template/picture.tpl index eacb81beb..f64e04856 100644 --- a/themes/default/template/picture.tpl +++ b/themes/default/template/picture.tpl @@ -1,11 +1,11 @@ -{* Example of resizeable -{include file='include/autosize.inc.tpl'} -*} +{combine_script id='core.switchbox' load='async' require='jquery' path='themes/default/js/switchbox.js'} {if isset($MENUBAR)}{$MENUBAR}{/if} <div id="content"{if isset($MENUBAR)} class="contentWithMenu"{/if}> + {if isset($errors) or not empty($infos)} {include file='infos_errors.tpl'} {/if} + {if !empty($PLUGIN_PICTURE_BEFORE)}{$PLUGIN_PICTURE_BEFORE}{/if} <div id="imageHeaderBar"> @@ -17,6 +17,7 @@ <div id="imageToolBar"> <div class="imageNumber">{$PHOTO}</div> {include file='picture_nav_buttons.tpl'|@get_extent:'picture_nav_buttons'} + <div class="actionButtons"> {if isset($current.unique_derivatives) && count($current.unique_derivatives)>1} {footer_script require='jquery'}{literal} @@ -30,26 +31,18 @@ function changeImgSrc(url,typeSave,typeMap) theImg.useMap = "#map"+typeMap; } jQuery('#derivativeSwitchBox .switchCheck').css('visibility','hidden'); - jQuery('#derivativeChecked'+typeSave).css('visibility','visible'); + jQuery('#derivativeChecked'+typeMap).css('visibility','visible'); document.cookie = 'picture_deriv='+typeSave+';path={/literal}{$COOKIE_PATH}{literal}'; } -jQuery("#derivativeSwitchLink").click(function() { - var elt = jQuery("#derivativeSwitchBox"); - elt.css("left", Math.min( jQuery(this).offset().left, jQuery(window).width() - elt.outerWidth(true) - 5)) - .css("top", jQuery(this).offset().top + jQuery(this).outerHeight(true)) - .toggle(); -}); -jQuery("#derivativeSwitchBox").on("mouseleave click", function() { - jQuery(this).hide(); -}); +(SwitchBox=window.SwitchBox||[]).push("#derivativeSwitchLink", "#derivativeSwitchBox"); {/literal}{/footer_script} {strip}<a id="derivativeSwitchLink" title="{'Photo sizes'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-sizes"> </span><span class="pwg-button-text">{'Photo sizes'|@translate}</span> + <span class="pwg-icon pwg-icon-sizes"></span><span class="pwg-button-text">{'Photo sizes'|@translate}</span> </a> <div id="derivativeSwitchBox" class="switchBox"> <div class="switchBoxTitle">{'Photo sizes'|@translate}</div> {foreach from=$current.unique_derivatives item=derivative key=derivative_type} - <span class="switchCheck" id="derivativeChecked{$derivative_type}"{if $derivative->get_type() ne $current.selected_derivative->get_type()} style="visibility:hidden"{/if}>✔ </span> + <span class="switchCheck" id="derivativeChecked{$derivative->get_type()}"{if $derivative->get_type() ne $current.selected_derivative->get_type()} style="visibility:hidden"{/if}>✔ </span> <a href="javascript:changeImgSrc('{$derivative->get_url()|@escape:javascript}','{$derivative_type}','{$derivative->get_type()}')"> {$derivative->get_type()|@translate}<span class="derivativeSizeDetails"> ({$derivative->get_size_hr()})</span> </a><br> @@ -63,33 +56,34 @@ jQuery("#derivativeSwitchBox").on("mouseleave click", function() { {/if} {strip}{if isset($U_SLIDESHOW_START)} <a href="{$U_SLIDESHOW_START}" title="{'slideshow'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-slideshow"> </span><span class="pwg-button-text">{'slideshow'|@translate}</span> + <span class="pwg-icon pwg-icon-slideshow"></span><span class="pwg-button-text">{'slideshow'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($U_METADATA)} <a href="{$U_METADATA}" title="{'Show file metadata'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-camera-info"> </span><span class="pwg-button-text">{'Show file metadata'|@translate}</span> + <span class="pwg-icon pwg-icon-camera-info"></span><span class="pwg-button-text">{'Show file metadata'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($current.U_DOWNLOAD)} <a href="{$current.U_DOWNLOAD}" title="{'Download this file'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-save"> </span><span class="pwg-button-text">{'Download'|@translate}</span> + <span class="pwg-icon pwg-icon-save"></span><span class="pwg-button-text">{'Download'|@translate}</span> </a> {/if}{/strip} +{if isset($PLUGIN_PICTURE_BUTTONS)}{foreach from=$PLUGIN_PICTURE_BUTTONS item=button}{$button}{/foreach}{/if} {if isset($PLUGIN_PICTURE_ACTIONS)}{$PLUGIN_PICTURE_ACTIONS}{/if} {strip}{if isset($favorite)} <a href="{$favorite.U_FAVORITE}" title="{if $favorite.IS_FAVORITE}{'delete this photo from your favorites'|@translate}{else}{'add this photo to your favorites'|@translate}{/if}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-favorite-{if $favorite.IS_FAVORITE}del{else}add{/if}"> </span><span class="pwg-button-text">{'Favorites'|@translate}</span> + <span class="pwg-icon pwg-icon-favorite-{if $favorite.IS_FAVORITE}del{else}add{/if}"></span><span class="pwg-button-text">{'Favorites'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($U_SET_AS_REPRESENTATIVE)} - <a href="{$U_SET_AS_REPRESENTATIVE}" title="{'set as album representative'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-representative"> </span><span class="pwg-button-text">{'representative'|@translate}</span> + <a id="cmdSetRepresentative" href="{$U_SET_AS_REPRESENTATIVE}" title="{'set as album representative'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> + <span class="pwg-icon pwg-icon-representative"></span><span class="pwg-button-text">{'representative'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($U_PHOTO_ADMIN)} - <a href="{$U_PHOTO_ADMIN}" title="{'Modify information'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-edit"> </span><span class="pwg-button-text">{'Edit'|@translate}</span> + <a id="cmdEditPhoto" href="{$U_PHOTO_ADMIN}" title="{'Modify information'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> + <span class="pwg-icon pwg-icon-edit"></span><span class="pwg-button-text">{'Edit'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($U_CADDIE)}{*caddie management BEGIN*} @@ -134,15 +128,23 @@ y.callService( {if $DISPLAY_NAV_THUMB} <div class="navThumbs"> {if isset($previous)} - <a class="navThumb" id="linkPrev" href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE|@escape}" rel="prev"> + <a class="navThumb" id="linkPrev" href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE_ESC}" rel="prev"> <span class="thumbHover prevThumbHover"></span> - <img src="{$previous.derivatives.square->get_url()}" alt="{$previous.TITLE|@escape}"> + <img src="{$previous.derivatives.square->get_url()}" alt="{$previous.TITLE_ESC}"> + </a> + {elseif isset($U_UP)} + <a class="navThumb" id="linkPrev" href="{$U_UP}" title="{'Thumbnails'|@translate}"> + <div class="thumbHover">{'First Page'|@translate}<br><br>{'Go back to the album'|@translate}</div> </a> {/if} {if isset($next)} - <a class="navThumb" id="linkNext" href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE|@escape}" rel="next"> + <a class="navThumb" id="linkNext" href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE_ESC}" rel="next"> <span class="thumbHover nextThumbHover"></span> - <img src="{$next.derivatives.square->get_url()}" alt="{$next.TITLE|@escape}"> + <img src="{$next.derivatives.square->get_url()}" alt="{$next.TITLE_ESC}"> + </a> + {elseif isset($U_UP)} + <a class="navThumb" id="linkNext" href="{$U_UP}" title="{'Thumbnails'|@translate}"> + <div class="thumbHover">{'Last Page'|@translate}<br><br>{'Go back to the album'|@translate}</div> </a> {/if} </div> @@ -218,12 +220,7 @@ y.callService( <dt>{'Rating score'|@translate}</dt> <dd> {if $rate_summary.count} - {if $rate_summary.count == 1} - {assign var='rate_text' value='%d rate'|@translate} - {else} - {assign var='rate_text' value='%d rates'|@translate} - {/if} - <span id="ratingScore">{$rate_summary.score}</span> <span id="ratingCount">({$pwg->sprintf($rate_text, $rate_summary.count)})</span> + <span id="ratingScore">{$rate_summary.score}</span> <span id="ratingCount">({$rate_summary.count|@translate_dec:'%d rate':'%d rates'})</span> {else} <span id="ratingScore">{'no rate'|@translate}</span> <span id="ratingCount"></span> {/if} @@ -274,51 +271,38 @@ y.callService( {/if} {if $display_info.privacy_level and isset($available_permission_levels)} - <div id="Privacy" class="imageInfo"><div class="relSwitchBox"> - <dt><a id="privacyLevelLink" href="javascript:togglePrivacyLevelBox()">{'Who can see this photo?'|@translate}</a></dt> + <div id="Privacy" class="imageInfo"> + <dt>{'Who can see this photo?'|@translate}</dt> <dd> + <div> + <a id="privacyLevelLink" href>{$available_permission_levels[$current.level]}</a> + </div> {combine_script id='core.scripts' load='async' path='themes/default/js/scripts.js'} -{footer_script require='jquery'} -{literal}function setPrivacyLevel(rootUrl, id, level) -{ -var y = new PwgWS(rootUrl); -y.callService( - "pwg.images.setPrivacyLevel", {image_id: id, level:level} , +{footer_script require='jquery'}{strip} +function setPrivacyLevel(id, level){ +(new PwgWS('{$ROOT_URL}')).callService( + "pwg.images.setPrivacyLevel", { image_id:id, level:level}, { method: "POST", onFailure: function(num, text) { alert(num + " " + text); }, onSuccess: function(result) { jQuery('#privacyLevelBox .switchCheck').css('visibility','hidden'); - jQuery('#levelCheck'+level).css('visibility','visible'); + jQuery('#switchLevel'+level).prev('.switchCheck').css('visibility','visible'); + jQuery('#privacyLevelLink').text(jQuery('#switchLevel'+level).text()); } } ); } -function togglePrivacyLevelBox() -{ - var elt = document.getElementById("privacyLevelBox"), - ePos = document.getElementById("privacyLevelLink"); - if (elt.style.display == "none") - { - elt.style.left = (ePos.offsetLeft)+"px"; - elt.style.top = (ePos.offsetTop+ePos.offsetHeight)+"px"; - elt.style.display="block"; - } - else - elt.style.display="none"; -} -{/literal} -{/footer_script} - - <div id="privacyLevelBox" class="switchBox" onclick="togglePrivacyLevelBox()" style="display:none" onmouseout="e=event.toElement||event.relatedTarget;e.parentNode==this||e==this||togglePrivacyLevelBox()"> +(SwitchBox=window.SwitchBox||[]).push("#privacyLevelLink", "#privacyLevelBox"); +{/strip}{/footer_script} + <div id="privacyLevelBox" class="switchBox" style="display:none"> {foreach from=$available_permission_levels item=label key=level} - <span id="levelCheck{$level}" class="switchCheck" {if $level != $current.level} style="visibility:hidden"{/if}>✔ </span> - <a id="switchLevel{$level}" href="javascript:setPrivacyLevel('{$ROOT_URL}', {$current.id}, {$level})">{$label}</a><br> + <span class="switchCheck"{if $level != $current.level} style="visibility:hidden"{/if}>✔ </span> + <a id="switchLevel{$level}" href="javascript:setPrivacyLevel({$current.id},{$level})">{$label}</a><br> {/foreach} </div> - </dd> - </div></div> + </div> {/if} {/strip} </dl> @@ -341,7 +325,7 @@ function togglePrivacyLevelBox() {if isset($COMMENT_COUNT)} <div id="comments" {if (!isset($comment_add) && ($COMMENT_COUNT == 0))}class="noCommentContent"{else}class="commentContent"{/if}><div id="commentsSwitcher"></div> - <h3>{$pwg->l10n_dec('%d comment', '%d comments',$COMMENT_COUNT)}</h3> + <h3>{$COMMENT_COUNT|@translate_dec:'%d comment':'%d comments'}</h3> <div id="pictureComments"> {if isset($comment_add)} @@ -353,7 +337,7 @@ function togglePrivacyLevelBox() <p><input type="text" name="author" id="author" value="{$comment_add.AUTHOR}"></p> {/if} {if $comment_add.SHOW_EMAIL} - <p><label for="email">{'Email'|@translate}{if $comment_add.EMAIL_MANDATORY} ({'mandatory'|@translate}){/if} :</label></p> + <p><label for="email">{'Email address'|@translate}{if $comment_add.EMAIL_MANDATORY} ({'mandatory'|@translate}){/if} :</label></p> <p><input type="text" name="email" id="email" value="{$comment_add.EMAIL}"></p> {/if} <p><label for="website_url">{'Website'|@translate} :</label></p> diff --git a/themes/default/template/picture_content.tpl b/themes/default/template/picture_content.tpl index 793c275ea..c2bbc2e39 100644 --- a/themes/default/template/picture_content.tpl +++ b/themes/default/template/picture_content.tpl @@ -4,17 +4,17 @@ {footer_script}var error_icon = "{$ROOT_URL}{$themeconf.icon_dir}/errors_small.png"{/footer_script} {/if} -<img {if $current.selected_derivative->is_cached()}src="{$current.selected_derivative->get_url()}" {$current.selected_derivative->get_size_htm()}{else}src="{$ROOT_URL}{$themeconf.img_dir}/ajax_loader.gif" data-src="{$current.selected_derivative->get_url()}"{/if} alt="{$ALT_IMG}" id="theMainImage" usemap="#map{$current.selected_derivative->get_type()}" title="{if isset($COMMENT_IMG)}{$COMMENT_IMG|@strip_tags:false|@replace:'"':' '}{else}{$current.TITLE|@replace:'"':' '} - {$ALT_IMG}{/if}"> +<img {if $current.selected_derivative->is_cached()}src="{$current.selected_derivative->get_url()}" {$current.selected_derivative->get_size_htm()}{else}src="{$ROOT_URL}{$themeconf.img_dir}/ajax_loader.gif" data-src="{$current.selected_derivative->get_url()}"{/if} alt="{$ALT_IMG}" id="theMainImage" usemap="#map{$current.selected_derivative->get_type()}" title="{if isset($COMMENT_IMG)}{$COMMENT_IMG|@strip_tags:false|@replace:'"':' '}{else}{$current.TITLE_ESC} - {$ALT_IMG}{/if}"> {foreach from=$current.unique_derivatives item=derivative key=derivative_type}{strip} <map name="map{$derivative->get_type()}"> {assign var='size' value=$derivative->get_size()} {if isset($previous)} -<area shape=rect coords="0,0,{$size[0]/4|@intval},{$size[1]}" href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE|@escape}" alt="{$previous.TITLE|@escape}"> +<area shape=rect coords="0,0,{($size[0]/4)|@intval},{$size[1]}" href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE_ESC}" alt="{$previous.TITLE_ESC}"> {/if} -<area shape=rect coords="{$size[0]/4|@intval},0,{$size[0]/1.34|@intval},{$size[1]/4|@intval}" href="{$U_UP}" title="{'Thumbnails'|@translate}" alt="{'Thumbnails'|@translate}"> +<area shape=rect coords="{($size[0]/4)|@intval},0,{($size[0]/1.34)|@intval},{($size[1]/4)|@intval}" href="{$U_UP}" title="{'Thumbnails'|@translate}" alt="{'Thumbnails'|@translate}"> {if isset($next)} -<area shape=rect coords="{$size[0]/1.33|@intval},0,{$size[0]},{$size[1]}" href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE|@escape}" alt="{$next.TITLE|@escape}"> +<area shape=rect coords="{($size[0]/1.33)|@intval},0,{$size[0]},{$size[1]}" href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE_ESC}" alt="{$next.TITLE_ESC}"> {/if} </map> {/strip}{/foreach}
\ No newline at end of file diff --git a/themes/default/template/picture_nav_buttons.tpl b/themes/default/template/picture_nav_buttons.tpl index 6da241c51..b56ab0eee 100644 --- a/themes/default/template/picture_nav_buttons.tpl +++ b/themes/default/template/picture_nav_buttons.tpl @@ -3,31 +3,31 @@ {if isset($slideshow)} {if isset($slideshow.U_INC_PERIOD)} <a href="{$slideshow.U_INC_PERIOD}" title="{'Reduce diaporama speed'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-clock-minus"> </span><span class="pwg-button-text">{'Reduce diaporama speed'|@translate}</span> + <span class="pwg-icon pwg-icon-clock-minus"></span><span class="pwg-button-text">{'Reduce diaporama speed'|@translate}</span> </a> {else} <span class="pwg-state-disabled pwg-button"> - <span class="pwg-icon pwg-icon-clock-minus"> </span><span class="pwg-button-text">{'Reduce diaporama speed'|@translate}</span> + <span class="pwg-icon pwg-icon-clock-minus"></span><span class="pwg-button-text">{'Reduce diaporama speed'|@translate}</span> </span> {/if} {if isset($slideshow.U_DEC_PERIOD)} <a href="{$slideshow.U_DEC_PERIOD}" title="{'Accelerate diaporama speed'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-clock-plus"> </span><span class="pwg-button-text">{'Accelerate diaporama speed'|@translate}</span> + <span class="pwg-icon pwg-icon-clock-plus"></span><span class="pwg-button-text">{'Accelerate diaporama speed'|@translate}</span> </a> {else} <span class="pwg-state-disabled pwg-button"> - <span class="pwg-icon pwg-icon-clock-plus"> </span><span class="pwg-button-text">{'Accelerate diaporama speed'|@translate}</span> + <span class="pwg-icon pwg-icon-clock-plus"></span><span class="pwg-button-text">{'Accelerate diaporama speed'|@translate}</span> </span> {/if} {/if} {if isset($slideshow.U_START_REPEAT)} <a href="{$slideshow.U_START_REPEAT}" title="{'Repeat the slideshow'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-repeat-play"> </span><span class="pwg-button-text">{'Repeat the slideshow'|@translate}</span> + <span class="pwg-icon pwg-icon-repeat-play"></span><span class="pwg-button-text">{'Repeat the slideshow'|@translate}</span> </a> {/if} {if isset($slideshow.U_STOP_REPEAT)} <a href="{$slideshow.U_STOP_REPEAT}" title="{'Not repeat the slideshow'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-repeat-stop"> </span><span class="pwg-button-text">{'Not repeat the slideshow'|@translate}</span> + <span class="pwg-icon pwg-icon-repeat-stop"></span><span class="pwg-button-text">{'Not repeat the slideshow'|@translate}</span> </a> {/if} {*<!--{strip}{if isset($first)} @@ -41,35 +41,35 @@ {/if}{/strip}-->*} {strip}{if isset($U_UP) and !isset($slideshow)} <a href="{$U_UP}" title="{'Thumbnails'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-arrow-n"> </span><span class="pwg-button-text">{'Thumbnails'|@translate}</span> + <span class="pwg-icon pwg-icon-arrow-n"></span><span class="pwg-button-text">{'Thumbnails'|@translate}</span> </a> {/if}{/strip} {strip}{if isset($previous)} - <a href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE|@escape}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-arrow-w"> </span><span class="pwg-button-text">{'Previous'|@translate}</span> + <a href="{$previous.U_IMG}" title="{'Previous'|@translate} : {$previous.TITLE_ESC}" class="pwg-state-default pwg-button"> + <span class="pwg-icon pwg-icon-arrow-w"></span><span class="pwg-button-text">{'Previous'|@translate}</span> </a> {else} <span class="pwg-state-disabled pwg-button"> - <span class="pwg-icon pwg-icon-arrow-w"> </span><span class="pwg-button-text">{'Previous'|@translate}</span> + <span class="pwg-icon pwg-icon-arrow-w"></span><span class="pwg-button-text">{'Previous'|@translate}</span> </span> {/if}{/strip} {if isset($slideshow.U_START_PLAY)} <a href="{$slideshow.U_START_PLAY}" title="{'Play of slideshow'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-play"> </span><span class="pwg-button-text">{'Play of slideshow'|@translate}</span> + <span class="pwg-icon pwg-icon-play"></span><span class="pwg-button-text">{'Play of slideshow'|@translate}</span> </a> {/if} {if isset($slideshow.U_STOP_PLAY)} <a href="{$slideshow.U_STOP_PLAY}" title="{'Pause of slideshow'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-pause"> </span><span class="pwg-button-text">{'Pause of slideshow'|@translate}</span> + <span class="pwg-icon pwg-icon-pause"></span><span class="pwg-button-text">{'Pause of slideshow'|@translate}</span> </a> {/if} {strip}{if isset($next)} - <a href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE|@escape}" class="pwg-state-default pwg-button pwg-button-icon-right"> - <span class="pwg-icon pwg-icon-arrow-e"> </span><span class="pwg-button-text">{'Next'|@translate}</span> + <a href="{$next.U_IMG}" title="{'Next'|@translate} : {$next.TITLE_ESC}" class="pwg-state-default pwg-button pwg-button-icon-right"> + <span class="pwg-icon pwg-icon-arrow-e"></span><span class="pwg-button-text">{'Next'|@translate}</span> </a> {else} <span class="pwg-state-disabled pwg-button pwg-button-icon-right"> - <span class="pwg-icon pwg-icon-arrow-e"> </span><span class="pwg-button-text">{'Next'|@translate}</span> + <span class="pwg-icon pwg-icon-arrow-e"></span><span class="pwg-button-text">{'Next'|@translate}</span> </span> {/if}{/strip} {*<!--{strip}{if isset($last)} diff --git a/themes/default/template/profile_content.tpl b/themes/default/template/profile_content.tpl index 3f2245523..0c4f26c10 100644 --- a/themes/default/template/profile_content.tpl +++ b/themes/default/template/profile_content.tpl @@ -50,7 +50,7 @@ </li> <li> <span class="property"> - <label for="template">{'Interface theme'|@translate}</label> + <label for="template">{'Theme'|@translate}</label> </span> {html_options name=theme options=$template_options selected=$template_selection} </li> diff --git a/themes/default/template/redirect.tpl b/themes/default/template/redirect.tpl index aa90953ec..bfab38386 100644 --- a/themes/default/template/redirect.tpl +++ b/themes/default/template/redirect.tpl @@ -1,12 +1,8 @@ -{html_head} -<style type="text/css">#the_page {ldelim}text-align:center;} </style> -{/html_head} - -<div> +<div style="margin:2em;text-align:center;font-size:larger"> {$REDIRECT_MSG} </div> -<p style="margin: 2em"> +<p style="margin:2em;text-align:center"> <a href="{$page_refresh.U_REFRESH}"> {'Click here if your browser does not automatically forward you'|@translate} </a> diff --git a/themes/default/template/search.tpl b/themes/default/template/search.tpl index c27b33202..4db60eb96 100644 --- a/themes/default/template/search.tpl +++ b/themes/default/template/search.tpl @@ -21,7 +21,7 @@ <ul class="categoryActions"> {combine_script id='core.scripts' load='async' path='themes/default/js/scripts.js'} <li><a href="{$U_HELP}" onclick="popuphelp(this.href); return false;" title="{'Help'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-help"> </span><span class="pwg-button-text">{'Help'|@translate}</span> + <span class="pwg-icon pwg-icon-help"></span><span class="pwg-button-text">{'Help'|@translate}</span> </a></li> </ul> <h2><a href="{$U_HOME}">{'Home'|@translate}</a>{$LEVEL_SEPARATOR}{'Search'|@translate}</h2> @@ -33,7 +33,7 @@ <fieldset> <legend>{'Filter'|@translate}</legend> <label>{'Search for words'|@translate} - <input type="text" style="width: 300px" name="search_allwords" size="30"> + <input type="text" name="search_allwords" size="35"> </label> <ul> <li><label> @@ -44,7 +44,7 @@ </label></li> </ul> <label>{'Search for Author'|@translate} - <input type="text" style="width: 300px" name="search_author" size="30"> + <input type="text" name="search_author" size="35"> </label> </fieldset> @@ -111,7 +111,7 @@ <fieldset> <legend>{'Search in albums'|@translate}</legend> <label>{'Albums'|@translate} - <select class="categoryList" name="cat[]" multiple="multiple" > + <select class="categoryList" name="cat[]" multiple="multiple" size="15"> {html_options options=$category_options selected=$category_options_selected} </select> </label> diff --git a/themes/default/template/tags.tpl b/themes/default/template/tags.tpl index c4327289a..b4f54b24d 100644 --- a/themes/default/template/tags.tpl +++ b/themes/default/template/tags.tpl @@ -5,12 +5,12 @@ <ul class="categoryActions"> {if $display_mode == 'letters'} <li><a href="{$U_CLOUD}" title="{'show tag cloud'|@translate}" class="pwg-state-default pwg-button"> - <span class="pwg-icon pwg-icon-cloud"> </span><span class="pwg-button-text">{'cloud'|@translate}</span> + <span class="pwg-icon pwg-icon-cloud"></span><span class="pwg-button-text">{'cloud'|@translate}</span> </a></li> {/if} {if $display_mode == 'cloud'} <li><a href="{$U_LETTERS}" title="{'group by letters'|@translate}" class="pwg-state-default pwg-button" rel="nofollow"> - <span class="pwg-icon pwg-icon-letters"> </span><span class="pwg-button-text">{'letters'|@translate}</span> + <span class="pwg-icon pwg-icon-letters"></span><span class="pwg-button-text">{'letters'|@translate}</span> </a></li> {/if} </ul> @@ -23,7 +23,7 @@ {if $display_mode == 'cloud' and isset($tags)} <div id="fullTagCloud"> {foreach from=$tags item=tag} - <span><a href="{$tag.URL}" class="tagLevel{$tag.level}" title="{$pwg->l10n_dec('%d photo', '%d photos', $tag.counter)}">{$tag.name}</a></span> + <span><a href="{$tag.URL}" class="tagLevel{$tag.level}" title="{$tag.counter|@translate_dec:'%d photo':'%d photos'}">{$tag.name}</a></span> {/foreach} </div> {/if} @@ -39,7 +39,7 @@ {foreach from=$letter.tags item=tag} <tr class="tagLine"> <td><a href="{$tag.URL}" title="{$tag.name}">{$tag.name}</a></td> - <td class="nbEntries">{$pwg->l10n_dec('%d photo', '%d photos', $tag.counter)}</td> + <td class="nbEntries">{$tag.counter|@translate_dec:'%d photo':'%d photos'}</td> </tr> {/foreach} </table> diff --git a/themes/default/theme.css b/themes/default/theme.css index 25444db30..a5f8e49ad 100644 --- a/themes/default/theme.css +++ b/themes/default/theme.css @@ -136,22 +136,19 @@ /* begin chronology/calendar elements*/ .calendarViews { - display: block; float: right; margin: 5px 5px 0 0; } -.calItem, .calItemEmpty { +.calItem { font-weight: bold; margin: 0 1px; + padding: 0 1px; border: 1px solid gray; } -.calItem A { border:0 } - .calendarCalBar { margin: 10px; - text-align: left; } .calCalHead { @@ -176,18 +173,6 @@ TD.calDayCellFull, TD.calDayCellEmpty { border: 1px solid gray; } -.calImg { - overflow: hidden; - vertical-align: bottom; - z-index: 1; - position: relative; /*<- this required by IE*/ -} - -.calImg IMG { - position: relative; - border: 0; -} - .calBackDate { padding-left: 4px; padding-top: 0; @@ -378,10 +363,6 @@ TD.calDayCellFull, TD.calDayCellEmpty { margin-bottom:5px; } -.relSwitchBox { - position: relative; -} - #theImage { text-align: center; } @@ -399,6 +380,16 @@ TD.calDayCellFull, TD.calDayCellEmpty { #linkNext { float: right; margin: 5px 5px 0 10px; + text-align: right; +} + + +DIV.thumbHover{ /*only first & last holders are divs*/ + width: 108px; + height: 118px; + border: 1px solid gray; + padding: 0 5px; + line-height: 1.2; } .imageInfoTable UL { /*this is the album list*/ @@ -574,14 +565,12 @@ FIELDSET { } .tagSelection { - width: 99%; - margin: 1em 0; - padding: 0; + margin: 1em 0 !important; } .tagSelection LI { display:inline-block; - width:150px!important; + width: 150px; overflow:hidden; white-space: nowrap; } @@ -590,7 +579,7 @@ FIELDSET { font-size: 120%; text-align: justify; padding: 0; - margin: 1em 2em; + margin: 1em; } #fullTagCloud SPAN { @@ -662,7 +651,7 @@ IMG.ui-datepicker-trigger { */ /* So that non-links are slightly greyed out */ -.content .navigationBar, .calItemEmpty, TD.calDayCellEmpty { +.content .navigationBar, SPAN.calItem, TD.calDayCellEmpty { color: #b0b0b0; } @@ -753,10 +742,6 @@ LEGEND { border-radius: 3px; } -#lostPassword { - padding: 1em; -} - #lostPassword p { text-align: left; margin: 1.5em 0; |