From dd85e54ab11597e7de861ef8d6fc111c56b1397e Mon Sep 17 00:00:00 2001 From: webchick Date: Tue, 9 Apr 2013 13:58:51 -0700 Subject: [PATCH] Issue #1799594 by nod_, Wim Leers, jessebeach, jcisio: Update to jQuery 1.9 version. --- core/misc/ajax.js | 6 +- core/misc/autocomplete.js | 2 +- core/misc/collapse.js | 10 +- core/misc/drupal.js | 111 +- core/misc/jquery.ba-bbq.js | 1375 +++- core/misc/jquery.js | 5899 +++++++++-------- core/misc/states.js | 6 +- core/misc/tableresponsive.js | 4 +- core/misc/tableselect.js | 2 +- core/misc/vertical-tabs.js | 2 +- core/modules/color/color.js | 12 +- core/modules/contextual/contextual.js | 14 +- core/modules/contextual/contextual.toolbar.js | 2 +- core/modules/edit/js/backbone.drupalform.js | 2 +- core/modules/field_ui/field_ui.js | 2 +- core/modules/file/file.js | 2 +- core/modules/openid/openid.js | 12 +- core/modules/overlay/overlay-parent.js | 12 +- core/modules/shortcut/shortcut.admin.js | 2 +- core/modules/system/system.module | 4 +- core/modules/text/text.js | 15 +- core/modules/toolbar/js/toolbar.js | 6 +- core/modules/tour/js/tour.js | 4 +- core/modules/translation/translation.js | 4 +- .../translation_entity.admin.js | 4 +- core/modules/user/user.js | 4 +- core/modules/views/views_ui/js/views-admin.js | 2 +- 27 files changed, 4518 insertions(+), 3002 deletions(-) diff --git a/core/misc/ajax.js b/core/misc/ajax.js index 1b5d0caac5b..cb44f51b4ba 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -390,7 +390,7 @@ Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) { // interaction while the Ajax request is in progress. ajax.ajaxing prevents // the element from triggering a new request, but does not prevent the user // from changing its value. - $(this.element).addClass('progress-disabled').attr('disabled', true); + $(this.element).addClass('progress-disabled').prop('disabled', true); // Insert progressbar or throbber. if (this.progress.type === 'bar') { @@ -425,7 +425,7 @@ Drupal.ajax.prototype.success = function (response, status) { if (this.progress.object) { this.progress.object.stopMonitoring(); } - $(this.element).removeClass('progress-disabled').removeAttr('disabled'); + $(this.element).removeClass('progress-disabled').prop('disabled', false); Drupal.freezeHeight(); @@ -493,7 +493,7 @@ Drupal.ajax.prototype.error = function (response, uri) { // Undo hide. $(this.wrapper).show(); // Re-enable the element. - $(this.element).removeClass('progress-disabled').removeAttr('disabled'); + $(this.element).removeClass('progress-disabled').prop('disabled', false); // Reattach behaviors, if they were detached in beforeSerialize(). if (this.form) { var settings = response.settings || this.settings || Drupal.settings; diff --git a/core/misc/autocomplete.js b/core/misc/autocomplete.js index d272c6c90cb..3be76c72566 100644 --- a/core/misc/autocomplete.js +++ b/core/misc/autocomplete.js @@ -14,7 +14,7 @@ Drupal.behaviors.autocomplete = { acdb[uri] = new Drupal.ACDB(uri); } var $input = $('#' + this.id.substr(0, this.id.length - 13)) - .attr('autocomplete', 'OFF') + .prop('autocomplete', 'OFF') .attr('aria-autocomplete', 'list'); $($input[0].form).submit(Drupal.autocompleteSubmit); $input.parent() diff --git a/core/misc/collapse.js b/core/misc/collapse.js index 62a7c0ef2fd..48bfaf675c4 100644 --- a/core/misc/collapse.js +++ b/core/misc/collapse.js @@ -53,7 +53,7 @@ function CollapsibleDetails(node, settings) { // element that is targeted by the URI fragment identifier. var anchor = location.hash && location.hash !== '#' ? ', ' + location.hash : ''; if (this.$node.find('.error' + anchor).length) { - this.$node.attr('open', true); + this.$node.prop('open', true); } // Initialize and setup the summary, this.setupSummary(); @@ -96,7 +96,7 @@ $.extend(CollapsibleDetails.prototype, { var $legend = this.$node.find('> summary'); $('') - .append(this.$node.attr('open') ? Drupal.t('Hide') : Drupal.t('Show')) + .append(this.$node.prop('open') ? Drupal.t('Hide') : Drupal.t('Show')) .prependTo($legend) .after(' '); @@ -129,7 +129,7 @@ $.extend(CollapsibleDetails.prototype, { if (this.animating) { return; } - if (!this.$node.attr('open')) { + if (!this.$node.prop('open')) { var $content = this.$node.find('> .details-wrapper').hide(); this.$node .trigger({ type:'collapsed', value:false }) @@ -153,7 +153,7 @@ $.extend(CollapsibleDetails.prototype, { * Completed opening details element. */ onCompleteSlideDown: function () { - this.$node.attr('open', true); + this.$node.prop('open', true); this.$node.trigger('completeSlideDown'); this.animating = false; }, @@ -161,7 +161,7 @@ $.extend(CollapsibleDetails.prototype, { * Completed closing details element. */ onCompleteSlideUp: function () { - this.$node.attr('open', false); + this.$node.prop('open', false); this.$node .find('> summary span.details-summary-prefix').html(Drupal.t('Show')); this.$node.trigger('completeSlideUp'); diff --git a/core/misc/drupal.js b/core/misc/drupal.js index d7a4e4033ae..b646e20aeec 100644 --- a/core/misc/drupal.js +++ b/core/misc/drupal.js @@ -261,65 +261,62 @@ Drupal.t = function (str, args, options) { /** * Adds an HTML element and method to trigger audio UAs to read system messages. */ -(function (document, Drupal) { +var liveElement; - var liveElement; +/** + * Builds a div element with the aria-live attribute and attaches it + * to the DOM. + */ +Drupal.behaviors.drupalAnnounce = { + attach: function (settings, context) { + liveElement = document.createElement('div'); + liveElement.id = 'drupal-live-announce'; + liveElement.className = 'element-invisible'; + liveElement.setAttribute('aria-live', 'polite'); + liveElement.setAttribute('aria-busy', 'false'); + document.body.appendChild(liveElement); + } +}; - /** - * Builds a div element with the aria-live attribute and attaches it - * to the DOM. - */ - Drupal.behaviors.drupalAnnounce = { - attach: function (settings, context) { - liveElement = document.createElement('div'); - liveElement.id = 'drupal-live-announce'; - liveElement.className = 'element-invisible'; - liveElement.setAttribute('aria-live', 'polite'); - liveElement.setAttribute('aria-busy', 'false'); - document.body.appendChild(liveElement); - } - }; - - /** - * Triggers audio UAs to read the supplied text. - * - * @param {String} text - * - A string to be read by the UA. - * - * @param {String} priority - * - A string to indicate the priority of the message. Can be either - * 'polite' or 'assertive'. Polite is the default. - * - * Use Drupal.announce to indicate to screen reader users that an element on - * the page has changed state. For instance, if clicking a link loads 10 more - * items into a list, one might announce the change like this. - * $('#search-list') - * .on('itemInsert', function (event, data) { - * // Insert the new items. - * $(data.container.el).append(data.items.el); - * // Announce the change to the page contents. - * Drupal.announce(Drupal.t('@count items added to @container', - * {'@count': data.items.length, '@container': data.container.title} - * )); - * }); - * - * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops - */ - Drupal.announce = function (text, priority) { - if (typeof text === 'string') { - // Clear the liveElement so that repeated strings will be read. - liveElement.innerHTML = ''; - // Set the busy state to true until the node changes are complete. - liveElement.setAttribute('aria-busy', 'true'); - // Set the priority to assertive, or default to polite. - liveElement.setAttribute('aria-live', (priority === 'assertive') ? 'assertive' : 'polite'); - // Print the text to the live region. - liveElement.innerHTML = Drupal.checkPlain(text); - // The live text area is updated. Allow the AT to announce the text. - liveElement.setAttribute('aria-busy', 'false'); - } - }; -}(document, Drupal)); +/** + * Triggers audio UAs to read the supplied text. + * + * @param {String} text + * - A string to be read by the UA. + * + * @param {String} priority + * - A string to indicate the priority of the message. Can be either + * 'polite' or 'assertive'. Polite is the default. + * + * Use Drupal.announce to indicate to screen reader users that an element on + * the page has changed state. For instance, if clicking a link loads 10 more + * items into a list, one might announce the change like this. + * $('#search-list') + * .on('itemInsert', function (event, data) { + * // Insert the new items. + * $(data.container.el).append(data.items.el); + * // Announce the change to the page contents. + * Drupal.announce(Drupal.t('@count items added to @container', + * {'@count': data.items.length, '@container': data.container.title} + * )); + * }); + * + * @see http://www.w3.org/WAI/PF/aria-practices/#liveprops + */ +Drupal.announce = function (text, priority) { + if (typeof text === 'string') { + // Clear the liveElement so that repeated strings will be read. + liveElement.innerHTML = ''; + // Set the busy state to true until the node changes are complete. + liveElement.setAttribute('aria-busy', 'true'); + // Set the priority to assertive, or default to polite. + liveElement.setAttribute('aria-live', (priority === 'assertive') ? 'assertive' : 'polite'); + // Print the text to the live region. + liveElement.innerHTML = Drupal.checkPlain(text); + // The live text area is updated. Allow the AT to announce the text. + liveElement.setAttribute('aria-busy', 'false'); + } +}; /** * Returns the URL to a Drupal page. diff --git a/core/misc/jquery.ba-bbq.js b/core/misc/jquery.ba-bbq.js index deb9a2fa4bc..1b02aca52af 100644 --- a/core/misc/jquery.ba-bbq.js +++ b/core/misc/jquery.ba-bbq.js @@ -1,19 +1,1380 @@ - -/* - * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010 +/*! + * jQuery BBQ: Back Button & Query Library - v1.3pre - 8/26/2010 * http://benalman.com/projects/jquery-bbq-plugin/ * * Copyright (c) 2010 "Cowboy" Ben Alman * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ -(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M v1.3, which adds +// document.title and document.domain support in IE6/7, BlackBerry +// support, better Iframe hiding for accessibility reasons, and the new +// "shortcut" method. Added the +// method which reduces the possibility of +// extraneous hashchange event triggering. Added the +// method which can be used to +// enable Google "AJAX Crawlable mode." +// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from +// in BBQ, which was the main reason for the +// previous release! +// 1.2 - (2/16/2010) Integrated v1.2, which fixes a +// Safari bug, the event can now be bound before DOM ready, and IE6/7 +// page should no longer scroll when the event is first bound. Also +// added the method, and reworked the +// internal "add" method to be compatible with +// changes made to the jQuery 1.4.2 special events API. +// 1.1.1 - (1/22/2010) Integrated v1.1, which fixes an +// obscure IE8 EmulateIE7 meta tag compatibility mode bug. +// 1.1 - (1/9/2010) Broke out the jQuery BBQ event.special +// functionality into a separate plugin for users who want just the +// basic event & back button support, without all the extra awesomeness +// that BBQ provides. This plugin will be included as part of jQuery BBQ, +// but also be available separately. See +// plugin for more information. Also added the +// method and added additional examples. +// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and +// location.hash would report incorrectly if the hash contained the ? +// character. Also and +// will no longer parse params out of a URL that doesn't contain ? or #, +// respectively. +// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused +// a "This page contains both secure and nonsecure items." warning when +// used on an https:// page. +// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both "IE7" and "IE8 +// Compatibility View" modes erroneously report that the browser +// supports the native window.onhashchange event, a slightly more +// robust test needed to be added. +// 1.0 - (10/2/2009) Initial release + +(function($,window){ + '$:nomunge'; // Used by YUI compressor. + + // Some convenient shortcuts. + var undefined, + aps = Array.prototype.slice, + decode = decodeURIComponent, + + // Method / object references. + jq_param = $.param, + jq_param_sorted, + jq_param_fragment, + jq_deparam, + jq_deparam_fragment, + jq_bbq = $.bbq = $.bbq || {}, + jq_bbq_pushState, + jq_bbq_getState, + jq_elemUrlAttr, + special = $.event.special, + + // Reused strings. + str_hashchange = 'hashchange', + str_querystring = 'querystring', + str_fragment = 'fragment', + str_elemUrlAttr = 'elemUrlAttr', + str_href = 'href', + str_src = 'src', + + // Reused RegExp. + re_params_querystring = /^.*\?|#.*$/g, + re_params_fragment, + re_fragment, + re_no_escape, + + ajax_crawlable, + fragment_prefix, + + // Used by jQuery.elemUrlAttr. + elemUrlAttr_cache = {}; + + // A few commonly used bits, broken out to help reduce minified file size. + + function is_string( arg ) { + return typeof arg === 'string'; + }; + + // Why write the same function twice? Let's curry! Mmmm, curry.. + + function curry( func ) { + var args = aps.call( arguments, 1 ); + + return function() { + return func.apply( this, args.concat( aps.call( arguments ) ) ); + }; + }; + + // Get location.hash (or what you'd expect location.hash to be) sans any + // leading #. Thanks for making this necessary, Firefox! + function get_fragment( url ) { + return url.replace( re_fragment, '$2' ); + }; + + // Get location.search (or what you'd expect location.search to be) sans any + // leading #. Thanks for making this necessary, IE6! + function get_querystring( url ) { + return url.replace( /(?:^[^?#]*\?([^#]*).*$)?.*/, '$1' ); + }; + + // Section: Param (to string) + // + // Method: jQuery.param.querystring + // + // Retrieve the query string from a URL or if no arguments are passed, the + // current window.location.href. + // + // Usage: + // + // > jQuery.param.querystring( [ url ] ); + // + // Arguments: + // + // url - (String) A URL containing query string params to be parsed. If url + // is not passed, the current window.location.href is used. + // + // Returns: + // + // (String) The parsed query string, with any leading "?" removed. + // + + // Method: jQuery.param.querystring (build url) + // + // Merge a URL, with or without pre-existing query string params, plus any + // object, params string or URL containing query string params into a new URL. + // + // Usage: + // + // > jQuery.param.querystring( url, params [, merge_mode ] ); + // + // Arguments: + // + // url - (String) A valid URL for params to be merged into. This URL may + // contain a query string and/or fragment (hash). + // params - (String) A params string or URL containing query string params to + // be merged into url. + // params - (Object) A params object to be merged into url. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any query string + // params in url. + // * 1: any query string params in url will override params in the params + // argument. + // * 2: params argument will completely replace any query string in url. + // + // Returns: + // + // (String) A URL with a urlencoded query string in the format '?a=b&c=d&e=f'. + + // Method: jQuery.param.fragment + // + // Retrieve the fragment (hash) from a URL or if no arguments are passed, the + // current window.location.href. + // + // Usage: + // + // > jQuery.param.fragment( [ url ] ); + // + // Arguments: + // + // url - (String) A URL containing fragment (hash) params to be parsed. If + // url is not passed, the current window.location.href is used. + // + // Returns: + // + // (String) The parsed fragment (hash) string, with any leading "#" removed. + + // Method: jQuery.param.fragment (build url) + // + // Merge a URL, with or without pre-existing fragment (hash) params, plus any + // object, params string or URL containing fragment (hash) params into a new + // URL. + // + // Usage: + // + // > jQuery.param.fragment( url, params [, merge_mode ] ); + // + // Arguments: + // + // url - (String) A valid URL for params to be merged into. This URL may + // contain a query string and/or fragment (hash). + // params - (String) A params string or URL containing fragment (hash) params + // to be merged into url. + // params - (Object) A params object to be merged into url. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any fragment (hash) + // params in url. + // * 1: any fragment (hash) params in url will override params in the + // params argument. + // * 2: params argument will completely replace any query string in url. + // + // Returns: + // + // (String) A URL with a urlencoded fragment (hash) in the format '#a=b&c=d&e=f'. + + function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) { + var result, + qs, + matches, + url_params, + hash; + + if ( params !== undefined ) { + // Build URL by merging params into url string. + + // matches[1] = url part that precedes params, not including trailing ?/# + // matches[2] = params, not including leading ?/# + // matches[3] = if in 'querystring' mode, hash including leading #, otherwise '' + matches = url.match( is_fragment ? re_fragment : /^([^#?]*)\??([^#]*)(#?.*)/ ); + + // Get the hash if in 'querystring' mode, and it exists. + hash = matches[3] || ''; + + if ( merge_mode === 2 && is_string( params ) ) { + // If merge_mode is 2 and params is a string, merge the fragment / query + // string into the URL wholesale, without converting it into an object. + qs = params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' ); + + } else { + // Convert relevant params in url to object. + url_params = jq_deparam( matches[2] ); + + params = is_string( params ) + + // Convert passed params string into object. + ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params ) + + // Passed params object. + : params; + + qs = merge_mode === 2 ? params // passed params replace url params + : merge_mode === 1 ? $.extend( {}, params, url_params ) // url params override passed params + : $.extend( {}, url_params, params ); // passed params override url params + + // Convert params object into a sorted params string. + qs = jq_param_sorted( qs ); + + // Unescape characters specified via $.param.noEscape. Since only hash- + // history users have requested this feature, it's only enabled for + // fragment-related params strings. + if ( is_fragment ) { + qs = qs.replace( re_no_escape, decode ); + } + } + + // Build URL from the base url, querystring and hash. In 'querystring' + // mode, ? is only added if a query string exists. In 'fragment' mode, # + // is always added. + result = matches[1] + ( is_fragment ? fragment_prefix : qs || !matches[1] ? '?' : '' ) + qs + hash; + + } else { + // If URL was passed in, parse params from URL string, otherwise parse + // params from window.location.href. + result = get_func( url !== undefined ? url : location.href ); + } + + return result; + }; + + jq_param[ str_querystring ] = curry( jq_param_sub, 0, get_querystring ); + jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment ); + + // Method: jQuery.param.sorted + // + // Returns a params string equivalent to that returned by the internal + // jQuery.param method, but sorted, which makes it suitable for use as a + // cache key. + // + // For example, in most browsers jQuery.param({z:1,a:2}) returns "z=1&a=2" + // and jQuery.param({a:2,z:1}) returns "a=2&z=1". Even though both the + // objects being serialized and the resulting params strings are equivalent, + // if these params strings were set into the location.hash fragment + // sequentially, the hashchange event would be triggered unnecessarily, since + // the strings are different (even though the data described by them is the + // same). By sorting the params string, unecessary hashchange event triggering + // can be avoided. + // + // Usage: + // + // > jQuery.param.sorted( obj [, traditional ] ); + // + // Arguments: + // + // obj - (Object) An object to be serialized. + // traditional - (Boolean) Params deep/shallow serialization mode. See the + // documentation at http://api.jquery.com/jQuery.param/ for more detail. + // + // Returns: + // + // (String) A sorted params string. + + jq_param.sorted = jq_param_sorted = function( a, traditional ) { + var arr = [], + obj = {}; + + $.each( jq_param( a, traditional ).split( '&' ), function(i,v){ + var key = v.replace( /(?:%5B|=).*$/, '' ), + key_obj = obj[ key ]; + + if ( !key_obj ) { + key_obj = obj[ key ] = []; + arr.push( key ); + } + + key_obj.push( v ); + }); + + return $.map( arr.sort(), function(v){ + return obj[ v ]; + }).join( '&' ); + }; + + // Method: jQuery.param.fragment.noEscape + // + // Specify characters that will be left unescaped when fragments are created + // or merged using , or when the fragment is modified + // using . This option only applies to serialized data + // object fragments, and not set-as-string fragments. Does not affect the + // query string. Defaults to ",/" (comma, forward slash). + // + // Note that this is considered a purely aesthetic option, and will help to + // create URLs that "look pretty" in the address bar or bookmarks, without + // affecting functionality in any way. That being said, be careful to not + // unescape characters that are used as delimiters or serve a special + // purpose, such as the "#?&=+" (octothorpe, question mark, ampersand, + // equals, plus) characters. + // + // Usage: + // + // > jQuery.param.fragment.noEscape( [ chars ] ); + // + // Arguments: + // + // chars - (String) The characters to not escape in the fragment. If + // unspecified, defaults to empty string (escape all characters). + // + // Returns: + // + // Nothing. + + jq_param_fragment.noEscape = function( chars ) { + chars = chars || ''; + var arr = $.map( chars.split(''), encodeURIComponent ); + re_no_escape = new RegExp( arr.join('|'), 'g' ); + }; + + // A sensible default. These are the characters people seem to complain about + // "uglifying up the URL" the most. + jq_param_fragment.noEscape( ',/' ); + + // Method: jQuery.param.fragment.ajaxCrawlable + // + // TODO: DESCRIBE + // + // Usage: + // + // > jQuery.param.fragment.ajaxCrawlable( [ state ] ); + // + // Arguments: + // + // state - (Boolean) TODO: DESCRIBE + // + // Returns: + // + // (Boolean) The current ajaxCrawlable state. + + jq_param_fragment.ajaxCrawlable = function( state ) { + if ( state !== undefined ) { + if ( state ) { + re_params_fragment = /^.*(?:#!|#)/; + re_fragment = /^([^#]*)(?:#!|#)?(.*)$/; + fragment_prefix = '#!'; + } else { + re_params_fragment = /^.*#/; + re_fragment = /^([^#]*)#?(.*)$/; + fragment_prefix = '#'; + } + ajax_crawlable = !!state; + } + + return ajax_crawlable; + }; + + jq_param_fragment.ajaxCrawlable( 0 ); + + // Section: Deparam (from string) + // + // Method: jQuery.deparam + // + // Deserialize a params string into an object, optionally coercing numbers, + // booleans, null and undefined values; this method is the counterpart to the + // internal jQuery.param method. + // + // Usage: + // + // > jQuery.deparam( params [, coerce ] ); + // + // Arguments: + // + // params - (String) A params string to be parsed. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + $.deparam = jq_deparam = function( params, coerce ) { + var obj = {}, + coerce_types = { 'true': !0, 'false': !1, 'null': null }; + + // Iterate over all name=value pairs. + $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){ + var param = v.split( '=' ), + key = decode( param[0] ), + val, + cur = obj, + i = 0, + + // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it + // into its component parts. + keys = key.split( '][' ), + keys_last = keys.length - 1; + + // If the first keys part contains [ and the last ends with ], then [] + // are correctly balanced. + if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) { + // Remove the trailing ] from the last keys part. + keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' ); + + // Split first keys part into two parts on the [ and add them back onto + // the beginning of the keys array. + keys = keys.shift().split('[').concat( keys ); + + keys_last = keys.length - 1; + } else { + // Basic 'foo' style key. + keys_last = 0; + } + + // Are we dealing with a name=value pair, or just a name? + if ( param.length === 2 ) { + val = decode( param[1] ); + + // Coerce values. + if ( coerce ) { + val = val && !isNaN(val) ? +val // number + : val === 'undefined' ? undefined // undefined + : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null + : val; // string + } + + if ( keys_last ) { + // Complex key, build deep object structure based on a few rules: + // * The 'cur' pointer starts at the object top-level. + // * [] = array push (n is set to array length), [n] = array if n is + // numeric, otherwise object. + // * If at the last keys part, set the value. + // * For each keys part, if the current level is undefined create an + // object or array based on the type of the next keys part. + // * Move the 'cur' pointer to the next level. + // * Rinse & repeat. + for ( ; i <= keys_last; i++ ) { + key = keys[i] === '' ? cur.length : keys[i]; + cur = cur[key] = i < keys_last + ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] ) + : val; + } + + } else { + // Simple key, even simpler rules, since only scalars and shallow + // arrays are allowed. + + if ( $.isArray( obj[key] ) ) { + // val is already an array, so push on the next value. + obj[key].push( val ); + + } else if ( obj[key] !== undefined ) { + // val isn't an array, but since a second value has been specified, + // convert val into an array. + obj[key] = [ obj[key], val ]; + + } else { + // val is a scalar. + obj[key] = val; + } + } + + } else if ( key ) { + // No value was defined, so set something meaningful. + obj[key] = coerce + ? undefined + : ''; + } + }); + + return obj; + }; + + // Method: jQuery.deparam.querystring + // + // Parse the query string from a URL or the current window.location.href, + // deserializing it into an object, optionally coercing numbers, booleans, + // null and undefined values. + // + // Usage: + // + // > jQuery.deparam.querystring( [ url ] [, coerce ] ); + // + // Arguments: + // + // url - (String) An optional params string or URL containing query string + // params to be parsed. If url is omitted, the current + // window.location.href is used. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + // Method: jQuery.deparam.fragment + // + // Parse the fragment (hash) from a URL or the current window.location.href, + // deserializing it into an object, optionally coercing numbers, booleans, + // null and undefined values. + // + // Usage: + // + // > jQuery.deparam.fragment( [ url ] [, coerce ] ); + // + // Arguments: + // + // url - (String) An optional params string or URL containing fragment (hash) + // params to be parsed. If url is omitted, the current window.location.href + // is used. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false if omitted. + // + // Returns: + // + // (Object) An object representing the deserialized params string. + + function jq_deparam_sub( is_fragment, url_or_params, coerce ) { + if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) { + // url_or_params not specified. + coerce = url_or_params; + url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ](); + } else { + url_or_params = is_string( url_or_params ) + ? url_or_params.replace( is_fragment ? re_params_fragment : re_params_querystring, '' ) + : url_or_params; + } + + return jq_deparam( url_or_params, coerce ); + }; + + jq_deparam[ str_querystring ] = curry( jq_deparam_sub, 0 ); + jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 ); + + // Section: Element manipulation + // + // Method: jQuery.elemUrlAttr + // + // Get the internal "Default URL attribute per tag" list, or augment the list + // with additional tag-attribute pairs, in case the defaults are insufficient. + // + // In the and methods, this list + // is used to determine which attribute contains the URL to be modified, if + // an "attr" param is not specified. + // + // Default Tag-Attribute List: + // + // a - href + // base - href + // iframe - src + // img - src + // input - src + // form - action + // link - href + // script - src + // + // Usage: + // + // > jQuery.elemUrlAttr( [ tag_attr ] ); + // + // Arguments: + // + // tag_attr - (Object) An object containing a list of tag names and their + // associated default attribute names in the format { tag: 'attr', ... } to + // be merged into the internal tag-attribute list. + // + // Returns: + // + // (Object) An object containing all stored tag-attribute values. + + // Only define function and set defaults if function doesn't already exist, as + // the urlInternal plugin will provide this method as well. + $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) { + return $.extend( elemUrlAttr_cache, obj ); + })({ + a: str_href, + base: str_href, + iframe: str_src, + img: str_src, + input: str_src, + form: 'action', + link: str_href, + script: str_src + }); + + jq_elemUrlAttr = $[ str_elemUrlAttr ]; + + // Method: jQuery.fn.querystring + // + // Update URL attribute in one or more elements, merging the current URL (with + // or without pre-existing query string params) plus any params object or + // string into a new URL, which is then set into that attribute. Like + // , but for all elements in a jQuery + // collection. + // + // Usage: + // + // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] ); + // + // Arguments: + // + // attr - (String) Optional name of an attribute that will contain a URL to + // merge params or url into. See for a list of default + // attributes. + // params - (Object) A params object to be merged into the URL attribute. + // params - (String) A URL containing query string params, or params string + // to be merged into the URL attribute. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any params in attr URL. + // * 1: any params in attr URL will override params in the params argument. + // * 2: params argument will completely replace any query string in attr + // URL. + // + // Returns: + // + // (jQuery) The initial jQuery collection of elements, but with modified URL + // attribute values. + + // Method: jQuery.fn.fragment + // + // Update URL attribute in one or more elements, merging the current URL (with + // or without pre-existing fragment/hash params) plus any params object or + // string into a new URL, which is then set into that attribute. Like + // , but for all elements in a jQuery + // collection. + // + // Usage: + // + // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] ); + // + // Arguments: + // + // attr - (String) Optional name of an attribute that will contain a URL to + // merge params into. See for a list of default + // attributes. + // params - (Object) A params object to be merged into the URL attribute. + // params - (String) A URL containing fragment (hash) params, or params + // string to be merged into the URL attribute. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified, and is as-follows: + // + // * 0: params in the params argument will override any params in attr URL. + // * 1: any params in attr URL will override params in the params argument. + // * 2: params argument will completely replace any fragment (hash) in attr + // URL. + // + // Returns: + // + // (jQuery) The initial jQuery collection of elements, but with modified URL + // attribute values. + + function jq_fn_sub( mode, force_attr, params, merge_mode ) { + if ( !is_string( params ) && typeof params !== 'object' ) { + // force_attr not specified. + merge_mode = params; + params = force_attr; + force_attr = undefined; + } + + return this.each(function(){ + var that = $(this), + + // Get attribute specified, or default specified via $.elemUrlAttr. + attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '', + + // Get URL value. + url = attr && that.attr( attr ) || ''; + + // Update attribute with new URL. + that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) ); + }); + + }; + + $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring ); + $.fn[ str_fragment ] = curry( jq_fn_sub, str_fragment ); + + // Section: History, hashchange event + // + // Method: jQuery.bbq.pushState + // + // Adds a 'state' into the browser history at the current position, setting + // location.hash and triggering any bound callbacks + // (provided the new state is different than the previous state). + // + // If no arguments are passed, an empty state is created, which is just a + // shortcut for jQuery.bbq.pushState( {}, 2 ). + // + // Usage: + // + // > jQuery.bbq.pushState( [ params [, merge_mode ] ] ); + // + // Arguments: + // + // params - (String) A serialized params string or a hash string beginning + // with # to merge into location.hash. + // params - (Object) A params object to merge into location.hash. + // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not + // specified (unless a hash string beginning with # is specified, in which + // case merge behavior defaults to 2), and is as-follows: + // + // * 0: params in the params argument will override any params in the + // current state. + // * 1: any params in the current state will override params in the params + // argument. + // * 2: params argument will completely replace current state. + // + // Returns: + // + // Nothing. + // + // Additional Notes: + // + // * Setting an empty state may cause the browser to scroll. + // * Unlike the fragment and querystring methods, if a hash string beginning + // with # is specified as the params agrument, merge_mode defaults to 2. + + jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) { + if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) { + // Params string begins with # and merge_mode not specified, so completely + // overwrite window.location.hash. + merge_mode = 2; + } + + var has_args = params !== undefined, + // Merge params into window.location using $.param.fragment. + url = jq_param_fragment( location.href, + has_args ? params : {}, has_args ? merge_mode : 2 ); + + // Set new window.location.href. Note that Safari 3 & Chrome barf on + // location.hash = '#' so the entire URL is set. + location.href = url; + }; + + // Method: jQuery.bbq.getState + // + // Retrieves the current 'state' from the browser history, parsing + // location.hash for a specific key or returning an object containing the + // entire state, optionally coercing numbers, booleans, null and undefined + // values. + // + // Usage: + // + // > jQuery.bbq.getState( [ key ] [, coerce ] ); + // + // Arguments: + // + // key - (String) An optional state key for which to return a value. + // coerce - (Boolean) If true, coerces any numbers or true, false, null, and + // undefined to their actual value. Defaults to false. + // + // Returns: + // + // (Anything) If key is passed, returns the value corresponding with that key + // in the location.hash 'state', or undefined. If not, an object + // representing the entire 'state' is returned. + + jq_bbq.getState = jq_bbq_getState = function( key, coerce ) { + return key === undefined || typeof key === 'boolean' + ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here + : jq_deparam_fragment( coerce )[ key ]; + }; + + // Method: jQuery.bbq.removeState + // + // Remove one or more keys from the current browser history 'state', creating + // a new state, setting location.hash and triggering any bound + // callbacks (provided the new state is different than + // the previous state). + // + // If no arguments are passed, an empty state is created, which is just a + // shortcut for jQuery.bbq.pushState( {}, 2 ). + // + // Usage: + // + // > jQuery.bbq.removeState( [ key [, key ... ] ] ); + // + // Arguments: + // + // key - (String) One or more key values to remove from the current state, + // passed as individual arguments. + // key - (Array) A single array argument that contains a list of key values + // to remove from the current state. + // + // Returns: + // + // Nothing. + // + // Additional Notes: + // + // * Setting an empty state may cause the browser to scroll. + + jq_bbq.removeState = function( arr ) { + var state = {}; + + // If one or more arguments is passed.. + if ( arr !== undefined ) { + + // Get the current state. + state = jq_bbq_getState(); + + // For each passed key, delete the corresponding property from the current + // state. + $.each( $.isArray( arr ) ? arr : arguments, function(i,v){ + delete state[ v ]; + }); + } + + // Set the state, completely overriding any existing state. + jq_bbq_pushState( state, 2 ); + }; + + // Event: hashchange event (BBQ) + // + // Usage in jQuery 1.4 and newer: + // + // In jQuery 1.4 and newer, the event object passed into any hashchange event + // callback is augmented with a copy of the location.hash fragment at the time + // the event was triggered as its event.fragment property. In addition, the + // event.getState method operates on this property (instead of location.hash) + // which allows this fragment-as-a-state to be referenced later, even after + // window.location may have changed. + // + // Note that event.fragment and event.getState are not defined according to + // W3C (or any other) specification, but will still be available whether or + // not the hashchange event exists natively in the browser, because of the + // utility they provide. + // + // The event.fragment property contains the output of + // and the event.getState method is equivalent to the + // method. + // + // > $(window).bind( 'hashchange', function( event ) { + // > var hash_str = event.fragment, + // > param_obj = event.getState(), + // > param_val = event.getState( 'param_name' ), + // > param_val_coerced = event.getState( 'param_name', true ); + // > ... + // > }); + // + // Usage in jQuery 1.3.2: + // + // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+, + // so the fragment state isn't bound to the event object and must instead be + // parsed using the and methods. + // + // > $(window).bind( 'hashchange', function( event ) { + // > var hash_str = $.param.fragment(), + // > param_obj = $.bbq.getState(), + // > param_val = $.bbq.getState( 'param_name' ), + // > param_val_coerced = $.bbq.getState( 'param_name', true ); + // > ... + // > }); + // + // Additional Notes: + // + // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is + // required to enable the augmented event object in jQuery 1.4.2 and newer. + // * See for more detailed information. + + special[ str_hashchange ] = $.extend( special[ str_hashchange ], { + + // Augmenting the event object with the .fragment property and .getState + // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will + // work, but the event won't be augmented) + add: function( handleObj ) { + var old_handler; + + function new_handler(e) { + // e.fragment is set to the value of location.hash (with any leading # + // removed) at the time the event is triggered. + var hash = e[ str_fragment ] = jq_param_fragment(); + + // e.getState() works just like $.bbq.getState(), but uses the + // e.fragment property stored on the event object. + e.getState = function( key, coerce ) { + return key === undefined || typeof key === 'boolean' + ? jq_deparam( hash, key ) // 'key' really means 'coerce' here + : jq_deparam( hash, coerce )[ key ]; + }; + + old_handler.apply( this, arguments ); + }; + + // This may seem a little complicated, but it normalizes the special event + // .add method between jQuery 1.4/1.4.1 and 1.4.2+ + if ( $.isFunction( handleObj ) ) { + // 1.4, 1.4.1 + old_handler = handleObj; + return new_handler; + } else { + // 1.4.2+ + old_handler = handleObj.handler; + handleObj.handler = new_handler; + } + } + + }); + +})(jQuery,this); + +/*! + * jQuery hashchange event - v1.3 - 7/21/2010 * http://benalman.com/projects/jquery-hashchange-plugin/ * * Copyright (c) 2010 "Cowboy" Ben Alman * Dual licensed under the MIT and GPL licenses. * http://benalman.com/about/license/ */ -(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('