From 692233ef766ed54e321e2b99fcd8d0b345e1762b Mon Sep 17 00:00:00 2001
From: David Regla
Date: Sun, 18 Dec 2011 14:38:38 -0600
Subject: [PATCH 01/17] fixed variable name
---
model/list/local/local.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/model/list/local/local.js b/model/list/local/local.js
index 568a63cb..eb9bfb0f 100644
--- a/model/list/local/local.js
+++ b/model/list/local/local.js
@@ -26,7 +26,7 @@ $.Model.List("jQuery.Model.List.Local",
// go through and listen to instance updating
var ids = [], days = this.days;
this.each(function(i, inst){
- window.localStorage[inst.identity()] = instance.attrs();
+ window.localStorage[inst.identity()] = inst.attrs();
ids.push(inst.identity());
});
window.localStorage[name] = {
From 8a7ffcb6354d8230de9a3e38aaf3462499766406 Mon Sep 17 00:00:00 2001
From: David Regla
Date: Mon, 30 Jan 2012 15:28:16 -0600
Subject: [PATCH 02/17] merge
---
dom/route/route.js | 471 ---------------------------------------------
1 file changed, 471 deletions(-)
delete mode 100644 dom/route/route.js
diff --git a/dom/route/route.js b/dom/route/route.js
deleted file mode 100644
index 4159adec..00000000
--- a/dom/route/route.js
+++ /dev/null
@@ -1,471 +0,0 @@
-steal('jquery/lang/observe', 'jquery/event/hashchange', 'jquery/lang/string/deparam',
-function( $ ) {
-
- // Helper methods used for matching routes.
- var
- // RegEx used to match route variables of the type ':name'.
- // Any word character or a period is matched.
- matcher = /\:([\w\.]+)/g,
- // Regular expression for identifying &key=value lists.
- paramsMatcher = /^(?:&[^=]+=[^&]*)+/,
- // Converts a JS Object into a list of parameters that can be
- // inserted into an html element tag.
- makeProps = function( props ) {
- var html = [],
- name, val;
- each(props, function(name, val){
- if ( name === 'className' ) {
- name = 'class'
- }
- val && html.push(escapeHTML(name), "=\"", escapeHTML(val), "\" ");
- })
- return html.join("")
- },
- // Escapes ' and " for safe insertion into html tag parameters.
- escapeHTML = function( content ) {
- return content.replace(/"/g, '"').replace(/'/g, "'");
- },
- // Checks if a route matches the data provided. If any route variable
- // is not present in the data the route does not match. If all route
- // variables are present in the data the number of matches is returned
- // to allow discerning between general and more specific routes.
- matchesData = function(route, data) {
- var count = 0;
- for ( var i = 0; i < route.names.length; i++ ) {
- if (!data.hasOwnProperty(route.names[i]) ) {
- return -1;
- }
- count++;
- }
- return count;
- },
- //
- onready = true,
- location = window.location,
- encode = encodeURIComponent,
- decode = decodeURIComponent,
- each = $.each,
- extend = $.extend;
-
- /**
- * @class jQuery.route
- * @inherits jQuery.Observe
- * @plugin jquery/dom/route
- * @parent dom
- * @tag 3.2
- *
- * jQuery.route helps manage browser history (and
- * client state) by
- * synchronizing the window.location.hash with
- * an [jQuery.Observe].
- *
- * ## Background Information
- *
- * To support the browser's back button and bookmarking
- * in an Ajax application, most applications use
- * the window.location.hash. By
- * changing the hash (via a link or JavaScript),
- * one is able to add to the browser's history
- * without changing the page. The [jQuery.event.special.hashchange event] allows
- * you to listen to when the hash is changed.
- *
- * Combined, this provides the basics needed to
- * create history enabled Ajax websites. However,
- * jQuery.Route addresses several other needs such as:
- *
- * - Pretty Routes
- * - Keeping routes independent of application code
- * - Listening to specific parts of the history changing
- * - Setup / Teardown of widgets.
- *
- * ## How it works
- *
- * $.route is a [jQuery.Observe $.Observe] that represents the
- * window.location.hash as an
- * object. For example, if the hash looks like:
- *
- * #!type=videos&id=5
- *
- * the data in $.route would look like:
- *
- * { type: 'videos', id: 5 }
- *
- *
- * $.route keeps the state of the hash in-sync with the data in
- * $.route.
- *
- * ## $.Observe
- *
- * $.route is a [jQuery.Observe $.Observe]. Understanding
- * $.Observe is essential for using $.route correctly.
- *
- * You can
- * listen to changes in an Observe with bind and
- * delegate and change $.route's properties with
- * attr and attrs.
- *
- * ### Listening to changes in an Observable
- *
- * Listen to changes in history
- * by [jQuery.Observe.prototype.bind bind]ing to
- * changes in $.route like:
- *
- * $.route.bind('change', function(ev, attr, how, newVal, oldVal) {
- *
- * })
- *
- * - attr - the name of the changed attribute
- * - how - the type of Observe change event (add, set or remove)
- * - newVal/oldVal - the new and old values of the attribute
- *
- * You can also listen to specific changes
- * with [jQuery.Observe.prototype.delegate delegate]:
- *
- * $.route.delegate('id','change', function(){ ... })
- *
- * Observe lets you listen to the following events:
- *
- * - change - any change to the object
- * - add - a property is added
- * - set - a property value is added or changed
- * - remove - a property is removed
- *
- * Listening for add is useful for widget setup
- * behavior, remove is useful for teardown.
- *
- * ### Updating an observable
- *
- * Create changes in the route data like:
- *
- * $.route.attr('type','images');
- *
- * Or change multiple properties at once with
- * [jQuery.Observe.prototype.attrs attrs]:
- *
- * $.route.attr({type: 'pages', id: 5}, true)
- *
- * When you make changes to $.route, they will automatically
- * change the hash.
- *
- * ## Creating a Route
- *
- * Use $.route(url, defaults) to create a
- * route. A route is a mapping from a url to
- * an object (that is the $.route's state).
- *
- * If no routes are added, or no route is matched,
- * $.route's data is updated with the [jQuery.String.deparam deparamed]
- * hash.
- *
- * location.hash = "#!type=videos";
- * // $.route -> {type : "videos"}
- *
- * Once routes are added and the hash changes,
- * $.route looks for matching routes and uses them
- * to update $.route's data.
- *
- * $.route( "content/:type" );
- * location.hash = "#!content/images";
- * // $.route -> {type : "images"}
- *
- * Default values can also be added:
- *
- * $.route("content/:type",{type: "videos" });
- * location.hash = "#!content/"
- * // $.route -> {type : "videos"}
- *
- * ## Delay setting $.route
- *
- * By default, $.route sets its initial data
- * on document ready. Sometimes, you want to wait to set
- * this data. To wait, call:
- *
- * $.route.ready(false);
- *
- * and when ready, call:
- *
- * $.route.ready(true);
- *
- * ## Changing the route.
- *
- * Typically, you never want to set location.hash
- * directly. Instead, you can change properties on $.route
- * like:
- *
- * $.route.attr('type', 'videos')
- *
- * This will automatically look up the appropriate
- * route and update the hash.
- *
- * Often, you want to create links. $.route provides
- * the [jQuery.route.link] and [jQuery.route.url] helpers to make this
- * easy:
- *
- * $.route.link("Videos", {type: 'videos'})
- *
- * @param {String} url the fragment identifier to match.
- * @param {Object} [defaults] an object of default values
- * @return {jQuery.route}
- */
- $.route = function( url, defaults ) {
- // Extract the variable names and replace with regEx that will match an atual URL with values.
- var names = [],
- test = url.replace(matcher, function( whole, name ) {
- names.push(name)
- // TODO: I think this should have a +
- return "([^\\/\\&]*)" // The '\\' is for string-escaping giving single '\' for regEx escaping
- });
-
- // Add route in a form that can be easily figured out
- $.route.routes[url] = {
- // A regular expression that will match the route when variable values
- // are present; i.e. for :page/:type the regEx is /([\w\.]*)/([\w\.]*)/ which
- // will match for any value of :page and :type (word chars or period).
- test: new RegExp("^" + test+"($|&)"),
- // The original URL, same as the index for this entry in routes.
- route: url,
- // An array of all the variable names in this route
- names: names,
- // Default values provided for the variables.
- defaults: defaults || {},
- // The number of parts in the URL separated by '/'.
- length: url.split('/').length
- }
- return $.route;
- };
-
- extend($.route, {
- /**
- * Parameterizes the raw JS object representation provided in data.
- * If a route matching the provided data is found that URL is built
- * from the data. Any remaining data is added at the end of the
- * URL as & separated key/value parameters.
- *
- * @param {Object} data
- * @return {String} The route URL and & separated parameters.
- */
- param: function( data ) {
- // Check if the provided data keys match the names in any routes;
- // get the one with the most matches.
- var route,
- // need it to be at least 1 match
- matches = 0,
- matchCount,
- routeName = data.route;
-
- delete data.route;
- // if we have a route name in our $.route data, use it
- if(routeName && (route = $.route.routes[routeName])){
-
- } else {
- // otherwise find route
- each($.route.routes, function(name, temp){
- matchCount = matchesData(temp, data);
- if ( matchCount > matches ) {
- route = temp;
- matches = matchCount
- }
- });
- }
- // if this is match
-
- if ( route ) {
- var cpy = extend({}, data),
- // Create the url by replacing the var names with the provided data.
- // If the default value is found an empty string is inserted.
- res = route.route.replace(matcher, function( whole, name ) {
- delete cpy[name];
- return data[name] === route.defaults[name] ? "" : encode( data[name] );
- }),
- after;
- // remove matching default values
- each(route.defaults, function(name,val){
- if(cpy[name] === val) {
- delete cpy[name]
- }
- })
-
- // The remaining elements of data are added as
- // $amp; separated parameters to the url.
- after = $.param(cpy);
- return res + (after ? "&" + after : "")
- }
- // If no route was found there is no hash URL, only paramters.
- return $.isEmptyObject(data) ? "" : "&" + $.param(data);
- },
- /**
- * Populate the JS data object from a given URL.
- *
- * @param {Object} url
- */
- deparam: function( url ) {
- // See if the url matches any routes by testing it against the route.test regEx.
- // By comparing the URL length the most specialized route that matches is used.
- var route = {
- length: -1
- };
- each($.route.routes, function(name, temp){
- if ( temp.test.test(url) && temp.length > route.length ) {
- route = temp;
- }
- });
- // If a route was matched
- if ( route.length > -1 ) {
- var // Since RegEx backreferences are used in route.test (round brackets)
- // the parts will contain the full matched string and each variable (backreferenced) value.
- parts = url.match(route.test),
- // start will contain the full matched string; parts contain the variable values.
- start = parts.shift(),
- // The remainder will be the &key=value list at the end of the URL.
- remainder = url.substr(start.length - (parts[parts.length-1] === "&" ? 1 : 0) ),
- // If there is a remainder and it contains a &key=value list deparam it.
- obj = (remainder && paramsMatcher.test(remainder)) ? $.String.deparam( remainder.slice(1) ) : {};
-
- // Add the default values for this route
- obj = extend(true, {}, route.defaults, obj);
- // Overwrite each of the default values in obj with those in parts if that part is not empty.
- each(parts,function(i, part){
- if ( part && part !== '&') {
- obj[route.names[i]] = decode( part );
- }
- });
- obj.route = route.route;
- return obj;
- }
- // If no route was matched it is parsed as a &key=value list.
- if ( url.charAt(0) !== '&' ) {
- url = '&' + url;
- }
- return paramsMatcher.test(url) ? $.String.deparam( url.slice(1) ) : {};
- },
- /**
- * @hide
- * A $.Observe that represents the state of the history.
- */
- data: new $.Observe({}),
- /**
- * @attribute
- * @type Object
- * @hide
- *
- * A list of routes recognized by the router indixed by the url used to add it.
- * Each route is an object with these members:
- *
- * - test - A regular expression that will match the route when variable values
- * are present; i.e. for :page/:type the regEx is /([\w\.]*)/([\w\.]*)/ which
- * will match for any value of :page and :type (word chars or period).
- *
- * - route - The original URL, same as the index for this entry in routes.
- *
- * - names - An array of all the variable names in this route
- *
- * - defaults - Default values provided for the variables or an empty object.
- *
- * - length - The number of parts in the URL separated by '/'.
- */
- routes: {},
- /**
- * Indicates that all routes have been added and sets $.route.data
- * based upon the routes and the current hash.
- *
- * By default, ready is fired on jQuery's ready event. Sometimes
- * you might want it to happen sooner or earlier. To do this call
- *
- * $.route.ready(false); //prevents firing by the ready event
- * $.route.ready(true); // fire the first route change
- *
- * @param {Boolean} [start]
- * @return $.route
- */
- ready: function(val) {
- if( val === false ) {
- onready = false;
- }
- if( val === true || onready === true ) {
- setState();
- }
- return $.route;
- },
- /**
- * Returns a url from the options
- * @param {Object} options
- * @param {Boolean} merge true if the options should be merged with the current options
- * @return {String}
- */
- url: function( options, merge ) {
- if (merge) {
- return "#!" + $.route.param(extend({}, curParams, options))
- } else {
- return "#!" + $.route.param(options)
- }
- },
- /**
- * Returns a link
- * @param {Object} name The text of the link.
- * @param {Object} options The route options (variables)
- * @param {Object} props Properties of the <a> other than href.
- * @param {Boolean} merge true if the options should be merged with the current options
- */
- link: function( name, options, props, merge ) {
- return "" + name + "";
- },
- /**
- * Returns true if the options represent the current page.
- * @param {Object} options
- * @return {Boolean}
- */
- current: function( options ) {
- return location.hash == "#!" + $.route.param(options)
- }
- });
- // onready
- $(function() {
- $.route.ready();
- });
-
- // The functions in the following list applied to $.route (e.g. $.route.attr('...')) will
- // instead act on the $.route.data Observe.
- each(['bind','unbind','delegate','undelegate','attr','attrs','serialize','removeAttr'], function(i, name){
- $.route[name] = function(){
- return $.route.data[name].apply($.route.data, arguments)
- }
- })
-
- var // A throttled function called multiple times will only fire once the
- // timer runs down. Each call resets the timer.
- throttle = function( func ) {
- var timer;
- return function() {
- var args = arguments,
- self = this;
- clearTimeout(timer);
- timer = setTimeout(function(){
- func.apply(self, args)
- }, 1);
- }
- },
- // Intermediate storage for $.route.data.
- curParams,
- // Deparameterizes the portion of the hash of interest and assign the
- // values to the $.route.data removing existing values no longer in the hash.
- setState = function() {
- var hash = location.hash.substr(1, 1) === '!' ?
- location.hash.slice(2) :
- location.hash.slice(1); // everything after #!
- curParams = $.route.deparam( hash );
- $.route.attrs(curParams, true);
- };
-
- // If the hash changes, update the $.route.data
- $(window).bind('hashchange', setState);
-
- // If the $.route.data changes, update the hash.
- // Using .serialize() retrieves the raw data contained in the observable.
- // This function is throttled so it only updates once even if multiple values changed.
- $.route.bind("change", throttle(function() {
- location.hash = "#!" + $.route.param($.route.serialize())
- }));
-})
\ No newline at end of file
From df1bcabbdfc80f5caa571a058e5e0a05b74c734e Mon Sep 17 00:00:00 2001
From: David Regla
Date: Mon, 30 Jan 2012 15:35:19 -0600
Subject: [PATCH 03/17] merge
---
dom/route/route.js | 471 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 471 insertions(+)
create mode 100644 dom/route/route.js
diff --git a/dom/route/route.js b/dom/route/route.js
new file mode 100644
index 00000000..4159adec
--- /dev/null
+++ b/dom/route/route.js
@@ -0,0 +1,471 @@
+steal('jquery/lang/observe', 'jquery/event/hashchange', 'jquery/lang/string/deparam',
+function( $ ) {
+
+ // Helper methods used for matching routes.
+ var
+ // RegEx used to match route variables of the type ':name'.
+ // Any word character or a period is matched.
+ matcher = /\:([\w\.]+)/g,
+ // Regular expression for identifying &key=value lists.
+ paramsMatcher = /^(?:&[^=]+=[^&]*)+/,
+ // Converts a JS Object into a list of parameters that can be
+ // inserted into an html element tag.
+ makeProps = function( props ) {
+ var html = [],
+ name, val;
+ each(props, function(name, val){
+ if ( name === 'className' ) {
+ name = 'class'
+ }
+ val && html.push(escapeHTML(name), "=\"", escapeHTML(val), "\" ");
+ })
+ return html.join("")
+ },
+ // Escapes ' and " for safe insertion into html tag parameters.
+ escapeHTML = function( content ) {
+ return content.replace(/"/g, '"').replace(/'/g, "'");
+ },
+ // Checks if a route matches the data provided. If any route variable
+ // is not present in the data the route does not match. If all route
+ // variables are present in the data the number of matches is returned
+ // to allow discerning between general and more specific routes.
+ matchesData = function(route, data) {
+ var count = 0;
+ for ( var i = 0; i < route.names.length; i++ ) {
+ if (!data.hasOwnProperty(route.names[i]) ) {
+ return -1;
+ }
+ count++;
+ }
+ return count;
+ },
+ //
+ onready = true,
+ location = window.location,
+ encode = encodeURIComponent,
+ decode = decodeURIComponent,
+ each = $.each,
+ extend = $.extend;
+
+ /**
+ * @class jQuery.route
+ * @inherits jQuery.Observe
+ * @plugin jquery/dom/route
+ * @parent dom
+ * @tag 3.2
+ *
+ * jQuery.route helps manage browser history (and
+ * client state) by
+ * synchronizing the window.location.hash with
+ * an [jQuery.Observe].
+ *
+ * ## Background Information
+ *
+ * To support the browser's back button and bookmarking
+ * in an Ajax application, most applications use
+ * the window.location.hash. By
+ * changing the hash (via a link or JavaScript),
+ * one is able to add to the browser's history
+ * without changing the page. The [jQuery.event.special.hashchange event] allows
+ * you to listen to when the hash is changed.
+ *
+ * Combined, this provides the basics needed to
+ * create history enabled Ajax websites. However,
+ * jQuery.Route addresses several other needs such as:
+ *
+ * - Pretty Routes
+ * - Keeping routes independent of application code
+ * - Listening to specific parts of the history changing
+ * - Setup / Teardown of widgets.
+ *
+ * ## How it works
+ *
+ * $.route is a [jQuery.Observe $.Observe] that represents the
+ * window.location.hash as an
+ * object. For example, if the hash looks like:
+ *
+ * #!type=videos&id=5
+ *
+ * the data in $.route would look like:
+ *
+ * { type: 'videos', id: 5 }
+ *
+ *
+ * $.route keeps the state of the hash in-sync with the data in
+ * $.route.
+ *
+ * ## $.Observe
+ *
+ * $.route is a [jQuery.Observe $.Observe]. Understanding
+ * $.Observe is essential for using $.route correctly.
+ *
+ * You can
+ * listen to changes in an Observe with bind and
+ * delegate and change $.route's properties with
+ * attr and attrs.
+ *
+ * ### Listening to changes in an Observable
+ *
+ * Listen to changes in history
+ * by [jQuery.Observe.prototype.bind bind]ing to
+ * changes in $.route like:
+ *
+ * $.route.bind('change', function(ev, attr, how, newVal, oldVal) {
+ *
+ * })
+ *
+ * - attr - the name of the changed attribute
+ * - how - the type of Observe change event (add, set or remove)
+ * - newVal/oldVal - the new and old values of the attribute
+ *
+ * You can also listen to specific changes
+ * with [jQuery.Observe.prototype.delegate delegate]:
+ *
+ * $.route.delegate('id','change', function(){ ... })
+ *
+ * Observe lets you listen to the following events:
+ *
+ * - change - any change to the object
+ * - add - a property is added
+ * - set - a property value is added or changed
+ * - remove - a property is removed
+ *
+ * Listening for add is useful for widget setup
+ * behavior, remove is useful for teardown.
+ *
+ * ### Updating an observable
+ *
+ * Create changes in the route data like:
+ *
+ * $.route.attr('type','images');
+ *
+ * Or change multiple properties at once with
+ * [jQuery.Observe.prototype.attrs attrs]:
+ *
+ * $.route.attr({type: 'pages', id: 5}, true)
+ *
+ * When you make changes to $.route, they will automatically
+ * change the hash.
+ *
+ * ## Creating a Route
+ *
+ * Use $.route(url, defaults) to create a
+ * route. A route is a mapping from a url to
+ * an object (that is the $.route's state).
+ *
+ * If no routes are added, or no route is matched,
+ * $.route's data is updated with the [jQuery.String.deparam deparamed]
+ * hash.
+ *
+ * location.hash = "#!type=videos";
+ * // $.route -> {type : "videos"}
+ *
+ * Once routes are added and the hash changes,
+ * $.route looks for matching routes and uses them
+ * to update $.route's data.
+ *
+ * $.route( "content/:type" );
+ * location.hash = "#!content/images";
+ * // $.route -> {type : "images"}
+ *
+ * Default values can also be added:
+ *
+ * $.route("content/:type",{type: "videos" });
+ * location.hash = "#!content/"
+ * // $.route -> {type : "videos"}
+ *
+ * ## Delay setting $.route
+ *
+ * By default, $.route sets its initial data
+ * on document ready. Sometimes, you want to wait to set
+ * this data. To wait, call:
+ *
+ * $.route.ready(false);
+ *
+ * and when ready, call:
+ *
+ * $.route.ready(true);
+ *
+ * ## Changing the route.
+ *
+ * Typically, you never want to set location.hash
+ * directly. Instead, you can change properties on $.route
+ * like:
+ *
+ * $.route.attr('type', 'videos')
+ *
+ * This will automatically look up the appropriate
+ * route and update the hash.
+ *
+ * Often, you want to create links. $.route provides
+ * the [jQuery.route.link] and [jQuery.route.url] helpers to make this
+ * easy:
+ *
+ * $.route.link("Videos", {type: 'videos'})
+ *
+ * @param {String} url the fragment identifier to match.
+ * @param {Object} [defaults] an object of default values
+ * @return {jQuery.route}
+ */
+ $.route = function( url, defaults ) {
+ // Extract the variable names and replace with regEx that will match an atual URL with values.
+ var names = [],
+ test = url.replace(matcher, function( whole, name ) {
+ names.push(name)
+ // TODO: I think this should have a +
+ return "([^\\/\\&]*)" // The '\\' is for string-escaping giving single '\' for regEx escaping
+ });
+
+ // Add route in a form that can be easily figured out
+ $.route.routes[url] = {
+ // A regular expression that will match the route when variable values
+ // are present; i.e. for :page/:type the regEx is /([\w\.]*)/([\w\.]*)/ which
+ // will match for any value of :page and :type (word chars or period).
+ test: new RegExp("^" + test+"($|&)"),
+ // The original URL, same as the index for this entry in routes.
+ route: url,
+ // An array of all the variable names in this route
+ names: names,
+ // Default values provided for the variables.
+ defaults: defaults || {},
+ // The number of parts in the URL separated by '/'.
+ length: url.split('/').length
+ }
+ return $.route;
+ };
+
+ extend($.route, {
+ /**
+ * Parameterizes the raw JS object representation provided in data.
+ * If a route matching the provided data is found that URL is built
+ * from the data. Any remaining data is added at the end of the
+ * URL as & separated key/value parameters.
+ *
+ * @param {Object} data
+ * @return {String} The route URL and & separated parameters.
+ */
+ param: function( data ) {
+ // Check if the provided data keys match the names in any routes;
+ // get the one with the most matches.
+ var route,
+ // need it to be at least 1 match
+ matches = 0,
+ matchCount,
+ routeName = data.route;
+
+ delete data.route;
+ // if we have a route name in our $.route data, use it
+ if(routeName && (route = $.route.routes[routeName])){
+
+ } else {
+ // otherwise find route
+ each($.route.routes, function(name, temp){
+ matchCount = matchesData(temp, data);
+ if ( matchCount > matches ) {
+ route = temp;
+ matches = matchCount
+ }
+ });
+ }
+ // if this is match
+
+ if ( route ) {
+ var cpy = extend({}, data),
+ // Create the url by replacing the var names with the provided data.
+ // If the default value is found an empty string is inserted.
+ res = route.route.replace(matcher, function( whole, name ) {
+ delete cpy[name];
+ return data[name] === route.defaults[name] ? "" : encode( data[name] );
+ }),
+ after;
+ // remove matching default values
+ each(route.defaults, function(name,val){
+ if(cpy[name] === val) {
+ delete cpy[name]
+ }
+ })
+
+ // The remaining elements of data are added as
+ // $amp; separated parameters to the url.
+ after = $.param(cpy);
+ return res + (after ? "&" + after : "")
+ }
+ // If no route was found there is no hash URL, only paramters.
+ return $.isEmptyObject(data) ? "" : "&" + $.param(data);
+ },
+ /**
+ * Populate the JS data object from a given URL.
+ *
+ * @param {Object} url
+ */
+ deparam: function( url ) {
+ // See if the url matches any routes by testing it against the route.test regEx.
+ // By comparing the URL length the most specialized route that matches is used.
+ var route = {
+ length: -1
+ };
+ each($.route.routes, function(name, temp){
+ if ( temp.test.test(url) && temp.length > route.length ) {
+ route = temp;
+ }
+ });
+ // If a route was matched
+ if ( route.length > -1 ) {
+ var // Since RegEx backreferences are used in route.test (round brackets)
+ // the parts will contain the full matched string and each variable (backreferenced) value.
+ parts = url.match(route.test),
+ // start will contain the full matched string; parts contain the variable values.
+ start = parts.shift(),
+ // The remainder will be the &key=value list at the end of the URL.
+ remainder = url.substr(start.length - (parts[parts.length-1] === "&" ? 1 : 0) ),
+ // If there is a remainder and it contains a &key=value list deparam it.
+ obj = (remainder && paramsMatcher.test(remainder)) ? $.String.deparam( remainder.slice(1) ) : {};
+
+ // Add the default values for this route
+ obj = extend(true, {}, route.defaults, obj);
+ // Overwrite each of the default values in obj with those in parts if that part is not empty.
+ each(parts,function(i, part){
+ if ( part && part !== '&') {
+ obj[route.names[i]] = decode( part );
+ }
+ });
+ obj.route = route.route;
+ return obj;
+ }
+ // If no route was matched it is parsed as a &key=value list.
+ if ( url.charAt(0) !== '&' ) {
+ url = '&' + url;
+ }
+ return paramsMatcher.test(url) ? $.String.deparam( url.slice(1) ) : {};
+ },
+ /**
+ * @hide
+ * A $.Observe that represents the state of the history.
+ */
+ data: new $.Observe({}),
+ /**
+ * @attribute
+ * @type Object
+ * @hide
+ *
+ * A list of routes recognized by the router indixed by the url used to add it.
+ * Each route is an object with these members:
+ *
+ * - test - A regular expression that will match the route when variable values
+ * are present; i.e. for :page/:type the regEx is /([\w\.]*)/([\w\.]*)/ which
+ * will match for any value of :page and :type (word chars or period).
+ *
+ * - route - The original URL, same as the index for this entry in routes.
+ *
+ * - names - An array of all the variable names in this route
+ *
+ * - defaults - Default values provided for the variables or an empty object.
+ *
+ * - length - The number of parts in the URL separated by '/'.
+ */
+ routes: {},
+ /**
+ * Indicates that all routes have been added and sets $.route.data
+ * based upon the routes and the current hash.
+ *
+ * By default, ready is fired on jQuery's ready event. Sometimes
+ * you might want it to happen sooner or earlier. To do this call
+ *
+ * $.route.ready(false); //prevents firing by the ready event
+ * $.route.ready(true); // fire the first route change
+ *
+ * @param {Boolean} [start]
+ * @return $.route
+ */
+ ready: function(val) {
+ if( val === false ) {
+ onready = false;
+ }
+ if( val === true || onready === true ) {
+ setState();
+ }
+ return $.route;
+ },
+ /**
+ * Returns a url from the options
+ * @param {Object} options
+ * @param {Boolean} merge true if the options should be merged with the current options
+ * @return {String}
+ */
+ url: function( options, merge ) {
+ if (merge) {
+ return "#!" + $.route.param(extend({}, curParams, options))
+ } else {
+ return "#!" + $.route.param(options)
+ }
+ },
+ /**
+ * Returns a link
+ * @param {Object} name The text of the link.
+ * @param {Object} options The route options (variables)
+ * @param {Object} props Properties of the <a> other than href.
+ * @param {Boolean} merge true if the options should be merged with the current options
+ */
+ link: function( name, options, props, merge ) {
+ return "" + name + "";
+ },
+ /**
+ * Returns true if the options represent the current page.
+ * @param {Object} options
+ * @return {Boolean}
+ */
+ current: function( options ) {
+ return location.hash == "#!" + $.route.param(options)
+ }
+ });
+ // onready
+ $(function() {
+ $.route.ready();
+ });
+
+ // The functions in the following list applied to $.route (e.g. $.route.attr('...')) will
+ // instead act on the $.route.data Observe.
+ each(['bind','unbind','delegate','undelegate','attr','attrs','serialize','removeAttr'], function(i, name){
+ $.route[name] = function(){
+ return $.route.data[name].apply($.route.data, arguments)
+ }
+ })
+
+ var // A throttled function called multiple times will only fire once the
+ // timer runs down. Each call resets the timer.
+ throttle = function( func ) {
+ var timer;
+ return function() {
+ var args = arguments,
+ self = this;
+ clearTimeout(timer);
+ timer = setTimeout(function(){
+ func.apply(self, args)
+ }, 1);
+ }
+ },
+ // Intermediate storage for $.route.data.
+ curParams,
+ // Deparameterizes the portion of the hash of interest and assign the
+ // values to the $.route.data removing existing values no longer in the hash.
+ setState = function() {
+ var hash = location.hash.substr(1, 1) === '!' ?
+ location.hash.slice(2) :
+ location.hash.slice(1); // everything after #!
+ curParams = $.route.deparam( hash );
+ $.route.attrs(curParams, true);
+ };
+
+ // If the hash changes, update the $.route.data
+ $(window).bind('hashchange', setState);
+
+ // If the $.route.data changes, update the hash.
+ // Using .serialize() retrieves the raw data contained in the observable.
+ // This function is throttled so it only updates once even if multiple values changed.
+ $.route.bind("change", throttle(function() {
+ location.hash = "#!" + $.route.param($.route.serialize())
+ }));
+})
\ No newline at end of file
From 75004b1d5ed10aa804ff3c42524008481d92dd12 Mon Sep 17 00:00:00 2001
From: Austin McDaniel
Date: Tue, 20 Mar 2012 10:17:15 -0500
Subject: [PATCH 04/17] Added 'indexOf' method to model.list
---
model/list/list.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/model/list/list.js b/model/list/list.js
index 42ce9acf..6996b8db 100644
--- a/model/list/list.js
+++ b/model/list/list.js
@@ -760,6 +760,14 @@ steal('jquery/model').then(function( $ ) {
*
*/
splice: [].splice,
+ /**
+ * @function indexOf
+ * Finds the index of the item in the list. Returns -1 if not found.
+ *
+ * list.indexOf(item)
+ *
+ */
+ indexOf: [].indexOf,
/**
* @function sort
* Sorts the instances in the list.
From aa55f5cac81f6b8c563ff0183c54d16d8da8d3af Mon Sep 17 00:00:00 2001
From: Justin Meyer
Date: Wed, 11 Apr 2012 01:07:40 -0500
Subject: [PATCH 05/17] class, controller, observe all work right from can
---
class/class.html | 109 -
class/class.js | 778 +-
class/class_test.js | 8 +-
controller/controller.js | 1090 +--
controller/controller_test.js | 4 +-
dom/fixture/fixture.html | 144 -
dom/fixture/fixture.js | 903 ---
dom/fixture/fixture_test.js | 332 -
dom/fixture/fixtures/foo.json | 1 -
dom/fixture/fixtures/foobar.json | 3 -
dom/fixture/fixtures/messages.html | 31 -
dom/fixture/fixtures/remove.json | 3 -
dom/fixture/fixtures/test.json | 3 -
dom/fixture/qunit.html | 22 -
jquery.js | 9266 ------------------------
lang/observe/delegate/delegate.js | 313 +-
lang/observe/delegate/delegate_test.js | 6 +-
lang/observe/observe.js | 1021 +--
lang/observe/observe_test.js | 24 +-
model/model.js | 1720 +----
model/test/qunit/model_test.js | 23 +-
model/test/qunit/qunit.js | 2 +-
22 files changed, 62 insertions(+), 15744 deletions(-)
delete mode 100644 class/class.html
delete mode 100644 dom/fixture/fixture.html
delete mode 100644 dom/fixture/fixture.js
delete mode 100644 dom/fixture/fixture_test.js
delete mode 100644 dom/fixture/fixtures/foo.json
delete mode 100644 dom/fixture/fixtures/foobar.json
delete mode 100644 dom/fixture/fixtures/messages.html
delete mode 100644 dom/fixture/fixtures/remove.json
delete mode 100644 dom/fixture/fixtures/test.json
delete mode 100644 dom/fixture/qunit.html
delete mode 100644 jquery.js
diff --git a/class/class.html b/class/class.html
deleted file mode 100644
index ef16143d..00000000
--- a/class/class.html
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
- jQuery.Class Demo
-
-
-
-
jQuery.Class Demo shows a tabs controller extended to work with history.
-
-
-
-
-
\ No newline at end of file
diff --git a/class/class.js b/class/class.js
index 8df6f95d..38771b9b 100644
--- a/class/class.js
+++ b/class/class.js
@@ -3,783 +3,9 @@
// http://ejohn.org/blog/simple-javascript-inheritance/
// It provides class level inheritance and callbacks.
//!steal-clean
-steal("jquery","jquery/lang/string",function( $ ) {
+steal("can/construct/proxy","can/construct/super",function( $ ) {
- // =============== HELPERS =================
-
- // if we are initializing a new class
- var initializing = false,
- makeArray = $.makeArray,
- isFunction = $.isFunction,
- isArray = $.isArray,
- extend = $.extend,
- getObject = $.String.getObject,
- concatArgs = function(arr, args){
- return arr.concat(makeArray(args));
- },
-
- // tests if we can get super in .toString()
- fnTest = /xyz/.test(function() {
- xyz;
- }) ? /\b_super\b/ : /.*/,
-
- // overwrites an object with methods, sets up _super
- // newProps - new properties
- // oldProps - where the old properties might be
- // addTo - what we are adding to
- inheritProps = function( newProps, oldProps, addTo ) {
- addTo = addTo || newProps
- for ( var name in newProps ) {
- // Check if we're overwriting an existing function
- addTo[name] = isFunction(newProps[name]) &&
- isFunction(oldProps[name]) &&
- fnTest.test(newProps[name]) ? (function( name, fn ) {
- return function() {
- var tmp = this._super,
- ret;
-
- // Add a new ._super() method that is the same method
- // but on the super-class
- this._super = oldProps[name];
-
- // The method only need to be bound temporarily, so we
- // remove it when we're done executing
- ret = fn.apply(this, arguments);
- this._super = tmp;
- return ret;
- };
- })(name, newProps[name]) : newProps[name];
- }
- },
- STR_PROTOTYPE = 'prototype'
-
- /**
- * @class jQuery.Class
- * @plugin jquery/class
- * @parent jquerymx
- * @download dist/jquery/jquery.class.js
- * @test jquery/class/qunit.html
- * @description Easy inheritance in JavaScript.
- *
- * Class provides simulated inheritance in JavaScript. Use clss to bridge the gap between
- * jQuery's functional programming style and Object Oriented Programming. It
- * is based off John Resig's [http://ejohn.org/blog/simple-javascript-inheritance/|Simple Class]
- * Inheritance library. Besides prototypal inheritance, it includes a few important features:
- *
- * - Static inheritance
- * - Introspection
- * - Namespaces
- * - Setup and initialization methods
- * - Easy callback function creation
- *
- *
- * The [mvc.class Get Started with jQueryMX] has a good walkthrough of $.Class.
- *
- * ## Static v. Prototype
- *
- * Before learning about Class, it's important to
- * understand the difference between
- * a class's __static__ and __prototype__ properties.
- *
- * //STATIC
- * MyClass.staticProperty //shared property
- *
- * //PROTOTYPE
- * myclass = new MyClass()
- * myclass.prototypeMethod() //instance method
- *
- * A static (or class) property is on the Class constructor
- * function itself
- * and can be thought of being shared by all instances of the
- * Class. Prototype propertes are available only on instances of the Class.
- *
- * ## A Basic Class
- *
- * The following creates a Monster class with a
- * name (for introspection), static, and prototype members.
- * Every time a monster instance is created, the static
- * count is incremented.
- *
- * @codestart
- * $.Class('Monster',
- * /* @static *|
- * {
- * count: 0
- * },
- * /* @prototype *|
- * {
- * init: function( name ) {
- *
- * // saves name on the monster instance
- * this.name = name;
- *
- * // sets the health
- * this.health = 10;
- *
- * // increments count
- * this.constructor.count++;
- * },
- * eat: function( smallChildren ){
- * this.health += smallChildren;
- * },
- * fight: function() {
- * this.health -= 2;
- * }
- * });
- *
- * hydra = new Monster('hydra');
- *
- * dragon = new Monster('dragon');
- *
- * hydra.name // -> hydra
- * Monster.count // -> 2
- * Monster.shortName // -> 'Monster'
- *
- * hydra.eat(2); // health = 12
- *
- * dragon.fight(); // health = 8
- *
- * @codeend
- *
- *
- * Notice that the prototype init function is called when a new instance of Monster is created.
- *
- *
- * ## Inheritance
- *
- * When a class is extended, all static and prototype properties are available on the new class.
- * If you overwrite a function, you can call the base class's function by calling
- * this._super. Lets create a SeaMonster class. SeaMonsters are less
- * efficient at eating small children, but more powerful fighters.
- *
- *
- * Monster("SeaMonster",{
- * eat: function( smallChildren ) {
- * this._super(smallChildren / 2);
- * },
- * fight: function() {
- * this.health -= 1;
- * }
- * });
- *
- * lockNess = new SeaMonster('Lock Ness');
- * lockNess.eat(4); //health = 12
- * lockNess.fight(); //health = 11
- *
- * ### Static property inheritance
- *
- * You can also inherit static properties in the same way:
- *
- * $.Class("First",
- * {
- * staticMethod: function() { return 1;}
- * },{})
- *
- * First("Second",{
- * staticMethod: function() { return this._super()+1;}
- * },{})
- *
- * Second.staticMethod() // -> 2
- *
- * ## Namespaces
- *
- * Namespaces are a good idea! We encourage you to namespace all of your code.
- * It makes it possible to drop your code into another app without problems.
- * Making a namespaced class is easy:
- *
- *
- * $.Class("MyNamespace.MyClass",{},{});
- *
- * new MyNamespace.MyClass()
- *
- *
- *
Introspection
- *
- * Often, it's nice to create classes whose name helps determine functionality. Ruby on
- * Rails's [http://api.rubyonrails.org/classes/ActiveRecord/Base.html|ActiveRecord] ORM class
- * is a great example of this. Unfortunately, JavaScript doesn't have a way of determining
- * an object's name, so the developer must provide a name. Class fixes this by taking a String name for the class.
- *
- * $.Class("MyOrg.MyClass",{},{})
- * MyOrg.MyClass.shortName //-> 'MyClass'
- * MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
- *
- * The fullName (with namespaces) and the shortName (without namespaces) are added to the Class's
- * static properties.
- *
- *
- * ## Setup and initialization methods
- *
- *
- * Class provides static and prototype initialization functions.
- * These come in two flavors - setup and init.
- * Setup is called before init and
- * can be used to 'normalize' init's arguments.
- *
- *
PRO TIP: Typically, you don't need setup methods in your classes. Use Init instead.
- * Reserve setup methods for when you need to do complex pre-processing of your class before init is called.
- *
- *
- * @codestart
- * $.Class("MyClass",
- * {
- * setup: function() {} //static setup
- * init: function() {} //static constructor
- * },
- * {
- * setup: function() {} //prototype setup
- * init: function() {} //prototype constructor
- * })
- * @codeend
- *
- * ### Setup
- *
- * Setup functions are called before init functions. Static setup functions are passed
- * the base class followed by arguments passed to the extend function.
- * Prototype static functions are passed the Class constructor
- * function arguments.
- *
- * If a setup function returns an array, that array will be used as the arguments
- * for the following init method. This provides setup functions the ability to normalize
- * arguments passed to the init constructors. They are also excellent places
- * to put setup code you want to almost always run.
- *
- *
- * The following is similar to how [jQuery.Controller.prototype.setup]
- * makes sure init is always called with a jQuery element and merged options
- * even if it is passed a raw
- * HTMLElement and no second parameter.
- *
- * $.Class("jQuery.Controller",{
- * ...
- * },{
- * setup: function( el, options ) {
- * ...
- * return [$(el),
- * $.extend(true,
- * this.Class.defaults,
- * options || {} ) ]
- * }
- * })
- *
- * Typically, you won't need to make or overwrite setup functions.
- *
- * ### Init
- *
- * Init functions are called after setup functions.
- * Typically, they receive the same arguments
- * as their preceding setup function. The Foo class's init method
- * gets called in the following example:
- *
- * $.Class("Foo", {
- * init: function( arg1, arg2, arg3 ) {
- * this.sum = arg1+arg2+arg3;
- * }
- * })
- * var foo = new Foo(1,2,3);
- * foo.sum //-> 6
- *
- * ## Proxies
- *
- * Similar to jQuery's proxy method, Class provides a
- * [jQuery.Class.static.proxy proxy]
- * function that returns a callback to a method that will always
- * have
- * this set to the class or instance of the class.
- *
- *
- * The following example uses this.proxy to make sure
- * this.name is available in show.
- *
- * $.Class("Todo",{
- * init: function( name ) {
- * this.name = name
- * },
- * get: function() {
- * $.get("/stuff",this.proxy('show'))
- * },
- * show: function( txt ) {
- * alert(this.name+txt)
- * }
- * })
- * new Todo("Trash").get()
- *
- * Callback is available as a static and prototype method.
- *
- * ## Demo
- *
- * @demo jquery/class/class.html
- *
- *
- * @constructor
- *
- * To create a Class call:
- *
- * $.Class( [NAME , STATIC,] PROTOTYPE ) -> Class
- *
- *
- *
{optional:String}
- *
If provided, this sets the shortName and fullName of the
- * class and adds it and any necessary namespaces to the
- * window object.
- *
- *
{optional:Object}
- *
If provided, this creates static properties and methods
- * on the class.
- *
- *
{Object}
- *
Creates prototype methods on the class.
- *
- *
- *
- * When a Class is created, the static [jQuery.Class.static.setup setup]
- * and [jQuery.Class.static.init init] methods are called.
- *
- * To create an instance of a Class, call:
- *
- * new Class([args ... ]) -> instance
- *
- * The created instance will have all the
- * prototype properties and methods defined by the PROTOTYPE object.
- *
- * When an instance is created, the prototype [jQuery.Class.prototype.setup setup]
- * and [jQuery.Class.prototype.init init] methods
- * are called.
- */
-
- clss = $.Class = function() {
- if (arguments.length) {
- return clss.extend.apply(clss, arguments);
- }
- };
-
- /* @Static*/
- extend(clss, {
- /**
- * @function proxy
- * Returns a callback function for a function on this Class.
- * Proxy ensures that 'this' is set appropriately.
- * @codestart
- * $.Class("MyClass",{
- * getData: function() {
- * this.showing = null;
- * $.get("data.json",this.proxy('gotData'),'json')
- * },
- * gotData: function( data ) {
- * this.showing = data;
- * }
- * },{});
- * MyClass.showData();
- * @codeend
- *
Currying Arguments
- * Additional arguments to proxy will fill in arguments on the returning function.
- * @codestart
- * $.Class("MyClass",{
- * getData: function( callback ) {
- * $.get("data.json",this.proxy('process',callback),'json');
- * },
- * process: function( callback, jsonData ) { //callback is added as first argument
- * jsonData.processed = true;
- * callback(jsonData);
- * }
- * },{});
- * MyClass.getData(showDataFunc)
- * @codeend
- *
Nesting Functions
- * Proxy can take an array of functions to call as
- * the first argument. When the returned callback function
- * is called each function in the array is passed the return value of the prior function. This is often used
- * to eliminate currying initial arguments.
- * @codestart
- * $.Class("MyClass",{
- * getData: function( callback ) {
- * //calls process, then callback with value from process
- * $.get("data.json",this.proxy(['process2',callback]),'json')
- * },
- * process2: function( type,jsonData ) {
- * jsonData.processed = true;
- * return [jsonData];
- * }
- * },{});
- * MyClass.getData(showDataFunc);
- * @codeend
- * @param {String|Array} fname If a string, it represents the function to be called.
- * If it is an array, it will call each function in order and pass the return value of the prior function to the
- * next function.
- * @return {Function} the callback function.
- */
- proxy: function( funcs ) {
-
- //args that should be curried
- var args = makeArray(arguments),
- self;
-
- // get the functions to callback
- funcs = args.shift();
-
- // if there is only one function, make funcs into an array
- if (!isArray(funcs) ) {
- funcs = [funcs];
- }
-
- // keep a reference to us in self
- self = this;
-
- //!steal-remove-start
- for( var i =0; i< funcs.length;i++ ) {
- if(typeof funcs[i] == "string" && !isFunction(this[funcs[i]])){
- throw ("class.js "+( this.fullName || this.Class.fullName)+" does not have a "+funcs[i]+"method!");
- }
- }
- //!steal-remove-end
- return function class_cb() {
- // add the arguments after the curried args
- var cur = concatArgs(args, arguments),
- isString,
- length = funcs.length,
- f = 0,
- func;
-
- // go through each function to call back
- for (; f < length; f++ ) {
- func = funcs[f];
- if (!func ) {
- continue;
- }
-
- // set called with the name of the function on self (this is how this.view works)
- isString = typeof func == "string";
- if ( isString && self._set_called ) {
- self.called = func;
- }
-
- // call the function
- cur = (isString ? self[func] : func).apply(self, cur || []);
-
- // pass the result to the next function (if there is a next function)
- if ( f < length - 1 ) {
- cur = !isArray(cur) || cur._use_call ? [cur] : cur
- }
- }
- return cur;
- }
- },
- /**
- * @function newInstance
- * Creates a new instance of the class. This method is useful for creating new instances
- * with arbitrary parameters.
- *
Example
- * @codestart
- * $.Class("MyClass",{},{})
- * var mc = MyClass.newInstance.apply(null, new Array(parseInt(Math.random()*10,10))
- * @codeend
- * @return {class} instance of the class
- */
- newInstance: function() {
- // get a raw instance objet (init is not called)
- var inst = this.rawInstance(),
- args;
-
- // call setup if there is a setup
- if ( inst.setup ) {
- args = inst.setup.apply(inst, arguments);
- }
- // call init if there is an init, if setup returned args, use those as the arguments
- if ( inst.init ) {
- inst.init.apply(inst, isArray(args) ? args : arguments);
- }
- return inst;
- },
- /**
- * Setup gets called on the inherting class with the base class followed by the
- * inheriting class's raw properties.
- *
- * Setup will deeply extend a static defaults property on the base class with
- * properties on the base class. For example:
- *
- * $.Class("MyBase",{
- * defaults : {
- * foo: 'bar'
- * }
- * },{})
- *
- * MyBase("Inheriting",{
- * defaults : {
- * newProp : 'newVal'
- * }
- * },{}
- *
- * Inheriting.defaults -> {foo: 'bar', 'newProp': 'newVal'}
- *
- * @param {Object} baseClass the base class that is being inherited from
- * @param {String} fullName the name of the new class
- * @param {Object} staticProps the static properties of the new class
- * @param {Object} protoProps the prototype properties of the new class
- */
- setup: function( baseClass, fullName ) {
- // set defaults as the merger of the parent defaults and this object's defaults
- this.defaults = extend(true, {}, baseClass.defaults, this.defaults);
- return arguments;
- },
- rawInstance: function() {
- // prevent running init
- initializing = true;
- var inst = new this();
- initializing = false;
- // allow running init
- return inst;
- },
- /**
- * Extends a class with new static and prototype functions. There are a variety of ways
- * to use extend:
- *
- * // with className, static and prototype functions
- * $.Class('Task',{ STATIC },{ PROTOTYPE })
- * // with just classname and prototype functions
- * $.Class('Task',{ PROTOTYPE })
- * // with just a className
- * $.Class('Task')
- *
- * You no longer have to use .extend. Instead, you can pass those options directly to
- * $.Class (and any inheriting classes):
- *
- * // with className, static and prototype functions
- * $.Class('Task',{ STATIC },{ PROTOTYPE })
- * // with just classname and prototype functions
- * $.Class('Task',{ PROTOTYPE })
- * // with just a className
- * $.Class('Task')
- *
- * @param {String} [fullName] the classes name (used for classes w/ introspection)
- * @param {Object} [klass] the new classes static/class functions
- * @param {Object} [proto] the new classes prototype functions
- *
- * @return {jQuery.Class} returns the new class
- */
- extend: function( fullName, klass, proto ) {
- // figure out what was passed and normalize it
- if ( typeof fullName != 'string' ) {
- proto = klass;
- klass = fullName;
- fullName = null;
- }
- if (!proto ) {
- proto = klass;
- klass = null;
- }
-
- proto = proto || {};
- var _super_class = this,
- _super = this[STR_PROTOTYPE],
- name, shortName, namespace, prototype;
-
- // Instantiate a base class (but only create the instance,
- // don't run the init constructor)
- initializing = true;
- prototype = new this();
- initializing = false;
-
- // Copy the properties over onto the new prototype
- inheritProps(proto, _super, prototype);
-
- // The dummy class constructor
- function Class() {
- // All construction is actually done in the init method
- if ( initializing ) return;
-
- // we are being called w/o new, we are extending
- if ( this.constructor !== Class && arguments.length ) {
- return arguments.callee.extend.apply(arguments.callee, arguments)
- } else { //we are being called w/ new
- return this.Class.newInstance.apply(this.Class, arguments)
- }
- }
- // Copy old stuff onto class
- for ( name in this ) {
- if ( this.hasOwnProperty(name) ) {
- Class[name] = this[name];
- }
- }
-
- // copy new static props on class
- inheritProps(klass, this, Class);
-
- // do namespace stuff
- if ( fullName ) {
-
- var parts = fullName.split(/\./),
- shortName = parts.pop(),
- current = getObject(parts.join('.'), window, true),
- namespace = current;
-
- //!steal-remove-start
- if (!Class.nameOk ) {
- //steal.dev.isHappyName(fullName)
- }
- if(current[shortName]){
- steal.dev.warn("class.js There's already something called "+fullName)
- }
- //!steal-remove-end
- current[shortName] = Class;
- }
-
- // set things that can't be overwritten
- extend(Class, {
- prototype: prototype,
- /**
- * @attribute namespace
- * The namespaces object
- *
- * $.Class("MyOrg.MyClass",{},{})
- * MyOrg.MyClass.namespace //-> MyOrg
- *
- */
- namespace: namespace,
- /**
- * @attribute shortName
- * The name of the class without its namespace, provided for introspection purposes.
- *
- * $.Class("MyOrg.MyClass",{},{})
- * MyOrg.MyClass.shortName //-> 'MyClass'
- * MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
- *
- */
- shortName: shortName,
- constructor: Class,
- /**
- * @attribute fullName
- * The full name of the class, including namespace, provided for introspection purposes.
- *
- * $.Class("MyOrg.MyClass",{},{})
- * MyOrg.MyClass.shortName //-> 'MyClass'
- * MyOrg.MyClass.fullName //-> 'MyOrg.MyClass'
- *
- */
- fullName: fullName
- });
-
- //make sure our prototype looks nice
- Class[STR_PROTOTYPE].Class = Class[STR_PROTOTYPE].constructor = Class;
-
-
-
- // call the class setup
- var args = Class.setup.apply(Class, concatArgs([_super_class],arguments));
-
- // call the class init
- if ( Class.init ) {
- Class.init.apply(Class, args || concatArgs([_super_class],arguments));
- }
-
- /* @Prototype*/
- return Class;
- /**
- * @function setup
- * If a setup method is provided, it is called when a new
- * instances is created. It gets passed the same arguments that
- * were given to the Class constructor function ( new Class( arguments ... )).
- *
- * $.Class("MyClass",
- * {
- * setup: function( val ) {
- * this.val = val;
- * }
- * })
- * var mc = new MyClass("Check Check")
- * mc.val //-> 'Check Check'
- *
- * Setup is called before [jQuery.Class.prototype.init init]. If setup
- * return an array, those arguments will be used for init.
- *
- * $.Class("jQuery.Controller",{
- * setup : function(htmlElement, rawOptions){
- * return [$(htmlElement),
- * $.extend({}, this.Class.defaults, rawOptions )]
- * }
- * })
- *
- *
PRO TIP:
- * Setup functions are used to normalize constructor arguments and provide a place for
- * setup code that extending classes don't have to remember to call _super to
- * run.
- *
- *
- * Setup is not defined on $.Class itself, so calling super in inherting classes
- * will break. Don't do the following:
- *
- * $.Class("Thing",{
- * setup : function(){
- * this._super(); // breaks!
- * }
- * })
- *
- * @return {Array|undefined} If an array is return, [jQuery.Class.prototype.init] is
- * called with those arguments; otherwise, the original arguments are used.
- */
- //break up
- /**
- * @function init
- * If an init method is provided, it gets called when a new instance
- * is created. Init gets called after [jQuery.Class.prototype.setup setup], typically with the
- * same arguments passed to the Class
- * constructor: ( new Class( arguments ... )).
- *
- * $.Class("MyClass",
- * {
- * init: function( val ) {
- * this.val = val;
- * }
- * })
- * var mc = new MyClass(1)
- * mc.val //-> 1
- *
- * [jQuery.Class.prototype.setup Setup] is able to modify the arguments passed to init. Read
- * about it there.
- *
- */
- //Breaks up code
- /**
- * @attribute constructor
- *
- * A reference to the Class (or constructor function). This allows you to access
- * a class's static properties from an instance.
- *
- * ### Quick Example
- *
- * // a class with a static property
- * $.Class("MyClass", {staticProperty : true}, {});
- *
- * // a new instance of myClass
- * var mc1 = new MyClass();
- *
- * // read the static property from the instance:
- * mc1.constructor.staticProperty //-> true
- *
- * Getting static properties with the constructor property, like
- * [jQuery.Class.static.fullName fullName], is very common.
- *
- */
- }
-
- })
-
-
-
-
-
- clss.callback = clss[STR_PROTOTYPE].callback = clss[STR_PROTOTYPE].
- /**
- * @function proxy
- * Returns a method that sets 'this' to the current instance. This does the same thing as
- * and is described better in [jQuery.Class.static.proxy].
- * The only difference is this proxy works
- * on a instance instead of a class.
- * @param {String|Array} fname If a string, it represents the function to be called.
- * If it is an array, it will call each function in order and pass the return value of the prior function to the
- * next function.
- * @return {Function} the callback function
- */
- proxy = clss.proxy;
+ $.Class = can.Construct;
})();
diff --git a/class/class_test.js b/class/class_test.js
index ec95179c..61caa64d 100644
--- a/class/class_test.js
+++ b/class/class_test.js
@@ -14,7 +14,7 @@ test("Creating", function(){
},
{
init: function() {
- this.Class.count++;
+ this.constructor.count++;
this.eyes = false;
}
}
@@ -139,12 +139,12 @@ test("callback", function(){
}
})
- var cb = Car.callback('show');
+ var cb = Car.proxy('show');
curVal = 1;
cb(1)
curVal = 2;
- var cb2 = Car.callback('show',2)
+ var cb2 = Car.proxy('show',2)
cb2();
});
@@ -159,7 +159,7 @@ test("callback error", 1,function(){
}
})
try{
- Car.callback('huh');
+ Car.proxy('huh');
ok(false, "I should have errored")
}catch(e){
ok(true, "Error was thrown")
diff --git a/controller/controller.js b/controller/controller.js
index f3bd8476..2d735d3b 100644
--- a/controller/controller.js
+++ b/controller/controller.js
@@ -1,1089 +1,7 @@
-steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function( $ ) {
- // ------- HELPER FUNCTIONS ------
-
- // Binds an element, returns a function that unbinds
- var bind = function( el, ev, callback ) {
- var wrappedCallback,
- binder = el.bind && el.unbind ? el : $(isFunction(el) ? [el] : el);
- //this is for events like >click.
- if ( ev.indexOf(">") === 0 ) {
- ev = ev.substr(1);
- wrappedCallback = function( event ) {
- if ( event.target === el ) {
- callback.apply(this, arguments);
- }
- };
- }
- binder.bind(ev, wrappedCallback || callback);
- // if ev name has >, change the name and bind
- // in the wrapped callback, check that the element matches the actual element
- return function() {
- binder.unbind(ev, wrappedCallback || callback);
- el = ev = callback = wrappedCallback = null;
- };
- },
- makeArray = $.makeArray,
- isArray = $.isArray,
- isFunction = $.isFunction,
- extend = $.extend,
- Str = $.String,
- each = $.each,
-
- STR_PROTOTYPE = 'prototype',
- STR_CONSTRUCTOR = 'constructor',
- slice = Array[STR_PROTOTYPE].slice,
-
- // Binds an element, returns a function that unbinds
- delegate = function( el, selector, ev, callback ) {
- var binder = el.delegate && el.undelegate ? el : $(isFunction(el) ? [el] : el)
- binder.delegate(selector, ev, callback);
- return function() {
- binder.undelegate(selector, ev, callback);
- binder = el = ev = callback = selector = null;
- };
- },
-
- // calls bind or unbind depending if there is a selector
- binder = function( el, ev, callback, selector ) {
- return selector ? delegate(el, selector, ev, callback) : bind(el, ev, callback);
- },
-
- // moves 'this' to the first argument, wraps it with jQuery if it's an element
- shifter = function shifter(context, name) {
- var method = typeof name == "string" ? context[name] : name;
- return function() {
- context.called = name;
- return method.apply(context, [this.nodeName ? $(this) : this].concat( slice.call(arguments, 0) ) );
- };
- },
- // matches dots
- dotsReg = /\./g,
- // matches controller
- controllersReg = /_?controllers?/ig,
- //used to remove the controller from the name
- underscoreAndRemoveController = function( className ) {
- return Str.underscore(className.replace("jQuery.", "").replace(dotsReg, '_').replace(controllersReg, ""));
- },
- // checks if it looks like an action
- actionMatcher = /[^\w]/,
- // handles parameterized action names
- parameterReplacer = /\{([^\}]+)\}/g,
- breaker = /^(?:(.*?)\s)?([\w\.\:>]+)$/,
- basicProcessor,
- data = function(el, data){
- return $.data(el, "controllers", data)
- };
- /**
- * @class jQuery.Controller
- * @parent jquerymx
- * @plugin jquery/controller
- * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/controller/controller.js
- * @test jquery/controller/qunit.html
- * @inherits jQuery.Class
- * @description jQuery widget factory.
- *
- * jQuery.Controller helps create organized, memory-leak free, rapidly performing
- * jQuery widgets. Its extreme flexibility allows it to serve as both
- * a traditional View and a traditional Controller.
- *
- * This means it is used to
- * create things like tabs, grids, and contextmenus as well as
- * organizing them into higher-order business rules.
- *
- * Controllers make your code deterministic, reusable, organized and can tear themselves
- * down auto-magically. Read about [http://jupiterjs.com/news/writing-the-perfect-jquery-plugin
- * the theory behind controller] and
- * a [http://jupiterjs.com/news/organize-jquery-widgets-with-jquery-controller walkthrough of its features]
- * on Jupiter's blog. [mvc.controller Get Started with jQueryMX] also has a great walkthrough.
- *
- * Controller inherits from [jQuery.Class $.Class] and makes heavy use of
- * [http://api.jquery.com/delegate/ event delegation]. Make sure
- * you understand these concepts before using it.
- *
- * ## Basic Example
- *
- * Instead of
- *
- *
- * $(function(){
- * $('#tabs').click(someCallbackFunction1)
- * $('#tabs .tab').click(someCallbackFunction2)
- * $('#tabs .delete click').click(someCallbackFunction3)
- * });
- *
- * do this
- *
- * $.Controller('Tabs',{
- * click: function() {...},
- * '.tab click' : function() {...},
- * '.delete click' : function() {...}
- * })
- * $('#tabs').tabs();
- *
- *
- * ## Tabs Example
- *
- * @demo jquery/controller/controller.html
- *
- * ## Using Controller
- *
- * Controller helps you build and organize jQuery plugins. It can be used
- * to build simple widgets, like a slider, or organize multiple
- * widgets into something greater.
- *
- * To understand how to use Controller, you need to understand
- * the typical lifecycle of a jQuery widget and how that maps to
- * controller's functionality:
- *
- * ### A controller class is created.
- *
- * $.Controller("MyWidget",
- * {
- * defaults : {
- * message : "Remove Me"
- * }
- * },
- * {
- * init : function(rawEl, rawOptions){
- * this.element.append(
- * "
"+this.options.message+"
"
- * );
- * },
- * "div click" : function(div, ev){
- * div.remove();
- * }
- * })
- *
- * This creates a $.fn.my_widget jQuery helper function
- * that can be used to create a new controller instance on an element. Find
- * more information [jquery.controller.plugin here] about the plugin gets created
- * and the rules around its name.
- *
- * ### An instance of controller is created on an element
- *
- * $('.thing').my_widget(options) // calls new MyWidget(el, options)
- *
- * This calls new MyWidget(el, options) on
- * each '.thing' element.
- *
- * When a new [jQuery.Class Class] instance is created, it calls the class's
- * prototype setup and init methods. Controller's [jQuery.Controller.prototype.setup setup]
- * method:
- *
- * - Sets [jQuery.Controller.prototype.element this.element] and adds the controller's name to element's className.
- * - Merges passed in options with defaults object and sets it as [jQuery.Controller.prototype.options this.options]
- * - Saves a reference to the controller in $.data.
- * - [jquery.controller.listening Binds all event handler methods].
- *
- *
- * ### The controller responds to events
- *
- * Typically, Controller event handlers are automatically bound. However, there are
- * multiple ways to [jquery.controller.listening listen to events] with a controller.
- *
- * Once an event does happen, the callback function is always called with 'this'
- * referencing the controller instance. This makes it easy to use helper functions and
- * save state on the controller.
- *
- *
- * ### The widget is destroyed
- *
- * If the element is removed from the page, the
- * controller's [jQuery.Controller.prototype.destroy] method is called.
- * This is a great place to put any additional teardown functionality.
- *
- * You can also teardown a controller programatically like:
- *
- * $('.thing').my_widget('destroy');
- *
- * ## Todos Example
- *
- * Lets look at a very basic example -
- * a list of todos and a button you want to click to create a new todo.
- * Your HTML might look like:
- *
- * @codestart html
- * <div id='todos'>
- * <ol>
- * <li class="todo">Laundry</li>
- * <li class="todo">Dishes</li>
- * <li class="todo">Walk Dog</li>
- * </ol>
- * <a class="create">Create</a>
- * </div>
- * @codeend
- *
- * To add a mousover effect and create todos, your controller might look like:
- *
- * $.Controller('Todos',{
- * ".todo mouseover" : function( el, ev ) {
- * el.css("backgroundColor","red")
- * },
- * ".todo mouseout" : function( el, ev ) {
- * el.css("backgroundColor","")
- * },
- * ".create click" : function() {
- * this.find("ol").append("
New Todo
");
- * }
- * })
- *
- * Now that you've created the controller class, you've must attach the event handlers on the '#todos' div by
- * creating [jQuery.Controller.prototype.setup|a new controller instance]. There are 2 ways of doing this.
- *
- * @codestart
- * //1. Create a new controller directly:
- * new Todos($('#todos'));
- * //2. Use jQuery function
- * $('#todos').todos();
- * @codeend
- *
- * ## Controller Initialization
- *
- * It can be extremely useful to add an init method with
- * setup functionality for your widget.
- *
- * In the following example, I create a controller that when created, will put a message as the content of the element:
- *
- * $.Controller("SpecialController",
- * {
- * init: function( el, message ) {
- * this.element.html(message)
- * }
- * })
- * $(".special").special("Hello World")
- *
- * ## Removing Controllers
- *
- * Controller removal is built into jQuery. So to remove a controller, you just have to remove its element:
- *
- * @codestart
- * $(".special_controller").remove()
- * $("#containsControllers").html("")
- * @codeend
- *
- * It's important to note that if you use raw DOM methods (innerHTML, removeChild), the controllers won't be destroyed.
- *
- * If you just want to remove controller functionality, call destroy on the controller instance:
- *
- * @codestart
- * $(".special_controller").controller().destroy()
- * @codeend
- *
- * ## Accessing Controllers
- *
- * Often you need to get a reference to a controller, there are a few ways of doing that. For the
- * following example, we assume there are 2 elements with className="special".
- *
- * @codestart
- * //creates 2 foo controllers
- * $(".special").foo()
- *
- * //creates 2 bar controllers
- * $(".special").bar()
- *
- * //gets all controllers on all elements:
- * $(".special").controllers() //-> [foo, bar, foo, bar]
- *
- * //gets only foo controllers
- * $(".special").controllers(FooController) //-> [foo, foo]
- *
- * //gets all bar controllers
- * $(".special").controllers(BarController) //-> [bar, bar]
- *
- * //gets first controller
- * $(".special").controller() //-> foo
- *
- * //gets foo controller via data
- * $(".special").data("controllers")["FooController"] //-> foo
- * @codeend
- *
- * ## Calling methods on Controllers
- *
- * Once you have a reference to an element, you can call methods on it. However, Controller has
- * a few shortcuts:
- *
- * @codestart
- * //creates foo controller
- * $(".special").foo({name: "value"})
- *
- * //calls FooController.prototype.update
- * $(".special").foo({name: "value2"})
- *
- * //calls FooController.prototype.bar
- * $(".special").foo("bar","something I want to pass")
- * @codeend
- *
- * These methods let you call one controller from another controller.
- *
- */
- $.Class("jQuery.Controller",
- /**
- * @Static
- */
- {
- /**
- * Does 2 things:
- *
- * - Creates a jQuery helper for this controller.
- * - Calculates and caches which functions listen for events.
- *
- * ### jQuery Helper Naming Examples
- *
- *
- * "TaskController" -> $().task_controller()
- * "Controllers.Task" -> $().controllers_task()
- *
- */
- setup: function() {
- // Allow contollers to inherit "defaults" from superclasses as it done in $.Class
- this._super.apply(this, arguments);
-
- // if you didn't provide a name, or are controller, don't do anything
- if (!this.shortName || this.fullName == "jQuery.Controller" ) {
- return;
- }
- // cache the underscored names
- this._fullName = underscoreAndRemoveController(this.fullName);
- this._shortName = underscoreAndRemoveController(this.shortName);
-
- var controller = this,
- /**
- * @attribute pluginName
- * Setting the pluginName property allows you
- * to change the jQuery plugin helper name from its
- * default value.
- *
- * $.Controller("Mxui.Layout.Fill",{
- * pluginName: "fillWith"
- * },{});
- *
- * $("#foo").fillWith();
- */
- pluginname = this.pluginName || this._fullName,
- funcName, forLint;
-
- // create jQuery plugin
- if (!$.fn[pluginname] ) {
- $.fn[pluginname] = function( options ) {
-
- var args = makeArray(arguments),
- //if the arg is a method on this controller
- isMethod = typeof options == "string" && isFunction(controller[STR_PROTOTYPE][options]),
- meth = args[0];
- return this.each(function() {
- //check if created
- var controllers = data(this),
- //plugin is actually the controller instance
- plugin = controllers && controllers[pluginname];
-
- if ( plugin ) {
- if ( isMethod ) {
- // call a method on the controller with the remaining args
- plugin[meth].apply(plugin, args.slice(1));
- } else {
- // call the plugin's update method
- plugin.update.apply(plugin, args);
- }
-
- } else {
- //create a new controller instance
- controller.newInstance.apply(controller, [this].concat(args));
- }
- });
- };
- }
-
- // make sure listensTo is an array
- //!steal-remove-start
- if (!isArray(this.listensTo) ) {
- throw "listensTo is not an array in " + this.fullName;
- }
- //!steal-remove-end
- // calculate and cache actions
- this.actions = {};
-
- for ( funcName in this[STR_PROTOTYPE] ) {
- if (funcName == 'constructor' || !isFunction(this[STR_PROTOTYPE][funcName]) ) {
- continue;
- }
- if ( this._isAction(funcName) ) {
- this.actions[funcName] = this._action(funcName);
- }
- }
- },
- hookup: function( el ) {
- return new this(el);
- },
-
- /**
- * @hide
- * @param {String} methodName a prototype function
- * @return {Boolean} truthy if an action or not
- */
- _isAction: function( methodName ) {
- if ( actionMatcher.test(methodName) ) {
- return true;
- } else {
- return $.inArray(methodName, this.listensTo) > -1 || $.event.special[methodName] || processors[methodName];
- }
-
- },
- /**
- * @hide
- * This takes a method name and the options passed to a controller
- * and tries to return the data necessary to pass to a processor
- * (something that binds things).
- *
- * For performance reasons, this called twice. First, it is called when
- * the Controller class is created. If the methodName is templated
- * like : "{window} foo", it returns null. If it is not templated
- * it returns event binding data.
- *
- * The resulting data is added to this.actions.
- *
- * When a controller instance is created, _action is called again, but only
- * on templated actions.
- *
- * @param {Object} methodName the method that will be bound
- * @param {Object} [options] first param merged with class default options
- * @return {Object} null or the processor and pre-split parts.
- * The processor is what does the binding/subscribing.
- */
- _action: function( methodName, options ) {
- // reset the test index
- parameterReplacer.lastIndex = 0;
-
- //if we don't have options (a controller instance), we'll run this later
- if (!options && parameterReplacer.test(methodName) ) {
- return null;
- }
- // If we have options, run sub to replace templates "{}" with a value from the options
- // or the window
- var convertedName = options ? Str.sub(methodName, [options, window]) : methodName,
-
- // If a "{}" resolves to an object, convertedName will be an array
- arr = isArray(convertedName),
-
- // get the parts of the function = [convertedName, delegatePart, eventPart]
- parts = (arr ? convertedName[1] : convertedName).match(breaker),
- event = parts[2],
- processor = processors[event] || basicProcessor;
- return {
- processor: processor,
- parts: parts,
- delegate : arr ? convertedName[0] : undefined
- };
- },
- /**
- * @attribute processors
- * An object of {eventName : function} pairs that Controller uses to hook up events
- * auto-magically. A processor function looks like:
- *
- * jQuery.Controller.processors.
- * myprocessor = function( el, event, selector, cb, controller ) {
- * //el - the controller's element
- * //event - the event (myprocessor)
- * //selector - the left of the selector
- * //cb - the function to call
- * //controller - the binding controller
- * };
- *
- * This would bind anything like: "foo~3242 myprocessor".
- *
- * The processor must return a function that when called,
- * unbinds the event handler.
- *
- * Controller already has processors for the following events:
- *
- * - change
- * - click
- * - contextmenu
- * - dblclick
- * - focusin
- * - focusout
- * - keydown
- * - keyup
- * - keypress
- * - mousedown
- * - mouseenter
- * - mouseleave
- * - mousemove
- * - mouseout
- * - mouseover
- * - mouseup
- * - reset
- * - resize
- * - scroll
- * - select
- * - submit
- *
- * Listen to events on the document or window
- * with templated event handlers:
- *
- *
- * $.Controller('Sized',{
- * "{window} resize" : function(){
- * this.element.width(this.element.parent().width() / 2);
- * }
- * });
- *
- * $('.foo').sized();
- */
- processors: {},
- /**
- * @attribute listensTo
- * An array of special events this controller
- * listens too. You only need to add event names that
- * are whole words (ie have no special characters).
- *
- * $.Controller('TabPanel',{
- * listensTo : ['show']
- * },{
- * 'show' : function(){
- * this.element.show();
- * }
- * })
- *
- * $('.foo').tab_panel().trigger("show");
- *
- */
- listensTo: [],
- /**
- * @attribute defaults
- * A object of name-value pairs that act as default values for a controller's
- * [jQuery.Controller.prototype.options options].
- *
- * $.Controller("Message",
- * {
- * defaults : {
- * message : "Hello World"
- * }
- * },{
- * init : function(){
- * this.element.text(this.options.message);
- * }
- * })
- *
- * $("#el1").message(); //writes "Hello World"
- * $("#el12").message({message: "hi"}); //writes hi
- *
- * In [jQuery.Controller.prototype.setup setup] the options passed to the controller
- * are merged with defaults. This is not a deep merge.
- */
- defaults: {}
- },
- /**
- * @Prototype
- */
- {
- /**
- * Setup is where most of controller's magic happens. It does the following:
- *
- * ### 1. Sets this.element
- *
- * The first parameter passed to new Controller(el, options) is expected to be
- * an element. This gets converted to a jQuery wrapped element and set as
- * [jQuery.Controller.prototype.element this.element].
- *
- * ### 2. Adds the controller's name to the element's className.
- *
- * Controller adds it's plugin name to the element's className for easier
- * debugging. For example, if your Controller is named "Foo.Bar", it adds
- * "foo_bar" to the className.
- *
- * ### 3. Saves the controller in $.data
- *
- * A reference to the controller instance is saved in $.data. You can find
- * instances of "Foo.Bar" like:
- *
- * $("#el").data("controllers")['foo_bar'].
- *
- * ### Binds event handlers
- *
- * Setup does the event binding described in [jquery.controller.listening Listening To Events].
- *
- * @param {HTMLElement} element the element this instance operates on.
- * @param {Object} [options] option values for the controller. These get added to
- * this.options and merged with [jQuery.Controller.static.defaults defaults].
- * @return {Array} return an array if you wan to change what init is called with. By
- * default it is called with the element and options passed to the controller.
- */
- setup: function( element, options ) {
- var funcName, ready, cls = this[STR_CONSTRUCTOR];
-
- //want the raw element here
- element = (typeof element == 'string' ? $(element) :
- (element.jquery ? element : [element]) )[0];
-
- //set element and className on element
- var pluginname = cls.pluginName || cls._fullName;
-
- //set element and className on element
- this.element = $(element).addClass(pluginname);
-
- //set in data
- (data(element) || data(element, {}))[pluginname] = this;
-
-
- /**
- * @attribute options
- *
- * Options are used to configure an controller. They are
- * the 2nd argument
- * passed to a controller (or the first argument passed to the
- * [jquery.controller.plugin controller's jQuery plugin]).
- *
- * For example:
- *
- * $.Controller('Hello')
- *
- * var h1 = new Hello($('#content1'), {message: 'World'} );
- * equal( h1.options.message , "World" )
- *
- * var h2 = $('#content2').hello({message: 'There'})
- * .controller();
- * equal( h2.options.message , "There" )
- *
- * Options are merged with [jQuery.Controller.static.defaults defaults] in
- * [jQuery.Controller.prototype.setup setup].
- *
- * For example:
- *
- * $.Controller("Tabs",
- * {
- * defaults : {
- * activeClass: "ui-active-state"
- * }
- * },
- * {
- * init : function(){
- * this.element.addClass(this.options.activeClass);
- * }
- * })
- *
- * $("#tabs1").tabs() // adds 'ui-active-state'
- * $("#tabs2").tabs({activeClass : 'active'}) // adds 'active'
- *
- * Options are typically updated by calling
- * [jQuery.Controller.prototype.update update];
- *
- */
- this.options = extend( extend(true, {}, cls.defaults), options);
-
-
-
- /**
- * @attribute called
- * String name of current function being called on controller instance. This is
- * used for picking the right view in render.
- * @hide
- */
- this.called = "init";
-
- // bind all event handlers
- this.bind();
-
- /**
- * @attribute element
- * The controller instance's delegated element. This
- * is set by [jQuery.Controller.prototype.setup setup]. It
- * is a jQuery wrapped element.
- *
- * For example, if I add MyWidget to a '#myelement' element like:
- *
- * $.Controller("MyWidget",{
- * init : function(){
- * this.element.css("color","red")
- * }
- * })
- *
- * $("#myelement").my_widget()
- *
- * MyWidget will turn #myelement's font color red.
- *
- * ## Using a different element.
- *
- * Sometimes, you want a different element to be this.element. A
- * very common example is making progressively enhanced form widgets.
- *
- * To change this.element, overwrite Controller's setup method like:
- *
- * $.Controller("Combobox",{
- * setup : function(el, options){
- * this.oldElement = $(el);
- * var newEl = $('');
- * this.oldElement.wrap(newEl);
- * this._super(newEl, options);
- * },
- * init : function(){
- * this.element //-> the div
- * },
- * ".option click" : function(){
- * // event handler bound on the div
- * },
- * destroy : function(){
- * var div = this.element; //save reference
- * this._super();
- * div.replaceWith(this.oldElement);
- * }
- * }
- */
- return [this.element, this.options].concat(makeArray(arguments).slice(2));
- /**
- * @function init
- *
- * Implement this.
- */
- },
- /**
- * Bind attaches event handlers that will be
- * removed when the controller is removed.
- *
- * This used to be a good way to listen to events outside the controller's
- * [jQuery.Controller.prototype.element element]. However,
- * using templated event listeners is now the prefered way of doing this.
- *
- * ### Example:
- *
- * init: function() {
- * // calls somethingClicked(el,ev)
- * this.bind('click','somethingClicked')
- *
- * // calls function when the window is clicked
- * this.bind(window, 'click', function(ev){
- * //do something
- * })
- * },
- * somethingClicked: function( el, ev ) {
- *
- * }
- *
- * @param {HTMLElement|jQuery.fn|Object} [el=this.element]
- * The element to be bound. If an eventName is provided,
- * the controller's element is used instead.
- *
- * @param {String} eventName The event to listen for.
- * @param {Function|String} func A callback function or the String name of a controller function. If a controller
- * function name is given, the controller function is called back with the bound element and event as the first
- * and second parameter. Otherwise the function is called back like a normal bind.
- * @return {Integer} The id of the binding in this._bindings
- */
- bind: function( el, eventName, func ) {
- if( el === undefined ) {
- //adds bindings
- this._bindings = [];
- //go through the cached list of actions and use the processor to bind
-
- var cls = this[STR_CONSTRUCTOR],
- bindings = this._bindings,
- actions = cls.actions,
- element = this.element;
-
- for ( funcName in actions ) {
- if ( actions.hasOwnProperty(funcName) ) {
- ready = actions[funcName] || cls._action(funcName, this.options);
- bindings.push(
- ready.processor(ready.delegate || element,
- ready.parts[2],
- ready.parts[1],
- funcName,
- this));
- }
- }
-
-
- //setup to be destroyed ... don't bind b/c we don't want to remove it
- var destroyCB = shifter(this,"destroy");
- element.bind("destroyed", destroyCB);
- bindings.push(function( el ) {
- $(el).unbind("destroyed", destroyCB);
- });
- return bindings.length;
- }
- if ( typeof el == 'string' ) {
- func = eventName;
- eventName = el;
- el = this.element;
- }
- return this._binder(el, eventName, func);
- },
- _binder: function( el, eventName, func, selector ) {
- if ( typeof func == 'string' ) {
- func = shifter(this,func);
- }
- this._bindings.push(binder(el, eventName, func, selector));
- return this._bindings.length;
- },
- _unbind : function(){
- var el = this.element[0];
- each(this._bindings, function( key, value ) {
- value(el);
- });
- //adds bindings
- this._bindings = [];
- },
- /**
- * Delegate will delegate on an elememt and will be undelegated when the controller is removed.
- * This is a good way to delegate on elements not in a controller's element.
- *
Example:
- * @codestart
- * // calls function when the any 'a.foo' is clicked.
- * this.delegate(document.documentElement,'a.foo', 'click', function(ev){
- * //do something
- * })
- * @codeend
- * @param {HTMLElement|jQuery.fn} [element=this.element] the element to delegate from
- * @param {String} selector the css selector
- * @param {String} eventName the event to bind to
- * @param {Function|String} func A callback function or the String name of a controller function. If a controller
- * function name is given, the controller function is called back with the bound element and event as the first
- * and second parameter. Otherwise the function is called back like a normal bind.
- * @return {Integer} The id of the binding in this._bindings
- */
- delegate: function( element, selector, eventName, func ) {
- if ( typeof element == 'string' ) {
- func = eventName;
- eventName = selector;
- selector = element;
- element = this.element;
- }
- return this._binder(element, eventName, func, selector);
- },
- /**
- * Update extends [jQuery.Controller.prototype.options this.options]
- * with the `options` argument and rebinds all events. It basically
- * re-configures the controller.
- *
- * For example, the following controller wraps a recipe form. When the form
- * is submitted, it creates the recipe on the server. When the recipe
- * is `created`, it resets the form with a new instance.
- *
- * $.Controller('Creator',{
- * "{recipe} created" : function(){
- * this.update({recipe : new Recipe()});
- * this.element[0].reset();
- * this.find("[type=submit]").val("Create Recipe")
- * },
- * "submit" : function(el, ev){
- * ev.preventDefault();
- * var recipe = this.options.recipe;
- * recipe.attrs( this.element.formParams() );
- * this.find("[type=submit]").val("Saving...")
- * recipe.save();
- * }
- * });
- * $('#createRecipes').creator({recipe : new Recipe()})
- *
- *
- * @demo jquery/controller/demo-update.html
- *
- * Update is called if a controller's [jquery.controller.plugin jQuery helper] is
- * called on an element that already has a controller instance
- * of the same type.
- *
- * For example, a widget that listens for model updates
- * and updates it's html would look like.
- *
- * $.Controller('Updater',{
- * // when the controller is created, update the html
- * init : function(){
- * this.updateView();
- * },
- *
- * // update the html with a template
- * updateView : function(){
- * this.element.html( "content.ejs",
- * this.options.model );
- * },
- *
- * // if the model is updated
- * "{model} updated" : function(){
- * this.updateView();
- * },
- * update : function(options){
- * // make sure you call super
- * this._super(options);
- *
- * this.updateView();
- * }
- * })
- *
- * // create the controller
- * // this calls init
- * $('#item').updater({model: recipe1});
- *
- * // later, update that model
- * // this calls "{model} updated"
- * recipe1.update({name: "something new"});
- *
- * // later, update the controller with a new recipe
- * // this calls update
- * $('#item').updater({model: recipe2});
- *
- * // later, update the new model
- * // this calls "{model} updated"
- * recipe2.update({name: "something newer"});
- *
- * _NOTE:_ If you overwrite `update`, you probably need to call
- * this._super.
- *
- * ### Example
- *
- * $.Controller("Thing",{
- * init: function( el, options ) {
- * alert( 'init:'+this.options.prop )
- * },
- * update: function( options ) {
- * this._super(options);
- * alert('update:'+this.options.prop)
- * }
- * });
- * $('#myel').thing({prop : 'val1'}); // alerts init:val1
- * $('#myel').thing({prop : 'val2'}); // alerts update:val2
- *
- * @param {Object} options A list of options to merge with
- * [jQuery.Controller.prototype.options this.options]. Often, this method
- * is called by the [jquery.controller.plugin jQuery helper function].
- */
- update: function( options ) {
- extend(this.options, options);
- this._unbind();
- this.bind();
- },
- /**
- * Destroy unbinds and undelegates all event handlers on this controller,
- * and prevents memory leaks. This is called automatically
- * if the element is removed. You can overwrite it to add your own
- * teardown functionality:
- *
- * $.Controller("ChangeText",{
- * init : function(){
- * this.oldText = this.element.text();
- * this.element.text("Changed!!!")
- * },
- * destroy : function(){
- * this.element.text(this.oldText);
- * this._super(); //Always call this!
- * })
- *
- * Make sure you always call _super when overwriting
- * controller's destroy event. The base destroy functionality unbinds
- * all event handlers the controller has created.
- *
- * You could call destroy manually on an element with ChangeText
- * added like:
- *
- * $("#changed").change_text("destroy");
- *
- */
- destroy: function() {
- if ( this._destroyed ) {
- throw this[STR_CONSTRUCTOR].shortName + " controller already deleted";
- }
- var self = this,
- fname = this[STR_CONSTRUCTOR].pluginName || this[STR_CONSTRUCTOR]._fullName,
- controllers;
-
- // mark as destroyed
- this._destroyed = true;
-
- // remove the className
- this.element.removeClass(fname);
-
- // unbind bindings
- this._unbind();
- // clean up
- delete this._actions;
-
- delete this.element.data("controllers")[fname];
-
- $(this).triggerHandler("destroyed"); //in case we want to know if the controller is removed
-
- this.element = null;
- },
- /**
- * Queries from the controller's element.
- * @codestart
- * ".destroy_all click" : function() {
- * this.find(".todos").remove();
- * }
- * @codeend
- * @param {String} selector selection string
- * @return {jQuery.fn} returns the matched elements
- */
- find: function( selector ) {
- return this.element.find(selector);
- },
- //tells callback to set called on this. I hate this.
- _set_called: true
- });
-
- var processors = $.Controller.processors,
-
- //------------- PROCESSSORS -----------------------------
- //processors do the binding. They return a function that
- //unbinds when called.
- //the basic processor that binds events
- basicProcessor = function( el, event, selector, methodName, controller ) {
- return binder(el, event, shifter(controller, methodName), selector);
- };
-
-
-
-
- //set common events to be processed as a basicProcessor
- each("change click contextmenu dblclick keydown keyup keypress mousedown mousemove mouseout mouseover mouseup reset resize scroll select submit focusin focusout mouseenter mouseleave".split(" "), function( i, v ) {
- processors[v] = basicProcessor;
- });
- /**
- * @add jQuery.fn
- */
-
- //used to determine if a controller instance is one of controllers
- //controllers can be strings or classes
- var i, isAControllerOf = function( instance, controllers ) {
- for ( i = 0; i < controllers.length; i++ ) {
- if ( typeof controllers[i] == 'string' ? instance[STR_CONSTRUCTOR]._shortName == controllers[i] : instance instanceof controllers[i] ) {
- return true;
- }
- }
- return false;
- };
- $.fn.extend({
- /**
- * @function controllers
- * Gets all controllers in the jQuery element.
- * @return {Array} an array of controller instances.
- */
- controllers: function() {
- var controllerNames = makeArray(arguments),
- instances = [],
- controllers, c, cname;
- //check if arguments
- this.each(function() {
-
- controllers = $.data(this, "controllers");
- for ( cname in controllers ) {
- if ( controllers.hasOwnProperty(cname) ) {
- c = controllers[cname];
- if (!controllerNames.length || isAControllerOf(c, controllerNames) ) {
- instances.push(c);
- }
- }
- }
- });
- return instances;
- },
- /**
- * @function controller
- * Gets a controller in the jQuery element. With no arguments, returns the first one found.
- * @param {Object} controller (optional) if exists, the first controller instance with this class type will be returned.
- * @return {jQuery.Controller} the first controller.
- */
- controller: function( controller ) {
- return this.controllers.apply(this, arguments)[0];
- }
- });
+steal('jquery/class','can/control/plugin',function( $ ) {
+ $.Controller = can.Control;
+ $.fn.controller = $.fn.control;
+ $.fn.controllers = $.fn.controllers;
});
diff --git a/controller/controller_test.js b/controller/controller_test.js
index d94799e9..d2322b85 100644
--- a/controller/controller_test.js
+++ b/controller/controller_test.js
@@ -31,7 +31,7 @@ test("subscribe testing works", function(){
OpenAjax.hub.publish("a.b",{})
equals(subscribes,1, "can subscribe")
var controllerInstance = ta.controller('my_test')
- ok( controllerInstance.Class == MyTest, "can get controller" )
+ ok( controllerInstance.constructor == MyTest, "can get controller" )
controllerInstance.destroy()
equals(destroys,1, "destroy called once")
@@ -117,7 +117,7 @@ test("delegate", function(){
})
var els = $("
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/jquery.js b/jquery.js
deleted file mode 100644
index 74ce4119..00000000
--- a/jquery.js
+++ /dev/null
@@ -1,9266 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.7.1
- * http://jquery.com/
- *
- * Copyright 2011, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Mon Nov 21 21:11:03 2011 -0500
- */
-(function( window, undefined ) {
-
-// Use the correct document accordingly with window argument (sandbox)
-var document = window.document,
- navigator = window.navigator,
- location = window.location;
-var jQuery = (function() {
-
-// Define a local copy of jQuery
-var jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context, rootjQuery );
- },
-
- // Map over jQuery in case of overwrite
- _jQuery = window.jQuery,
-
- // Map over the $ in case of overwrite
- _$ = window.$,
-
- // A central reference to the root jQuery(document)
- rootjQuery,
-
- // A simple way to check for HTML strings or ID strings
- // Prioritize #id over to avoid XSS via location.hash (#9521)
- quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
-
- // Check if a string has a non-whitespace character in it
- rnotwhite = /\S/,
-
- // Used for trimming whitespace
- trimLeft = /^\s+/,
- trimRight = /\s+$/,
-
- // Match a standalone tag
- rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
-
- // JSON RegExp
- rvalidchars = /^[\],:{}\s]*$/,
- rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
- rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
- rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
-
- // Useragent RegExp
- rwebkit = /(webkit)[ \/]([\w.]+)/,
- ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
- rmsie = /(msie) ([\w.]+)/,
- rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
-
- // Matches dashed string for camelizing
- rdashAlpha = /-([a-z]|[0-9])/ig,
- rmsPrefix = /^-ms-/,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return ( letter + "" ).toUpperCase();
- },
-
- // Keep a UserAgent string for use with jQuery.browser
- userAgent = navigator.userAgent,
-
- // For matching the engine and version of the browser
- browserMatch,
-
- // The deferred used on DOM ready
- readyList,
-
- // The ready event handler
- DOMContentLoaded,
-
- // Save a reference to some core methods
- toString = Object.prototype.toString,
- hasOwn = Object.prototype.hasOwnProperty,
- push = Array.prototype.push,
- slice = Array.prototype.slice,
- trim = String.prototype.trim,
- indexOf = Array.prototype.indexOf,
-
- // [[Class]] -> type pairs
- class2type = {};
-
-jQuery.fn = jQuery.prototype = {
- constructor: jQuery,
- init: function( selector, context, rootjQuery ) {
- var match, elem, ret, doc;
-
- // Handle $(""), $(null), or $(undefined)
- if ( !selector ) {
- return this;
- }
-
- // Handle $(DOMElement)
- if ( selector.nodeType ) {
- this.context = this[0] = selector;
- this.length = 1;
- return this;
- }
-
- // The body element only exists once, optimize finding it
- if ( selector === "body" && !context && document.body ) {
- this.context = document;
- this[0] = document.body;
- this.selector = selector;
- this.length = 1;
- return this;
- }
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- // Are we dealing with HTML string or an ID?
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = quickExpr.exec( selector );
- }
-
- // Verify a match, and that no context was specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
- doc = ( context ? context.ownerDocument || context : document );
-
- // If a single string is passed in and it's a single tag
- // just do a createElement and skip the rest
- ret = rsingleTag.exec( selector );
-
- if ( ret ) {
- if ( jQuery.isPlainObject( context ) ) {
- selector = [ document.createElement( ret[1] ) ];
- jQuery.fn.attr.call( selector, context, true );
-
- } else {
- selector = [ doc.createElement( ret[1] ) ];
- }
-
- } else {
- ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
- selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
- }
-
- return jQuery.merge( this, selector );
-
- // HANDLE: $("#id")
- } else {
- elem = document.getElementById( match[2] );
-
- // 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 and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
-
- // Otherwise, we inject the element directly into the jQuery object
- this.length = 1;
- this[0] = elem;
- }
-
- this.context = document;
- this.selector = selector;
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return rootjQuery.ready( selector );
- }
-
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
- return jQuery.makeArray( selector, this );
- },
-
- // Start with an empty selector
- selector: "",
-
- // The current version of jQuery being used
- jquery: "1.7.1",
-
- // 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 slice.call( this, 0 );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num == null ?
-
- // Return a 'clean' array
- this.toArray() :
-
- // Return just the object
- ( num < 0 ? this[ this.length + num ] : this[ num ] );
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems, name, selector ) {
- // Build a new jQuery matched element set
- var ret = this.constructor();
-
- if ( jQuery.isArray( elems ) ) {
- push.apply( ret, elems );
-
- } else {
- jQuery.merge( ret, 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;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- ready: function( fn ) {
- // Attach the listeners
- jQuery.bindReady();
-
- // Add the callback
- readyList.add( fn );
-
- return this;
- },
-
- eq: function( i ) {
- i = +i;
- return i === -1 ?
- this.slice( i ) :
- this.slice( i, i + 1 );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ),
- "slice", slice.call(arguments).join(",") );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
-
- end: function() {
- return this.prevObject || this.constructor(null);
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: [].sort,
- splice: [].splice
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-jQuery.extend = jQuery.fn.extend = function() {
- var options, name, src, copy, copyIsArray, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
-
- // extend jQuery itself if only one argument is passed
- if ( length === i ) {
- target = this;
- --i;
- }
-
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
-
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend({
- noConflict: function( deep ) {
- if ( window.$ === jQuery ) {
- window.$ = _$;
- }
-
- if ( deep && window.jQuery === jQuery ) {
- window.jQuery = _jQuery;
- }
-
- return jQuery;
- },
-
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
-
- // Handle when the DOM is ready
- ready: function( wait ) {
- // Either a released hold or an DOMready/load event and not yet ready
- if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready, 1 );
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.fireWith( document, [ jQuery ] );
-
- // Trigger any bound ready events
- if ( jQuery.fn.trigger ) {
- jQuery( document ).trigger( "ready" ).off( "ready" );
- }
- }
- },
-
- bindReady: function() {
- if ( readyList ) {
- return;
- }
-
- readyList = jQuery.Callbacks( "once memory" );
-
- // Catch cases where $(document).ready() is called after the
- // browser event has already occurred.
- if ( document.readyState === "complete" ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- return setTimeout( jQuery.ready, 1 );
- }
-
- // Mozilla, Opera and webkit nightlies currently support this event
- if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", jQuery.ready, false );
-
- // If IE event model is used
- } else if ( document.attachEvent ) {
- // ensure firing before onload,
- // maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", DOMContentLoaded );
-
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", jQuery.ready );
-
- // If IE and not a frame
- // continually check to see if the document is ready
- var toplevel = false;
-
- try {
- toplevel = window.frameElement == null;
- } catch(e) {}
-
- if ( document.documentElement.doScroll && toplevel ) {
- doScrollCheck();
- }
- }
- },
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
- },
-
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
-
- // A crude way of determining if an object is a window
- isWindow: function( obj ) {
- return obj && typeof obj === "object" && "setInterval" in obj;
- },
-
- isNumeric: function( obj ) {
- return !isNaN( parseFloat(obj) ) && isFinite( obj );
- },
-
- type: function( obj ) {
- return obj == null ?
- String( obj ) :
- class2type[ toString.call(obj) ] || "object";
- },
-
- isPlainObject: function( obj ) {
- // 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
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
-
- // 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 || hasOwn.call( obj, key );
- },
-
- isEmptyObject: function( obj ) {
- for ( var name in obj ) {
- return false;
- }
- return true;
- },
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- parseJSON: function( data ) {
- if ( typeof data !== "string" || !data ) {
- 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, "")) ) {
-
- return ( new Function( "return " + data ) )();
-
- }
- jQuery.error( "Invalid JSON: " + data );
- },
-
- // Cross-browser xml parsing
- parseXML: function( data ) {
- var xml, tmp;
- try {
- if ( window.DOMParser ) { // Standard
- tmp = new DOMParser();
- xml = tmp.parseFromString( data , "text/xml" );
- } else { // IE
- xml = new ActiveXObject( "Microsoft.XMLDOM" );
- xml.async = "false";
- xml.loadXML( data );
- }
- } catch( e ) {
- xml = undefined;
- }
- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
- jQuery.error( "Invalid XML: " + data );
- }
- return xml;
- },
-
- noop: function() {},
-
- // Evaluates a script in a global context
- // 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 && rnotwhite.test( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Microsoft forgot to hump their vendor prefix (#9572)
- camelCase: function( string ) {
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
- },
-
- // args is for internal usage only
- each: function( object, callback, args ) {
- var name, i = 0,
- length = object.length,
- isObj = length === undefined || jQuery.isFunction( object );
-
- if ( args ) {
- if ( isObj ) {
- for ( name in object ) {
- if ( callback.apply( object[ name ], args ) === false ) {
- break;
- }
- }
- } else {
- for ( ; i < length; ) {
- if ( callback.apply( object[ i++ ], args ) === false ) {
- break;
- }
- }
- }
-
- // A special, fast, case for the most common use of each
- } else {
- if ( isObj ) {
- for ( name in object ) {
- if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
- break;
- }
- }
- } else {
- for ( ; i < length; ) {
- if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
- break;
- }
- }
- }
- }
-
- return object;
- },
-
- // Use native String.trim function wherever possible
- trim: trim ?
- function( text ) {
- return text == null ?
- "" :
- trim.call( text );
- } :
-
- // Otherwise use our own trimming functionality
- function( text ) {
- return text == null ?
- "" :
- text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
- },
-
- // results is for internal usage only
- makeArray: function( array, results ) {
- var ret = results || [];
-
- if ( array != null ) {
- // The window, strings (and functions) also have 'length'
- // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
- var type = jQuery.type( array );
-
- if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
- push.call( ret, array );
- } else {
- jQuery.merge( ret, array );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, array, i ) {
- var len;
-
- if ( array ) {
- if ( indexOf ) {
- return indexOf.call( array, elem, i );
- }
-
- len = array.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in array && array[ i ] === elem ) {
- return i;
- }
- }
- }
-
- return -1;
- },
-
- merge: function( first, second ) {
- var i = first.length,
- j = 0;
-
- if ( typeof second.length === "number" ) {
- for ( var l = second.length; j < l; j++ ) {
- first[ i++ ] = second[ j ];
- }
-
- } else {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, inv ) {
- var ret = [], retVal;
- inv = !!inv;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( var i = 0, length = elems.length; i < length; i++ ) {
- retVal = !!callback( elems[ i ], i );
- if ( inv !== retVal ) {
- ret.push( elems[ i ] );
- }
- }
-
- return ret;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var value, key, ret = [],
- 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 ) ) ;
-
- // Go through the array, translating each of the items to their
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret[ ret.length ] = value;
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( key in elems ) {
- value = callback( elems[ key ], key, arg );
-
- if ( value != null ) {
- ret[ ret.length ] = value;
- }
- }
- }
-
- // Flatten any nested arrays
- return ret.concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- if ( typeof context === "string" ) {
- var tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- var args = slice.call( arguments, 2 ),
- proxy = function() {
- return fn.apply( context, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
-
- return proxy;
- },
-
- // Mutifunctional method to get and set values to a collection
- // The value/s can optionally be executed if it's a function
- access: function( elems, key, value, exec, fn, pass ) {
- var length = elems.length;
-
- // Setting many attributes
- if ( typeof key === "object" ) {
- for ( var k in key ) {
- jQuery.access( elems, k, key[k], exec, fn, value );
- }
- return elems;
- }
-
- // Setting one attribute
- if ( value !== undefined ) {
- // Optionally, function values get executed if exec is true
- exec = !pass && exec && jQuery.isFunction(value);
-
- for ( var i = 0; i < length; i++ ) {
- fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
- }
-
- return elems;
- }
-
- // Getting an attribute
- return length ? fn( elems[0], key ) : undefined;
- },
-
- now: function() {
- return ( new Date() ).getTime();
- },
-
- // Use of jQuery.browser is frowned upon.
- // More details: http://docs.jquery.com/Utilities/jQuery.browser
- uaMatch: function( ua ) {
- ua = ua.toLowerCase();
-
- var match = rwebkit.exec( ua ) ||
- ropera.exec( ua ) ||
- rmsie.exec( ua ) ||
- ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
- [];
-
- return { browser: match[1] || "", version: match[2] || "0" };
- },
-
- 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 );
- }
-
- return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
- };
- jQuerySub.fn.init.prototype = jQuerySub.fn;
- var rootjQuerySub = jQuerySub(document);
- return jQuerySub;
- },
-
- browser: {}
-});
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-browserMatch = jQuery.uaMatch( userAgent );
-if ( browserMatch.browser ) {
- jQuery.browser[ browserMatch.browser ] = true;
- jQuery.browser.version = browserMatch.version;
-}
-
-// Deprecated, use jQuery.browser.webkit instead
-if ( jQuery.browser.webkit ) {
- jQuery.browser.safari = true;
-}
-
-// IE doesn't match non-breaking spaces with \s
-if ( rnotwhite.test( "\xA0" ) ) {
- trimLeft = /^[\s\xA0]+/;
- trimRight = /[\s\xA0]+$/;
-}
-
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
-
-// Cleanup functions for the document ready method
-if ( document.addEventListener ) {
- DOMContentLoaded = function() {
- document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
- jQuery.ready();
- };
-
-} else if ( document.attachEvent ) {
- DOMContentLoaded = function() {
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( document.readyState === "complete" ) {
- document.detachEvent( "onreadystatechange", DOMContentLoaded );
- jQuery.ready();
- }
- };
-}
-
-// The DOM ready check for Internet Explorer
-function doScrollCheck() {
- if ( jQuery.isReady ) {
- return;
- }
-
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch(e) {
- setTimeout( doScrollCheck, 1 );
- return;
- }
-
- // and execute any waiting functions
- jQuery.ready();
-}
-
-return jQuery;
-
-})();
-
-
-// String to Object flags format cache
-var flagsCache = {};
-
-// Convert String-formatted flags into Object-formatted ones and store in cache
-function createFlags( flags ) {
- var object = flagsCache[ flags ] = {},
- i, length;
- flags = flags.split( /\s+/ );
- for ( i = 0, length = flags.length; i < length; i++ ) {
- object[ flags[i] ] = true;
- }
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * flags: an optional list of space-separated flags that will change how
- * the callback list behaves
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible flags:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( flags ) {
-
- // Convert flags from String-formatted to Object-formatted
- // (we check in cache first)
- flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
-
- var // Actual callback list
- list = [],
- // Stack of fire calls for repeatable lists
- stack = [],
- // Last fire value (for non-forgettable lists)
- memory,
- // 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,
- // Add one or several callbacks to the list
- add = function( args ) {
- var i,
- length,
- elem,
- type,
- actual;
- for ( i = 0, length = args.length; i < length; i++ ) {
- elem = args[ i ];
- type = jQuery.type( elem );
- if ( type === "array" ) {
- // Inspect recursively
- add( elem );
- } else if ( type === "function" ) {
- // Add if not in unique mode and callback is not in
- if ( !flags.unique || !self.has( elem ) ) {
- list.push( elem );
- }
- }
- }
- },
- // Fire callbacks
- fire = function( context, args ) {
- args = args || [];
- memory = !flags.memory || [ context, args ];
- firing = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
- memory = true; // Mark as halted
- break;
- }
- }
- firing = false;
- if ( list ) {
- if ( !flags.once ) {
- if ( stack && stack.length ) {
- memory = stack.shift();
- self.fireWith( memory[ 0 ], memory[ 1 ] );
- }
- } else if ( memory === true ) {
- self.disable();
- } else {
- list = [];
- }
- }
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- var length = list.length;
- add( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away, unless previous
- // firing was halted (stopOnFalse)
- } else if ( memory && memory !== true ) {
- firingStart = length;
- fire( memory[ 0 ], memory[ 1 ] );
- }
- }
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- if ( list ) {
- var args = arguments,
- argIndex = 0,
- argLength = args.length;
- for ( ; argIndex < argLength ; argIndex++ ) {
- for ( var i = 0; i < list.length; i++ ) {
- if ( args[ argIndex ] === list[ i ] ) {
- // Handle firingIndex and firingLength
- if ( firing ) {
- if ( i <= firingLength ) {
- firingLength--;
- if ( i <= firingIndex ) {
- firingIndex--;
- }
- }
- }
- // Remove the element
- list.splice( i--, 1 );
- // If we have some unicity property then
- // we only need to do this once
- if ( flags.unique ) {
- break;
- }
- }
- }
- }
- }
- return this;
- },
- // Control if a given callback is in the list
- has: function( fn ) {
- if ( list ) {
- var i = 0,
- length = list.length;
- for ( ; i < length; i++ ) {
- if ( fn === list[ i ] ) {
- return true;
- }
- }
- }
- return false;
- },
- // Remove all callbacks from the list
- empty: function() {
- list = [];
- return this;
- },
- // Have the list do nothing anymore
- disable: function() {
- list = stack = memory = undefined;
- return this;
- },
- // Is it disabled?
- disabled: function() {
- return !list;
- },
- // Lock the list in its current state
- lock: function() {
- stack = undefined;
- if ( !memory || memory === true ) {
- self.disable();
- }
- return this;
- },
- // Is it locked?
- locked: function() {
- return !stack;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( stack ) {
- if ( firing ) {
- if ( !flags.once ) {
- stack.push( [ context, args ] );
- }
- } else if ( !( flags.once && memory ) ) {
- fire( context, args );
- }
- }
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!memory;
- }
- };
-
- return self;
-};
-
-
-
-
-var // Static reference to slice
- sliceDeferred = [].slice;
-
-jQuery.extend({
-
- Deferred: function( func ) {
- var doneList = jQuery.Callbacks( "once memory" ),
- failList = jQuery.Callbacks( "once memory" ),
- progressList = jQuery.Callbacks( "memory" ),
- state = "pending",
- lists = {
- resolve: doneList,
- reject: failList,
- notify: progressList
- },
- promise = {
- done: doneList.add,
- fail: failList.add,
- progress: progressList.add,
-
- state: function() {
- return state;
- },
-
- // Deprecated
- isResolved: doneList.fired,
- isRejected: failList.fired,
-
- then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
- deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
- return this;
- },
- always: function() {
- deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
- return this;
- },
- pipe: function( fnDone, fnFail, fnProgress ) {
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( {
- done: [ fnDone, "resolve" ],
- fail: [ fnFail, "reject" ],
- progress: [ fnProgress, "notify" ]
- }, function( handler, data ) {
- var fn = data[ 0 ],
- action = data[ 1 ],
- returned;
- if ( jQuery.isFunction( fn ) ) {
- deferred[ handler ](function() {
- returned = fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
- } else {
- newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
- }
- });
- } else {
- deferred[ handler ]( newDefer[ action ] );
- }
- });
- }).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- if ( obj == null ) {
- obj = promise;
- } else {
- for ( var key in promise ) {
- obj[ key ] = promise[ key ];
- }
- }
- return obj;
- }
- },
- deferred = promise.promise({}),
- key;
-
- for ( key in lists ) {
- deferred[ key ] = lists[ key ].fire;
- deferred[ key + "With" ] = lists[ key ].fireWith;
- }
-
- // Handle state
- deferred.done( function() {
- state = "resolved";
- }, failList.disable, progressList.lock ).fail( function() {
- state = "rejected";
- }, doneList.disable, progressList.lock );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( firstParam ) {
- var args = sliceDeferred.call( arguments, 0 ),
- i = 0,
- length = args.length,
- pValues = new Array( length ),
- count = length,
- pCount = length,
- deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
- firstParam :
- jQuery.Deferred(),
- promise = deferred.promise();
- function resolveFunc( i ) {
- return function( value ) {
- args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
- if ( !( --count ) ) {
- deferred.resolveWith( deferred, args );
- }
- };
- }
- function progressFunc( i ) {
- return function( value ) {
- pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
- deferred.notifyWith( promise, pValues );
- };
- }
- if ( length > 1 ) {
- for ( ; i < length; i++ ) {
- if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
- args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
- } else {
- --count;
- }
- }
- if ( !count ) {
- deferred.resolveWith( deferred, args );
- }
- } else if ( deferred !== firstParam ) {
- deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
- }
- return promise;
- }
-});
-
-
-
-
-jQuery.support = (function() {
-
- var support,
- all,
- a,
- select,
- opt,
- input,
- marginDiv,
- fragment,
- tds,
- events,
- eventName,
- i,
- isSupported,
- div = document.createElement( "div" ),
- documentElement = document.documentElement;
-
- // Preliminary tests
- div.setAttribute("className", "t");
- div.innerHTML = "
a";
-
- all = div.getElementsByTagName( "*" );
- a = div.getElementsByTagName( "a" )[ 0 ];
-
- // Can't get basic test support
- if ( !all || !all.length || !a ) {
- return {};
- }
-
- // First batch of supports tests
- select = document.createElement( "select" );
- opt = select.appendChild( document.createElement("option") );
- input = div.getElementsByTagName( "input" )[ 0 ];
-
- 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.55/.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>",
-
- // Will be defined later
- submitBubbles: true,
- changeBubbles: true,
- focusinBubbles: false,
- deleteExpando: true,
- noCloneEvent: true,
- inlineBlockNeedsLayout: false,
- shrinkWrapBlocks: false,
- reliableMarginRight: true
- };
-
- // Make sure checked status is properly cloned
- input.checked = true;
- support.noCloneChecked = input.cloneNode( true ).checked;
-
- // Make sure that the options inside disabled selects aren't marked as disabled
- // (WebKit marks them as disabled)
- 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
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
-
- if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
- div.attachEvent( "onclick", function() {
- // Cloning a node shouldn't copy over any
- // bound event handlers (IE does this)
- support.noCloneEvent = false;
- });
- div.cloneNode( true ).fireEvent( "onclick" );
- }
-
- // Check if a radio maintains its value
- // after being appended to the DOM
- input = document.createElement("input");
- input.value = "t";
- input.setAttribute("type", "radio");
- support.radioValue = input.value === "t";
-
- input.setAttribute("checked", "checked");
- 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;
-
- // 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 );
-
- div.innerHTML = "";
-
- // 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
- // Fails in WebKit before Feb 2011 nightlies
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
- if ( window.getComputedStyle ) {
- marginDiv = document.createElement( "div" );
- marginDiv.style.width = "0";
- marginDiv.style.marginRight = "0";
- div.style.width = "2px";
- div.appendChild( marginDiv );
- support.reliableMarginRight =
- ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
- }
-
- // 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
- if ( div.attachEvent ) {
- for( i in {
- submit: 1,
- change: 1,
- focusin: 1
- }) {
- eventName = "on" + i;
- isSupported = ( eventName in div );
- if ( !isSupported ) {
- div.setAttribute( eventName, "return;" );
- isSupported = ( typeof div[ eventName ] === "function" );
- }
- support[ i + "Bubbles" ] = isSupported;
- }
- }
-
- fragment.removeChild( div );
-
- // Null elements to avoid leaks in IE
- fragment = select = opt = marginDiv = div = input = null;
-
- // Run tests that need a body at doc ready
- jQuery(function() {
- var container, outer, inner, table, td, offsetSupport,
- conMarginTop, ptlm, vb, style, html,
- body = document.getElementsByTagName("body")[0];
-
- if ( !body ) {
- // Return for frameset docs that don't have a body
- return;
- }
-
- conMarginTop = 1;
- ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
- vb = "visibility:hidden;border:0;";
- style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
- html = "
" +
- "
" +
- "
";
-
- container = document.createElement("div");
- container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
- body.insertBefore( container, body.firstChild );
-
- // Construct the test element
- div = document.createElement("div");
- container.appendChild( div );
-
- // 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 = "
t
";
- tds = div.getElementsByTagName( "td" );
- isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
- tds[ 0 ].style.display = "";
- tds[ 1 ].style.display = "none";
-
- // Check if empty table cells still have offsetWidth/Height
- // (IE <= 8 fail this test)
- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
- // Figure out if the W3C box model works as expected
- div.innerHTML = "";
- div.style.width = div.style.paddingLeft = "1px";
- jQuery.boxModel = support.boxModel = div.offsetWidth === 2;
-
- if ( typeof div.style.zoom !== "undefined" ) {
- // 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.style.display = "inline";
- div.style.zoom = 1;
- support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
-
- // Check if elements with layout shrink-wrap their children
- // (IE 6 does this)
- div.style.display = "";
- div.innerHTML = "";
- support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
- }
-
- div.style.cssText = ptlm + vb;
- div.innerHTML = html;
-
- outer = div.firstChild;
- inner = outer.firstChild;
- td = outer.nextSibling.firstChild.firstChild;
-
- offsetSupport = {
- doesNotAddBorder: ( inner.offsetTop !== 5 ),
- doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
- };
-
- inner.style.position = "fixed";
- inner.style.top = "20px";
-
- // safari subtracts parent border width here which is 5px
- offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
- inner.style.position = inner.style.top = "";
-
- outer.style.overflow = "hidden";
- outer.style.position = "relative";
-
- offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
- offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
-
- body.removeChild( container );
- div = container = null;
-
- jQuery.extend( support, offsetSupport );
- });
-
- return support;
-})();
-
-
-
-
-var rbrace = /^(?:\{.*\}|\[.*\])$/,
- rmultiDash = /([A-Z])/g;
-
-jQuery.extend({
- cache: {},
-
- // Please use with caution
- uuid: 0,
-
- // 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, "" ),
-
- // 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
- },
-
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
-
- data: function( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var privateCache, 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,
- isEvents = name === "events";
-
- // 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] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
- 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 ) {
- elem[ internalKey ] = id = ++jQuery.uuid;
- } else {
- id = internalKey;
- }
- }
-
- 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;
- }
- }
-
- // 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 );
- }
- }
-
- privateCache = 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;
- }
-
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
-
- // Users should not attempt to inspect the internal events object using jQuery.data,
- // it is undocumented and subject to change. But does anyone listen? No.
- if ( isEvents && !thisCache[ name ] ) {
- return privateCache.events;
- }
-
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( getByName ) {
-
- // First Try to find as-is property data
- ret = thisCache[ name ];
-
- // Test for null|undefined property data
- if ( ret == null ) {
-
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
-
- return ret;
- },
-
- removeData: function( elem, name, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, i, l,
-
- // Reference to internal data cache key
- internalKey = jQuery.expando,
-
- isNode = elem.nodeType,
-
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
-
- // See jQuery.data for more information
- id = isNode ? elem[ internalKey ] : internalKey;
-
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
-
- if ( name ) {
-
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
- if ( thisCache ) {
-
- // 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 {
-
- // 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( " " );
- }
- }
- }
-
- for ( i = 0, l = name.length; i < l; 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;
- }
- }
- }
-
- // 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;
- }
- }
-
- // Browsers that fail expando deletion also refuse to delete expandos on
- // the window, but it will allow it on all other JS objects; other browsers
- // don't care
- // Ensure that `cache` is not a window object #10080
- if ( jQuery.support.deleteExpando || !cache.setInterval ) {
- delete cache[ id ];
- } else {
- cache[ id ] = null;
- }
-
- // We destroyed the cache and need to eliminate the expando on the node to avoid
- // false lookups in the cache for entries that no longer exist
- if ( isNode ) {
- // IE does not allow us to delete expando properties from nodes,
- // nor does it have a removeAttribute function on Document nodes;
- // we must handle all of these cases
- if ( jQuery.support.deleteExpando ) {
- delete elem[ internalKey ];
- } else if ( elem.removeAttribute ) {
- elem.removeAttribute( internalKey );
- } else {
- elem[ internalKey ] = null;
- }
- }
- },
-
- // For internal use only.
- _data: function( elem, name, data ) {
- return jQuery.data( elem, name, data, true );
- },
-
- // A method for determining if a DOM node can handle the data expando
- acceptData: function( elem ) {
- if ( elem.nodeName ) {
- var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
-
- if ( match ) {
- return !(match === true || elem.getAttribute("classid") !== match);
- }
- }
-
- return true;
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ) {
- var parts, attr, name,
- data = null;
-
- if ( typeof key === "undefined" ) {
- if ( this.length ) {
- data = jQuery.data( this[0] );
-
- if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
- attr = this[0].attributes;
- for ( var i = 0, l = attr.length; i < l; i++ ) {
- name = attr[i].name;
-
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.substring(5) );
-
- dataAttr( this[0], name, data[ name ] );
- }
- }
- jQuery._data( this[0], "parsedAttrs", true );
- }
- }
-
- return data;
-
- } else if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
-
- parts = key.split(".");
- parts[1] = parts[1] ? "." + parts[1] : "";
-
- if ( value === undefined ) {
- data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
-
- // Try to fetch any internally stored data first
- if ( data === undefined && this.length ) {
- data = jQuery.data( this[0], key );
- data = dataAttr( this[0], key, data );
- }
-
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
-
- } else {
- return this.each(function() {
- var self = jQuery( this ),
- args = [ parts[0], value ];
-
- self.triggerHandler( "setData" + parts[1] + "!", args );
- jQuery.data( this, key, value );
- self.triggerHandler( "changeData" + parts[1] + "!", args );
- });
- }
- },
-
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
-
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- jQuery.isNumeric( data ) ? parseFloat( data ) :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
-
- } else {
- data = undefined;
- }
- }
-
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- for ( var name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
-
- return true;
-}
-
-
-
-
-function handleQueueMarkDefer( elem, type, src ) {
- var deferDataKey = type + "defer",
- queueDataKey = type + "queue",
- markDataKey = type + "mark",
- defer = jQuery._data( elem, deferDataKey );
- if ( defer &&
- ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
- ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
- // Give room for hard-coded callbacks to fire first
- // and eventually mark/queue something else on the element
- setTimeout( function() {
- if ( !jQuery._data( elem, queueDataKey ) &&
- !jQuery._data( elem, markDataKey ) ) {
- jQuery.removeData( elem, deferDataKey, true );
- defer.fire();
- }
- }, 0 );
- }
-}
-
-jQuery.extend({
-
- _mark: function( elem, type ) {
- if ( elem ) {
- type = ( type || "fx" ) + "mark";
- jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
- }
- },
-
- _unmark: function( force, elem, type ) {
- if ( force !== true ) {
- type = elem;
- elem = force;
- force = false;
- }
- if ( elem ) {
- type = type || "fx";
- var key = type + "mark",
- count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
- if ( count ) {
- jQuery._data( elem, key, count );
- } else {
- jQuery.removeData( elem, key, true );
- handleQueueMarkDefer( elem, type, "mark" );
- }
- }
- },
-
- queue: function( elem, type, data ) {
- var q;
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- q = jQuery._data( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !q || jQuery.isArray(data) ) {
- q = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- q.push( data );
- }
- }
- return q || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- fn = queue.shift(),
- hooks = {};
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- }
-
- if ( fn ) {
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- jQuery._data( elem, type + ".run", hooks );
- fn.call( elem, function() {
- jQuery.dequeue( elem, type );
- }, hooks );
- }
-
- if ( !queue.length ) {
- jQuery.removeData( elem, type + "queue " + type + ".run", true );
- handleQueueMarkDefer( elem, type, "queue" );
- }
- }
-});
-
-jQuery.fn.extend({
- queue: function( type, data ) {
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- }
-
- if ( data === undefined ) {
- return jQuery.queue( this[0], type );
- }
- return this.each(function() {
- var queue = jQuery.queue( this, type, data );
-
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- // Based off of the plugin by Clint Helfers, with permission.
- // http://blindsignals.com/index.php/2009/07/jquery-delay/
- delay: function( time, type ) {
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
- type = type || "fx";
-
- return this.queue( type, function( next, hooks ) {
- var timeout = setTimeout( next, time );
- hooks.stop = function() {
- clearTimeout( timeout );
- };
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, object ) {
- if ( typeof type !== "string" ) {
- object = type;
- type = undefined;
- }
- type = type || "fx";
- var defer = jQuery.Deferred(),
- elements = this,
- i = elements.length,
- count = 1,
- deferDataKey = type + "defer",
- queueDataKey = type + "queue",
- markDataKey = type + "mark",
- tmp;
- function resolve() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- }
- while( i-- ) {
- if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
- ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
- jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
- jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
- count++;
- tmp.add( resolve );
- }
- }
- resolve();
- return defer.promise();
- }
-});
-
-
-
-
-var rclass = /[\n\t\r]/g,
- rspace = /\s+/,
- 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,
- nodeHook, boolHook, fixSpecified;
-
-jQuery.fn.extend({
- attr: function( name, value ) {
- return jQuery.access( this, name, value, true, jQuery.attr );
- },
-
- removeAttr: function( name ) {
- return this.each(function() {
- jQuery.removeAttr( this, name );
- });
- },
-
- prop: function( name, value ) {
- return jQuery.access( this, name, value, true, jQuery.prop );
- },
-
- removeProp: function( name ) {
- name = jQuery.propFix[ name ] || name;
- return this.each(function() {
- // try/catch handles cases where IE balks (such as removing a property on window)
- try {
- this[ name ] = undefined;
- delete this[ name ];
- } catch( e ) {}
- });
- },
-
- addClass: function( value ) {
- var classNames, i, l, elem,
- setClass, c, cl;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).addClass( value.call(this, j, this.className) );
- });
- }
-
- if ( value && typeof value === "string" ) {
- classNames = value.split( rspace );
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
-
- 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 ] + " " ) ) {
- setClass += classNames[ c ] + " ";
- }
- }
- elem.className = jQuery.trim( setClass );
- }
- }
- }
- }
-
- return this;
- },
-
- removeClass: function( value ) {
- var classNames, i, l, elem, className, c, cl;
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( j ) {
- jQuery( this ).removeClass( value.call(this, j, this.className) );
- });
- }
-
- if ( (value && typeof value === "string") || value === undefined ) {
- classNames = ( value || "" ).split( rspace );
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- elem = this[ i ];
-
- if ( elem.nodeType === 1 && elem.className ) {
- if ( value ) {
- className = (" " + elem.className + " ").replace( rclass, " " );
- for ( c = 0, cl = classNames.length; c < cl; c++ ) {
- className = className.replace(" " + classNames[ c ] + " ", " ");
- }
- elem.className = jQuery.trim( className );
-
- } else {
- elem.className = "";
- }
- }
- }
- }
-
- return this;
- },
-
- toggleClass: function( value, stateVal ) {
- var type = typeof value,
- isBool = typeof stateVal === "boolean";
-
- if ( jQuery.isFunction( value ) ) {
- return this.each(function( i ) {
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
- });
- }
-
- return this.each(function() {
- if ( type === "string" ) {
- // toggle individual class names
- var className,
- i = 0,
- self = jQuery( this ),
- state = stateVal,
- classNames = value.split( rspace );
-
- while ( (className = classNames[ i++ ]) ) {
- // check each className given, space seperated list
- state = isBool ? state : !self.hasClass( className );
- self[ state ? "addClass" : "removeClass" ]( className );
- }
-
- } else if ( type === "undefined" || type === "boolean" ) {
- if ( this.className ) {
- // store className if set
- jQuery._data( this, "__className__", this.className );
- }
-
- // toggle whole className
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
- }
- });
- },
-
- hasClass: function( selector ) {
- var className = " " + selector + " ",
- i = 0,
- l = this.length;
- for ( ; i < l; i++ ) {
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
- return true;
- }
- }
-
- return false;
- },
-
- val: function( value ) {
- var hooks, ret, isFunction,
- elem = this[0];
-
- if ( !arguments.length ) {
- if ( elem ) {
- hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
-
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
- return ret;
- }
-
- ret = elem.value;
-
- return typeof ret === "string" ?
- // handle most common string cases
- ret.replace(rreturn, "") :
- // handle cases where value is null/undef or number
- ret == null ? "" : ret;
- }
-
- return;
- }
-
- isFunction = jQuery.isFunction( value );
-
- return this.each(function( i ) {
- var self = jQuery(this), val;
-
- if ( this.nodeType !== 1 ) {
- return;
- }
-
- if ( isFunction ) {
- val = value.call( this, i, self.val() );
- } else {
- val = value;
- }
-
- // Treat null/undefined as ""; convert numbers to string
- if ( val == null ) {
- val = "";
- } else if ( typeof val === "number" ) {
- val += "";
- } else if ( jQuery.isArray( val ) ) {
- val = jQuery.map(val, function ( value ) {
- return value == null ? "" : value + "";
- });
- }
-
- hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
-
- // If set returns undefined, fall back to normal setting
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
- this.value = val;
- }
- });
- }
-});
-
-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;
- }
- },
- select: {
- get: function( elem ) {
- var value, i, max, option,
- index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type === "select-one";
-
- // Nothing was selected
- if ( index < 0 ) {
- return null;
- }
-
- // Loop through all the selected options
- i = one ? index : 0;
- max = one ? index + 1 : options.length;
- for ( ; i < max; i++ ) {
- option = options[ i ];
-
- // Don't return options that are disabled or in a disabled optgroup
- if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
- (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
-
- // Get the specific value for the option
- value = jQuery( option ).val();
-
- // We don't need an array for one selects
- if ( one ) {
- return value;
- }
-
- // Multi-Selects return an array
- values.push( value );
- }
- }
-
- // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
- if ( one && !values.length && options.length ) {
- return jQuery( options[ index ] ).val();
- }
-
- return values;
- },
-
- set: function( elem, value ) {
- var values = jQuery.makeArray( value );
-
- jQuery(elem).find("option").each(function() {
- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
- });
-
- if ( !values.length ) {
- elem.selectedIndex = -1;
- }
- return values;
- }
- }
- },
-
- attrFn: {
- val: true,
- css: true,
- html: true,
- text: true,
- data: true,
- width: true,
- height: true,
- offset: true
- },
-
- attr: function( elem, name, value, pass ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set attributes on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- if ( pass && name in jQuery.attrFn ) {
- return jQuery( elem )[ name ]( value );
- }
-
- // Fallback to prop when attributes are not supported
- if ( typeof elem.getAttribute === "undefined" ) {
- 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 ) {
- name = name.toLowerCase();
- hooks = jQuery.attrHooks[ name ] || ( rboolean.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 ) {
- return ret;
-
- } else {
- elem.setAttribute( name, "" + value );
- return value;
- }
-
- } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
-
- ret = elem.getAttribute( name );
-
- // Non-existent attributes return null, we normalize to undefined
- return ret === null ?
- undefined :
- ret;
- }
- },
-
- removeAttr: function( elem, value ) {
- var propName, attrNames, name, l,
- i = 0;
-
- if ( value && elem.nodeType === 1 ) {
- attrNames = value.toLowerCase().split( rspace );
- l = attrNames.length;
-
- for ( ; i < l; i++ ) {
- name = attrNames[ i ];
-
- if ( name ) {
- propName = jQuery.propFix[ name ] || name;
-
- // See #9699 for explanation of this approach (setting first, then removal)
- jQuery.attr( elem, name, "" );
- elem.removeAttribute( getSetAttribute ? name : propName );
-
- // Set corresponding property to false for boolean attributes
- if ( rboolean.test( name ) && propName in elem ) {
- elem[ propName ] = false;
- }
- }
- }
- }
- },
-
- 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") ) {
- // 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
- var val = elem.value;
- elem.setAttribute( "type", value );
- if ( val ) {
- elem.value = val;
- }
- 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"
- },
-
- prop: function( elem, name, value ) {
- var ret, hooks, notxml,
- nType = elem.nodeType;
-
- // don't get/set properties on text, comment and attribute nodes
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
- return;
- }
-
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
- if ( notxml ) {
- // Fix name and attach hooks
- name = jQuery.propFix[ name ] || name;
- hooks = jQuery.propHooks[ name ];
- }
-
- if ( value !== undefined ) {
- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
- return ret;
-
- } else {
- return ( elem[ name ] = value );
- }
-
- } else {
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
- return ret;
-
- } else {
- return elem[ name ];
- }
- }
- },
-
- propHooks: {
- tabIndex: {
- 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");
-
- return attributeNode && attributeNode.specified ?
- parseInt( attributeNode.value, 10 ) :
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
- 0 :
- undefined;
- }
- }
- }
-});
-
-// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
-jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
-
-// Hook 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;
- }
-
- elem.setAttribute( name, name.toLowerCase() );
- }
- return name;
- }
-};
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
- fixSpecified = {
- name: true,
- id: 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.nodeValue !== "" : ret.specified ) ?
- ret.nodeValue :
- undefined;
- },
- 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 );
- }
- return ( ret.nodeValue = value + "" );
- }
- };
-
- // Apply the nodeHook to tabindex
- jQuery.attrHooks.tabindex.set = nodeHook.set;
-
- // 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 ], {
- 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
-if ( !jQuery.support.hrefNormalized ) {
- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
- get: function( elem ) {
- var ret = elem.getAttribute( name, 2 );
- return ret === null ? undefined : ret;
- }
- });
- });
-}
-
-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;
- },
- set: function( elem, value ) {
- return ( elem.style.cssText = "" + value );
- }
- };
-}
-
-// 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, {
- get: function( elem ) {
- var parent = elem.parentNode;
-
- if ( parent ) {
- parent.selectedIndex;
-
- // Make sure that it also works with optgroups, see #5701
- if ( parent.parentNode ) {
- parent.parentNode.selectedIndex;
- }
- }
- return null;
- }
- });
-}
-
-// 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 ], {
- set: function( elem, value ) {
- if ( jQuery.isArray( value ) ) {
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
- }
- }
- });
-});
-
-
-
-
-var rformElems = /^(?:textarea|input|select)$/i,
- rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
- rhoverHack = /\bhover(\.\S+)?\b/,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
- quickParse = function( selector ) {
- var quick = rquickIs.exec( selector );
- if ( quick ) {
- // 0 1 2 3
- // [ _, tag, id, class ]
- quick[1] = ( quick[1] || "" ).toLowerCase();
- quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
- }
- return quick;
- },
- quickIs = function( elem, m ) {
- var attrs = elem.attributes || {};
- return (
- (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
- (!m[2] || (attrs.id || {}).value === m[2]) &&
- (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
- );
- },
- hoverHack = function( events ) {
- return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
- };
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- add: function( elem, types, handler, data, selector ) {
-
- var elemData, eventHandle, events,
- t, tns, type, namespaces, handleObj,
- handleObjIn, quick, handlers, special;
-
- // 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 )) ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- events = elemData.events;
- if ( !events ) {
- elemData.events = events = {};
- }
- eventHandle = elemData.handle;
- if ( !eventHandle ) {
- elemData.handle = eventHandle = 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) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
- };
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
- }
-
- // 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();
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: tns[1],
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- quick: quickParse( selector ),
- namespace: namespaces.join(".")
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- handlers = events[ type ];
- if ( !handlers ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
-
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- global: {},
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
-
- var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
- t, tns, type, origType, namespaces, origCount,
- j, events, special, handle, eventType, handleObj;
-
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
-
- // 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];
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- 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;
-
- // Remove matching events
- for ( j = 0; j < eventType.length; j++ ) {
- handleObj = eventType[ 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 );
-
- if ( handleObj.selector ) {
- eventType.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // 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 ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- handle = elemData.handle;
- if ( handle ) {
- handle.elem = null;
- }
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery.removeData( elem, [ "events", "handle" ], true );
- }
- },
-
- // 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 ) {
- // Don't do events on text and comment nodes
- if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
- return;
- }
-
- // Event object or event type
- var type = event.type || event,
- namespaces = [],
- cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
-
- // 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 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
-
- 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 ) {
-
- // 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;
- }
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data != null ? jQuery.makeArray( data ) : [];
- data.unshift( event );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( 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;
- old = null;
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push([ cur, bubbleType ]);
- old = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( old && old === elem.ownerDocument ) {
- eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
- }
- }
-
- // Fire handlers on the event path
- for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
-
- cur = eventPath[i][0];
- event.type = eventPath[i][1];
-
- 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
- handle = ontype && cur[ ontype ];
- if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
- event.preventDefault();
- }
- }
- event.type = type;
-
- // 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 ) ) {
-
- // 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 ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- old = elem[ ontype ];
-
- if ( old ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- elem[ type ]();
- jQuery.event.triggered = undefined;
-
- if ( old ) {
- elem[ ontype ] = old;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
-
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event || window.event );
-
- var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
- delegateCount = handlers.delegateCount,
- args = [].slice.call( arguments, 0 ),
- run_all = !event.exclusive && !event.namespace,
- handlerQueue = [],
- i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
-
- // Determine handlers that should run if there are delegated events
- // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
- if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
-
- // Pregenerate a single jQuery object for reuse with .is()
- jqcur = jQuery(this);
- jqcur.context = this.ownerDocument || this;
-
- for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
- selMatch = {};
- matches = [];
- jqcur[0] = cur;
- for ( i = 0; i < delegateCount; i++ ) {
- handleObj = handlers[ i ];
- sel = handleObj.selector;
-
- if ( selMatch[ sel ] === undefined ) {
- selMatch[ sel ] = (
- handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
- );
- }
- if ( selMatch[ sel ] ) {
- matches.push( handleObj );
- }
- }
- if ( matches.length ) {
- handlerQueue.push({ elem: cur, matches: matches });
- }
- }
- }
-
- // Add the remaining (directly-bound) handlers
- if ( handlers.length > delegateCount ) {
- handlerQueue.push({ elem: this, matches: 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;
-
- for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
- handleObj = matched.matches[ j ];
-
- // 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 ) ) {
-
- event.data = handleObj.data;
- event.handleObj = handleObj;
-
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- event.result = ret;
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- return event.result;
- },
-
- // 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(" "),
-
- fixHooks: {},
-
- keyHooks: {
- props: "char charCode key keyCode".split(" "),
- filter: function( event, original ) {
-
- // Add which for key events
- if ( event.which == null ) {
- event.which = original.charCode != null ? original.charCode : original.keyCode;
- }
-
- return event;
- }
- },
-
- mouseHooks: {
- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
- filter: function( event, original ) {
- var eventDoc, doc, body,
- button = original.button,
- fromElement = original.fromElement;
-
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && original.clientX != null ) {
- eventDoc = event.target.ownerDocument || document;
- doc = eventDoc.documentElement;
- body = eventDoc.body;
-
- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
- }
-
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && fromElement ) {
- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
- }
-
- // Add which for click: 1 === left; 2 === middle; 3 === right
- // Note: button is not normalized, so don't use it
- if ( !event.which && button !== undefined ) {
- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
- }
-
- return 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; add metaKey if it's not there (#3368, IE6/7/8)
- if ( event.metaKey === undefined ) {
- event.metaKey = event.ctrlKey;
- }
-
- return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
- },
-
- special: {
- ready: {
- // Make sure the ready event is setup
- setup: jQuery.bindReady
- },
-
- load: {
- // Prevent triggered image.load events from bubbling to window.load
- noBubble: true
- },
-
- focus: {
- delegateType: "focusin"
- },
- blur: {
- 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;
- }
- },
-
- teardown: function( namespaces, eventHandle ) {
- if ( this.onbeforeunload === eventHandle ) {
- this.onbeforeunload = null;
- }
- }
- }
- },
-
- simulate: function( type, elem, event, bubble ) {
- // Piggyback on a donor event to simulate a different one.
- // Fake originalEvent to avoid donor's stopPropagation, but if the
- // simulated event prevents default then we do the same on the donor.
- var e = jQuery.extend(
- new jQuery.Event(),
- event,
- { type: type,
- isSimulated: true,
- originalEvent: {}
- }
- );
- if ( bubble ) {
- jQuery.event.trigger( e, null, elem );
- } else {
- jQuery.event.dispatch.call( elem, e );
- }
- if ( e.isDefaultPrevented() ) {
- event.preventDefault();
- }
- }
-};
-
-// 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 ) {
- elem.removeEventListener( type, handle, false );
- }
- } :
- function( elem, type, handle ) {
- if ( elem.detachEvent ) {
- elem.detachEvent( "on" + type, handle );
- }
- };
-
-jQuery.Event = function( src, props ) {
- // Allow instantiation without the 'new' keyword
- if ( !(this instanceof jQuery.Event) ) {
- return new jQuery.Event( src, props );
- }
-
- // Event object
- if ( src && src.type ) {
- this.originalEvent = src;
- this.type = src.type;
-
- // Events bubbling up the document may have been marked as prevented
- // by a handler lower down the tree; reflect the correct value.
- this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
- src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
-
- // Event type
- } else {
- this.type = src;
- }
-
- // Put explicitly provided properties onto the event object
- if ( props ) {
- jQuery.extend( this, props );
- }
-
- // Create a timestamp if incoming event doesn't have one
- this.timeStamp = src && src.timeStamp || jQuery.now();
-
- // Mark it as fixed
- 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;
-
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
-
- // 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)
- } else {
- e.returnValue = false;
- }
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
-
- var e = this.originalEvent;
- if ( !e ) {
- return;
- }
- // 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)
- 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
-jQuery.each({
- mouseenter: "mouseover",
- mouseleave: "mouseout"
-}, function( orig, fix ) {
- jQuery.event.special[ orig ] = {
- delegateType: fix,
- bindType: fix,
-
- handle: function( event ) {
- var target = this,
- related = event.relatedTarget,
- handleObj = event.handleObj,
- selector = handleObj.selector,
- ret;
-
- // For mousenter/leave call the handler if related is outside the target.
- // NB: No relatedTarget if the mouse left/entered the browser window
- if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
- event.type = handleObj.origType;
- ret = handleObj.handler.apply( this, arguments );
- event.type = fix;
- }
- return ret;
- }
- };
-});
-
-// IE submit delegation
-if ( !jQuery.support.submitBubbles ) {
-
- jQuery.event.special.submit = {
- setup: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
-
- // Lazy-add a submit handler when a descendant form may potentially be submitted
- jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
- // 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 && !form._submit_attached ) {
- jQuery.event.add( form, "submit._submit", function( event ) {
- // If form was submitted by the user, bubble the event up the tree
- if ( this.parentNode && !event.isTrigger ) {
- jQuery.event.simulate( "submit", this.parentNode, event, true );
- }
- });
- form._submit_attached = true;
- }
- });
- // return undefined since we don't need an event listener
- },
-
- teardown: function() {
- // Only need this for delegated form submit events
- if ( jQuery.nodeName( this, "form" ) ) {
- return false;
- }
-
- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
- jQuery.event.remove( this, "._submit" );
- }
- };
-}
-
-// IE change delegation and checkbox/radio fix
-if ( !jQuery.support.changeBubbles ) {
-
- jQuery.event.special.change = {
-
- setup: function() {
-
- if ( rformElems.test( this.nodeName ) ) {
- // IE doesn't fire change on a check/radio until blur; trigger it on click
- // after a propertychange. Eat the blur-change in special.change.handle.
- // This still fires onchange a second time for check/radio after blur.
- if ( this.type === "checkbox" || this.type === "radio" ) {
- jQuery.event.add( this, "propertychange._change", function( event ) {
- if ( event.originalEvent.propertyName === "checked" ) {
- this._just_changed = true;
- }
- });
- jQuery.event.add( this, "click._change", function( event ) {
- if ( this._just_changed && !event.isTrigger ) {
- this._just_changed = false;
- jQuery.event.simulate( "change", this, event, true );
- }
- });
- }
- return false;
- }
- // Delegated event; lazy-add a change handler on descendant inputs
- jQuery.event.add( this, "beforeactivate._change", function( e ) {
- var elem = e.target;
-
- if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
- jQuery.event.add( elem, "change._change", function( event ) {
- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
- jQuery.event.simulate( "change", this.parentNode, event, true );
- }
- });
- elem._change_attached = true;
- }
- });
- },
-
- handle: function( event ) {
- var elem = event.target;
-
- // Swallow native change events from checkbox/radio, we already triggered them above
- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
- return event.handleObj.handler.apply( this, arguments );
- }
- },
-
- teardown: function() {
- jQuery.event.remove( this, "._change" );
-
- return rformElems.test( this.nodeName );
- }
- };
-}
-
-// Create "bubbling" focus and blur events
-if ( !jQuery.support.focusinBubbles ) {
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
- // Attach a single capturing handler while someone wants focusin/focusout
- var attaches = 0,
- handler = function( event ) {
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
- };
-
- jQuery.event.special[ fix ] = {
- setup: function() {
- if ( attaches++ === 0 ) {
- document.addEventListener( orig, handler, true );
- }
- },
- teardown: function() {
- if ( --attaches === 0 ) {
- document.removeEventListener( orig, handler, true );
- }
- }
- };
- });
-}
-
-jQuery.fn.extend({
-
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
- var origFn, type;
-
- // Types can be a map of types/handlers
- if ( typeof types === "object" ) {
- // ( types-Object, selector, data )
- if ( typeof selector !== "string" ) {
- // ( types-Object, data )
- data = selector;
- selector = undefined;
- }
- for ( type in types ) {
- this.on( type, selector, data, types[ type ], one );
- }
- return this;
- }
-
- if ( data == null && fn == null ) {
- // ( types, fn )
- fn = selector;
- data = selector = undefined;
- } else if ( fn == null ) {
- if ( typeof selector === "string" ) {
- // ( types, selector, fn )
- fn = data;
- data = undefined;
- } else {
- // ( types, data, fn )
- fn = data;
- data = selector;
- selector = undefined;
- }
- }
- if ( fn === false ) {
- fn = returnFalse;
- } else if ( !fn ) {
- return this;
- }
-
- if ( one === 1 ) {
- origFn = fn;
- fn = function( event ) {
- // Can use an empty set, since event contains the info
- jQuery().off( event );
- return origFn.apply( this, arguments );
- };
- // Use same guid so caller can remove using origFn
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
- }
- return this.each( function() {
- jQuery.event.add( this, types, fn, data, selector );
- });
- },
- one: function( types, selector, data, fn ) {
- return this.on.call( this, types, selector, data, fn, 1 );
- },
- off: function( types, selector, fn ) {
- if ( types && types.preventDefault && types.handleObj ) {
- // ( event ) dispatched jQuery.Event
- var handleObj = types.handleObj;
- jQuery( types.delegateTarget ).off(
- handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
- handleObj.selector,
- handleObj.handler
- );
- return this;
- }
- if ( typeof types === "object" ) {
- // ( types-object [, selector] )
- for ( var type in types ) {
- this.off( type, selector, types[ type ] );
- }
- return this;
- }
- if ( selector === false || typeof selector === "function" ) {
- // ( types [, fn] )
- fn = selector;
- selector = undefined;
- }
- if ( fn === false ) {
- fn = returnFalse;
- }
- return this.each(function() {
- jQuery.event.remove( this, types, fn, selector );
- });
- },
-
- 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;
- }
-
- return arguments.length > 0 ?
- this.on( name, null, data, fn ) :
- this.trigger( name );
- };
-
- if ( jQuery.attrFn ) {
- jQuery.attrFn[ name ] = true;
- }
-
- 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 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){
-
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
- expando = "sizcache" + (Math.random() + '').replace('.', ''),
- done = 0,
- toString = Object.prototype.toString,
- hasDuplicate = false,
- baseHasDuplicate = true,
- rBackslash = /\\/g,
- rReturn = /\r\n/g,
- rNonWord = /\W/;
-
-// Here we check if the JavaScript engine is using some sort of
-// optimization where it does not always call our comparision
-// function. If that is the case, discard the hasDuplicate value.
-// Thus far that includes Google Chrome.
-[0, 0].sort(function() {
- baseHasDuplicate = false;
- return 0;
-});
-
-var Sizzle = function( selector, context, results, seed ) {
- results = results || [];
- context = context || document;
-
- var origContext = context;
-
- if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
- return [];
- }
-
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
-
- var m, set, checkSet, extra, ret, cur, pop, i,
- prune = true,
- contextXML = Sizzle.isXML( context ),
- parts = [],
- soFar = selector;
-
- // Reset the position of the chunker regexp (start from head)
- do {
- chunker.exec( "" );
- m = chunker.exec( soFar );
-
- if ( m ) {
- soFar = m[3];
-
- parts.push( m[1] );
-
- if ( m[2] ) {
- extra = m[3];
- break;
- }
- }
- } while ( m );
-
- if ( parts.length > 1 && origPOS.exec( selector ) ) {
-
- if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
- set = posProcess( parts[0] + parts[1], context, seed );
-
- } else {
- set = Expr.relative[ parts[0] ] ?
- [ context ] :
- Sizzle( parts.shift(), context );
-
- while ( parts.length ) {
- selector = parts.shift();
-
- if ( Expr.relative[ selector ] ) {
- selector += parts.shift();
- }
-
- set = posProcess( selector, set, seed );
- }
- }
-
- } else {
- // Take a shortcut and set the context if the root selector is an ID
- // (but not if it'll be faster if the inner selector is an ID)
- if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
- Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
-
- ret = Sizzle.find( parts.shift(), context, contextXML );
- context = ret.expr ?
- Sizzle.filter( ret.expr, ret.set )[0] :
- ret.set[0];
- }
-
- if ( context ) {
- ret = seed ?
- { expr: parts.pop(), set: makeArray(seed) } :
- Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
-
- set = ret.expr ?
- Sizzle.filter( ret.expr, ret.set ) :
- ret.set;
-
- if ( parts.length > 0 ) {
- checkSet = makeArray( set );
-
- } else {
- prune = false;
- }
-
- while ( parts.length ) {
- cur = parts.pop();
- pop = cur;
-
- if ( !Expr.relative[ cur ] ) {
- cur = "";
- } else {
- pop = parts.pop();
- }
-
- if ( pop == null ) {
- pop = context;
- }
-
- Expr.relative[ cur ]( checkSet, pop, contextXML );
- }
-
- } else {
- checkSet = parts = [];
- }
- }
-
- if ( !checkSet ) {
- checkSet = set;
- }
-
- if ( !checkSet ) {
- Sizzle.error( cur || selector );
- }
-
- if ( toString.call(checkSet) === "[object Array]" ) {
- if ( !prune ) {
- results.push.apply( results, checkSet );
-
- } else if ( context && context.nodeType === 1 ) {
- for ( i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
- results.push( set[i] );
- }
- }
-
- } else {
- for ( i = 0; checkSet[i] != null; i++ ) {
- if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
- results.push( set[i] );
- }
- }
- }
-
- } else {
- makeArray( checkSet, results );
- }
-
- if ( extra ) {
- Sizzle( extra, origContext, results, seed );
- Sizzle.uniqueSort( results );
- }
-
- return results;
-};
-
-Sizzle.uniqueSort = function( results ) {
- if ( sortOrder ) {
- hasDuplicate = baseHasDuplicate;
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[ i - 1 ] ) {
- results.splice( i--, 1 );
- }
- }
- }
- }
-
- return results;
-};
-
-Sizzle.matches = function( expr, set ) {
- return Sizzle( expr, null, null, set );
-};
-
-Sizzle.matchesSelector = function( node, expr ) {
- return Sizzle( expr, null, null, [node] ).length > 0;
-};
-
-Sizzle.find = function( expr, context, isXML ) {
- var set, i, len, match, type, left;
-
- if ( !expr ) {
- return [];
- }
-
- for ( i = 0, len = Expr.order.length; i < len; i++ ) {
- type = Expr.order[i];
-
- if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
- left = match[1];
- match.splice( 1, 1 );
-
- if ( left.substr( left.length - 1 ) !== "\\" ) {
- match[1] = (match[1] || "").replace( rBackslash, "" );
- set = Expr.find[ type ]( match, context, isXML );
-
- if ( set != null ) {
- expr = expr.replace( Expr.match[ type ], "" );
- break;
- }
- }
- }
- }
-
- if ( !set ) {
- set = typeof context.getElementsByTagName !== "undefined" ?
- context.getElementsByTagName( "*" ) :
- [];
- }
-
- return { set: set, expr: expr };
-};
-
-Sizzle.filter = function( expr, set, inplace, not ) {
- var match, anyFound,
- type, found, item, filter, left,
- i, pass,
- old = expr,
- result = [],
- curLoop = set,
- isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
-
- while ( expr && set.length ) {
- for ( type in Expr.filter ) {
- if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
- filter = Expr.filter[ type ];
- left = match[1];
-
- anyFound = false;
-
- match.splice(1,1);
-
- if ( left.substr( left.length - 1 ) === "\\" ) {
- continue;
- }
-
- if ( curLoop === result ) {
- result = [];
- }
-
- if ( Expr.preFilter[ type ] ) {
- match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
-
- if ( !match ) {
- anyFound = found = true;
-
- } else if ( match === true ) {
- continue;
- }
- }
-
- if ( match ) {
- for ( i = 0; (item = curLoop[i]) != null; i++ ) {
- if ( item ) {
- found = filter( item, match, i, curLoop );
- pass = not ^ found;
-
- if ( inplace && found != null ) {
- if ( pass ) {
- anyFound = true;
-
- } else {
- curLoop[i] = false;
- }
-
- } else if ( pass ) {
- result.push( item );
- anyFound = true;
- }
- }
- }
- }
-
- if ( found !== undefined ) {
- if ( !inplace ) {
- curLoop = result;
- }
-
- expr = expr.replace( Expr.match[ type ], "" );
-
- if ( !anyFound ) {
- return [];
- }
-
- break;
- }
- }
- }
-
- // Improper expression
- if ( expr === old ) {
- if ( anyFound == null ) {
- Sizzle.error( expr );
-
- } else {
- break;
- }
- }
-
- old = expr;
- }
-
- return curLoop;
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Utility function for retreiving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-var getText = Sizzle.getText = function( elem ) {
- var i, node,
- nodeType = elem.nodeType,
- ret = "";
-
- if ( nodeType ) {
- if ( nodeType === 1 || nodeType === 9 ) {
- // Use textContent || innerText for elements
- if ( typeof elem.textContent === 'string' ) {
- return elem.textContent;
- } else if ( typeof elem.innerText === 'string' ) {
- // Replace IE's carriage returns
- return elem.innerText.replace( rReturn, '' );
- } else {
- // Traverse it's children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- } else {
-
- // If no nodeType, this is expected to be an array
- for ( i = 0; (node = elem[i]); i++ ) {
- // Do not traverse comment nodes
- if ( node.nodeType !== 8 ) {
- ret += getText( node );
- }
- }
- }
- return ret;
-};
-
-var Expr = Sizzle.selectors = {
- order: [ "ID", "NAME", "TAG" ],
-
- match: {
- ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
- CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
- TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
- CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
- POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
- PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
- },
-
- leftMatch: {},
-
- attrMap: {
- "class": "className",
- "for": "htmlFor"
- },
-
- attrHandle: {
- href: function( elem ) {
- return elem.getAttribute( "href" );
- },
- type: function( elem ) {
- return elem.getAttribute( "type" );
- }
- },
-
- relative: {
- "+": function(checkSet, part){
- var isPartStr = typeof part === "string",
- isTag = isPartStr && !rNonWord.test( part ),
- isPartStrNotTag = isPartStr && !isTag;
-
- if ( isTag ) {
- part = part.toLowerCase();
- }
-
- for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
- if ( (elem = checkSet[i]) ) {
- while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
-
- checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
- elem || false :
- elem === part;
- }
- }
-
- if ( isPartStrNotTag ) {
- Sizzle.filter( part, checkSet, true );
- }
- },
-
- ">": function( checkSet, part ) {
- var elem,
- isPartStr = typeof part === "string",
- i = 0,
- l = checkSet.length;
-
- if ( isPartStr && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
-
- for ( ; i < l; i++ ) {
- elem = checkSet[i];
-
- if ( elem ) {
- var parent = elem.parentNode;
- checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
- }
- }
-
- } else {
- for ( ; i < l; i++ ) {
- elem = checkSet[i];
-
- if ( elem ) {
- checkSet[i] = isPartStr ?
- elem.parentNode :
- elem.parentNode === part;
- }
- }
-
- if ( isPartStr ) {
- Sizzle.filter( part, checkSet, true );
- }
- }
- },
-
- "": function(checkSet, part, isXML){
- var nodeCheck,
- doneName = done++,
- checkFn = dirCheck;
-
- if ( typeof part === "string" && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
- nodeCheck = part;
- checkFn = dirNodeCheck;
- }
-
- checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
- },
-
- "~": function( checkSet, part, isXML ) {
- var nodeCheck,
- doneName = done++,
- checkFn = dirCheck;
-
- if ( typeof part === "string" && !rNonWord.test( part ) ) {
- part = part.toLowerCase();
- nodeCheck = part;
- checkFn = dirNodeCheck;
- }
-
- checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
- }
- },
-
- find: {
- ID: function( match, context, isXML ) {
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [m] : [];
- }
- },
-
- NAME: function( match, context ) {
- if ( typeof context.getElementsByName !== "undefined" ) {
- var ret = [],
- results = context.getElementsByName( match[1] );
-
- for ( var i = 0, l = results.length; i < l; i++ ) {
- if ( results[i].getAttribute("name") === match[1] ) {
- ret.push( results[i] );
- }
- }
-
- return ret.length === 0 ? null : ret;
- }
- },
-
- TAG: function( match, context ) {
- if ( typeof context.getElementsByTagName !== "undefined" ) {
- return context.getElementsByTagName( match[1] );
- }
- }
- },
- preFilter: {
- CLASS: function( match, curLoop, inplace, result, not, isXML ) {
- match = " " + match[1].replace( rBackslash, "" ) + " ";
-
- if ( isXML ) {
- return match;
- }
-
- for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
- if ( elem ) {
- if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
- if ( !inplace ) {
- result.push( elem );
- }
-
- } else if ( inplace ) {
- curLoop[i] = false;
- }
- }
- }
-
- return false;
- },
-
- ID: function( match ) {
- return match[1].replace( rBackslash, "" );
- },
-
- TAG: function( match, curLoop ) {
- return match[1].replace( rBackslash, "" ).toLowerCase();
- },
-
- CHILD: function( match ) {
- if ( match[1] === "nth" ) {
- if ( !match[2] ) {
- Sizzle.error( match[0] );
- }
-
- match[2] = match[2].replace(/^\+|\s*/g, '');
-
- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
- var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
- match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
- !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
-
- // calculate the numbers (first)n+(last) including if they are negative
- match[2] = (test[1] + (test[2] || 1)) - 0;
- match[3] = test[3] - 0;
- }
- else if ( match[2] ) {
- Sizzle.error( match[0] );
- }
-
- // TODO: Move to normal caching system
- match[0] = done++;
-
- return match;
- },
-
- ATTR: function( match, curLoop, inplace, result, not, isXML ) {
- var name = match[1] = match[1].replace( rBackslash, "" );
-
- if ( !isXML && Expr.attrMap[name] ) {
- match[1] = Expr.attrMap[name];
- }
-
- // Handle if an un-quoted value was used
- match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
-
- if ( match[2] === "~=" ) {
- match[4] = " " + match[4] + " ";
- }
-
- return match;
- },
-
- PSEUDO: function( match, curLoop, inplace, result, not ) {
- if ( match[1] === "not" ) {
- // If we're dealing with a complex expression, or a simple one
- if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
- match[3] = Sizzle(match[3], null, null, curLoop);
-
- } else {
- var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
-
- if ( !inplace ) {
- result.push.apply( result, ret );
- }
-
- return false;
- }
-
- } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
- return true;
- }
-
- return match;
- },
-
- POS: function( match ) {
- match.unshift( true );
-
- return match;
- }
- },
-
- filters: {
- enabled: function( elem ) {
- return elem.disabled === false && elem.type !== "hidden";
- },
-
- disabled: function( elem ) {
- return elem.disabled === true;
- },
-
- checked: function( elem ) {
- return elem.checked === true;
- },
-
- 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 !!elem.firstChild;
- },
-
- empty: function( elem ) {
- return !elem.firstChild;
- },
-
- has: function( elem, i, match ) {
- return !!Sizzle( match[3], elem ).length;
- },
-
- header: function( elem ) {
- return (/h\d/i).test( elem.nodeName );
- },
-
- text: function( elem ) {
- var attr = elem.getAttribute( "type" ), type = elem.type;
- // 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" && "text" === type && ( attr === type || attr === null );
- },
-
- radio: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
- },
-
- checkbox: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
- },
-
- file: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
- },
-
- password: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
- },
-
- submit: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && "submit" === elem.type;
- },
-
- image: function( elem ) {
- return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
- },
-
- reset: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && "reset" === elem.type;
- },
-
- button: function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && "button" === elem.type || name === "button";
- },
-
- input: function( elem ) {
- return (/input|select|textarea|button/i).test( elem.nodeName );
- },
-
- focus: function( elem ) {
- return elem === elem.ownerDocument.activeElement;
- }
- },
- setFilters: {
- first: function( elem, i ) {
- return i === 0;
- },
-
- last: function( elem, i, match, array ) {
- return i === array.length - 1;
- },
-
- even: function( elem, i ) {
- return i % 2 === 0;
- },
-
- odd: function( elem, i ) {
- return i % 2 === 1;
- },
-
- lt: function( elem, i, match ) {
- return i < match[3] - 0;
- },
-
- gt: function( elem, i, match ) {
- return i > match[3] - 0;
- },
-
- nth: function( elem, i, match ) {
- return match[3] - 0 === i;
- },
-
- eq: function( elem, i, match ) {
- return match[3] - 0 === i;
- }
- },
- filter: {
- PSEUDO: function( elem, match, i, array ) {
- var name = match[1],
- filter = Expr.filters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
-
- } else if ( name === "contains" ) {
- return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
-
- } else if ( name === "not" ) {
- var not = match[3];
-
- for ( var j = 0, l = not.length; j < l; j++ ) {
- if ( not[j] === elem ) {
- return false;
- }
- }
-
- return true;
-
- } else {
- Sizzle.error( name );
- }
- },
-
- CHILD: function( elem, match ) {
- var first, last,
- doneName, parent, cache,
- count, diff,
- type = match[1],
- 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;
-
- case "last":
- while ( (node = node.nextSibling) ) {
- if ( node.nodeType === 1 ) {
- return false;
- }
- }
-
- return true;
-
- case "nth":
- first = match[2];
- last = match[3];
-
- if ( first === 1 && last === 0 ) {
- return true;
- }
-
- doneName = match[0];
- parent = elem.parentNode;
-
- if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
- count = 0;
-
- for ( node = parent.firstChild; node; node = node.nextSibling ) {
- if ( node.nodeType === 1 ) {
- node.nodeIndex = ++count;
- }
- }
-
- parent[ expando ] = doneName;
- }
-
- diff = elem.nodeIndex - last;
-
- if ( first === 0 ) {
- return diff === 0;
-
- } else {
- return ( diff % first === 0 && diff / first >= 0 );
- }
- }
- },
-
- ID: function( elem, match ) {
- return elem.nodeType === 1 && elem.getAttribute("id") === match;
- },
-
- TAG: function( elem, match ) {
- return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
- },
-
- CLASS: function( elem, match ) {
- return (" " + (elem.className || elem.getAttribute("class")) + " ")
- .indexOf( match ) > -1;
- },
-
- ATTR: function( elem, match ) {
- var name = match[1],
- result = Sizzle.attr ?
- Sizzle.attr( elem, name ) :
- Expr.attrHandle[ name ] ?
- Expr.attrHandle[ name ]( elem ) :
- elem[ name ] != null ?
- elem[ name ] :
- elem.getAttribute( name ),
- value = result + "",
- type = match[2],
- check = match[4];
-
- return result == null ?
- type === "!=" :
- !type && Sizzle.attr ?
- result != null :
- type === "=" ?
- value === check :
- type === "*=" ?
- value.indexOf(check) >= 0 :
- type === "~=" ?
- (" " + value + " ").indexOf(check) >= 0 :
- !check ?
- value && result !== false :
- type === "!=" ?
- value !== check :
- type === "^=" ?
- value.indexOf(check) === 0 :
- type === "$=" ?
- value.substr(value.length - check.length) === check :
- type === "|=" ?
- value === check || value.substr(0, check.length + 1) === check + "-" :
- false;
- },
-
- POS: function( elem, match, i, array ) {
- var name = match[2],
- filter = Expr.setFilters[ name ];
-
- if ( filter ) {
- return filter( elem, i, match, array );
- }
- }
- }
-};
-
-var origPOS = Expr.match.POS,
- fescape = function(all, num){
- return "\\" + (num - 0 + 1);
- };
-
-for ( var type in Expr.match ) {
- Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
- Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
-}
-
-var makeArray = function( array, results ) {
- array = Array.prototype.slice.call( array, 0 );
-
- if ( results ) {
- results.push.apply( results, array );
- return results;
- }
-
- return array;
-};
-
-// Perform a simple check to determine if the browser is capable of
-// converting a NodeList to an array using builtin methods.
-// Also verifies that the returned array holds DOM nodes
-// (which is not the case in the Blackberry browser)
-try {
- Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
-
-// Provide a fallback method if it does not work
-} catch( e ) {
- makeArray = function( array, results ) {
- var i = 0,
- ret = results || [];
-
- if ( toString.call(array) === "[object Array]" ) {
- Array.prototype.push.apply( ret, array );
-
- } else {
- if ( typeof array.length === "number" ) {
- for ( var l = array.length; i < l; i++ ) {
- ret.push( array[i] );
- }
-
- } else {
- for ( ; array[i]; i++ ) {
- ret.push( array[i] );
- }
- }
- }
-
- return ret;
- };
-}
-
-var sortOrder, siblingCheck;
-
-if ( document.documentElement.compareDocumentPosition ) {
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
- return a.compareDocumentPosition ? -1 : 1;
- }
-
- return a.compareDocumentPosition(b) & 4 ? -1 : 1;
- };
-
-} else {
- sortOrder = 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 );
- };
-
- siblingCheck = function( a, b, ret ) {
- if ( a === b ) {
- return ret;
- }
-
- var cur = a.nextSibling;
-
- while ( cur ) {
- if ( cur === b ) {
- return -1;
- }
-
- cur = cur.nextSibling;
- }
-
- return 1;
- };
-}
-
-// Check to see if the browser returns elements by name when
-// querying by getElementById (and provide a workaround)
-(function(){
- // We're going to inject a fake input element with a specified name
- var form = document.createElement("div"),
- id = "script" + (new Date()).getTime(),
- root = document.documentElement;
-
- form.innerHTML = "";
-
- // Inject it into the root element, check its status, and remove it quickly
- root.insertBefore( form, root.firstChild );
-
- // The workaround has to do additional checks after a getElementById
- // Which slows things down for other browsers (hence the branching)
- if ( document.getElementById( id ) ) {
- Expr.find.ID = function( match, context, isXML ) {
- if ( typeof context.getElementById !== "undefined" && !isXML ) {
- var m = context.getElementById(match[1]);
-
- return m ?
- m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
- [m] :
- undefined :
- [];
- }
- };
-
- Expr.filter.ID = function( elem, match ) {
- var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
-
- return elem.nodeType === 1 && node && node.nodeValue === match;
- };
- }
-
- root.removeChild( form );
-
- // release memory in IE
- root = form = null;
-})();
-
-(function(){
- // Check to see if the browser returns only elements
- // when doing getElementsByTagName("*")
-
- // Create a fake element
- var div = document.createElement("div");
- div.appendChild( document.createComment("") );
-
- // Make sure no comments are found
- if ( div.getElementsByTagName("*").length > 0 ) {
- Expr.find.TAG = function( match, context ) {
- var results = context.getElementsByTagName( match[1] );
-
- // Filter out possible comments
- if ( match[1] === "*" ) {
- var tmp = [];
-
- for ( var i = 0; results[i]; i++ ) {
- if ( results[i].nodeType === 1 ) {
- tmp.push( results[i] );
- }
- }
-
- results = tmp;
- }
-
- return results;
- };
- }
-
- // Check to see if an attribute returns normalized href attributes
- div.innerHTML = "";
-
- if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
- div.firstChild.getAttribute("href") !== "#" ) {
-
- Expr.attrHandle.href = function( elem ) {
- return elem.getAttribute( "href", 2 );
- };
- }
-
- // release memory in IE
- div = null;
-})();
-
-if ( document.querySelectorAll ) {
- (function(){
- var oldSizzle = Sizzle,
- div = document.createElement("div"),
- id = "__sizzle__";
-
- div.innerHTML = "";
-
- // Safari can't handle uppercase or unicode characters when
- // in quirks mode.
- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
- return;
- }
-
- Sizzle = function( query, context, extra, seed ) {
- context = context || document;
-
- // Only use querySelectorAll on non-XML documents
- // (ID selectors don't work in non-HTML documents)
- if ( !seed && !Sizzle.isXML(context) ) {
- // See if we find a selector to speed up
- var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
-
- if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
- // Speed-up: Sizzle("TAG")
- if ( match[1] ) {
- return makeArray( context.getElementsByTagName( query ), extra );
-
- // Speed-up: Sizzle(".CLASS")
- } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
- return makeArray( context.getElementsByClassName( match[2] ), extra );
- }
- }
-
- if ( context.nodeType === 9 ) {
- // Speed-up: Sizzle("body")
- // The body element only exists once, optimize finding it
- if ( query === "body" && context.body ) {
- return makeArray( [ context.body ], extra );
-
- // Speed-up: Sizzle("#ID")
- } else if ( match && match[3] ) {
- var elem = context.getElementById( match[3] );
-
- // 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 and Opera return items
- // by name instead of ID
- if ( elem.id === match[3] ) {
- return makeArray( [ elem ], extra );
- }
-
- } else {
- return makeArray( [], extra );
- }
- }
-
- try {
- return makeArray( context.querySelectorAll(query), extra );
- } catch(qsaError) {}
-
- // 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
- } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- var oldContext = context,
- old = context.getAttribute( "id" ),
- nid = old || id,
- hasParent = context.parentNode,
- relativeHierarchySelector = /^\s*[+~]/.test( query );
-
- if ( !old ) {
- context.setAttribute( "id", nid );
- } else {
- nid = nid.replace( /'/g, "\\$&" );
- }
- if ( relativeHierarchySelector && hasParent ) {
- context = context.parentNode;
- }
-
- try {
- if ( !relativeHierarchySelector || hasParent ) {
- return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
- }
-
- } catch(pseudoError) {
- } finally {
- if ( !old ) {
- oldContext.removeAttribute( "id" );
- }
- }
- }
- }
-
- return oldSizzle(query, context, extra, seed);
- };
-
- for ( var prop in oldSizzle ) {
- Sizzle[ prop ] = oldSizzle[ prop ];
- }
-
- // release memory in IE
- div = null;
- })();
-}
-
-(function(){
- var html = document.documentElement,
- matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
-
- if ( matches ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9 fails this)
- var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
- pseudoWorks = false;
-
- try {
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( document.documentElement, "[test!='']:sizzle" );
-
- } catch( pseudoError ) {
- pseudoWorks = true;
- }
-
- Sizzle.matchesSelector = function( node, expr ) {
- // Make sure that attribute selectors are quoted
- expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
-
- if ( !Sizzle.isXML( node ) ) {
- try {
- if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
- var ret = matches.call( node, 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, so check for that
- node.document && node.document.nodeType !== 11 ) {
- return ret;
- }
- }
- } catch(e) {}
- }
-
- return Sizzle(expr, null, null, [node]).length > 0;
- };
- }
-})();
-
-(function(){
- var div = document.createElement("div");
-
- div.innerHTML = "";
-
- // Opera can't find a second classname (in 9.6)
- // Also, make sure that getElementsByClassName actually exists
- if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
- return;
- }
-
- // Safari caches class attributes, doesn't catch changes (in 3.2)
- div.lastChild.className = "e";
-
- if ( div.getElementsByClassName("e").length === 1 ) {
- return;
- }
-
- Expr.order.splice(1, 0, "CLASS");
- Expr.find.CLASS = function( match, context, isXML ) {
- if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
- return context.getElementsByClassName(match[1]);
- }
- };
-
- // release memory in IE
- div = null;
-})();
-
-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
-
- if ( elem ) {
- var match = false;
-
- elem = elem[dir];
-
- while ( elem ) {
- if ( elem[ expando ] === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 && !isXML ){
- elem[ expando ] = doneName;
- elem.sizset = i;
- }
-
- if ( elem.nodeName.toLowerCase() === cur ) {
- match = elem;
- break;
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- for ( var i = 0, l = checkSet.length; i < l; i++ ) {
- var elem = checkSet[i];
-
- if ( elem ) {
- var match = false;
-
- elem = elem[dir];
-
- while ( elem ) {
- if ( elem[ expando ] === doneName ) {
- match = checkSet[elem.sizset];
- break;
- }
-
- if ( elem.nodeType === 1 ) {
- if ( !isXML ) {
- elem[ expando ] = doneName;
- elem.sizset = i;
- }
-
- if ( typeof cur !== "string" ) {
- if ( elem === cur ) {
- match = true;
- break;
- }
-
- } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
- match = elem;
- break;
- }
- }
-
- elem = elem[dir];
- }
-
- checkSet[i] = match;
- }
- }
-}
-
-if ( document.documentElement.contains ) {
- Sizzle.contains = function( a, b ) {
- return a !== b && (a.contains ? a.contains(b) : true);
- };
-
-} else if ( document.documentElement.compareDocumentPosition ) {
- Sizzle.contains = function( a, b ) {
- return !!(a.compareDocumentPosition(b) & 16);
- };
-
-} else {
- Sizzle.contains = function() {
- return false;
- };
-}
-
-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 : 0).documentElement;
-
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-var posProcess = function( selector, context, seed ) {
- var match,
- tmpSet = [],
- later = "",
- root = context.nodeType ? [context] : context;
-
- // Position selectors must be done after the filter
- // And so must :not(positional) so we move all PSEUDOs to the end
- while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
- later += match[0];
- selector = selector.replace( Expr.match.PSEUDO, "" );
- }
-
- selector = Expr.relative[selector] ? selector + "*" : selector;
-
- for ( var i = 0, l = root.length; i < l; i++ ) {
- Sizzle( selector, root[i], tmpSet, seed );
- }
-
- return Sizzle.filter( later, tmpSet );
-};
-
-// EXPOSE
-// Override sizzle attribute retrieval
-Sizzle.attr = jQuery.attr;
-Sizzle.selectors.attrMap = {};
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.filters;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-
-
-})();
-
-
-var runtil = /Until$/,
- rparentsprev = /^(?:parents|prevUntil|prevAll)/,
- // Note: This RegExp should be improved, or likely pulled from Sizzle
- rmultiselector = /,/,
- isSimple = /^.[^:#\[\.,]*$/,
- slice = Array.prototype.slice,
- POS = jQuery.expr.match.POS,
- // methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.fn.extend({
- find: function( selector ) {
- var self = this,
- i, l;
-
- if ( typeof selector !== "string" ) {
- return jQuery( selector ).filter(function() {
- for ( i = 0, l = self.length; i < l; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- });
- }
-
- var ret = this.pushStack( "", "find", selector ),
- length, n, r;
-
- 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;
- }
- }
- }
- }
- }
-
- return ret;
- },
-
- has: function( target ) {
- var targets = jQuery( target );
- return this.filter(function() {
- for ( var i = 0, l = targets.length; i < l; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
- return true;
- }
- }
- });
- },
-
- not: function( selector ) {
- return this.pushStack( winnow(this, selector, false), "not", selector);
- },
-
- filter: function( selector ) {
- return this.pushStack( winnow(this, selector, true), "filter", selector );
- },
-
- is: function( selector ) {
- return !!selector && (
- typeof selector === "string" ?
- // If this is a positional selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- POS.test( selector ) ?
- jQuery( selector, this.context ).index( this[0] ) >= 0 :
- jQuery.filter( selector, this ).length > 0 :
- this.filter( selector ).length > 0 );
- },
-
- closest: function( selectors, context ) {
- var ret = [], i, l, cur = this[0];
-
- // Array (deprecated as of jQuery 1.7)
- if ( jQuery.isArray( selectors ) ) {
- var level = 1;
-
- while ( cur && cur.ownerDocument && cur !== context ) {
- for ( i = 0; i < selectors.length; i++ ) {
-
- if ( jQuery( cur ).is( selectors[ i ] ) ) {
- ret.push({ selector: selectors[ i ], elem: cur, level: level });
- }
- }
-
- cur = cur.parentNode;
- level++;
- }
-
- return ret;
- }
-
- // String
- var pos = POS.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
-
- for ( i = 0, l = this.length; i < l; i++ ) {
- cur = this[i];
-
- while ( cur ) {
- if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
- ret.push( cur );
- break;
-
- } else {
- cur = cur.parentNode;
- if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
- break;
- }
- }
- }
- }
-
- ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
-
- return this.pushStack( ret, "closest", selectors );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
- }
-
- // index in selector
- if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
- }
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
- },
-
- add: function( selector, context ) {
- var set = typeof selector === "string" ?
- jQuery( selector, context ) :
- 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 ) );
- },
-
- andSelf: function() {
- return this.add( this.prevObject );
- }
-});
-
-// 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;
-}
-
-jQuery.each({
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return jQuery.nth( elem, 2, "nextSibling" );
- },
- prev: function( elem ) {
- return jQuery.nth( elem, 2, "previousSibling" );
- },
- nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return jQuery.sibling( elem.parentNode.firstChild, elem );
- },
- children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
- },
- contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.makeArray( elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
-
- if ( !runtil.test( name ) ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
- }
-
- ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
-
- if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
- ret = ret.reverse();
- }
-
- return this.pushStack( ret, name, slice.call( arguments ).join(",") );
- };
-});
-
-jQuery.extend({
- filter: function( expr, elems, not ) {
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return elems.length === 1 ?
- jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
- jQuery.find.matches(expr, elems);
- },
-
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
-
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
- }
- cur = cur[dir];
- }
- return matched;
- },
-
- nth: function( cur, result, dir, elem ) {
- result = result || 1;
- var num = 0;
-
- for ( ; cur; cur = cur[dir] ) {
- if ( cur.nodeType === 1 && ++num === result ) {
- break;
- }
- }
-
- return cur;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
- }
- }
-
- return r;
- }
-});
-
-// 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;
-
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep(elements, function( elem, i ) {
- var retVal = !!qualifier.call( elem, i, elem );
- return retVal === keep;
- });
-
- } 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 ( isSimple.test( qualifier ) ) {
- return jQuery.filter(qualifier, filtered, !keep);
- } else {
- qualifier = jQuery.filter( qualifier, filtered );
- }
- }
-
- return jQuery.grep(elements, function( elem, i ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
- });
-}
-
-
-
-
-function createSafeFragment( document ) {
- var list = nodeNames.split( "|" ),
- safeFrag = document.createDocumentFragment();
-
- if ( safeFrag.createElement ) {
- while ( list.length ) {
- safeFrag.createElement(
- list.pop()
- );
- }
- }
- return safeFrag;
-}
-
-var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
- rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
- rleadingWhitespace = /^\s+/,
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
- rtagName = /<([\w:]+)/,
- rtbody = /<(?:" + nodeNames + ")", "i"),
- // checked="checked" or checked
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
- rscriptType = /\/(java|ecma)script/i,
- rcleanScript = /^\s*", "" ],
- legend: [ 1, "" ],
- thead: [ 1, "