diff --git a/dashboard-ui/bower_components/emby-apiclient/.bower.json b/dashboard-ui/bower_components/emby-apiclient/.bower.json index 257ccdae1e..0a72e4c328 100644 --- a/dashboard-ui/bower_components/emby-apiclient/.bower.json +++ b/dashboard-ui/bower_components/emby-apiclient/.bower.json @@ -16,12 +16,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.0.21", - "_release": "1.0.21", + "version": "1.0.25", + "_release": "1.0.25", "_resolution": { "type": "version", - "tag": "1.0.21", - "commit": "e341b097c05c31ec012e04dfbd0455ae9dfc4929" + "tag": "1.0.25", + "commit": "f2e83b0e30527b5182ceb043d170ad7188368245" }, "_source": "git://github.com/MediaBrowser/Emby.ApiClient.Javascript.git", "_target": "~1.0.3", diff --git a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js index 7f2e84ecaf..efa177a53b 100644 --- a/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js +++ b/dashboard-ui/bower_components/emby-apiclient/connectionmanager.js @@ -1123,7 +1123,7 @@ if (options.updateDateLastAccessed !== false) { server.DateLastAccessed = new Date().getTime(); - if (server.LastConnectionMode == ConnectionMode.Local) { + if (connectionMode == ConnectionMode.Local) { server.DateLastLocalConnection = new Date().getTime(); } } @@ -1466,6 +1466,17 @@ self.getRegistrationInfo = function (feature, apiClient) { + if (isConnectUserSupporter()) { + return new Promise(function (resolve, reject) { + + resolve({ + Name: feature, + IsRegistered: true, + IsTrial: false + }); + }); + } + return self.getAvailableServers().then(function (servers) { var matchedServers = servers.filter(function (s) { @@ -1498,6 +1509,19 @@ }); }; + function isConnectUserSupporter() { + + if (self.isLoggedIntoConnect()) { + + var connectUser = self.connectUser(); + + if (connectUser && connectUser.IsSupporter) { + return true; + } + } + return false; + } + function updateDateLastLocalConnection(serverId) { var credentials = credentialProvider.credentials(); diff --git a/dashboard-ui/bower_components/emby-apiclient/store.js b/dashboard-ui/bower_components/emby-apiclient/store.js index 6599f47c1b..8bd070c5cc 100644 --- a/dashboard-ui/bower_components/emby-apiclient/store.js +++ b/dashboard-ui/bower_components/emby-apiclient/store.js @@ -1,4 +1,4 @@ -(function (globalScope, localStorage, sessionStorage) { +(function (globalScope) { function myStore(defaultObject) { @@ -45,7 +45,7 @@ }; } - globalScope.appStorage = new myStore(localStorage); - globalScope.sessionStore = new myStore(sessionStorage); + globalScope.appStorage = new myStore(globalScope.localStorage); + globalScope.sessionStore = new myStore(globalScope.sessionStorage); -})(window, window.localStorage, window.sessionStorage); \ No newline at end of file +})(this); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/visibleinviewport.js b/dashboard-ui/bower_components/emby-webcomponents/visibleinviewport.js new file mode 100644 index 0000000000..74202df5b0 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/visibleinviewport.js @@ -0,0 +1,34 @@ +define([], function () { + + /** + * Copyright 2012, Digital Fusion + * Licensed under the MIT license. + * http://teamdf.com/jquery-plugins/license/ + * + * @author Sam Sehnert + * @desc A small plugin that checks whether elements are within + * the user visible viewport of a web browser. + * only accounts for vertical position, not horizontal. + */ + function visibleInViewport(elem, partial, thresholdX, thresholdY) { + + thresholdX = thresholdX || 0; + thresholdY = thresholdY || 0; + + var vpWidth = window.innerWidth, + vpHeight = window.innerHeight; + + // Use this native browser method, if available. + var rec = elem.getBoundingClientRect(), + tViz = rec.top >= 0 && rec.top < vpHeight + thresholdY, + bViz = rec.bottom > 0 && rec.bottom <= vpHeight + thresholdY, + lViz = rec.left >= 0 && rec.left < vpWidth + thresholdX, + rViz = rec.right > 0 && rec.right <= vpWidth + thresholdX, + vVisible = partial ? tViz || bViz : tViz && bViz, + hVisible = partial ? lViz || rViz : lViz && rViz; + + return vVisible && hVisible; + } + + return visibleInViewport; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/hls.js/.bower.json b/dashboard-ui/bower_components/hls.js/.bower.json index daddb3e9d1..44c282c016 100644 --- a/dashboard-ui/bower_components/hls.js/.bower.json +++ b/dashboard-ui/bower_components/hls.js/.bower.json @@ -1,6 +1,6 @@ { "name": "hls.js", - "version": "0.3.15", + "version": "0.4.5", "description": "Media Source Extension - HLS library, by/for Dailymotion", "homepage": "https://github.com/dailymotion/hls.js", "authors": [ @@ -15,13 +15,14 @@ "test", "tests" ], - "_release": "0.3.15", + "_release": "0.4.5", "_resolution": { "type": "version", - "tag": "v0.3.15", - "commit": "d3ecf55b89063d7ba3bd70800d5839755b0c7e63" + "tag": "v0.4.5", + "commit": "908ac4a44a182bdbede9c1830828983c18532ca0" }, "_source": "git://github.com/dailymotion/hls.js.git", - "_target": "~0.3.11", - "_originalSource": "dailymotion/hls.js" + "_target": "~0.4.5", + "_originalSource": "dailymotion/hls.js", + "_direct": true } \ No newline at end of file diff --git a/dashboard-ui/bower_components/hls.js/API.md b/dashboard-ui/bower_components/hls.js/API.md index 1567735bd9..dee1907066 100644 --- a/dashboard-ui/bower_components/hls.js/API.md +++ b/dashboard-ui/bower_components/hls.js/API.md @@ -184,17 +184,21 @@ configuration parameters could be provided to hls.js upon instantiation of Hls O debug : false, autoStartLoad : true, maxBufferLength : 30, + maxMaxBufferLength : 600, maxBufferSize : 60*1000*1000, liveSyncDurationCount : 3, liveMaxLatencyDurationCount: 10, enableWorker : true, enableSoftwareAES: true, - fragLoadingTimeOut : 20000, - fragLoadingMaxRetry : 6, - fragLoadingRetryDelay : 500, manifestLoadingTimeOut : 10000, manifestLoadingMaxRetry : 6, manifestLoadingRetryDelay : 500, + levelLoadingTimeOut : 10000, + levelLoadingMaxRetry : 6, + levelLoadingRetryDelay : 500, + fragLoadingTimeOut : 20000, + fragLoadingMaxRetry : 6, + fragLoadingRetryDelay : 500, fpsDroppedMonitoringPeriod : 5000, fpsDroppedMonitoringThreshold : 0.2, appendErrorMaxRetry : 3, @@ -209,6 +213,10 @@ configuration parameters could be provided to hls.js upon instantiation of Hls O var hls = new Hls(config); ``` +#### ```Hls.DefaultConfig get/set``` +this getter/setter allows to retrieve and override Hls default configuration. +this configuration will be applied by default to all instances. + #### ```debug``` (default false) @@ -225,10 +233,24 @@ a logger object could also be provided for custom logging : ```config.debug=cust (default 30s) maximum buffer Length in seconds. if buffer length is/become less than this value, a new fragment will be loaded. +this is the guaranteed buffer length hls.js will try to reach, regardless of maxBufferSize. + #### ```maxBufferSize``` (default 60 MB) -maximum buffer size in bytes. if buffer size upfront is bigger than this value, no fragment will be loaded. +'minimum' maximum buffer size in bytes. if buffer size upfront is bigger than this value, no fragment will be loaded. + +#### ```maxMaxBufferLength``` +(default 600s) + +maximum buffer Length in seconds. hls.js will never exceed this value. even if maxBufferSize is not reached yet. + +hls.js tries to buffer up to a maximum number of bytes (60 MB by default) rather than to buffer up to a maximum nb of seconds. +this is to mimic the browser behaviour (the buffer eviction algorithm is starting after the browser detects that video buffer size reaches a limit in bytes) + +config.maxBufferLength is the minimum guaranteed buffer length that hls.js will try to achieve, even if that value exceeds the amount of bytes 60 MB of memory. +maxMaxBufferLength acts as a capping value, as if bitrate is really low, you could need more than one hour of buffer to fill 60 MB.... + #### ```liveSyncDurationCount``` (default 3) @@ -255,19 +277,19 @@ enable webworker (if available on browser) for TS demuxing/MP4 remuxing, to impr enable to use JavaScript version AES decryption for fallback of WebCrypto API. -#### ```fragLoadingTimeOut```/```manifestLoadingTimeOut``` -(default 60000ms for fragment/10000ms for manifest) +#### ```fragLoadingTimeOut```/```manifestLoadingTimeOut```/```levelLoadingTimeOut``` +(default 60000ms for fragment/10000ms for level and manifest) URL Loader timeout. A timeout callback will be triggered if loading duration exceeds this timeout. no further action will be done : the load operation will not be cancelled/aborted. It is up to the application to catch this event and treat it as needed. -#### ```fragLoadingMaxRetry```/```manifestLoadingMaxRetry``` +#### ```fragLoadingMaxRetry```/```manifestLoadingMaxRetry```/```levelLoadingMaxRetry``` (default 3) max nb of load retry -#### ```fragLoadingRetryDelay```/```manifestLoadingRetryDelay``` -(default 500ms) +#### ```fragLoadingRetryDelay```/```manifestLoadingRetryDelay```/```levelLoadingRetryDelay``` +(default 1000ms) initial delay between XmlHttpRequest error and first load retry (in ms) any I/O error will trigger retries every 500ms,1s,2s,4s,8s, ... capped to 64s (exponential backoff) @@ -485,7 +507,7 @@ full list of Events available below : - `Hls.Events.FRAG_LOADING` - fired when a fragment loading starts - data: { frag : fragment object} - `Hls.Events.FRAG_LOAD_PROGRESS` - fired when a fragment load is in progress - - data: { frag : fragment object, stats : progress event } + - data: { frag : fragment object with frag.loaded=stats.loaded, stats : { trequest, tfirst, loaded} } - `Hls.Events.FRAG_LOADED` - fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length}} - `Hls.Events.FRAG_PARSING_INIT_SEGMENT` - fired when Init Segment has been extracted from fragment diff --git a/dashboard-ui/bower_components/hls.js/bower.json b/dashboard-ui/bower_components/hls.js/bower.json index c7f08e5ea7..b47f29f9e2 100644 --- a/dashboard-ui/bower_components/hls.js/bower.json +++ b/dashboard-ui/bower_components/hls.js/bower.json @@ -1,6 +1,6 @@ { "name": "hls.js", - "version": "0.3.15", + "version": "0.4.5", "description": "Media Source Extension - HLS library, by/for Dailymotion", "homepage": "https://github.com/dailymotion/hls.js", "authors": [ diff --git a/dashboard-ui/bower_components/hls.js/demo/index.html b/dashboard-ui/bower_components/hls.js/demo/index.html index 446804bb1e..404a86adc1 100644 --- a/dashboard-ui/bower_components/hls.js/demo/index.html +++ b/dashboard-ui/bower_components/hls.js/demo/index.html @@ -75,6 +75,7 @@ header { +
" + + ""; // Support: IE8, Opera 11-12.16 @@ -1195,7 +1199,7 @@ setDocument = Sizzle.setDocument = function( node ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } - // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { rbuggyQSA.push("~="); } @@ -1218,7 +1222,7 @@ setDocument = Sizzle.setDocument = function( node ) { assert(function( div ) { // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); + var input = document.createElement("input"); input.setAttribute( "type", "hidden" ); div.appendChild( input ).setAttribute( "name", "D" ); @@ -1266,7 +1270,7 @@ setDocument = Sizzle.setDocument = function( node ) { hasCompare = rnative.test( docElem.compareDocumentPosition ); // Element contains another - // Purposefully does not implement inclusive descendent + // Purposefully self-exclusive // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { @@ -1320,10 +1324,10 @@ setDocument = Sizzle.setDocument = function( node ) { (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { return -1; } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { return 1; } @@ -1351,8 +1355,8 @@ setDocument = Sizzle.setDocument = function( node ) { // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : + return a === document ? -1 : + b === document ? 1 : aup ? -1 : bup ? 1 : sortInput ? @@ -1389,7 +1393,7 @@ setDocument = Sizzle.setDocument = function( node ) { 0; }; - return doc; + return document; }; Sizzle.matches = function( expr, elements ) { @@ -1406,6 +1410,7 @@ Sizzle.matchesSelector = function( elem, expr ) { expr = expr.replace( rattributeQuotes, "='$1']" ); if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { @@ -1679,11 +1684,12 @@ Expr = Sizzle.selectors = { } : function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, + var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; + useCache = !xml && !ofType, + diff = false; if ( parent ) { @@ -1692,7 +1698,10 @@ Expr = Sizzle.selectors = { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + return false; } } @@ -1706,11 +1715,21 @@ Expr = Sizzle.selectors = { // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { + // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; while ( (node = ++nodeIndex && node && node[ dir ] || @@ -1720,29 +1739,55 @@ Expr = Sizzle.selectors = { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); - if ( node === elem ) { - break; + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } } } } @@ -2104,10 +2149,10 @@ function addCombinator( matcher, combinator, base ) { // Check against all ancestor/preceding elements function( elem, context, xml ) { - var oldCache, outerCache, + var oldCache, uniqueCache, outerCache, newCache = [ dirruns, doneName ]; - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if ( xml ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { @@ -2120,14 +2165,19 @@ function addCombinator( matcher, combinator, base ) { while ( (elem = elem[ dir ]) ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( (oldCache = uniqueCache[ dir ]) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements return (newCache[ 2 ] = oldCache[ 2 ]); } else { // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; + uniqueCache[ dir ] = newCache; // A match means we're done; a fail means we have to keep checking if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { @@ -2352,18 +2402,21 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { len = elems.length; if ( outermost ) { - outermostContext = context !== document && context; + outermostContext = context === document || context || outermost; } // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id for ( ; i !== len && (elem = elems[i]) != null; i++ ) { if ( byElement && elem ) { j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { + if ( matcher( elem, context || document, xml) ) { results.push( elem ); break; } @@ -2387,8 +2440,17 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { } } - // Apply set filters to unmatched elements + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. if ( bySet && i !== matchedCount ) { j = 0; while ( (matcher = setMatchers[j++]) ) { @@ -2480,10 +2542,11 @@ select = Sizzle.select = function( selector, context, results, seed ) { results = results || []; - // Try to minimize operations if there is no seed and only one group + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) if ( match.length === 1 ) { - // Take a shortcut and set the context if the root selector is an ID + // Reduce context if the leading compound selector is an ID tokens = match[0] = match[0].slice( 0 ); if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && support.getById && context.nodeType === 9 && documentIsHTML && @@ -2538,7 +2601,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { context, !documentIsHTML, results, - rsibling.test( selector ) && testContext( context.parentNode ) || context + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context ); return results; }; @@ -2614,17 +2677,46 @@ return Sizzle; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + var rneedsContext = jQuery.expr.match.needsContext; -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); +var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ ); @@ -2636,14 +2728,14 @@ function winnow( elements, qualifier, not ) { return jQuery.grep( elements, function( elem, i ) { /* jshint -W018 */ return !!qualifier.call( elem, i, elem ) !== not; - }); + } ); } if ( qualifier.nodeType ) { return jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) !== not; - }); + } ); } @@ -2656,8 +2748,8 @@ function winnow( elements, qualifier, not ) { } return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); } jQuery.filter = function( expr, elems, not ) { @@ -2671,10 +2763,10 @@ jQuery.filter = function( expr, elems, not ) { jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { return elem.nodeType === 1; - })); + } ) ); }; -jQuery.fn.extend({ +jQuery.fn.extend( { find: function( selector ) { var i, len = this.length, @@ -2682,13 +2774,13 @@ jQuery.fn.extend({ self = this; if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { + return this.pushStack( jQuery( selector ).filter( function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } - }) ); + } ) ); } for ( i = 0; i < len; i++ ) { @@ -2701,10 +2793,10 @@ jQuery.fn.extend({ return ret; }, filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); + return this.pushStack( winnow( this, selector || [], false ) ); }, not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); + return this.pushStack( winnow( this, selector || [], true ) ); }, is: function( selector ) { return !!winnow( @@ -2718,7 +2810,7 @@ jQuery.fn.extend({ false ).length; } -}); +} ); // Initialize a jQuery object @@ -2732,7 +2824,7 @@ var rootjQuery, // Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - init = jQuery.fn.init = function( selector, context ) { + init = jQuery.fn.init = function( selector, context, root ) { var match, elem; // HANDLE: $(""), $(null), $(undefined), $(false) @@ -2740,9 +2832,16 @@ var rootjQuery, return this; } + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + // Handle HTML strings if ( typeof selector === "string" ) { - if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { + if ( selector[ 0 ] === "<" && + selector[ 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 ]; @@ -2751,23 +2850,24 @@ var rootjQuery, } // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { + if ( match && ( match[ 1 ] || !context ) ) { // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( - match[1], + match[ 1 ], context && context.nodeType ? context.ownerDocument || context : document, true ) ); // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { for ( match in context ) { + // Properties of context are called as methods if possible if ( jQuery.isFunction( this[ match ] ) ) { this[ match ]( context[ match ] ); @@ -2783,14 +2883,15 @@ var rootjQuery, // HANDLE: $(#id) } else { - elem = document.getElementById( match[2] ); + elem = document.getElementById( match[ 2 ] ); // Support: Blackberry 4.6 // gEBID returns nodes no longer in the document (#6963) if ( elem && elem.parentNode ) { + // Inject the element directly into the jQuery object this.length = 1; - this[0] = elem; + this[ 0 ] = elem; } this.context = document; @@ -2800,7 +2901,7 @@ var rootjQuery, // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); + return ( context || root ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) @@ -2810,15 +2911,16 @@ var rootjQuery, // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { - this.context = this[0] = selector; + this.context = this[ 0 ] = selector; this.length = 1; return this; // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : + return root.ready !== undefined ? + root.ready( selector ) : + // Execute immediately if ready is not present selector( jQuery ); } @@ -2839,6 +2941,7 @@ rootjQuery = jQuery( document ); var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // Methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, @@ -2847,48 +2950,19 @@ var rparentsprev = /^(?:parents|prev(?:Until|All))/, prev: true }; -jQuery.extend({ - dir: function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }, - - sibling: function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - } -}); - -jQuery.fn.extend({ +jQuery.fn.extend( { has: function( target ) { var targets = jQuery( target, this ), l = targets.length; - return this.filter(function() { + return this.filter( function() { var i = 0; for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { + if ( jQuery.contains( this, targets[ i ] ) ) { return true; } } - }); + } ); }, closest: function( selectors, context ) { @@ -2901,14 +2975,15 @@ jQuery.fn.extend({ 0; for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : + if ( cur.nodeType < 11 && ( pos ? + pos.index( cur ) > -1 : // Don't pass non-elements to Sizzle cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { + jQuery.find.matchesSelector( cur, selectors ) ) ) { matched.push( cur ); break; @@ -2916,7 +2991,7 @@ jQuery.fn.extend({ } } - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); }, // Determine the position of an element within the set @@ -2942,7 +3017,7 @@ jQuery.fn.extend({ add: function( selector, context ) { return this.pushStack( - jQuery.unique( + jQuery.uniqueSort( jQuery.merge( this.get(), jQuery( selector, context ) ) ) ); @@ -2950,26 +3025,26 @@ jQuery.fn.extend({ addBack: function( selector ) { return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) + this.prevObject : this.prevObject.filter( selector ) ); } -}); +} ); function sibling( cur, dir ) { - while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} return cur; } -jQuery.each({ +jQuery.each( { parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); + return dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); + return dir( elem, "parentNode", until ); }, next: function( elem ) { return sibling( elem, "nextSibling" ); @@ -2978,22 +3053,22 @@ jQuery.each({ return sibling( elem, "previousSibling" ); }, nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); + return dir( elem, "nextSibling" ); }, prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); + return dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); + return dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); + return dir( elem, "previousSibling", until ); }, siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + return siblings( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { - return jQuery.sibling( elem.firstChild ); + return siblings( elem.firstChild ); }, contents: function( elem ) { return elem.contentDocument || jQuery.merge( [], elem.childNodes ); @@ -3011,9 +3086,10 @@ jQuery.each({ } if ( this.length > 1 ) { + // Remove duplicates if ( !guaranteedUnique[ name ] ) { - jQuery.unique( matched ); + jQuery.uniqueSort( matched ); } // Reverse order for parents* and prev-derivatives @@ -3024,20 +3100,17 @@ jQuery.each({ return this.pushStack( matched ); }; -}); -var rnotwhite = (/\S+/g); +} ); +var rnotwhite = ( /\S+/g ); -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache +// Convert String-formatted options into Object-formatted ones function createOptions( options ) { - var object = optionsCache[ options ] = {}; + var object = {}; jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; - }); + } ); return object; } @@ -3068,156 +3141,186 @@ jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : + createOptions( options ) : jQuery.extend( {}, options ); - var // Last fire value (for non-forgettable lists) + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists memory, + // Flag to know if list was already fired fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, + + // Flag to prevent firing + locked, + // Actual callback list list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } } } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { list = []; + + // Otherwise, this object is spent } else { - self.disable(); + list = ""; } } }, + // Actual Callbacks object self = { + // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { + if ( jQuery.isFunction( arg ) ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } - } else if ( arg && arg.length && type !== "string" ) { + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + // Inspect recursively add( arg ); } - }); - })( 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 - } else if ( memory ) { - firingStart = start; - fire( memory ); + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); } } return this; }, + // Remove a callback from the list remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; } - }); - } + } + } ); return this; }, + // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; }, + // Remove all callbacks from the list empty: function() { - list = []; - firingLength = 0; - 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 ) { - self.disable(); + if ( list ) { + list = []; } return this; }, - // Is it locked? - locked: function() { - return !stack; + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + // Call all callbacks with the given context and arguments fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { + if ( !locked ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); + queue.push( args ); + if ( !firing ) { + fire(); } } 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 !!fired; @@ -3228,14 +3331,15 @@ jQuery.Callbacks = function( options ) { }; -jQuery.extend({ +jQuery.extend( { Deferred: function( func ) { var tuples = [ + // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] + [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], + [ "notify", "progress", jQuery.Callbacks( "memory" ) ] ], state = "pending", promise = { @@ -3248,25 +3352,30 @@ jQuery.extend({ }, then: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; - return jQuery.Deferred(function( newDefer ) { + return jQuery.Deferred( function( newDefer ) { jQuery.each( tuples, function( i, tuple ) { var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { + deferred[ tuple[ 1 ] ]( function() { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() + .progress( newDefer.notify ) .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); + .fail( newDefer.reject ); } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + newDefer[ tuple[ 0 ] + "With" ]( + this === promise ? newDefer.promise() : this, + fn ? [ returned ] : arguments + ); } - }); - }); + } ); + } ); fns = null; - }).promise(); + } ).promise(); }, + // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { @@ -3284,11 +3393,12 @@ jQuery.extend({ stateString = tuple[ 3 ]; // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; + promise[ tuple[ 1 ] ] = list.add; // Handle state if ( stateString ) { - list.add(function() { + list.add( function() { + // state = [ resolved | rejected ] state = stateString; @@ -3297,12 +3407,12 @@ jQuery.extend({ } // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); return this; }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); // Make the deferred a promise promise.promise( deferred ); @@ -3323,9 +3433,11 @@ jQuery.extend({ length = resolveValues.length, // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + remaining = length !== 1 || + ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + // the master Deferred. + // If resolveValues consist of only a single Deferred, just use that. deferred = remaining === 1 ? subordinate : jQuery.Deferred(), // Update function for both resolve and progress values @@ -3351,9 +3463,9 @@ jQuery.extend({ for ( ; i < length; i++ ) { if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { resolveValues[ i ].promise() + .progress( updateFunc( i, progressContexts, progressValues ) ) .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); + .fail( deferred.reject ); } else { --remaining; } @@ -3367,20 +3479,22 @@ jQuery.extend({ return deferred.promise(); } -}); +} ); // The deferred used on DOM ready var readyList; jQuery.fn.ready = function( fn ) { + // Add the callback jQuery.ready.promise().done( fn ); return this; }; -jQuery.extend({ +jQuery.extend( { + // Is the DOM ready to be used? Set to true once it occurs. isReady: false, @@ -3422,14 +3536,14 @@ jQuery.extend({ jQuery( document ).off( "ready" ); } } -}); +} ); /** * The ready event handler and self cleanup method */ function completed() { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); jQuery.ready(); } @@ -3438,20 +3552,23 @@ jQuery.ready.promise = function( obj ) { readyList = jQuery.Deferred(); - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // We once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { + // Catch cases where $(document).ready() is called + // after the browser event has already occurred. + // Support: IE9-10 only + // Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); + window.setTimeout( jQuery.ready ); } else { // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); + document.addEventListener( "DOMContentLoaded", completed ); // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); + window.addEventListener( "load", completed ); } } return readyList.promise( obj ); @@ -3465,7 +3582,7 @@ jQuery.ready.promise(); // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { var i = 0, len = elems.length, bulk = key == null; @@ -3474,7 +3591,7 @@ var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGe if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + access( elems, fn, i, key[ i ], true, emptyGet, raw ); } // Sets one value @@ -3486,6 +3603,7 @@ var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGe } if ( bulk ) { + // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); @@ -3502,7 +3620,11 @@ var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGe if ( fn ) { for ( ; i < len; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); } } } @@ -3513,14 +3635,10 @@ var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGe // Gets bulk ? fn.call( elems ) : - len ? fn( elems[0], key ) : emptyGet; + len ? fn( elems[ 0 ], key ) : emptyGet; }; +var acceptData = function( owner ) { - -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( owner ) { // Accepts only: // - Node // - Node.ELEMENT_NODE @@ -3532,66 +3650,79 @@ jQuery.acceptData = function( owner ) { }; -function Data() { - // Support: Android<4, - // Old WebKit does not have Object.preventExtensions/freeze method, - // return new empty object instead with no [[set]] accessor - Object.defineProperty( this.cache = {}, 0, { - get: function() { - return {}; - } - }); + +function Data() { this.expando = jQuery.expando + Data.uid++; } Data.uid = 1; -Data.accepts = jQuery.acceptData; Data.prototype = { - key: function( owner ) { + + register: function( owner, initial ) { + var value = initial || {}; + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable, non-writable property + // configurability must be true to allow the property to be + // deleted with the delete operator + } else { + Object.defineProperty( owner, this.expando, { + value: value, + writable: true, + configurable: true + } ); + } + return owner[ this.expando ]; + }, + cache: function( owner ) { + // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. - // Always return the key for a frozen object. - if ( !Data.accepts( owner ) ) { - return 0; + // Always return an empty object. + if ( !acceptData( owner ) ) { + return {}; } - var descriptor = {}, - // Check if the owner object already has a cache key - unlock = owner[ this.expando ]; + // Check if the owner object already has a cache + var value = owner[ this.expando ]; // If not, create one - if ( !unlock ) { - unlock = Data.uid++; + if ( !value ) { + value = {}; - // Secure it in a non-enumerable, non-writable property - try { - descriptor[ this.expando ] = { value: unlock }; - Object.defineProperties( owner, descriptor ); + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { - // Support: Android<4 - // Fallback to a less secure definition - } catch ( e ) { - descriptor[ this.expando ] = unlock; - jQuery.extend( owner, descriptor ); + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } } } - // Ensure the cache object - if ( !this.cache[ unlock ] ) { - this.cache[ unlock ] = {}; - } - - return unlock; + return value; }, set: function( owner, data, value ) { var prop, - // There may be an unlock assigned to this node, - // if there is no entry for this "owner", create one inline - // and set the unlock as though an owner entry had always existed - unlock = this.key( owner ), - cache = this.cache[ unlock ]; + cache = this.cache( owner ); // Handle: [ owner, key, value ] args if ( typeof data === "string" ) { @@ -3599,30 +3730,22 @@ Data.prototype = { // Handle: [ owner, { properties } ] args } else { - // Fresh assignments by object are shallow copied - if ( jQuery.isEmptyObject( cache ) ) { - jQuery.extend( this.cache[ unlock ], data ); - // Otherwise, copy the properties one-by-one to the cache object - } else { - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ prop ] = data[ prop ]; } } return cache; }, get: function( owner, key ) { - // Either a valid cache is found, or will be created. - // New caches will be created and the unlock returned, - // allowing direct access to the newly created - // empty data object. A valid owner object must be provided. - var cache = this.cache[ this.key( owner ) ]; - return key === undefined ? - cache : cache[ key ]; + this.cache( owner ) : + owner[ this.expando ] && owner[ this.expando ][ key ]; }, access: function( owner, key, value ) { var stored; + // In cases where either: // // 1. No key was specified @@ -3635,15 +3758,15 @@ Data.prototype = { // 2. The data stored at the key // if ( key === undefined || - ((key && typeof key === "string") && value === undefined) ) { + ( ( key && typeof key === "string" ) && value === undefined ) ) { stored = this.get( owner, key ); return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase(key) ); + stored : this.get( owner, jQuery.camelCase( key ) ); } - // [*]When the key is not a string, or both a key and value + // When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties @@ -3657,15 +3780,20 @@ Data.prototype = { }, remove: function( owner, key ) { var i, name, camel, - unlock = this.key( owner ), - cache = this.cache[ unlock ]; + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } if ( key === undefined ) { - this.cache[ unlock ] = {}; + this.register( owner ); } else { + // Support array or space separated string of keys if ( jQuery.isArray( key ) ) { + // If "name" is an array of keys... // When data is initially created, via ("key", "val") signature, // keys will be converted to camelCase. @@ -3675,10 +3803,12 @@ Data.prototype = { name = key.concat( key.map( jQuery.camelCase ) ); } else { camel = jQuery.camelCase( key ); + // Try the string as a key before any manipulation if ( key in cache ) { name = [ key, camel ]; } else { + // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace name = camel; @@ -3688,25 +3818,34 @@ Data.prototype = { } i = name.length; + while ( i-- ) { delete cache[ name[ i ] ]; } } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <= 35-45+ + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://code.google.com/p/chromium/issues/detail?id=378607 + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } }, hasData: function( owner ) { - return !jQuery.isEmptyObject( - this.cache[ owner[ this.expando ] ] || {} - ); - }, - discard: function( owner ) { - if ( owner[ this.expando ] ) { - delete this.cache[ owner[ this.expando ] ]; - } + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); } }; -var data_priv = new Data(); +var dataPriv = new Data(); -var data_user = new Data(); +var dataUser = new Data(); @@ -3721,7 +3860,7 @@ var data_user = new Data(); // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; + rmultiDash = /[A-Z]/g; function dataAttr( elem, key, data ) { var name; @@ -3729,7 +3868,7 @@ 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 ) { - name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { @@ -3737,14 +3876,15 @@ function dataAttr( elem, key, data ) { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : + // Only convert to a number if it doesn't change the string +data + "" === data ? +data : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; - } catch( e ) {} + } catch ( e ) {} // Make sure we set the data so it isn't changed later - data_user.set( elem, key, data ); + dataUser.set( elem, key, data ); } else { data = undefined; } @@ -3752,31 +3892,31 @@ function dataAttr( elem, key, data ) { return data; } -jQuery.extend({ +jQuery.extend( { hasData: function( elem ) { - return data_user.hasData( elem ) || data_priv.hasData( elem ); + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); }, data: function( elem, name, data ) { - return data_user.access( elem, name, data ); + return dataUser.access( elem, name, data ); }, removeData: function( elem, name ) { - data_user.remove( elem, name ); + dataUser.remove( elem, name ); }, // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to data_priv methods, these can be deprecated. + // with direct calls to dataPriv methods, these can be deprecated. _data: function( elem, name, data ) { - return data_priv.access( elem, name, data ); + return dataPriv.access( elem, name, data ); }, _removeData: function( elem, name ) { - data_priv.remove( elem, name ); + dataPriv.remove( elem, name ); } -}); +} ); -jQuery.fn.extend({ +jQuery.fn.extend( { data: function( key, value ) { var i, name, data, elem = this[ 0 ], @@ -3785,9 +3925,9 @@ jQuery.fn.extend({ // Gets all values if ( key === undefined ) { if ( this.length ) { - data = data_user.get( elem ); + data = dataUser.get( elem ); - if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { i = attrs.length; while ( i-- ) { @@ -3796,12 +3936,12 @@ jQuery.fn.extend({ if ( attrs[ i ] ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); + name = jQuery.camelCase( name.slice( 5 ) ); dataAttr( elem, name, data[ name ] ); } } } - data_priv.set( elem, "hasDataAttrs", true ); + dataPriv.set( elem, "hasDataAttrs", true ); } } @@ -3810,14 +3950,13 @@ jQuery.fn.extend({ // Sets multiple values if ( typeof key === "object" ) { - return this.each(function() { - data_user.set( this, key ); - }); + return this.each( function() { + dataUser.set( this, key ); + } ); } return access( this, function( value ) { - var data, - camelKey = jQuery.camelCase( key ); + var data, camelKey; // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the @@ -3825,16 +3964,24 @@ jQuery.fn.extend({ // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. if ( elem && value === undefined ) { + // Attempt to get data from the cache // with the key as-is - data = data_user.get( elem, key ); + data = dataUser.get( elem, key ) || + + // Try to find dashed key if it exists (gh-2779) + // This is for 2.2.x only + dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() ); + if ( data !== undefined ) { return data; } + camelKey = jQuery.camelCase( key ); + // Attempt to get data from the cache // with the key camelized - data = data_user.get( elem, camelKey ); + data = dataUser.get( elem, camelKey ); if ( data !== undefined ) { return data; } @@ -3851,46 +3998,48 @@ jQuery.fn.extend({ } // Set the data... - this.each(function() { + camelKey = jQuery.camelCase( key ); + this.each( function() { + // First, attempt to store a copy or reference of any // data that might've been store with a camelCased key. - var data = data_user.get( this, camelKey ); + var data = dataUser.get( this, camelKey ); // For HTML5 data-* attribute interop, we have to // store property names with dashes in a camelCase form. // This might not apply to all properties...* - data_user.set( this, camelKey, value ); + dataUser.set( this, camelKey, value ); // *... In the case of properties that might _actually_ // have dashes, we need to also store a copy of that // unchanged property. - if ( key.indexOf("-") !== -1 && data !== undefined ) { - data_user.set( this, key, value ); + if ( key.indexOf( "-" ) > -1 && data !== undefined ) { + dataUser.set( this, key, value ); } - }); + } ); }, null, value, arguments.length > 1, null, true ); }, removeData: function( key ) { - return this.each(function() { - data_user.remove( this, key ); - }); + return this.each( function() { + dataUser.remove( this, key ); + } ); } -}); +} ); -jQuery.extend({ +jQuery.extend( { queue: function( elem, type, data ) { var queue; if ( elem ) { type = ( type || "fx" ) + "queue"; - queue = data_priv.get( elem, type ); + queue = dataPriv.get( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !queue || jQuery.isArray( data ) ) { - queue = data_priv.access( elem, type, jQuery.makeArray(data) ); + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); } else { queue.push( data ); } @@ -3937,15 +4086,15 @@ jQuery.extend({ // Not public - generate a queueHooks object, or return the current one _queueHooks: function( elem, type ) { var key = type + "queueHooks"; - return data_priv.get( elem, key ) || data_priv.access( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - data_priv.remove( elem, [ type + "queue", key ] ); - }) - }); + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); } -}); +} ); -jQuery.fn.extend({ +jQuery.fn.extend( { queue: function( type, data ) { var setter = 2; @@ -3956,30 +4105,31 @@ jQuery.fn.extend({ } if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); + return jQuery.queue( this[ 0 ], type ); } return data === undefined ? this : - this.each(function() { + this.each( function() { var queue = jQuery.queue( this, type, data ); // Ensure a hooks for this queue jQuery._queueHooks( this, type ); - if ( type === "fx" && queue[0] !== "inprogress" ) { + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { jQuery.dequeue( this, type ); } - }); + } ); }, dequeue: function( type ) { - return this.each(function() { + return this.each( function() { jQuery.dequeue( this, type ); - }); + } ); }, 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, obj ) { @@ -4001,7 +4151,7 @@ jQuery.fn.extend({ type = type || "fx"; while ( i-- ) { - tmp = data_priv.get( elements[ i ], type + "queueHooks" ); + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; tmp.empty.add( resolve ); @@ -4010,28 +4160,243 @@ jQuery.fn.extend({ resolve(); return defer.promise( obj ); } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + return jQuery.css( elem, "display" ) === "none" || + !jQuery.contains( elem.ownerDocument, elem ); }; -var rcheckableType = (/^(?:checkbox|radio)$/i); + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { return tween.cur(); } : + function() { return jQuery.css( elem, prop, "" ); }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([\w:-]+)/ ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); -(function() { +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE9 + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +// Support: IE9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE9-11+ + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? + context.querySelectorAll( tag || "*" ) : + []; + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { var fragment = document.createDocumentFragment(), div = fragment.appendChild( document.createElement( "div" ) ), input = document.createElement( "input" ); - // Support: Safari<=5.1 + // Support: Android 4.0-4.3, Safari<=5.1 // Check state lost if the name is set (#11217) // Support: Windows Web Apps (WWA) // `name` and `type` must use .setAttribute for WWA (#14901) @@ -4049,19 +4414,13 @@ var rcheckableType = (/^(?:checkbox|radio)$/i); // Make sure textarea (and checkbox) defaultValue is properly cloned div.innerHTML = ""; support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -})(); -var strundefined = typeof undefined; - - - -support.focusinBubbles = "onfocusin" in window; +} )(); var rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { return true; @@ -4071,12 +4430,75 @@ function returnFalse() { return false; } +// Support: IE9 +// See #13393 for more info function safeActiveElement() { try { return document.activeElement; } catch ( err ) { } } +function on( elem, types, selector, data, fn, 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 = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + 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 elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. @@ -4090,7 +4512,7 @@ jQuery.event = { var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, - elemData = data_priv.get( elem ); + elemData = dataPriv.get( elem ); // Don't attach events to noData or text/comment nodes (but allow plain objects) if ( !elemData ) { @@ -4110,14 +4532,15 @@ jQuery.event = { } // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { + if ( !( events = elemData.events ) ) { events = elemData.events = {}; } - if ( !(eventHandle = elemData.handle) ) { + if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; }; } @@ -4126,9 +4549,9 @@ jQuery.event = { types = ( types || "" ).match( rnotwhite ) || [ "" ]; t = types.length; while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // There *must* be a type, no attaching namespace-only handlers if ( !type ) { @@ -4145,7 +4568,7 @@ jQuery.event = { special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers - handleObj = jQuery.extend({ + handleObj = jQuery.extend( { type: type, origType: origType, data: data, @@ -4153,18 +4576,20 @@ jQuery.event = { guid: handler.guid, selector: selector, needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") + namespace: namespaces.join( "." ) }, handleObjIn ); // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { + if ( !( handlers = events[ type ] ) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); + elem.addEventListener( type, eventHandle ); } } } @@ -4196,9 +4621,9 @@ jQuery.event = { var j, origCount, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, - elemData = data_priv.hasData( elem ) && data_priv.get( elem ); + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - if ( !elemData || !(events = elemData.events) ) { + if ( !elemData || !( events = elemData.events ) ) { return; } @@ -4206,9 +4631,9 @@ jQuery.event = { types = ( types || "" ).match( rnotwhite ) || [ "" ]; t = types.length; while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); // Unbind all events (on this namespace, if provided) for the element if ( !type ) { @@ -4221,7 +4646,8 @@ jQuery.event = { special = jQuery.event.special[ type ] || {}; type = ( selector ? special.delegateType : special.bindType ) || type; handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); // Remove matching events origCount = j = handlers.length; @@ -4231,7 +4657,8 @@ jQuery.event = { if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { handlers.splice( j, 1 ); if ( handleObj.selector ) { @@ -4246,7 +4673,9 @@ jQuery.event = { // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); } @@ -4254,145 +4683,12 @@ jQuery.event = { } } - // Remove the expando if it's no longer used + // Remove data and the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - data_priv.remove( elem, "events" ); + dataPriv.remove( elem, "handle events" ); } }, - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // 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 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === 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( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - 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 ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - dispatch: function( event ) { // Make a writable jQuery.Event from the native event object @@ -4401,11 +4697,11 @@ jQuery.event = { var i, j, ret, matched, handleObj, handlerQueue = [], args = slice.call( arguments ), - handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; + args[ 0 ] = event; event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired @@ -4418,24 +4714,25 @@ jQuery.event = { // Run delegates first; they may want to stop propagation beneath us i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { event.currentTarget = matched.elem; j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { // Triggered event must either 1) have no namespace, or 2) have namespace(s) // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { event.handleObj = handleObj; event.data = handleObj.data; - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { + if ( ( event.result = ret ) === false ) { event.preventDefault(); event.stopPropagation(); } @@ -4458,15 +4755,20 @@ jQuery.event = { delegateCount = handlers.delegateCount, cur = event.target; + // Support (at least): Chrome, IE9 // Find delegate handlers // Black-hole SVG instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + // + // Support: Firefox<=42+ + // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) + if ( delegateCount && cur.nodeType && + ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { for ( ; cur !== this; cur = cur.parentNode || this ) { + // Don't check non-elements (#13208) // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { matches = []; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; @@ -4476,7 +4778,7 @@ jQuery.event = { if ( matches[ sel ] === undefined ) { matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : + jQuery( sel, this ).index( cur ) > -1 : jQuery.find( sel, this, null, [ cur ] ).length; } if ( matches[ sel ] ) { @@ -4484,7 +4786,7 @@ jQuery.event = { } } if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); + handlerQueue.push( { elem: cur, handlers: matches } ); } } } @@ -4492,19 +4794,20 @@ jQuery.event = { // Add the remaining (directly-bound) handlers if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); } return handlerQueue; }, // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + + "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), fixHooks: {}, keyHooks: { - props: "char charCode key keyCode".split(" "), + props: "char charCode key keyCode".split( " " ), filter: function( event, original ) { // Add which for key events @@ -4517,7 +4820,8 @@ jQuery.event = { }, mouseHooks: { - props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " + + "screenX screenY toElement" ).split( " " ), filter: function( event, original ) { var eventDoc, doc, body, button = original.button; @@ -4528,8 +4832,12 @@ jQuery.event = { 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 ); + 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 which for click: 1 === left; 2 === middle; 3 === right @@ -4586,10 +4894,12 @@ jQuery.event = { special: { load: { + // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { + // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== safeActiveElement() && this.focus ) { @@ -4609,6 +4919,7 @@ jQuery.event = { delegateType: "focusout" }, click: { + // For checkbox, fire native event so checked state will be right trigger: function() { if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { @@ -4633,41 +4944,21 @@ jQuery.event = { } } } - }, - - 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(); - } } }; jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); + elem.removeEventListener( type, handle ); } }; jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { + if ( !( this instanceof jQuery.Event ) ) { return new jQuery.Event( src, props ); } @@ -4680,6 +4971,7 @@ jQuery.Event = function( src, props ) { // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && + // Support: Android<4.0 src.returnValue === false ? returnTrue : @@ -4705,6 +4997,7 @@ jQuery.Event = function( src, props ) { // 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 = { + constructor: jQuery.Event, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, @@ -4714,7 +5007,7 @@ jQuery.Event.prototype = { this.isDefaultPrevented = returnTrue; - if ( e && e.preventDefault ) { + if ( e ) { e.preventDefault(); } }, @@ -4723,7 +5016,7 @@ jQuery.Event.prototype = { this.isPropagationStopped = returnTrue; - if ( e && e.stopPropagation ) { + if ( e ) { e.stopPropagation(); } }, @@ -4732,7 +5025,7 @@ jQuery.Event.prototype = { this.isImmediatePropagationStopped = returnTrue; - if ( e && e.stopImmediatePropagation ) { + if ( e ) { e.stopImmediatePropagation(); } @@ -4741,8 +5034,14 @@ jQuery.Event.prototype = { }; // Create mouseenter/leave events using mouseover/out and event-time checks -// Support: Chrome 15+ -jQuery.each({ +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://code.google.com/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", @@ -4758,9 +5057,9 @@ jQuery.each({ related = event.relatedTarget, handleObj = event.handleObj; - // For mousenter/leave call the handler if related is outside the target. + // For mouseenter/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 )) ) { + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; @@ -4768,115 +5067,32 @@ jQuery.each({ return ret; } }; -}); +} ); -// Support: Firefox, Chrome, Safari -// Create "bubbling" focus and blur events -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - data_priv.remove( doc, fix ); - - } else { - data_priv.access( doc, fix, attaches ); - } - } - }; - }); -} - -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 = 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 ); - }); +jQuery.fn.extend( { + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); }, one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); + return on( this, types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { var handleObj, type; if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event handleObj = types.handleObj; jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { + // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); @@ -4884,6 +5100,7 @@ jQuery.fn.extend({ return this; } if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) fn = selector; selector = undefined; @@ -4891,70 +5108,39 @@ jQuery.fn.extend({ if ( fn === false ) { fn = returnFalse; } - return this.each(function() { + return this.each( function() { jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } + } ); } -}); +} ); var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, + + // Support: IE 10-11, Edge 10240+ + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g, + rcleanScript = /^\s*\s*$/g; - // We have to close these tags to support XHTML (#13200) - wrapMap = { - - // Support: IE9 - option: [ 1, "" ], - - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] - }; - -// Support: IE9 -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: 1.x compatibility -// Manipulating tables requires a tbody function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + if ( jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; + return elem.getElementsByTagName( "tbody" )[ 0 ] || elem; + } + + return elem; } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript( elem ) { - elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; return elem; } function restoreScript( elem ) { @@ -4963,24 +5149,12 @@ function restoreScript( elem ) { if ( match ) { elem.type = match[ 1 ]; } else { - elem.removeAttribute("type"); + elem.removeAttribute( "type" ); } return elem; } -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - data_priv.set( - elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) - ); - } -} - function cloneCopyEvent( src, dest ) { var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; @@ -4989,9 +5163,9 @@ function cloneCopyEvent( src, dest ) { } // 1. Copy private data: events, handlers, etc. - if ( data_priv.hasData( src ) ) { - pdataOld = data_priv.access( src ); - pdataCur = data_priv.set( dest, pdataOld ); + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); events = pdataOld.events; if ( events ) { @@ -5007,24 +5181,14 @@ function cloneCopyEvent( src, dest ) { } // 2. Copy user data - if ( data_user.hasData( src ) ) { - udataOld = data_user.access( src ); + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); udataCur = jQuery.extend( {}, udataOld ); - data_user.set( dest, udataCur ); + dataUser.set( dest, udataCur ); } } -function getAll( context, tag ) { - var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : - context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; -} - // Fix IE bugs, see support tests function fixInput( src, dest ) { var nodeName = dest.nodeName.toLowerCase(); @@ -5039,7 +5203,122 @@ function fixInput( src, dest ) { } } -jQuery.extend({ +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), @@ -5082,102 +5361,14 @@ jQuery.extend({ return clone; }, - buildFragment: function( elems, context, scripts, selection ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - // Support: QtWebKit, PhantomJS - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: QtWebKit, PhantomJS - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - }, - cleanData: function( elems ) { - var data, elem, type, key, + var data, elem, type, special = jQuery.event.special, i = 0; - for ( ; (elem = elems[ i ]) !== undefined; i++ ) { - if ( jQuery.acceptData( elem ) ) { - key = elem[ data_priv.expando ]; - - if ( key && (data = data_priv.cache[ key ]) ) { + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { if ( data.events ) { for ( type in data.events ) { if ( special[ type ] ) { @@ -5189,91 +5380,86 @@ jQuery.extend({ } } } - if ( data_priv.cache[ key ] ) { - // Discard any remaining `private` data - delete data_priv.cache[ key ]; - } + + // Support: Chrome <= 35-45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <= 35-45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; } } - // Discard any remaining `user` data - delete data_user.cache[ elem[ data_user.expando ] ]; } } -}); +} ); + +jQuery.fn.extend( { + + // Keep domManip exposed until 3.0 (gh-2225) + domManip: domManip, + + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, -jQuery.fn.extend({ text: function( value ) { return access( this, function( value ) { return value === undefined ? jQuery.text( this ) : - this.empty().each(function() { + this.empty().each( function() { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { this.textContent = value; } - }); + } ); }, null, value, arguments.length ); }, append: function() { - return this.domManip( arguments, function( elem ) { + return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } - }); + } ); }, prepend: function() { - return this.domManip( arguments, function( elem ) { + return domManip( this, arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } - }); + } ); }, before: function() { - return this.domManip( arguments, function( elem ) { + return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } - }); + } ); }, after: function() { - return this.domManip( arguments, function( elem ) { + return domManip( this, arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; + } ); }, empty: function() { var elem, i = 0; - for ( ; (elem = this[i]) != null; i++ ) { + for ( ; ( elem = this[ i ] ) != null; i++ ) { if ( elem.nodeType === 1 ) { // Prevent memory leaks @@ -5291,9 +5477,9 @@ jQuery.fn.extend({ dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - return this.map(function() { + return this.map( function() { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); + } ); }, html: function( value ) { @@ -5310,7 +5496,7 @@ jQuery.fn.extend({ if ( typeof value === "string" && !rnoInnerhtml.test( value ) && !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - value = value.replace( rxhtmlTag, "<$1>" ); + value = jQuery.htmlPrefilter( value ); try { for ( ; i < l; i++ ) { @@ -5326,7 +5512,7 @@ jQuery.fn.extend({ elem = 0; // If using innerHTML throws an exception, use the fallback method - } catch( e ) {} + } catch ( e ) {} } if ( elem ) { @@ -5336,115 +5522,25 @@ jQuery.fn.extend({ }, replaceWith: function() { - var arg = arguments[ 0 ]; + var ignored = []; - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; - jQuery.cleanData( getAll( this ) ); - - if ( arg ) { - arg.replaceChild( elem, this ); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - self.domManip( args, callback ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); } } - } - return this; + // Force callback invocation + }, ignored ); } -}); +} ); -jQuery.each({ +jQuery.each( { appendTo: "append", prependTo: "prepend", insertBefore: "before", @@ -5469,28 +5565,29 @@ jQuery.each({ return this.pushStack( ret ); }; -}); +} ); var iframe, - elemdisplay = {}; + elemdisplay = { + + // Support: Firefox + // We have to pre-define these values for FF (#10227) + HTML: "block", + BODY: "block" + }; /** * Retrieve the actual display of a element * @param {String} name nodeName of the element * @param {Object} doc Document object */ + // Called only from within defaultDisplay function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? - - // Use of this method is a temporary fix (more like optimization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); + display = jQuery.css( elem[ 0 ], "display" ); // We don't have any data stored on the element, // so use "detach" method as fast way to get rid of the element @@ -5514,7 +5611,8 @@ function defaultDisplay( nodeName ) { if ( display === "none" || !display ) { // Use the already-created iframe if possible - iframe = (iframe || jQuery( " + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/core/onready.html b/dashboard-ui/bower_components/jquery/test/data/core/onready.html new file mode 100644 index 0000000000..1e8f127e77 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/core/onready.html @@ -0,0 +1,24 @@ + + + + + alias-masked DOM properties (#14074) + + + + +
+ +
+ + + \ No newline at end of file diff --git a/dashboard-ui/bower_components/jquery/test/data/css/cssWidthBeforeDocReady.html b/dashboard-ui/bower_components/jquery/test/data/css/cssWidthBeforeDocReady.html new file mode 100644 index 0000000000..12e954dc09 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/css/cssWidthBeforeDocReady.html @@ -0,0 +1,22 @@ + + + + + + + +
+ + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/dashboard.xml b/dashboard-ui/bower_components/jquery/test/data/dashboard.xml new file mode 100644 index 0000000000..5a6f56142b --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/dashboard.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/data/dataAttrs.html b/dashboard-ui/bower_components/jquery/test/data/data/dataAttrs.html new file mode 100644 index 0000000000..5e6e442a6b --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/data/dataAttrs.html @@ -0,0 +1,16 @@ + + + + + IE11 onpageshow strangeness (#14894) + + + + + Test for #14894 + + diff --git a/dashboard-ui/bower_components/jquery/test/data/dimensions/documentLarge.html b/dashboard-ui/bower_components/jquery/test/data/dimensions/documentLarge.html new file mode 100644 index 0000000000..a6598fcc86 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/dimensions/documentLarge.html @@ -0,0 +1,17 @@ + + + + + + + +
+ +
+ + diff --git a/dashboard-ui/bower_components/jquery/test/data/echoData.php b/dashboard-ui/bower_components/jquery/test/data/echoData.php new file mode 100644 index 0000000000..a37ba515ad --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/echoData.php @@ -0,0 +1 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/echoQuery.php b/dashboard-ui/bower_components/jquery/test/data/echoQuery.php new file mode 100644 index 0000000000..b72f329c9c --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/echoQuery.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dashboard-ui/bower_components/jquery/test/data/errorWithJSON.php b/dashboard-ui/bower_components/jquery/test/data/errorWithJSON.php new file mode 100644 index 0000000000..62b187ecc9 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/errorWithJSON.php @@ -0,0 +1,6 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/focusElem.html b/dashboard-ui/bower_components/jquery/test/data/event/focusElem.html new file mode 100644 index 0000000000..a9a9765184 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/focusElem.html @@ -0,0 +1,16 @@ + + + + + .focus() (activeElement access #13393) + + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/focusinCrossFrame.html b/dashboard-ui/bower_components/jquery/test/data/event/focusinCrossFrame.html new file mode 100644 index 0000000000..487f8de8fd --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/focusinCrossFrame.html @@ -0,0 +1,18 @@ + + + + + focusin event cross-frame (#14180) + + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/interactiveReady.html b/dashboard-ui/bower_components/jquery/test/data/event/interactiveReady.html new file mode 100644 index 0000000000..77b37104d0 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/interactiveReady.html @@ -0,0 +1,23 @@ + + + + +Test case for gh-2100 + + + + + + + + +
+ + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/longLoadScript.php b/dashboard-ui/bower_components/jquery/test/data/event/longLoadScript.php new file mode 100644 index 0000000000..ba47168b48 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/longLoadScript.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/dashboard-ui/bower_components/jquery/test/data/event/onbeforeunload.html b/dashboard-ui/bower_components/jquery/test/data/event/onbeforeunload.html new file mode 100644 index 0000000000..11ad1964a3 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/onbeforeunload.html @@ -0,0 +1,20 @@ + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/promiseReady.html b/dashboard-ui/bower_components/jquery/test/data/event/promiseReady.html new file mode 100644 index 0000000000..17b6e7f2c6 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/promiseReady.html @@ -0,0 +1,17 @@ + + + + +Test case for jQuery ticket #11470 + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/syncReady.html b/dashboard-ui/bower_components/jquery/test/data/event/syncReady.html new file mode 100644 index 0000000000..e0885707ed --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/syncReady.html @@ -0,0 +1,23 @@ + + + + +Test case for jQuery ticket #10067 + + + + + + + + +
+ + diff --git a/dashboard-ui/bower_components/jquery/test/data/event/triggerunload.html b/dashboard-ui/bower_components/jquery/test/data/event/triggerunload.html new file mode 100644 index 0000000000..a7879c7728 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/event/triggerunload.html @@ -0,0 +1,18 @@ + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/headers.php b/dashboard-ui/bower_components/jquery/test/data/headers.php new file mode 100644 index 0000000000..79c1830551 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/headers.php @@ -0,0 +1,23 @@ + $value ) { + + $key = str_replace( "_" , "-" , substr( $key , 0 , 5 ) == "HTTP_" ? substr( $key , 5 ) : $key ); + $headers[ $key ] = $value; + +} + +foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) { + + // Only echo if key exists in the header + if ( isset( $headers[ strtoupper( $key ) ] ) ) { + echo "$key: " . @$headers[ strtoupper( $key ) ] . "\n"; + } + +} diff --git a/dashboard-ui/bower_components/jquery/test/data/if_modified_since.php b/dashboard-ui/bower_components/jquery/test/data/if_modified_since.php new file mode 100644 index 0000000000..098b7da850 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/if_modified_since.php @@ -0,0 +1,20 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/iframe.html b/dashboard-ui/bower_components/jquery/test/data/iframe.html new file mode 100644 index 0000000000..ad646c4300 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/iframe.html @@ -0,0 +1,8 @@ + + + iframe + + +
span text
+ + diff --git a/dashboard-ui/bower_components/jquery/test/data/jquery-1.9.1.js b/dashboard-ui/bower_components/jquery/test/data/jquery-1.9.1.js new file mode 100644 index 0000000000..80c97a226a --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/jquery-1.9.1.js @@ -0,0 +1,9885 @@ +/*! + * jQuery JavaScript Library v1.9.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-2-4 + */ +( function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<9 + // For `typeof node.method` instead of `node.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + location = window.location, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.9.1", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + 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 = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // 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: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + 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 default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return core_slice.call( this ); + }, + + // 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 ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // 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 ) { + + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + map: function( callback ) { + 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: core_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 src, copyIsArray, copy, name, options, 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 ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // 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.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + }, + + // 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"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat( obj ) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call( obj ) ] || "object" : + typeof obj; + }, + + 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 && + !core_hasOwn.call( obj, "constructor" ) && + !core_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 || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[ 1 ] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "" ) ) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + 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 && jQuery.trim( 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.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call( "\uFEFF\xA0" ) ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; 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 retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; 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, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // 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 ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_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 ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + 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 + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[ i ], key, raw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[ 0 ], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + } +} ); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch ( e ) {} + + if ( top && top.doScroll ) { + ( function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll( "left" ); + } catch ( e ) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + } )(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error".split( " " ), function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery( document ); + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * 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( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value (for non-forgettable lists) + memory, + + // Flag to know if list was already fired + fired, + + // End of the loop when firing + firingLength, + + // Index of currently firing callback (modified by remove if needed) + firingIndex, + + // First callback to fire (used internally by add and fireWith) + firingStart, + + // Actual callback list + list = [], + + // Stack of fire calls for repeatable lists + stack = !options.once && [], + + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // First, we save the current length + var start = list.length; + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( 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 + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + } ); + } + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + + // 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 ) { + self.disable(); + } + return this; + }, + + // Is it locked? + locked: function() { + return !stack; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( 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 !!fired; + } + }; + + return self; +}; +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], + [ "notify", "progress", jQuery.Callbacks( "memory" ) ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( function() { + + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +} ); +jQuery.support = ( function() { + + var support, all, a, + input, select, fragment, + opt, eventName, isSupported, i, + div = document.createElement( "div" ); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Support tests won't run in some limited or non-browser environments + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + if ( !all || !a || !all.length ) { + return {}; + } + + // First batch of tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement( "option" ) ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + support = { + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute( "style" ) ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute( "href" ) === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.5/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + checkOn: !!input.value, + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // 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>", + + // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode + boxModel: document.compatMode === "CSS1Compat", + + // Will be defined later + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + boxSizingReliable: true, + pixelPosition: false + }; + + // 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; + + // Support: IE<9 + try { + delete div.test; + } catch ( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement( "input" ); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + } ); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php + for ( i in { submit: true, change: true, focusin: true } ) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Run tests that need a body at doc ready + jQuery( function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName( "body" )[ 0 ]; + + if ( !body ) { + + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement( "div" ); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + support.boxSizing = ( div.offsetWidth === 4 ); + support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement( "div" ) ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + } ); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +} )(); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) && getByName && data === undefined ) { + return; + } + + if ( !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 = core_deletedIds.pop() || jQuery.guid++; + } 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 ); + } + } + + 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; + } + + // 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; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var i, l, thisCache, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( 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( " " ); + } + } + } else { + + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[ i ] ]; + } + + // 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; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend( { + cache: {}, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + 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 ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute( "classid" ) === noData; + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var attrs, name, + elem = this[ 0 ], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[ i ].name; + + if ( !name.indexOf( "data-" ) ) { + name = jQuery.camelCase( name.slice( 5 ) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + jQuery.data( this, key ); + } ); + } + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + + // Try to fetch any internally stored data first + return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + } + + this.each( function() { + jQuery.data( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + 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 : + + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( 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; +} +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = jQuery._data( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + hooks.cur = fn; + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + 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, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var nodeHook, boolHook, + rclass = /[\t\r\n]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend( { + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + 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 classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + } ); + } + + if ( proceed ) { + + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + } ); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + 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.match( core_rnotwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + } ); + }, + + 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 ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + 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 val, + self = jQuery( this ); + + 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.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // 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, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + ( 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 ); + } + } + + 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; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, notxml, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && notxml && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && notxml && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + + } else { + + // In IE9+, Flash objects don't have .getAttribute (#12945) + // Support: IE9+ + if ( typeof elem.getAttribute !== core_strundefined ) { + ret = elem.getAttribute( name ); + } + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( rboolean.test( name ) ) { + + // Set corresponding property to false for boolean attributes + // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 + if ( !getSetAttribute && ruseDefault.test( name ) ) { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } else { + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + 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 default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return 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; + } + } + } +} ); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + var + + // Use .prop to determine if this attribute is understood as boolean + prop = jQuery.prop( elem, name ), + + // Fetch it accordingly + attr = typeof prop === "boolean" && elem.getAttribute( name ), + detail = typeof prop === "boolean" ? + + getSetInput && getSetAttribute ? + attr != null : + + // oldIE fabricates an empty string for missing boolean attributes + // and conflates checked/selected into attroperties + ruseDefault.test( name ) ? + elem[ jQuery.camelCase( "default-" + name ) ] : + !!attr : + + // fetch an attribute node for properties not recognized as boolean + elem.getAttributeNode( name ); + + return detail && detail.value !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; + +// fix oldIE value attroperty +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return jQuery.nodeName( elem, "input" ) ? + + // Ignore the value *property* by using defaultValue + elem.defaultValue : + + ret && ret.specified ? ret.value : undefined; + }, + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // 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 = elem.getAttributeNode( name ); + return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? + ret.value : + undefined; + }, + set: function( elem, value, name ) { + + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + ( ret = elem.ownerDocument.createAttribute( name ) ) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + + // 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 ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each( [ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + } ); + } ); +} + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + jQuery.each( [ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret == null ? undefined : ret; + } + } ); + } ); + + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each( [ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + } ); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// 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 = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // 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 + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && ( !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 = ( types || "" ).match( core_rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 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: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + 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; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + 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; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.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 ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // 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 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + event.isTrigger = true; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && 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) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && ( !event.button || event.type !== "click" ) ) { + + for ( ; cur != this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push( { elem: cur, handlers: matches } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split( " " ), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split( " " ), + filter: function( 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 body, eventDoc, doc, + 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; + } + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + } + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== document.activeElement && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === document.activeElement && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + 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(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, 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; +}; + +// 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 = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// 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 ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + 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 && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + } ); + jQuery._data( form, "submitBubbles", true ); + } + } ); + + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + 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; + } + + // Allow triggered, simulated change events (#11500) + 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 ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + } ); + jQuery._data( elem, "changeBubbles", 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 type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + 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( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( 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 ); + }, + + 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 ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +( function( window, undefined ) { + +var i, + cachedruns, + Expr, + getText, + isXML, + compile, + hasDuplicate, + outermostContext, + + // Local document vars + setDocument, + document, + docElem, + documentIsXML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + sortOrder, + + // Instance-specific data + expando = "sizzle" + -( new Date() ), + preferredDoc = window.document, + support = {}, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Array methods + arr = [], + pop = arr.pop, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[ i ] === elem ) { + return i; + } + } + return -1; + }, + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rsibling = /[\x20\t\r\n\f]*[+~]/, + + rnative = /^[^{]+\{\s*\[native code/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, + funescape = function( _, escaped ) { + var high = "0x" + escaped - 0x10000; + + // NaN means non-codepoint + return high !== high ? + escaped : + + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Use a stripped-down slice if we can't use a native one +try { + slice.call( preferredDoc.documentElement.childNodes, 0 )[ 0 ].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + while ( ( elem = this[ i++ ] ) ) { + results.push( elem ); + } + return results; + }; +} + +/** + * For feature detection + * @param {Function} fn The function to test for native support + */ +function isNative( fn ) { + return rnative.test( fn + "" ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var cache, + keys = []; + + return ( cache = function( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key ] = value ); + } ); +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement( "div" ); + + try { + return fn( div ); + } catch ( e ) { + return false; + } finally { + + // release memory in IE + div = null; + } +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( ( nodeType = context.nodeType ) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !documentIsXML && !seed ) { + + // Shortcuts + if ( ( match = rquickExpr.exec( selector ) ) ) { + + // Speed-up: Sizzle("#ID") + if ( ( m = match[ 1 ] ) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + + // Context is not a document + if ( context.ownerDocument && ( elem = context.ownerDocument.getElementById( m ) ) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[ 2 ] ) { + push.apply( results, slice.call( context.getElementsByTagName( selector ), 0 ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( ( m = match[ 3 ] ) && support.getByClassName && context.getElementsByClassName ) { + push.apply( results, slice.call( context.getElementsByClassName( m ), 0 ) ); + return results; + } + } + + // QSA path + if ( support.qsa && !rbuggyQSA.test( selector ) ) { + old = true; + nid = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( ( old = context.getAttribute( "id" ) ) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[ i ] = nid + toSelector( groups[ i ] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join( "," ); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch ( qsaError ) { + } finally { + if ( !old ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && ( elem.ownerDocument || elem ).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsXML = isXML( doc ); + + // Check if getElementsByTagName("*") returns only elements + support.tagNameNoComments = assert( function( div ) { + div.appendChild( doc.createComment( "" ) ); + return !div.getElementsByTagName( "*" ).length; + } ); + + // Check if attributes should be retrieved by attribute nodes + support.attributes = assert( function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute( "multiple" ); + + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + } ); + + // Check if getElementsByClassName can be trusted + support.getByClassName = assert( function( div ) { + + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName( "e" ).length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName( "e" ).length === 2; + } ); + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + support.getByName = assert( function( div ) { + + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = doc.getElementsByName && + + // buggy browsers will return fewer than the correct 2 + doc.getElementsByName( expando ).length === 2 + + + // buggy browsers will return more than the correct 0 + doc.getElementsByName( expando + 0 ).length; + support.getIdNotName = !doc.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + } ); + + // IE6/7 return modified attributes + Expr.attrHandle = assert( function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute( "href" ) === "#"; + } ) ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute( "type" ); + } + }; + + // ID find and filter + if ( support.getIdNotName ) { + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + } else { + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode( "id" ).value === id ? + [ m ] : + undefined : + []; + } + }; + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find[ "TAG" ] = support.tagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Name + Expr.find[ "NAME" ] = support.getByName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }; + + // Class + Expr.find[ "CLASS" ] = support.getByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { + return context.getElementsByClassName( className ); + } + }; + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21), + // no need to also add to buggyMatches since matches checks buggyQSA + // A support test would require too much code (would include document ready) + rbuggyQSA = [ ":focus" ]; + + if ( ( support.qsa = isNative( doc.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( div ) { + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + } ); + + assert( function( div ) { + + // Opera 10-12/IE8 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = ""; + if ( div.querySelectorAll( "[i^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll( ":enabled" ).length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = isNative( ( matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( div ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = new RegExp( rbuggyMatches.join( "|" ) ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = isNative( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + var compare; + + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( ( compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ) ) ) { + if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) { + if ( a === doc || contains( preferredDoc, a ) ) { + return -1; + } + if ( b === doc || contains( preferredDoc, b ) ) { + return 1; + } + return 0; + } + return compare & 4 ? -1 : 1; + } + + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + ap[ i ] === preferredDoc ? -1 : + bp[ i ] === preferredDoc ? 1 : + 0; + }; + + // Always assume the presence of duplicates if sort doesn't + // pass them to our comparison function (as in Google Chrome). + hasDuplicate = false; + [ 0, 0 ].sort( sortOrder ); + support.detectDuplicates = hasDuplicate; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyQSA always contains :focus, so no need for an existence check + if ( support.matchesSelector && !documentIsXML && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && !rbuggyQSA.test( expr ) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + var val; + + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + if ( !documentIsXML ) { + name = name.toLowerCase(); + } + if ( ( val = Expr.attrHandle[ name ] ) ) { + return val( elem ); + } + if ( documentIsXML || support.attributes ) { + return elem.getAttribute( name ); + } + return ( ( val = elem.getAttributeNode( name ) ) || elem.getAttribute( name ) ) && elem[ name ] === true ? + name : + val && val.specified ? val.value : null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + i = 1, + j = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; ( elem = results[ i ] ); i++ ) { + if ( elem === results[ i - 1 ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + for ( ; ( node = elem[ i ] ); i++ ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 4 ] || match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? match[ 5 ] + ( match[ 6 ] || 1 ) : 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 5 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 4 ] ) { + match[ 2 ] = match[ 4 ]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + + nodeName = nodeName.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" ) ) && + classCache( className, function( elem ) { + return pattern.test( elem.className || ( typeof elem.getAttribute !== strundefined && elem.getAttribute( "class" ) ) || "" ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || ( parent[ expando ] = {} ); + cache = outerCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = cache[ 0 ] === dirruns && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && ( cache = ( elem[ expando ] || ( elem[ expando ] = {} ) )[ type ] ) && cache[ 0 ] === dirruns ) { + diff = cache[ 1 ]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + ( node[ expando ] || ( node[ expando ] = {} ) )[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifider + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsXML ? + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) : + elem.lang ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && ( !document.hasFocus || document.hasFocus() ) && !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( ( attr = elem.getAttribute( "type" ) ) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + if ( ( cache = outerCache[ dir ] ) && cache[ 0 ] === dirkey ) { + if ( ( data = cache[ 1 ] ) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[ 1 ] = matcher( elem, context, xml ) || cachedruns; + if ( cache[ 1 ] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + + // We must always have either seed elements or context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", expandContext && context.parentNode || context ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && !documentIsXML && + Expr.relative[ tokens[ 1 ].type ] ) { + + context = Expr.find[ "ID" ]( token.matches[ 0 ].replace( runescape, funescape ), context )[ 0 ]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && context.parentNode || context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + documentIsXML, + results, + rsibling.test( selector ) + ); + return results; +} + +// Deprecated +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Easy API for creating new setFilters +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + +// Initialize with the default document +setDocument(); + +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + +} )( window ); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + isSimple = /^.[^:#\[\.,]*$/, + rneedsContext = jQuery.expr.match.needsContext, + + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, self, + len = this.length; + + if ( typeof selector !== "string" ) { + self = this; + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = []; + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, this[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + not: function( selector ) { + return this.pushStack( winnow( this, selector, false ) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow( this, selector, true ) ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + rneedsContext.test( selector ) ? + jQuery( selector, this.context ).index( this[ 0 ] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + cur = this[ i ]; + + while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { + if ( pos ? pos.index( cur ) > -1 : jQuery.find.matchesSelector( cur, selectors ) ) { + ret.push( cur ); + break; + } + cur = cur.parentNode; + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // 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.first().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( jQuery.unique( all ) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +jQuery.fn.andSelf = jQuery.fn.addBack; + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +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 sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "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.merge( [], 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 && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret ); + }; +} ); + +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; + }, + + 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 ) { + 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 ) { + 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|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend( { + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapAll( html.call( this, i ) ); + } ); + } + + if ( this[ 0 ] ) { + + // The elements to wrap the target around + var wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function() { + return this.parent().each( function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + } ).end(); + }, + + append: function() { + return this.domManip( arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return this.domManip( arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.insertBefore( elem, this.firstChild ); + } + } ); + }, + + before: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for ( ; i < l; i++ ) { + + // Remove element nodes and prevent memory leaks + elem = this[ i ] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + var isFunc = jQuery.isFunction( value ); + + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( !isFunc && typeof value !== "string" ) { + value = jQuery( value ).not( this ).detach(); + } + + return this.domManip( [ value ], true, function( elem ) { + var next = this.nextSibling, + parent = this.parentNode; + + if ( parent ) { + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + } ); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each( function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, table ? self.html() : undefined ); + } + self.domManip( args, table, callback ); + } ); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( + table && jQuery.nodeName( this[ i ], "table" ) ? + findOrAppend( this[ i ], "tbody" ) : + this[ i ], + node, + i + ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Hope ajax is available... + jQuery.ajax( { + url: node.src, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + } ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +} ); + +function findOrAppend( elem, tag ) { + return elem.getElementsByTagName( tag )[ 0 ] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + var attr = elem.getAttributeNode( "type" ); + elem.type = ( attr && attr.specified ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[ i ], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; ( elem = elems[ i ] ) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend( { + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc( elem ) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( ( !jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked ) && + ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) { + + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[ i ] ) { + fixCloneNodeIssues( node, destElements[ i ] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) { + cloneCopyEvent( node, destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[ 1 ] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // 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 ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + } +} ); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt( 0 ).toUpperCase() + name.slice( 1 ), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay( elem.nodeName ) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend( { + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + var bool = typeof state === "boolean"; + + return this.each( function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && ( ret = rrelNum.exec( value ) ) ) { + value = ( ret[ 1 ] + 1 ) * ret[ 2 ] + parseFloat( jQuery.css( elem, name ) ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch ( e ) {} + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +} ); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + + // If we already have the right measurement, avoid augmentation + 4 : + + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test( val ) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery( " + + + +
    + +
    + +
    + + + + + + + + + + + + + + + +
    +
    Term
    This is the first definition in compact format.
    +
    Term
    This is the second definition in compact format.
    +
    + + + + Scrolling text (non-standard) + + diff --git a/dashboard-ui/bower_components/jquery/test/data/selector/sizzle_cache.html b/dashboard-ui/bower_components/jquery/test/data/selector/sizzle_cache.html new file mode 100644 index 0000000000..1055c75aea --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/selector/sizzle_cache.html @@ -0,0 +1,21 @@ + + + + + jQuery selector - sizzle cache + + + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/statusText.php b/dashboard-ui/bower_components/jquery/test/data/statusText.php new file mode 100644 index 0000000000..daf58ce3ff --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/statusText.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/dashboard-ui/bower_components/jquery/test/data/support/bodyBackground.html b/dashboard-ui/bower_components/jquery/test/data/support/bodyBackground.html new file mode 100644 index 0000000000..cac099805b --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/bodyBackground.html @@ -0,0 +1,28 @@ + + + + + + + +
    + + +
    + + + diff --git a/dashboard-ui/bower_components/jquery/test/data/support/csp-clean.php b/dashboard-ui/bower_components/jquery/test/data/support/csp-clean.php new file mode 100644 index 0000000000..e16d047a3f --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/csp-clean.php @@ -0,0 +1,3 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/support/csp-log.php b/dashboard-ui/bower_components/jquery/test/data/support/csp-log.php new file mode 100644 index 0000000000..efbb9d7bc3 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/csp-log.php @@ -0,0 +1,3 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/support/csp.js b/dashboard-ui/bower_components/jquery/test/data/support/csp.js new file mode 100644 index 0000000000..5ebdcea08f --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/csp.js @@ -0,0 +1,3 @@ +jQuery( function() { + parent.iframeCallback( getComputedSupport( jQuery.support ) ); +} ); diff --git a/dashboard-ui/bower_components/jquery/test/data/support/csp.php b/dashboard-ui/bower_components/jquery/test/data/support/csp.php new file mode 100644 index 0000000000..0783e1774b --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/csp.php @@ -0,0 +1,18 @@ + + + + + + CSP Test Page + + + + + +

    CSP Test Page

    + + diff --git a/dashboard-ui/bower_components/jquery/test/data/support/getComputedSupport.js b/dashboard-ui/bower_components/jquery/test/data/support/getComputedSupport.js new file mode 100644 index 0000000000..ce3f118eaf --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/support/getComputedSupport.js @@ -0,0 +1,14 @@ +function getComputedSupport( support ) { + var prop, + result = {}; + + for ( prop in support ) { + if ( typeof support[ prop ] === "function" ) { + result[ prop ] = support[ prop ](); + } else { + result[ prop ] = support[ prop ]; + } + } + + return result; +} diff --git a/dashboard-ui/bower_components/jquery/test/data/test.html b/dashboard-ui/bower_components/jquery/test/data/test.html new file mode 100644 index 0000000000..f5bc2199fc --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/test.html @@ -0,0 +1,7 @@ +html text
    + + +blabla diff --git a/dashboard-ui/bower_components/jquery/test/data/test.php b/dashboard-ui/bower_components/jquery/test/data/test.php new file mode 100644 index 0000000000..d93dafad82 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/test.php @@ -0,0 +1,7 @@ +html text
    + + +blabla diff --git a/dashboard-ui/bower_components/jquery/test/data/test2.html b/dashboard-ui/bower_components/jquery/test/data/test2.html new file mode 100644 index 0000000000..1df6151a0c --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/test2.html @@ -0,0 +1,5 @@ + diff --git a/dashboard-ui/bower_components/jquery/test/data/test3.html b/dashboard-ui/bower_components/jquery/test/data/test3.html new file mode 100644 index 0000000000..a7f862a869 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/test3.html @@ -0,0 +1,4 @@ +
    This is a user
    +
    This is a user
    +
    This is a teacher
    +
    This is a superuser
    diff --git a/dashboard-ui/bower_components/jquery/test/data/testbar.php b/dashboard-ui/bower_components/jquery/test/data/testbar.php new file mode 100644 index 0000000000..21aa6882bb --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/testbar.php @@ -0,0 +1,3 @@ +this.testBar = "bar"; +jQuery("#ap").html("bar"); +ok( true, "testbar.php executed"); diff --git a/dashboard-ui/bower_components/jquery/test/data/testinit.js b/dashboard-ui/bower_components/jquery/test/data/testinit.js new file mode 100644 index 0000000000..977847e9de --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/data/testinit.js @@ -0,0 +1,347 @@ +/*jshint multistr:true, quotmark:false */ + +var fireNative, originaljQuery, original$, + baseURL = "", + supportjQuery = this.jQuery, + + // see RFC 2606 + externalHost = "example.com"; + +this.hasPHP = true; +this.isLocal = window.location.protocol === "file:"; + +// Setup global variables before loading jQuery for testing .noConflict() +supportjQuery.noConflict( true ); +originaljQuery = this.jQuery = undefined; +original$ = this.$ = "replaced"; + +/** + * Returns an array of elements with the given IDs + * @example q( "main", "foo", "bar" ) + * @result [
    , , ] + */ +this.q = function() { + var r = [], + i = 0; + + for ( ; i < arguments.length; i++ ) { + r.push( document.getElementById( arguments[ i ] ) ); + } + return r; +}; + +/** + * Asserts that a select matches the given IDs + * @param {String} a - Assertion name + * @param {String} b - Sizzle selector + * @param {String} c - Array of ids to construct what is expected + * @example t("Check for something", "//[a]", ["foo", "bar"]); + * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'bar' + */ +QUnit.assert.t = function( a, b, c ) { + var f = jQuery( b ).get(), + s = "", + i = 0; + + for ( ; i < f.length; i++ ) { + s += ( s && "," ) + '"' + f[ i ].id + '"'; + } + + this.deepEqual( f, q.apply( q, c ), a + " (" + b + ")" ); +}; + +this.createDashboardXML = function() { + var string = ' \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + '; + + return jQuery.parseXML( string ); +}; + +this.createWithFriesXML = function() { + var string = ' \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + 1 \ + \ + \ + \ + \ + foo \ + \ + \ + \ + \ + \ + \ + '; + + return jQuery.parseXML( string.replace( /\{\{\s*externalHost\s*\}\}/g, externalHost ) ); +}; + +this.createXMLFragment = function() { + var xml, frag; + if ( window.ActiveXObject ) { + xml = new ActiveXObject( "msxml2.domdocument" ); + } else { + xml = document.implementation.createDocument( "", "", null ); + } + + if ( xml ) { + frag = xml.createElement( "data" ); + } + + return frag; +}; + +fireNative = document.createEvent ? + function( node, type ) { + var event = document.createEvent( "HTMLEvents" ); + + event.initEvent( type, true, true ); + node.dispatchEvent( event ); + } : + function( node, type ) { + node.fireEvent( "on" + type, document.createEventObject() ); + }; + +/** + * Add random number to url to stop caching + * + * @example url("data/test.html") + * @result "data/test.html?10538358428943" + * + * @example url("data/test.php?foo=bar") + * @result "data/test.php?foo=bar&10538358345554" + */ +function url( value ) { + return baseURL + value + ( /\?/.test( value ) ? "&" : "?" ) + + new Date().getTime() + "" + parseInt( Math.random() * 100000, 10 ); +} + +// Ajax testing helper +this.ajaxTest = function( title, expect, options ) { + QUnit.test( title, expect, function( assert ) { + var requestOptions; + + if ( jQuery.isFunction( options ) ) { + options = options( assert ); + } + options = options || []; + requestOptions = options.requests || options.request || options; + if ( !jQuery.isArray( requestOptions ) ) { + requestOptions = [ requestOptions ]; + } + + var done = assert.async(); + + if ( options.setup ) { + options.setup(); + } + + var completed = false, + remaining = requestOptions.length, + complete = function() { + if ( !completed && --remaining === 0 ) { + completed = true; + delete ajaxTest.abort; + if ( options.teardown ) { + options.teardown(); + } + + // Make sure all events will be called before done() + setTimeout( done ); + } + }, + requests = jQuery.map( requestOptions, function( options ) { + var request = ( options.create || jQuery.ajax )( options ), + callIfDefined = function( deferType, optionType ) { + var handler = options[ deferType ] || !!options[ optionType ]; + return function( _, status ) { + if ( !completed ) { + if ( !handler ) { + assert.ok( false, "unexpected " + status ); + } else if ( jQuery.isFunction( handler ) ) { + handler.apply( this, arguments ); + } + } + }; + }; + + if ( options.afterSend ) { + options.afterSend( request, assert ); + } + + return request + .done( callIfDefined( "done", "success" ) ) + .fail( callIfDefined( "fail", "error" ) ) + .always( complete ); + } ); + + ajaxTest.abort = function( reason ) { + if ( !completed ) { + completed = true; + delete ajaxTest.abort; + assert.ok( false, "aborted " + reason ); + jQuery.each( requests, function( i, request ) { + request.abort(); + } ); + } + }; + } ); +}; + +this.testIframe = function( fileName, name, fn ) { + QUnit.test( name, function( assert ) { + var done = assert.async(); + + // load fixture in iframe + var iframe = loadFixture(), + win = iframe.contentWindow, + interval = setInterval( function() { + if ( win && win.jQuery && win.jQuery.isReady ) { + clearInterval( interval ); + + // call actual tests passing the correct jQuery instance to use + fn.call( this, win.jQuery, win, win.document, assert ); + done(); + document.body.removeChild( iframe ); + iframe = null; + } + }, 15 ); + } ); + + function loadFixture() { + var src = url( "./data/" + fileName + ".html" ), + iframe = jQuery( " +
    +
    +
    + + +
    +
    +

    See this blog entry for more information.

    +

    + Here are some links in a normal paragraph: Google, + Google Groups (Link). + This link has class="blog": + diveintomark + +

    +
    +

    Everything inside the red border is inside a div with id="foo".

    +

    This is a normal link: Yahoo

    +

    This link has class="blog": Simon Willison's Weblog

    + +
    +
    +
    +
    + +

    Try them out:

    +
      +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test element + + Float test. + +
        + + + +
        + +
        + + + + +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        +
        + +
        +
        hi there
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        +
          +
        1. Rice
        2. +
        3. Beans
        4. +
        5. Blinis
        6. +
        7. Tofu
        8. +
        + +
        I'm hungry. I should...
        + ...Eat lots of food... | + ...Eat a little food... | + ...Eat no food... + ...Eat a burger... + ...Eat some funyuns... + ...Eat some funyuns... + + + + + + +
        + +
        + + +
        + +
        + 1 + 2 + + + + + + + + +
        +
        +
        +
        fadeIn
        fadeIn
        +
        fadeOut
        fadeOut
        + +
        show
        show
        +
        hide
        hide
        +
        hide
        hide
        + +
        togglein
        togglein
        +
        toggleout
        toggleout
        +
        toggleout
        toggleout
        + +
        slideUp
        slideUp
        +
        slideDown
        slideDown
        +
        slideUp
        slideUp
        + +
        slideToggleIn
        slideToggleIn
        +
        slideToggleOut
        slideToggleOut
        + +
        fadeToggleIn
        fadeToggleIn
        +
        fadeToggleOut
        fadeToggleOut
        + +
        fadeTo
        fadeTo
        +
        + +
        + +
        +
        + + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.css b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.css new file mode 100644 index 0000000000..ba4b4fa7d3 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.css @@ -0,0 +1,18 @@ +.result { + font-size: 24px; + margin: 0.5em 0; + width: 700px; + height: 56px; +} + +.error { + background-color: red; +} + +.warn { + background-color: yellow; +} + +.success { + background-color: lightgreen; +} diff --git a/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.html b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.html new file mode 100644 index 0000000000..bed56b8ecf --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen-iframe.html @@ -0,0 +1,21 @@ + + + + + + Test for gh-1764 - test iframe + + + + +
        +
        + +
        + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen.js b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen.js new file mode 100644 index 0000000000..b2bb4cdb5a --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/integration/data/gh-1764-fullscreen.js @@ -0,0 +1,99 @@ +/* exported bootstrapFrom */ + +// `mode` may be "iframe" or not specified. +function bootstrapFrom( mainSelector, mode ) { + if ( mode === "iframe" && window.parent === window ) { + jQuery( mainSelector + " .result" ) + .attr( "class", "result warn" ) + .text( "This test should be run in an iframe. Open ../gh-1764-fullscreen.html." ); + jQuery( mainSelector + " .toggle-fullscreen" ).remove(); + return; + } + + var fullscreenSupported = document.exitFullscreen || + document.exitFullscreen || + document.msExitFullscreen || + document.mozCancelFullScreen || + document.webkitExitFullscreen; + + function isFullscreen() { + return !!( document.fullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement || + document.msFullscreenElement ); + } + + function requestFullscreen( element ) { + if ( !isFullscreen() ) { + if ( element.requestFullscreen ) { + element.requestFullscreen(); + } else if ( element.msRequestFullscreen ) { + element.msRequestFullscreen(); + } else if ( element.mozRequestFullScreen ) { + element.mozRequestFullScreen(); + } else if ( element.webkitRequestFullscreen ) { + element.webkitRequestFullscreen(); + } + } + } + + function exitFullscreen() { + if ( document.exitFullscreen ) { + document.exitFullscreen(); + } else if ( document.msExitFullscreen ) { + document.msExitFullscreen(); + } else if ( document.mozCancelFullScreen ) { + document.mozCancelFullScreen(); + } else if ( document.webkitExitFullscreen ) { + document.webkitExitFullscreen(); + } + } + + function runTest() { + var dimensions; + if ( !fullscreenSupported ) { + jQuery( mainSelector + " .result" ) + .attr( "class", "result success" ) + .text( "Fullscreen mode is not supported in this browser. Test not run." ); + } else if ( !isFullscreen() ) { + jQuery( mainSelector + " .result" ) + .attr( "class", "result warn" ) + .text( "Enable fullscreen mode to fire the test." ); + } else { + dimensions = jQuery( mainSelector + " .result" ).css( [ "width", "height" ] ); + dimensions.width = parseFloat( dimensions.width ).toFixed( 3 ); + dimensions.height = parseFloat( dimensions.height ).toFixed( 3 ); + if ( dimensions.width === "700.000" && dimensions.height === "56.000" ) { + jQuery( mainSelector + " .result" ) + .attr( "class", "result success" ) + .text( "Dimensions in fullscreen mode are computed correctly." ); + } else { + jQuery( mainSelector + " .result" ) + .attr( "class", "result error" ) + .html( "Incorrect dimensions; " + + "expected: { width: '700.000', height: '56.000' };
        " + + "got: { width: '" + dimensions.width + "', height: '" + + dimensions.height + "' }." ); + } + } + } + + function toggleFullscreen() { + if ( isFullscreen() ) { + exitFullscreen(); + } else { + requestFullscreen( jQuery( mainSelector + " .container" )[ 0 ] ); + } + } + + $( mainSelector + " .toggle-fullscreen" ).on( "click", toggleFullscreen ); + + $( document ).on( [ + "webkitfullscreenchange", + "mozfullscreenchange", + "fullscreenchange", + "MSFullscreenChange" + ].join( " " ), runTest ); + + runTest(); +} diff --git a/dashboard-ui/bower_components/jquery/test/integration/gh-1764-fullscreen.html b/dashboard-ui/bower_components/jquery/test/integration/gh-1764-fullscreen.html new file mode 100644 index 0000000000..1cba659438 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/integration/gh-1764-fullscreen.html @@ -0,0 +1,34 @@ + + + + + + Test for gh-1764 + + + + + +
        +
        + +
        + + + + + + diff --git a/dashboard-ui/bower_components/jquery/test/integration/gh-2343-ie-radio-click.html b/dashboard-ui/bower_components/jquery/test/integration/gh-2343-ie-radio-click.html new file mode 100644 index 0000000000..4bc6956c3e --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/integration/gh-2343-ie-radio-click.html @@ -0,0 +1,33 @@ + + + + + + Test for gh-2343 (IE11) + + + + + + +

        Test for gh-2343 (IE11)

        +

        +Instructions: In IE11, click on or focus the first radio button. +Then use the left/right arrow keys to select the other radios. +You should see events logged in the results below. +

        +
        + 0 + 1 + 2 +
        +
        + + + diff --git a/dashboard-ui/bower_components/jquery/test/jquery.js b/dashboard-ui/bower_components/jquery/test/jquery.js new file mode 100644 index 0000000000..233e696d9d --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/jquery.js @@ -0,0 +1,58 @@ +// Use the right jQuery source on the test page (and iframes) +( function() { + /* global loadTests: false */ + + var src, + path = window.location.pathname.split( "test" )[ 0 ], + QUnit = window.QUnit || parent.QUnit, + require = window.require || parent.require; + + // iFrames won't load AMD (the iframe tests synchronously expect jQuery to be there) + QUnit.config.urlConfig.push( { + id: "amd", + label: "Load with AMD", + tooltip: "Load the AMD jQuery file (and its dependencies)" + } ); + + // If QUnit is on window, this is the main window + // This detection allows AMD tests to be run in an iframe + if ( QUnit.urlParams.amd && window.QUnit ) { + require.config( { + baseUrl: path, + paths: { + sizzle: "external/sizzle/dist/sizzle" + } + } ); + src = "src/jquery"; + + // Include tests if specified + if ( typeof loadTests !== "undefined" ) { + require( [ src ], loadTests ); + } else { + require( [ src ] ); + } + return; + } + + // Config parameter to use minified jQuery + QUnit.config.urlConfig.push( { + id: "dev", + label: "Load unminified", + tooltip: "Load the development (unminified) jQuery file" + } ); + if ( QUnit.urlParams.dev ) { + src = "dist/jquery.js"; + } else { + src = "dist/jquery.min.js"; + } + + // Load jQuery + document.write( " + + + +

        jQuery Local File Test

        +

        + Introduction +

        + +

        + Results +

        + +

        + Logs: +

        + + + diff --git a/dashboard-ui/bower_components/jquery/test/networkerror.html b/dashboard-ui/bower_components/jquery/test/networkerror.html new file mode 100644 index 0000000000..8057408e46 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/networkerror.html @@ -0,0 +1,84 @@ + + + + + + jQuery Network Error Test for Firefox + + + + + + +

        + jQuery Network Error Test for Firefox +

        +
        + This is a test page for + + #8135 + + which was reported in Firefox when accessing properties + of an XMLHttpRequest object after a network error occurred. +
        +
        Take the following steps:
        +
          +
        1. + make sure you accessed this page through a web server, +
        2. +
        3. + stop the web server, +
        4. +
        5. + open the console, +
        6. +
        7. + click this + + , +
        8. +
        9. + wait for both requests to fail. +
        10. +
        +
        + Test passes if you get two log lines: + +
        +
        + Test fails if the browser notifies an exception. +
        + + diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/.jshintrc b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/.jshintrc new file mode 100644 index 0000000000..1445c7b18b --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/.jshintrc @@ -0,0 +1,14 @@ +{ + "boss": true, + "curly": true, + "eqeqeq": true, + "eqnull": true, + "expr": true, + "immed": true, + "noarg": true, + "quotmark": "double", + "undef": true, + "unused": true, + + "node": true +} diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_missing.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_missing.js new file mode 100644 index 0000000000..348e9a4efa --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_missing.js @@ -0,0 +1,11 @@ +"use strict"; + +var assert = require( "assert" ), + ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQueryFactory = require( "../../dist/jquery.js" ); + +assert.throws( function() { + jQueryFactory( {} ); +}, /jQuery requires a window with a document/ ); + +ensureGlobalNotCreated( module.exports ); diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_passed.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_passed.js new file mode 100644 index 0000000000..5999cc7441 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_passed.js @@ -0,0 +1,14 @@ +"use strict"; + +var assert = require( "assert" ); + +require( "jsdom" ).env( "", function( errors, window ) { + assert.ifError( errors ); + + var ensureJQuery = require( "./lib/ensure_jquery" ), + ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQuery = require( "../../dist/jquery.js" )( window ); + + ensureJQuery( jQuery ); + ensureGlobalNotCreated( module.exports ); +} ); diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_present_originally.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_present_originally.js new file mode 100644 index 0000000000..f751487080 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/document_present_originally.js @@ -0,0 +1,17 @@ +"use strict"; + +var assert = require( "assert" ); + +require( "jsdom" ).env( "", function( errors, window ) { + assert.ifError( errors ); + + // Pretend the window is a global. + global.window = window; + + var ensureJQuery = require( "./lib/ensure_jquery" ), + ensureGlobalNotCreated = require( "./lib/ensure_global_not_created" ), + jQuery = require( "../../dist/jquery.js" ); + + ensureJQuery( jQuery ); + ensureGlobalNotCreated( module.exports, window ); +} ); diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_native_symbol.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_native_symbol.js new file mode 100644 index 0000000000..3376ebdc55 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_native_symbol.js @@ -0,0 +1,8 @@ +"use strict"; + +if ( typeof Symbol === "undefined" ) { + console.log( "Symbols not supported, skipping the test..." ); + process.exit(); +} + +require( "./lib/ensure_iterability_es6" )(); diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_symbol_polyfill.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_symbol_polyfill.js new file mode 100644 index 0000000000..dd377f19c2 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/iterable_with_symbol_polyfill.js @@ -0,0 +1,13 @@ +/* jshint esnext: true */ + +"use strict"; + +var assert = require( "assert" ); + +delete global.Symbol; +require( "core-js" ); + +assert.strictEqual( typeof Symbol, "function", "Expected Symbol to be a function" ); +assert.notEqual( typeof Symbol.iterator, "symbol", "Expected Symbol.iterator to be polyfilled" ); + +require( "./lib/ensure_iterability" )(); diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_global_not_created.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_global_not_created.js new file mode 100644 index 0000000000..7cc83b5411 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_global_not_created.js @@ -0,0 +1,15 @@ +"use strict"; + +var assert = require( "assert" ); + +// Ensure the jQuery property on global/window/module.exports/etc. was not +// created in a CommonJS environment. +// `global` is always checked in addition to passed parameters. +module.exports = function ensureGlobalNotCreated() { + var args = [].slice.call( arguments ).concat( global ); + + args.forEach( function( object ) { + assert.strictEqual( object.jQuery, undefined, + "A jQuery global was created in a CommonJS environment." ); + } ); +}; diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_iterability_es6.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_iterability_es6.js new file mode 100644 index 0000000000..ebe68539e1 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_iterability_es6.js @@ -0,0 +1,25 @@ +/* jshint esnext: true */ + +"use strict"; + +var assert = require( "assert" ); + +module.exports = function ensureIterability() { + require( "jsdom" ).env( "", function( errors, window ) { + assert.ifError( errors ); + + var i, + ensureJQuery = require( "./ensure_jquery" ), + jQuery = require( "../../../dist/jquery.js" )( window ), + elem = jQuery( "
        " ), + result = ""; + + ensureJQuery( jQuery ); + + for ( i of elem ) { + result += i.nodeName; + } + + assert.strictEqual( result, "DIVSPANA", "for-of doesn't work on jQuery objects" ); + } ); +}; diff --git a/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_jquery.js b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_jquery.js new file mode 100644 index 0000000000..0933a1d338 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/node_smoke_tests/lib/ensure_jquery.js @@ -0,0 +1,9 @@ +"use strict"; + +var assert = require( "assert" ); + +// Check if the object we got is the jQuery object by invoking a basic API. +module.exports = function ensureJQuery( jQuery ) { + assert( /^jQuery/.test( jQuery.expando ), + "jQuery.expando was not detected, the jQuery bootstrap process has failed" ); +}; diff --git a/dashboard-ui/bower_components/jquery/test/promises_aplus_adapter.js b/dashboard-ui/bower_components/jquery/test/promises_aplus_adapter.js new file mode 100644 index 0000000000..c7440b9691 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/promises_aplus_adapter.js @@ -0,0 +1,22 @@ +/* jshint node: true */ + +"use strict"; + +require( "jsdom" ).env( "", function( errors, window ) { + if ( errors ) { + console.error( errors ); + return; + } + + var jQuery = require( ".." )( window ); + + exports.deferred = function() { + var deferred = jQuery.Deferred(); + + return { + promise: deferred.promise(), + resolve: deferred.resolve.bind( deferred ), + reject: deferred.reject.bind( deferred ) + }; + }; +} ); diff --git a/dashboard-ui/bower_components/jquery/test/readywait.html b/dashboard-ui/bower_components/jquery/test/readywait.html new file mode 100644 index 0000000000..7a736bef5a --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/readywait.html @@ -0,0 +1,70 @@ + + + + + + jQuery.holdReady Test + + + + + + + + + + +

        + jQuery.holdReady Test +

        +

        + This is a test page for jQuery.readyWait and jQuery.holdReady, + see + #6781 + and + #8803. +

        +

        + Test for jQuery.holdReady, which can be used + by plugins and other scripts to indicate something + important to the page is still loading and needs + to block the DOM ready callbacks that are registered + with jQuery. +

        +

        + Script loaders are the most likely kind of script + to use jQuery.holdReady, but it could be used by + other things like a script that loads a CSS file + and wants to pause the DOM ready callbacks. +

        +

        + Expected Result: The text + It Worked! + appears below after about 2 seconds. +

        +

        + If there is an error in the console, + or the text does not show up, then the test failed. +

        +
        + + diff --git a/dashboard-ui/bower_components/jquery/test/unit/ajax.js b/dashboard-ui/bower_components/jquery/test/unit/ajax.js new file mode 100644 index 0000000000..69eae32112 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/ajax.js @@ -0,0 +1,2412 @@ +QUnit.module( "ajax", { + teardown: function() { + jQuery( document ).off( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError ajaxSuccess" ); + moduleTeardown.apply( this, arguments ); + } +} ); + +( function() { + QUnit.test( "Unit Testing Environment", function( assert ) { + assert.expect( 2 ); + + assert.ok( hasPHP, "Running in an environment with PHP support. The AJAX tests only run if the environment supports PHP!" ); + assert.ok( !isLocal, "Unit tests are not ran from file:// (especially in Chrome. If you must test from file:// with Chrome, run it with the --allow-file-access-from-files flag!)" ); + } ); + + if ( !jQuery.ajax || ( isLocal && !hasPHP ) ) { + return; + } + + function addGlobalEvents( expected, assert ) { + return function() { + expected = expected || ""; + jQuery( document ).on( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError ajaxSuccess", function( e ) { + assert.ok( expected.indexOf( e.type ) !== -1, e.type ); + } ); + }; + } + +//----------- jQuery.ajax() + + testIframeWithCallback( + "XMLHttpRequest - Attempt to block tests because of dangling XHR requests (IE)", + "ajax/unreleasedXHR.html", + function( assert ) { + assert.expect( 1 ); + assert.ok( true, "done" ); + } + ); + + ajaxTest( "jQuery.ajax() - success callbacks", 8, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess", assert ), + url: url( "data/name.html" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + success: function() { + assert.ok( true, "success" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - success callbacks - (url, options) syntax", 8, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess", assert ), + create: function( options ) { + return jQuery.ajax( url( "data/name.html" ), options ); + }, + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + success: function() { + assert.ok( true, "success" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - success callbacks (late binding)", 8, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess", assert ), + url: url( "data/name.html" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + success: true, + afterSend: function( request ) { + request.always( function() { + assert.ok( true, "complete" ); + } ).done( function() { + assert.ok( true, "success" ); + } ).fail( function() { + assert.ok( false, "error" ); + } ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - success callbacks (oncomplete binding)", 8, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess", assert ), + url: url( "data/name.html" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + success: true, + complete: function( xhr ) { + xhr.always( function() { + assert.ok( true, "complete" ); + } ).done( function() { + assert.ok( true, "success" ); + } ).fail( function() { + assert.ok( false, "error" ); + } ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - error callbacks", 8, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError", assert ), + url: url( "data/name.php?wait=5" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + afterSend: function( request ) { + request.abort(); + }, + error: function() { + assert.ok( true, "error" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - textStatus and errorThrown values", 4, function( assert ) { + return [ { + url: url( "data/name.php?wait=5" ), + error: function( _, textStatus, errorThrown ) { + assert.strictEqual( textStatus, "abort", "textStatus is 'abort' for abort" ); + assert.strictEqual( errorThrown, "abort", "errorThrown is 'abort' for abort" ); + }, + afterSend: function( request ) { + request.abort(); + } + }, + { + url: url( "data/name.php?wait=5" ), + error: function( _, textStatus, errorThrown ) { + assert.strictEqual( textStatus, "mystatus", "textStatus is 'mystatus' for abort('mystatus')" ); + assert.strictEqual( errorThrown, "mystatus", "errorThrown is 'mystatus' for abort('mystatus')" ); + }, + afterSend: function( request ) { + request.abort( "mystatus" ); + } + } ]; + } ); + + ajaxTest( "jQuery.ajax() - responseText on error", 1, function( assert ) { + return { + url: url( "data/errorWithText.php" ), + error: function( xhr ) { + assert.strictEqual( xhr.responseText, "plain text message", "Test jqXHR.responseText is filled for HTTP errors" ); + } + }; + } ); + + QUnit.asyncTest( "jQuery.ajax() - retry with jQuery.ajax( this )", 2, function( assert ) { + var previousUrl, + firstTime = true; + jQuery.ajax( { + url: url( "data/errorWithText.php" ), + error: function() { + if ( firstTime ) { + firstTime = false; + jQuery.ajax( this ); + } else { + assert.ok( true, "Test retrying with jQuery.ajax(this) works" ); + jQuery.ajax( { + url: url( "data/errorWithText.php" ), + data: { + "x": 1 + }, + beforeSend: function() { + if ( !previousUrl ) { + previousUrl = this.url; + } else { + assert.strictEqual( this.url, previousUrl, "url parameters are not re-appended" ); + QUnit.start(); + return false; + } + }, + error: function() { + jQuery.ajax( this ); + } + } ); + } + } + } ); + } ); + + ajaxTest( "jQuery.ajax() - headers", 5, function( assert ) { + return { + setup: function() { + jQuery( document ).ajaxSend( function( evt, xhr ) { + xhr.setRequestHeader( "ajax-send", "test" ); + } ); + }, + url: url( "data/headers.php?keys=siMPle_SometHing-elsE_OthEr_Nullable_undefined_Empty_ajax-send" ), + headers: { + "siMPle": "value", + "SometHing-elsE": "other value", + "OthEr": "something else", + "Nullable": null, + "undefined": undefined + + // Support: Firefox + // Not all browsers allow empty-string headers + // https://bugzilla.mozilla.org/show_bug.cgi?id=815299 + //"Empty": "" + }, + success: function( data, _, xhr ) { + var i, emptyHeader, + requestHeaders = jQuery.extend( this.headers, { + "ajax-send": "test" + } ), + tmp = []; + for ( i in requestHeaders ) { + tmp.push( i, ": ", requestHeaders[ i ] + "", "\n" ); + } + tmp = tmp.join( "" ); + + assert.strictEqual( data, tmp, "Headers were sent" ); + assert.strictEqual( xhr.getResponseHeader( "Sample-Header" ), "Hello World", "Sample header received" ); + assert.ok( data.indexOf( "undefined" ) < 0, "Undefined header value was not sent" ); + + emptyHeader = xhr.getResponseHeader( "Empty-Header" ); + if ( emptyHeader === null ) { + assert.ok( true, "Firefox doesn't support empty headers" ); + } else { + assert.strictEqual( emptyHeader, "", "Empty header received" ); + } + assert.strictEqual( xhr.getResponseHeader( "Sample-Header2" ), "Hello World 2", "Second sample header received" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - Accept header", 1, function( assert ) { + return { + url: url( "data/headers.php?keys=accept" ), + headers: { + Accept: "very wrong accept value" + }, + beforeSend: function( xhr ) { + xhr.setRequestHeader( "Accept", "*/*" ); + }, + success: function( data ) { + assert.strictEqual( data, "accept: */*\n", "Test Accept header is set to last value provided" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - contentType", 2, function( assert ) { + return [ + { + url: url( "data/headers.php?keys=content-type" ), + contentType: "test", + success: function( data ) { + assert.strictEqual( data, "content-type: test\n", "Test content-type is sent when options.contentType is set" ); + } + }, + { + url: url( "data/headers.php?keys=content-type" ), + contentType: false, + success: function( data ) { + + // Some server/interpreter combinations always supply a Content-Type to scripts + data = data || "content-type: \n"; + assert.strictEqual( data, "content-type: \n", "Test content-type is not set when options.contentType===false" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - protocol-less urls", 1, function( assert ) { + return { + url: "//somedomain.com", + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added." ); + return false; + }, + error: true + }; + } ); + + ajaxTest( "jQuery.ajax() - hash", 3, function( assert ) { + return [ + { + url: "data/name.html#foo", + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html", "Make sure that the URL is trimmed." ); + return false; + }, + error: true + }, + { + url: "data/name.html?abc#foo", + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html?abc", "Make sure that the URL is trimmed." ); + return false; + }, + error: true + }, + { + url: "data/name.html?abc#foo", + data: { + "test": 123 + }, + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html?abc&test=123", "Make sure that the URL is trimmed." ); + return false; + }, + error: true + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - cross-domain detection", 8, function( assert ) { + function request( url, title, crossDomainOrOptions ) { + return jQuery.extend( { + dataType: "jsonp", + url: url, + beforeSend: function( _, s ) { + assert.ok( crossDomainOrOptions === false ? !s.crossDomain : s.crossDomain, title ); + return false; + }, + error: true + }, crossDomainOrOptions ); + } + + var loc = document.location, + samePort = loc.port || ( loc.protocol === "http:" ? 80 : 443 ), + otherPort = loc.port === 666 ? 667 : 666, + otherProtocol = loc.protocol === "http:" ? "https:" : "http:"; + + return [ + request( + loc.protocol + "//" + loc.hostname + ":" + samePort, + "Test matching ports are not detected as cross-domain", + false + ), + request( + otherProtocol + "//" + loc.host, + "Test different protocols are detected as cross-domain" + ), + request( + "app:/path", + "Adobe AIR app:/ URL detected as cross-domain" + ), + request( + loc.protocol + "//example.invalid:" + ( loc.port || 80 ), + "Test different hostnames are detected as cross-domain" + ), + request( + loc.protocol + "//" + loc.hostname + ":" + otherPort, + "Test different ports are detected as cross-domain" + ), + request( + "about:blank", + "Test about:blank is detected as cross-domain" + ), + request( + loc.protocol + "//" + loc.host, + "Test forced crossDomain is detected as cross-domain", + { + crossDomain: true + } + ), + request( + " http://otherdomain.com", + "Cross-domain url with leading space is detected as cross-domain" + ) + ]; + } ); + + ajaxTest( "jQuery.ajax() - abort", 9, function( assert ) { + return { + setup: addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxError ajaxComplete", assert ), + url: url( "data/name.php?wait=5" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + afterSend: function( xhr ) { + assert.strictEqual( xhr.readyState, 1, "XHR readyState indicates successful dispatch" ); + xhr.abort(); + assert.strictEqual( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); + }, + error: true, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - native abort", 2, function( assert ) { + return { + url: url( "data/name.php?wait=1" ), + xhr: function() { + var xhr = new window.XMLHttpRequest(); + setTimeout( function() { + xhr.abort(); + }, 100 ); + return xhr; + }, + error: function( xhr, msg ) { + assert.strictEqual( msg, "error", "Native abort triggers error callback" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - events with context", 12, function( assert ) { + var context = document.createElement( "div" ); + + function event( e ) { + assert.equal( this, context, e.type ); + } + + function callback( msg ) { + return function() { + assert.equal( this, context, "context is preserved on callback " + msg ); + }; + } + + return { + setup: function() { + jQuery( context ).appendTo( "#foo" ) + .ajaxSend( event ) + .ajaxComplete( event ) + .ajaxError( event ) + .ajaxSuccess( event ); + }, + requests: [ { + url: url( "data/name.html" ), + context: context, + beforeSend: callback( "beforeSend" ), + success: callback( "success" ), + complete: callback( "complete" ) + }, { + url: url( "data/404.html" ), + context: context, + beforeSend: callback( "beforeSend" ), + error: callback( "error" ), + complete: callback( "complete" ) + } ] + }; + } ); + + ajaxTest( "jQuery.ajax() - events without context", 3, function( assert ) { + function nocallback( msg ) { + return function() { + assert.equal( typeof this.url, "string", "context is settings on callback " + msg ); + }; + } + return { + url: url( "data/404.html" ), + beforeSend: nocallback( "beforeSend" ), + error: nocallback( "error" ), + complete: nocallback( "complete" ) + }; + } ); + + ajaxTest( "#15118 - jQuery.ajax() - function without jQuery.event", 1, function( assert ) { + var holder; + return { + url: url( "data/json.php" ), + setup: function() { + holder = jQuery.event; + delete jQuery.event; + }, + complete: function() { + assert.ok( true, "Call can be made without jQuery.event" ); + jQuery.event = holder; + }, + success: true + }; + } ); + + ajaxTest( "#15160 - jQuery.ajax() - request manually aborted in ajaxSend", 3, function( assert ) { + return { + setup: function() { + jQuery( document ).on( "ajaxSend", function( e, jqXHR ) { + jqXHR.abort(); + } ); + + jQuery( document ).on( "ajaxError ajaxComplete", function( e, jqXHR ) { + assert.equal( jqXHR.statusText, "abort", "jqXHR.statusText equals abort on global ajaxComplete and ajaxError events" ); + } ); + }, + url: url( "data/name.html" ), + error: true, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - context modification", 1, function( assert ) { + return { + url: url( "data/name.html" ), + context: {}, + beforeSend: function() { + this.test = "foo"; + }, + afterSend: function() { + assert.strictEqual( this.context.test, "foo", "Make sure the original object is maintained." ); + }, + success: true + }; + } ); + + ajaxTest( "jQuery.ajax() - context modification through ajaxSetup", 3, function( assert ) { + var obj = {}; + return { + setup: function() { + jQuery.ajaxSetup( { + context: obj + } ); + assert.strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." ); + }, + requests: [ { + url: url( "data/name.html" ), + success: function() { + assert.strictEqual( this, obj, "Make sure the original object is maintained." ); + } + }, { + url: url( "data/name.html" ), + context: {}, + success: function() { + assert.ok( this !== obj, "Make sure overriding context is possible." ); + } + } ] + }; + } ); + + ajaxTest( "jQuery.ajax() - disabled globals", 3, function( assert ) { + return { + setup: addGlobalEvents( "", assert ), + global: false, + url: url( "data/name.html" ), + beforeSend: function() { + assert.ok( true, "beforeSend" ); + }, + success: function() { + assert.ok( true, "success" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - xml: non-namespace elements inside namespaced elements", 3, function( assert ) { + return { + url: url( "data/with_fries.xml" ), + dataType: "xml", + success: function( resp ) { + assert.equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); + assert.equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); + assert.equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - xml: non-namespace elements inside namespaced elements (over JSONP)", 3, function( assert ) { + return { + url: url( "data/with_fries_over_jsonp.php" ), + dataType: "jsonp xml", + success: function( resp ) { + assert.equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); + assert.equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); + assert.equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - HEAD requests", 2, function( assert ) { + return [ + { + url: url( "data/name.html" ), + type: "HEAD", + success: function( data, status, xhr ) { + assert.ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response" ); + } + }, + { + url: url( "data/name.html" ), + data: { + "whip_it": "good" + }, + type: "HEAD", + success: function( data, status, xhr ) { + assert.ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response with data" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - beforeSend", 1, function( assert ) { + return { + url: url( "data/name.html" ), + beforeSend: function() { + this.check = true; + }, + success: function() { + assert.ok( this.check, "check beforeSend was executed" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - beforeSend, cancel request manually", 2, function( assert ) { + return { + create: function() { + return jQuery.ajax( { + url: url( "data/name.html" ), + beforeSend: function( xhr ) { + assert.ok( true, "beforeSend got called, canceling" ); + xhr.abort(); + }, + success: function() { + assert.ok( false, "request didn't get canceled" ); + }, + complete: function() { + assert.ok( false, "request didn't get canceled" ); + }, + error: function() { + assert.ok( false, "request didn't get canceled" ); + } + } ); + }, + fail: function( _, reason ) { + assert.strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - dataType html", 5, function( assert ) { + return { + setup: function() { + Globals.register( "testFoo" ); + Globals.register( "testBar" ); + }, + dataType: "html", + url: url( "data/test.html" ), + success: function( data ) { + assert.ok( data.match( /^html text/ ), "Check content for datatype html" ); + jQuery( "#ap" ).html( data ); + assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated for datatype html" ); + assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated for datatype html" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - synchronous request", 1, function( assert ) { + return { + url: url( "data/json_obj.js" ), + dataType: "text", + async: false, + success: true, + afterSend: function( xhr ) { + assert.ok( /^\{ "data"/.test( xhr.responseText ), "check returned text" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - synchronous request with callbacks", 2, function( assert ) { + return { + url: url( "data/json_obj.js" ), + async: false, + dataType: "text", + success: true, + afterSend: function( xhr ) { + var result; + xhr.done( function( data ) { + assert.ok( true, "success callback executed" ); + result = data; + } ); + assert.ok( /^\{ "data"/.test( result ), "check returned text" ); + } + }; + } ); + + QUnit.asyncTest( "jQuery.ajax(), jQuery.get[Script|JSON](), jQuery.post(), pass-through request object", 8, function( assert ) { + var target = "data/name.html", + successCount = 0, + errorCount = 0, + errorEx = "", + success = function() { + successCount++; + }; + jQuery( document ).on( "ajaxError.passthru", function( e, xml ) { + errorCount++; + errorEx += ": " + xml.status; + } ); + jQuery( document ).one( "ajaxStop", function() { + assert.equal( successCount, 5, "Check all ajax calls successful" ); + assert.equal( errorCount, 0, "Check no ajax errors (status" + errorEx + ")" ); + jQuery( document ).off( "ajaxError.passthru" ); + QUnit.start(); + } ); + Globals.register( "testBar" ); + + assert.ok( jQuery.get( url( target ), success ), "get" ); + assert.ok( jQuery.post( url( target ), success ), "post" ); + assert.ok( jQuery.getScript( url( "data/testbar.php" ), success ), "script" ); + assert.ok( jQuery.getJSON( url( "data/json_obj.js" ), success ), "json" ); + assert.ok( jQuery.ajax( { + url: url( target ), + success: success + } ), "generic" ); + } ); + + ajaxTest( "jQuery.ajax() - cache", 12, function( assert ) { + var re = /_=(.*?)(&|$)/g; + + function request( url, title ) { + return { + url: url, + cache: false, + beforeSend: function() { + var parameter, tmp; + while ( ( tmp = re.exec( this.url ) ) ) { + assert.strictEqual( parameter, undefined, title + ": only one 'no-cache' parameter" ); + parameter = tmp[ 1 ]; + assert.notStrictEqual( parameter, "tobereplaced555", title + ": parameter (if it was there) was replaced" ); + } + return false; + }, + error: true + }; + } + + return [ + request( + "data/text.php", + "no parameter" + ), + request( + "data/text.php?pizza=true", + "1 parameter" + ), + request( + "data/text.php?_=tobereplaced555", + "_= parameter" + ), + request( + "data/text.php?pizza=true&_=tobereplaced555", + "1 parameter and _=" + ), + request( + "data/text.php?_=tobereplaced555&tv=false", + "_= and 1 parameter" + ), + request( + "data/text.php?name=David&_=tobereplaced555&washere=true", + "2 parameters surrounding _=" + ) + ]; + } ); + + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { + + ajaxTest( "jQuery.ajax() - JSONP - Query String (?n)" + label, 4, function( assert ) { + return [ + { + url: "data/jsonp.php?callback=?", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, url callback)" ); + } + }, + { + url: "data/jsonp.php?callback=??", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, url context-free callback)" ); + } + }, + { + url: "data/jsonp.php/??", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, REST-like)" ); + } + }, + { + url: "data/jsonp.php/???json=1", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.strictEqual( jQuery.type( data ), "array", "JSON results returned (GET, REST-like with param)" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - JSONP - Explicit callback param" + label, 10, function( assert ) { + return { + setup: function() { + Globals.register( "functionToCleanUp" ); + Globals.register( "XXX" ); + Globals.register( "jsonpResults" ); + window[ "jsonpResults" ] = function( data ) { + assert.ok( data[ "data" ], "JSON results returned (GET, custom callback function)" ); + }; + }, + requests: [ { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + jsonp: "callback", + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (GET, data obj callback)" ); + } + }, { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + jsonpCallback: "jsonpResults", + success: function( data ) { + assert.strictEqual( + typeof window[ "jsonpResults" ], + "function", + "should not rewrite original function" + ); + assert.ok( data.data, "JSON results returned (GET, custom callback name)" ); + } + }, { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + jsonpCallback: "functionToCleanUp", + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name to be cleaned up)" ); + assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed (GET, custom callback name to be cleaned up)" ); + var xhr; + jQuery.ajax( { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + jsonpCallback: "functionToCleanUp", + beforeSend: function( jqXHR ) { + xhr = jqXHR; + return false; + } + } ); + xhr.fail( function() { + assert.ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" ); + assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" ); + } ); + } + }, { + url: "data/jsonp.php?callback=XXX", + dataType: "jsonp", + jsonp: false, + jsonpCallback: "XXX", + crossDomain: crossDomain, + beforeSend: function() { + assert.ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" ); + }, + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name with no url manipulation)" ); + } + } ] + }; + } ); + + ajaxTest( "jQuery.ajax() - JSONP - Callback in data" + label, 2, function( assert ) { + return [ + { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + data: "callback=?", + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, data callback)" ); + } + }, + { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + data: "callback=??", + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, data context-free callback)" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - JSONP - POST" + label, 3, function( assert ) { + return [ + { + type: "POST", + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (POST, no callback)" ); + } + }, + { + type: "POST", + url: "data/jsonp.php", + data: "callback=?", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (POST, data callback)" ); + } + }, + { + type: "POST", + url: "data/jsonp.php", + jsonp: "callback", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data[ "data" ], "JSON results returned (POST, data obj callback)" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - JSONP" + label, 3, function( assert ) { + return [ + { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + assert.ok( data.data, "JSON results returned (GET, no callback)" ); + } + }, + { + create: function( options ) { + var request = jQuery.ajax( options ), + promise = request.then( function( data ) { + assert.ok( data.data, "first request: JSON results returned (GET, no callback)" ); + request = jQuery.ajax( this ).done( function( data ) { + assert.ok( data.data, "this re-used: JSON results returned (GET, no callback)" ); + } ); + promise.abort = request.abort; + return request; + } ); + promise.abort = request.abort; + return promise; + }, + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: true + } + ]; + } ); + + } ); + + ajaxTest( "jQuery.ajax() - script, Remote", 2, function( assert ) { + return { + setup: function() { + Globals.register( "testBar" ); + }, + url: window.location.href.replace( /[^\/]*$/, "" ) + "data/testbar.php", + dataType: "script", + success: function() { + assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - script, Remote with POST", 3, function( assert ) { + return { + setup: function() { + Globals.register( "testBar" ); + }, + url: window.location.href.replace( /[^\/]*$/, "" ) + "data/testbar.php", + type: "POST", + dataType: "script", + success: function( data, status ) { + assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (POST, no callback)" ); + assert.strictEqual( status, "success", "Script results returned (POST, no callback)" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - script, Remote with scheme-less URL", 2, function( assert ) { + return { + setup: function() { + Globals.register( "testBar" ); + }, + url: window.location.href.replace( /[^\/]*$/, "" ).replace( /^.*?\/\//, "//" ) + "data/testbar.php", + dataType: "script", + success: function() { + assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - malformed JSON", 2, function( assert ) { + return { + url: "data/badjson.js", + dataType: "json", + error: function( xhr, msg, detailedMsg ) { + assert.strictEqual( msg, "parsererror", "A parse error occurred." ); + assert.ok( /(invalid|error|exception)/i.test( detailedMsg ), "Detailed parsererror message provided" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - script by content-type", 2, function() { + return [ + { + url: "data/script.php", + data: { + "header": "script" + }, + success: true + }, + { + url: "data/script.php", + data: { + "header": "ecma" + }, + success: true + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - JSON by content-type", 5, function( assert ) { + return { + url: "data/json.php", + data: { + "header": "json", + "json": "array" + }, + success: function( json ) { + assert.ok( json.length >= 2, "Check length" ); + assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" ); + assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" ); + assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" ); + assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - JSON by content-type disabled with options", 6, function( assert ) { + return { + url: url( "data/json.php" ), + data: { + "header": "json", + "json": "array" + }, + contents: { + "json": false + }, + success: function( text ) { + assert.strictEqual( typeof text, "string", "json wasn't auto-determined" ); + var json = jQuery.parseJSON( text ); + assert.ok( json.length >= 2, "Check length" ); + assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" ); + assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" ); + assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" ); + assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - simple get", 1, function( assert ) { + return { + type: "GET", + url: url( "data/name.php?name=foo" ), + success: function( msg ) { + assert.strictEqual( msg, "bar", "Check for GET" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - simple post", 1, function( assert ) { + return { + type: "POST", + url: url( "data/name.php" ), + data: "name=peter", + success: function( msg ) { + assert.strictEqual( msg, "pan", "Check for POST" ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - data option - empty bodies for non-GET requests", 1, function( assert ) { + return { + url: "data/echoData.php", + data: undefined, + type: "post", + success: function( result ) { + assert.strictEqual( result, "" ); + } + }; + } ); + + var ifModifiedNow = new Date(); + + jQuery.each( + /* jQuery.each arguments start */ + { + " (cache)": true, + " (no cache)": false + }, + function( label, cache ) { + jQuery.each( + { + "If-Modified-Since": "if_modified_since.php", + "Etag": "etag.php" + }, + function( type, url ) { + url = "data/" + url + "?ts=" + ifModifiedNow++; + QUnit.asyncTest( "jQuery.ajax() - " + type + " support" + label, 4, function( assert ) { + jQuery.ajax( { + url: url, + ifModified: true, + cache: cache, + success: function( _, status ) { + assert.strictEqual( status, "success", "Initial status is 'success'" ); + jQuery.ajax( { + url: url, + ifModified: true, + cache: cache, + success: function( data, status, jqXHR ) { + assert.strictEqual( status, "notmodified", "Following status is 'notmodified'" ); + assert.strictEqual( jqXHR.status, 304, "XHR status is 304" ); + assert.equal( data, null, "no response body is given" ); + }, + complete: function() { + QUnit.start(); + } + } ); + } + } ); + } ); + } + ); + } + /* jQuery.each arguments end */ + ); + + ajaxTest( "jQuery.ajax() - failing cross-domain (non-existing)", 1, function( assert ) { + return { + + // see RFC 2606 + url: "http://example.invalid", + error: function( xhr, _, e ) { + assert.ok( true, "file not found: " + xhr.status + " => " + e ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - failing cross-domain", 1, function( assert ) { + return { + url: "http://" + externalHost, + error: function( xhr, _, e ) { + assert.ok( true, "access denied: " + xhr.status + " => " + e ); + } + }; + } ); + + ajaxTest( "jQuery.ajax() - atom+xml", 1, function( assert ) { + return { + url: url( "data/atom+xml.php" ), + success: function() { + assert.ok( true, "success" ); + } + }; + } ); + + QUnit.asyncTest( "jQuery.ajax() - statusText", 3, function( assert ) { + jQuery.ajax( url( "data/statusText.php?status=200&text=Hello" ) ).done( function( _, statusText, jqXHR ) { + assert.strictEqual( statusText, "success", "callback status text ok for success" ); + assert.ok( jqXHR.statusText === "Hello" || jqXHR.statusText === "OK", "jqXHR status text ok for success (" + jqXHR.statusText + ")" ); + jQuery.ajax( url( "data/statusText.php?status=404&text=World" ) ).fail( function( jqXHR, statusText ) { + assert.strictEqual( statusText, "error", "callback status text ok for error" ); + QUnit.start(); + } ); + } ); + } ); + + QUnit.asyncTest( "jQuery.ajax() - statusCode", 20, function( assert ) { + + var count = 12; + + function countComplete() { + if ( !--count ) { + QUnit.start(); + } + } + + function createStatusCodes( name, isSuccess ) { + name = "Test " + name + " " + ( isSuccess ? "success" : "error" ); + return { + 200: function() { + assert.ok( isSuccess, name ); + }, + 404: function() { + assert.ok( !isSuccess, name ); + } + }; + } + + jQuery.each( + /* jQuery.each arguments start */ + { + "data/name.html": true, + "data/someFileThatDoesNotExist.html": false + }, + function( uri, isSuccess ) { + + jQuery.ajax( url( uri ), { + statusCode: createStatusCodes( "in options", isSuccess ), + complete: countComplete + } ); + + jQuery.ajax( url( uri ), { + complete: countComplete + } ).statusCode( createStatusCodes( "immediately with method", isSuccess ) ); + + jQuery.ajax( url( uri ), { + complete: function( jqXHR ) { + jqXHR.statusCode( createStatusCodes( "on complete", isSuccess ) ); + countComplete(); + } + } ); + + jQuery.ajax( url( uri ), { + complete: function( jqXHR ) { + setTimeout( function() { + jqXHR.statusCode( createStatusCodes( "very late binding", isSuccess ) ); + countComplete(); + }, 100 ); + } + } ); + + jQuery.ajax( url( uri ), { + statusCode: createStatusCodes( "all (options)", isSuccess ), + complete: function( jqXHR ) { + jqXHR.statusCode( createStatusCodes( "all (on complete)", isSuccess ) ); + setTimeout( function() { + jqXHR.statusCode( createStatusCodes( "all (very late binding)", isSuccess ) ); + countComplete(); + }, 100 ); + } + } ).statusCode( createStatusCodes( "all (immediately with method)", isSuccess ) ); + + var testString = ""; + + jQuery.ajax( url( uri ), { + success: function( a, b, jqXHR ) { + assert.ok( isSuccess, "success" ); + var statusCode = {}; + statusCode[ jqXHR.status ] = function() { + testString += "B"; + }; + jqXHR.statusCode( statusCode ); + testString += "A"; + }, + error: function( jqXHR ) { + assert.ok( !isSuccess, "error" ); + var statusCode = {}; + statusCode[ jqXHR.status ] = function() { + testString += "B"; + }; + jqXHR.statusCode( statusCode ); + testString += "A"; + }, + complete: function() { + assert.strictEqual( + testString, + "AB", + "Test statusCode callbacks are ordered like " + ( isSuccess ? "success" : "error" ) + " callbacks" + ); + countComplete(); + } + } ); + + } + /* jQuery.each arguments end*/ + ); + } ); + + ajaxTest( "jQuery.ajax() - transitive conversions", 8, function( assert ) { + return [ + { + url: url( "data/json.php" ), + converters: { + "json myJson": function( data ) { + assert.ok( true, "converter called" ); + return data; + } + }, + dataType: "myJson", + success: function() { + assert.ok( true, "Transitive conversion worked" ); + assert.strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text" ); + assert.strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType" ); + } + }, + { + url: url( "data/json.php" ), + converters: { + "json myJson": function( data ) { + assert.ok( true, "converter called (*)" ); + return data; + } + }, + contents: false, /* headers are wrong so we ignore them */ + dataType: "* myJson", + success: function() { + assert.ok( true, "Transitive conversion worked (*)" ); + assert.strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text (*)" ); + assert.strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType (*)" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - overrideMimeType", 2, function( assert ) { + return [ + { + url: url( "data/json.php" ), + beforeSend: function( xhr ) { + xhr.overrideMimeType( "application/json" ); + }, + success: function( json ) { + assert.ok( json.data, "Mimetype overridden using beforeSend" ); + } + }, + { + url: url( "data/json.php" ), + mimeType: "application/json", + success: function( json ) { + assert.ok( json.data, "Mimetype overridden using mimeType option" ); + } + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - empty json gets to error callback instead of success callback.", 1, function( assert ) { + return { + url: url( "data/echoData.php" ), + error: function( _, __, error ) { + assert.equal( typeof error === "object", true, "Didn't get back error object for empty json response" ); + }, + dataType: "json" + }; + } ); + + ajaxTest( "#2688 - jQuery.ajax() - beforeSend, cancel request", 2, function( assert ) { + return { + create: function() { + return jQuery.ajax( { + url: url( "data/name.html" ), + beforeSend: function() { + assert.ok( true, "beforeSend got called, canceling" ); + return false; + }, + success: function() { + assert.ok( false, "request didn't get canceled" ); + }, + complete: function() { + assert.ok( false, "request didn't get canceled" ); + }, + error: function() { + assert.ok( false, "request didn't get canceled" ); + } + } ); + }, + fail: function( _, reason ) { + assert.strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); + } + }; + } ); + + ajaxTest( "#2806 - jQuery.ajax() - data option - evaluate function values", 1, function( assert ) { + return { + url: "data/echoQuery.php", + data: { + key: function() { + return "value"; + } + }, + success: function( result ) { + assert.strictEqual( result, "key=value" ); + } + }; + } ); + + QUnit.test( "#7531 - jQuery.ajax() - Location object as url", function( assert ) { + assert.expect( 1 ); + + var xhr, + success = false; + try { + xhr = jQuery.ajax( { + url: window.location + } ); + success = true; + xhr.abort(); + } catch ( e ) { + + } + assert.ok( success, "document.location did not generate exception" ); + } ); + + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { + ajaxTest( "#7578 - jQuery.ajax() - JSONP - default for cache option" + label, 1, function( assert ) { + return { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function() { + assert.strictEqual( this.cache, false, "cache must be false on JSON request" ); + return false; + }, + error: true + }; + } ); + } ); + + ajaxTest( "#8107 - jQuery.ajax() - multiple method signatures introduced in 1.5", 4, function( assert ) { + return [ + { + create: function() { + return jQuery.ajax(); + }, + done: function() { + assert.ok( true, "With no arguments" ); + } + }, + { + create: function() { + return jQuery.ajax( "data/name.html" ); + }, + done: function() { + assert.ok( true, "With only string URL argument" ); + } + }, + { + create: function() { + return jQuery.ajax( "data/name.html", {} ); + }, + done: function() { + assert.ok( true, "With string URL param and map" ); + } + }, + { + create: function( options ) { + return jQuery.ajax( options ); + }, + url: "data/name.html", + success: function() { + assert.ok( true, "With only map" ); + } + } + ]; + } ); + + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { + ajaxTest( "#8205 - jQuery.ajax() - JSONP - re-use callbacks name" + label, 4, function( assert ) { + return { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function( jqXHR, s ) { + s.callback = s.jsonpCallback; + + assert.ok( this.callback in window, "JSONP callback name is in the window" ); + }, + success: function() { + var previous = this; + + assert.strictEqual( + previous.jsonpCallback, + undefined, + "jsonpCallback option is set back to default in callbacks" + ); + + assert.ok( + !( this.callback in window ), + "JSONP callback name was removed from the window" + ); + + jQuery.ajax( { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function() { + assert.strictEqual( this.jsonpCallback, previous.callback, "JSONP callback name is re-used" ); + return false; + } + } ); + } + }; + } ); + } ); + + QUnit.test( "#9887 - jQuery.ajax() - Context with circular references (#9887)", function( assert ) { + assert.expect( 2 ); + + var success = false, + context = {}; + context.field = context; + try { + jQuery.ajax( "non-existing", { + context: context, + beforeSend: function() { + assert.ok( this === context, "context was not deep extended" ); + return false; + } + } ); + success = true; + } catch ( e ) { + console.log( e ); + } + assert.ok( success, "context with circular reference did not generate an exception" ); + } ); + + jQuery.each( [ "as argument", "in settings object" ], function( inSetting, title ) { + + function request( assert, url, test ) { + return { + create: function() { + return jQuery.ajax( inSetting ? { url: url } : url ); + }, + done: function() { + assert.ok( true, ( test || url ) + " " + title ); + } + }; + } + + ajaxTest( "#10093 - jQuery.ajax() - falsy url " + title, 4, function( assert ) { + return [ + request( assert, "", "empty string" ), + request( assert, false ), + request( assert, null ), + request( assert, undefined ) + ]; + } ); + } ); + + ajaxTest( "#11151 - jQuery.ajax() - parse error body", 2, function( assert ) { + return { + url: url( "data/errorWithJSON.php" ), + dataFilter: function( string ) { + assert.ok( false, "dataFilter called" ); + return string; + }, + error: function( jqXHR ) { + assert.strictEqual( jqXHR.responseText, "{ \"code\": 40, \"message\": \"Bad Request\" }", "Error body properly set" ); + assert.deepEqual( jqXHR.responseJSON, { code: 40, message: "Bad Request" }, "Error body properly parsed" ); + } + }; + } ); + + ajaxTest( "#11426 - jQuery.ajax() - loading binary data shouldn't throw an exception in IE", 1, function( assert ) { + return { + url: url( "data/1x1.jpg" ), + success: function( data ) { + assert.ok( data === undefined || /JFIF/.test( data ), "success callback reached" ); + } + }; + } ); + +if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().responseType !== "string" ) { + + QUnit.skip( "No ArrayBuffer support in XHR", jQuery.noop ); +} else { + + // No built-in support for binary data, but it's easy to add via a prefilter + jQuery.ajaxPrefilter( "arraybuffer", function( s ) { + s.xhrFields = { responseType: "arraybuffer" }; + s.responseFields.arraybuffer = "response"; + s.converters[ "binary arraybuffer" ] = true; + } ); + + ajaxTest( "gh-2498 - jQuery.ajax() - binary data shouldn't throw an exception", 2, function( assert ) { + return { + url: url( "data/1x1.jpg" ), + dataType: "arraybuffer", + success: function( data, s, jqxhr ) { + assert.ok( data instanceof window.ArrayBuffer, "correct data type" ); + assert.ok( jqxhr.response instanceof window.ArrayBuffer, "data in jQXHR" ); + } + }; + } ); +} + + QUnit.asyncTest( "#11743 - jQuery.ajax() - script, throws exception", 1, function( assert ) { + + // Support: Android 2.3 only + // Android 2.3 doesn't fire the window.onerror handler, just accept the reality there. + if ( /android 2\.3/i.test( navigator.userAgent ) ) { + assert.ok( true, "Test skipped, Android 2.3 doesn't fire window.onerror for " + + "errors in dynamically included scripts" ); + QUnit.start(); + return; + } + + var onerror = window.onerror; + window.onerror = function() { + assert.ok( true, "Exception thrown" ); + window.onerror = onerror; + QUnit.start(); + }; + jQuery.ajax( { + url: "data/badjson.js", + dataType: "script", + throws: true, + // Global events get confused by the exception + global: false, + success: function() { + assert.ok( false, "Success." ); + }, + error: function() { + assert.ok( false, "Error." ); + } + }); + }); + + jQuery.each( [ "method", "type" ], function( _, globalOption ) { + function request( assert, option ) { + var options = { + url: url( "data/echoData.php" ), + data: "hello", + success: function( msg ) { + assert.strictEqual( msg, "hello", "Check for POST (no override)" ); + } + }; + if ( option ) { + options[ option ] = "GET"; + options.success = function( msg ) { + assert.strictEqual( msg, "", "Check for no POST (overriding with " + option + ")" ); + }; + } + return options; + } + + ajaxTest( + "#12004 - jQuery.ajax() - method is an alias of type - " + + globalOption + " set globally", 3, + function( assert ) { + return { + setup: function() { + var options = {}; + options[ globalOption ] = "POST"; + jQuery.ajaxSetup( options ); + }, + requests: [ + request( assert, "type" ), + request( assert, "method" ), + request( assert ) + ] + }; + } + ); + } ); + + ajaxTest( "#13276 - jQuery.ajax() - compatibility between XML documents from ajax requests and parsed string", 1, function( assert ) { + return { + url: "data/dashboard.xml", + dataType: "xml", + success: function( ajaxXML ) { + var parsedXML = jQuery( jQuery.parseXML( "blibli" ) ).find( "tab" ); + ajaxXML = jQuery( ajaxXML ); + try { + + // Android 2.3 doesn't automatically adopt nodes from foreign documents. + // (see the comment in test/manipulation.js) + // Support: Android 2.3 + if ( /android 2\.3/i.test( navigator.userAgent ) ) { + parsedXML = jQuery( ajaxXML[ 0 ].adoptNode( parsedXML[ 0 ] ) ); + } + ajaxXML.find( "infowindowtab" ).append( parsedXML ); + } catch ( e ) { + assert.strictEqual( e, undefined, "error" ); + return; + } + assert.strictEqual( ajaxXML.find( "tab" ).length, 3, "Parsed node was added properly" ); + } + }; + } ); + + ajaxTest( "#13292 - jQuery.ajax() - converter is bypassed for 204 requests", 3, function( assert ) { + return { + url: "data/nocontent.php", + dataType: "testing", + converters: { + "* testing": function() { + throw "converter was called"; + } + }, + success: function( data, status, jqXHR ) { + assert.strictEqual( jqXHR.status, 204, "status code is 204" ); + assert.strictEqual( status, "nocontent", "status text is 'nocontent'" ); + assert.strictEqual( data, undefined, "data is undefined" ); + }, + error: function( _, status, error ) { + assert.ok( false, "error" ); + assert.strictEqual( status, "parsererror", "Parser Error" ); + assert.strictEqual( error, "converter was called", "Converter was called" ); + } + }; + } ); + + ajaxTest( "#13388 - jQuery.ajax() - responseXML", 3, function( assert ) { + return { + url: url( "data/with_fries.xml" ), + dataType: "xml", + success: function( resp, _, jqXHR ) { + assert.notStrictEqual( resp, undefined, "XML document exists" ); + assert.ok( "responseXML" in jqXHR, "jqXHR.responseXML exists" ); + assert.strictEqual( resp, jqXHR.responseXML, "jqXHR.responseXML is set correctly" ); + } + }; + } ); + + ajaxTest( "#13922 - jQuery.ajax() - converter is bypassed for HEAD requests", 3, function( assert ) { + return { + url: "data/json.php", + method: "HEAD", + data: { + header: "yes" + }, + converters: { + "text json": function() { + throw "converter was called"; + } + }, + success: function( data, status ) { + assert.ok( true, "success" ); + assert.strictEqual( status, "nocontent", "data is undefined" ); + assert.strictEqual( data, undefined, "data is undefined" ); + }, + error: function( _, status, error ) { + assert.ok( false, "error" ); + assert.strictEqual( status, "parsererror", "Parser Error" ); + assert.strictEqual( error, "converter was called", "Converter was called" ); + } + }; + } ); + + testIframeWithCallback( + "#14379 - jQuery.ajax() on unload", + "ajax/onunload.html", + function( status, assert ) { + assert.expect( 1 ); + assert.strictEqual( status, "success", "Request completed" ); + } + ); + + ajaxTest( "#14683 - jQuery.ajax() - Exceptions thrown synchronously by xhr.send should be caught", 4, function( assert ) { + return [ { + url: "data/params_html.php", + method: "POST", + data: { + toString: function() { + throw "Can't parse"; + } + }, + processData: false, + done: function( data ) { + assert.ok( false, "done: " + data ); + }, + fail: function( jqXHR, status, error ) { + assert.ok( true, "exception caught: " + error ); + assert.strictEqual( jqXHR.status, 0, "proper status code" ); + assert.strictEqual( status, "error", "proper status" ); + } + }, { + url: "http://domain.org:80d", + done: function( data ) { + assert.ok( false, "done: " + data ); + }, + fail: function( _, status, error ) { + assert.ok( true, "fail: " + status + " - " + error ); + } + } ]; + } + ); + + ajaxTest( "gh-2587 - when content-type not xml, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "response": "" + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not xml" + ); + } + }; + } ); + + ajaxTest( "gh-2587 - when content-type not xml, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "response": "" + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not xml" + ); + } + }; + } ); + + ajaxTest( "gh-2587 - when content-type not json, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "test/jsontest", + "response": JSON.stringify( { test: "test" } ) + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not json" + ); + } + }; + } ); + + ajaxTest( "gh-2587 - when content-type not html, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "test/htmltest", + "response": "

        test

        " + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not html" + ); + } + }; + } ); + + ajaxTest( "gh-2587 - when content-type not javascript, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "test/testjavascript", + "response": "alert(1)" + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not javascript" + ); + } + }; + } ); + + ajaxTest( "gh-2587 - when content-type not ecmascript, but looks like one", 1, function( assert ) { + return { + url: url( "data/ajax/content-type.php" ), + data: { + "content-type": "test/testjavascript", + "response": "alert(1)" + }, + success: function( result ) { + assert.strictEqual( + typeof result, + "string", + "Should handle it as a string, not ecmascript" + ); + } + }; + } ); + +//----------- jQuery.ajaxPrefilter() + + ajaxTest( "jQuery.ajaxPrefilter() - abort", 1, function( assert ) { + return { + dataType: "prefix", + setup: function() { + + // Ensure prefix does not throw an error + jQuery.ajaxPrefilter( "+prefix", function( options, _, jqXHR ) { + if ( options.abortInPrefilter ) { + jqXHR.abort(); + } + } ); + }, + abortInPrefilter: true, + error: function() { + assert.ok( false, "error callback called" ); + }, + fail: function( _, reason ) { + assert.strictEqual( reason, "canceled", "Request aborted by the prefilter must fail with 'canceled' status text" ); + } + }; + } ); + +//----------- jQuery.ajaxSetup() + + QUnit.asyncTest( "jQuery.ajaxSetup()", 1, function( assert ) { + jQuery.ajaxSetup( { + url: url( "data/name.php?name=foo" ), + success: function( msg ) { + assert.strictEqual( msg, "bar", "Check for GET" ); + QUnit.start(); + } + } ); + jQuery.ajax(); + } ); + + QUnit.asyncTest( "jQuery.ajaxSetup({ timeout: Number }) - with global timeout", 2, function( assert ) { + var passed = 0, + pass = function() { + assert.ok( passed++ < 2, "Error callback executed" ); + if ( passed === 2 ) { + jQuery( document ).off( "ajaxError.setupTest" ); + QUnit.start(); + } + }, + fail = function( a, b ) { + assert.ok( false, "Check for timeout failed " + a + " " + b ); + QUnit.start(); + }; + + jQuery( document ).on( "ajaxError.setupTest", pass ); + + jQuery.ajaxSetup( { + timeout: 1000 + } ); + + jQuery.ajax( { + type: "GET", + url: url( "data/name.php?wait=5" ), + error: pass, + success: fail + } ); + } ); + + QUnit.asyncTest( "jQuery.ajaxSetup({ timeout: Number }) with localtimeout", 1, function( assert ) { + jQuery.ajaxSetup( { + timeout: 50 + } ); + jQuery.ajax( { + type: "GET", + timeout: 15000, + url: url( "data/name.php?wait=1" ), + error: function() { + assert.ok( false, "Check for local timeout failed" ); + QUnit.start(); + }, + success: function() { + assert.ok( true, "Check for local timeout" ); + QUnit.start(); + } + } ); + } ); + +//----------- jQuery.domManip() + + QUnit.test( "#11264 - jQuery.domManip() - no side effect because of ajaxSetup or global events", function( assert ) { + assert.expect( 1 ); + + jQuery.ajaxSetup( { + type: "POST" + } ); + + jQuery( document ).on( "ajaxStart ajaxStop", function() { + assert.ok( false, "Global event triggered" ); + } ); + + jQuery( "#qunit-fixture" ).append( "" ); + + jQuery( document ).off( "ajaxStart ajaxStop" ); + } ); + + QUnit.test( + "jQuery#load() - always use GET method even if it overrided through ajaxSetup (#11264)", 1, + function( assert ) { + var done = assert.async(); + + jQuery.ajaxSetup( { + type: "POST" + } ); + + jQuery( "#qunit-fixture" ).load( "data/ajax/method.php", function( method ) { + assert.equal( method, "GET" ); + done(); + } ); + } + ); + + QUnit.test( + "#11402 - jQuery.domManip() - script in comments are properly evaluated", 2, + function( assert ) { + jQuery( "#qunit-fixture" ).load( "data/cleanScript.html", assert.async() ); + } + ); + +//----------- jQuery.get() + + QUnit.asyncTest( "jQuery.get( String, Hash, Function ) - parse xml and use text() on nodes", 2, function( assert ) { + jQuery.get( url( "data/dashboard.xml" ), function( xml ) { + var content = []; + jQuery( "tab", xml ).each( function() { + content.push( jQuery( this ).text() ); + } ); + assert.strictEqual( content[ 0 ], "blabla", "Check first tab" ); + assert.strictEqual( content[ 1 ], "blublu", "Check second tab" ); + QUnit.start(); + } ); + } ); + + QUnit.asyncTest( "#8277 - jQuery.get( String, Function ) - data in ajaxSettings", 1, function( assert ) { + jQuery.ajaxSetup( { + data: "helloworld" + } ); + jQuery.get( url( "data/echoQuery.php" ), function( data ) { + assert.ok( /helloworld$/.test( data ), "Data from ajaxSettings was used" ); + QUnit.start(); + } ); + } ); + +//----------- jQuery.getJSON() + + QUnit.asyncTest( "jQuery.getJSON( String, Hash, Function ) - JSON array", 5, function( assert ) { + jQuery.getJSON( + url( "data/json.php" ), + { + "json": "array" + }, + function( json ) { + assert.ok( json.length >= 2, "Check length" ); + assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" ); + assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" ); + assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" ); + assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" ); + QUnit.start(); + } + ); + } ); + + QUnit.asyncTest( "jQuery.getJSON( String, Function ) - JSON object", 2, function( assert ) { + jQuery.getJSON( url( "data/json.php" ), function( json ) { + if ( json && json[ "data" ] ) { + assert.strictEqual( json[ "data" ][ "lang" ], "en", "Check JSON: lang" ); + assert.strictEqual( json[ "data" ].length, 25, "Check JSON: length" ); + QUnit.start(); + } + } ); + } ); + + QUnit.asyncTest( "jQuery.getJSON( String, Function ) - JSON object with absolute url to local content", 2, function( assert ) { + jQuery.getJSON( url( window.location.href.replace( /[^\/]*$/, "" ) + "data/json.php" ), function( json ) { + assert.strictEqual( json.data.lang, "en", "Check JSON: lang" ); + assert.strictEqual( json.data.length, 25, "Check JSON: length" ); + QUnit.start(); + } ); + } ); + +//----------- jQuery.getScript() + + QUnit.test( "jQuery.getScript( String, Function ) - with callback", 2, + function( assert ) { + var done = assert.async(); + + Globals.register( "testBar" ); + jQuery.getScript( url( "data/testbar.php" ), function() { + assert.strictEqual( window[ "testBar" ], "bar", "Check if script was evaluated" ); + done(); + } ); + } + ); + + QUnit.test( "jQuery.getScript( String, Function ) - no callback", 1, function( assert ) { + Globals.register( "testBar" ); + jQuery.getScript( url( "data/testbar.php" ) ).done( assert.async() ); + } ); + + QUnit.test( "#8082 - jQuery.getScript( String, Function ) - source as responseText", 2, function( assert ) { + var done = assert.async(); + + Globals.register( "testBar" ); + jQuery.getScript( url( "data/testbar.php" ), function( data, _, jqXHR ) { + assert.strictEqual( data, jqXHR.responseText, "Same-domain script requests returns the source of the script" ); + done(); + } ); + } ); + +// //----------- jQuery.fn.load() + + // check if load can be called with only url + QUnit.test( "jQuery.fn.load( String )", 2, function( assert ) { + jQuery.ajaxSetup( { + beforeSend: function() { + assert.strictEqual( this.type, "GET", "no data means GET request" ); + } + } ); + jQuery( "#first" ).load( "data/name.html", assert.async() ); + } ); + + QUnit.test( "jQuery.fn.load() - 404 error callbacks", function( assert ) { + assert.expect( 6 ); + var done = assert.async(); + + addGlobalEvents( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError", assert )(); + jQuery( document ).ajaxStop( done ); + jQuery( "
        " ).load( "data/404.html", function() { + assert.ok( true, "complete" ); + } ); + } ); + + // check if load can be called with url and null data + QUnit.test( "jQuery.fn.load( String, null )", 2, function( assert ) { + jQuery.ajaxSetup( { + beforeSend: function() { + assert.strictEqual( this.type, "GET", "no data means GET request" ); + } + } ); + jQuery( "#first" ).load( "data/name.html", null, assert.async() ); + } ); + + // check if load can be called with url and undefined data + QUnit.test( "jQuery.fn.load( String, undefined )", 2, function( assert ) { + jQuery.ajaxSetup( { + beforeSend: function() { + assert.strictEqual( this.type, "GET", "no data means GET request" ); + } + } ); + jQuery( "#first" ).load( "data/name.html", undefined, assert.async() ); + } ); + + // check if load can be called with only url + QUnit.asyncTest( "jQuery.fn.load( URL_SELECTOR )", 1, function( assert ) { + jQuery( "#first" ).load( "data/test3.html div.user", function() { + assert.strictEqual( jQuery( this ).children( "div" ).length, 2, "Verify that specific elements were injected" ); + QUnit.start(); + } ); + } ); + + // Selector should be trimmed to avoid leading spaces (#14773) + QUnit.asyncTest( "jQuery.fn.load( URL_SELECTOR with spaces )", 1, function( assert ) { + jQuery( "#first" ).load( "data/test3.html #superuser ", function() { + assert.strictEqual( jQuery( this ).children( "div" ).length, 1, "Verify that specific elements were injected" ); + QUnit.start(); + } ); + } ); + + QUnit.asyncTest( "jQuery.fn.load( String, Function ) - simple: inject text into DOM", 2, function( assert ) { + jQuery( "#first" ).load( url( "data/name.html" ), function() { + assert.ok( /^ERROR/.test( jQuery( "#first" ).text() ), "Check if content was injected into the DOM" ); + QUnit.start(); + } ); + } ); + + QUnit.asyncTest( "jQuery.fn.load( String, Function ) - check scripts", 7, function( assert ) { + var verifyEvaluation = function() { + assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated after load" ); + assert.strictEqual( jQuery( "#ap" ).html(), "bar", "Check if script evaluation has modified DOM" ); + QUnit.start(); + }; + + Globals.register( "testFoo" ); + Globals.register( "testBar" ); + + jQuery( "#first" ).load( url( "data/test.html" ), function() { + assert.ok( jQuery( "#first" ).html().match( /^html text/ ), "Check content after loading html" ); + assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" ); + assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" ); + setTimeout( verifyEvaluation, 600 ); + } ); + } ); + + QUnit.asyncTest( "jQuery.fn.load( String, Function ) - check file with only a script tag", 3, function( assert ) { + Globals.register( "testFoo" ); + + jQuery( "#first" ).load( url( "data/test2.html" ), function() { + assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" ); + assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" ); + QUnit.start(); + } ); + } ); + + QUnit.asyncTest( "jQuery.fn.load( String, Function ) - dataFilter in ajaxSettings", 2, function( assert ) { + jQuery.ajaxSetup( { + dataFilter: function() { + return "Hello World"; + } + } ); + jQuery( "
        " ).load( url( "data/name.html" ), function( responseText ) { + assert.strictEqual( jQuery( this ).html(), "Hello World", "Test div was filled with filtered data" ); + assert.strictEqual( responseText, "Hello World", "Test callback receives filtered data" ); + QUnit.start(); + } ); + } ); + + QUnit.asyncTest( "jQuery.fn.load( String, Object, Function )", 2, function( assert ) { + jQuery( "
        " ).load( url( "data/params_html.php" ), { + "foo": 3, + "bar": "ok" + }, function() { + var $post = jQuery( this ).find( "#post" ); + assert.strictEqual( $post.find( "#foo" ).text(), "3", "Check if a hash of data is passed correctly" ); + assert.strictEqual( $post.find( "#bar" ).text(), "ok", "Check if a hash of data is passed correctly" ); + QUnit.start(); + } ); + } ); + + QUnit.test( "jQuery.fn.load( String, String, Function )", 2, function( assert ) { + var done = assert.async(); + + jQuery( "
        " ).load( url( "data/params_html.php" ), "foo=3&bar=ok", function() { + var $get = jQuery( this ).find( "#get" ); + assert.strictEqual( $get.find( "#foo" ).text(), "3", "Check if a string of data is passed correctly" ); + assert.strictEqual( $get.find( "#bar" ).text(), "ok", "Check if a of data is passed correctly" ); + done(); + } ); + } ); + + QUnit.test( "jQuery.fn.load() - callbacks get the correct parameters", 8, function( assert ) { + var completeArgs = {}; + var done = assert.async(); + + jQuery.ajaxSetup( { + success: function( _, status, jqXHR ) { + completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; + }, + error: function( jqXHR, status ) { + completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; + } + } ); + + jQuery.when.apply( + jQuery, + jQuery.map( [ + { + type: "success", + url: "data/echoQuery.php?arg=pop" + }, + { + type: "error", + url: "data/404.php" + } + ], + function( options ) { + return jQuery.Deferred( function( defer ) { + jQuery( "#foo" ).load( options.url, function() { + var args = arguments; + assert.strictEqual( completeArgs[ options.url ].length, args.length, "same number of arguments (" + options.type + ")" ); + jQuery.each( completeArgs[ options.url ], function( i, value ) { + assert.strictEqual( args[ i ], value, "argument #" + i + " is the same (" + options.type + ")" ); + } ); + defer.resolve(); + } ); + } ); + } ) + ).always( done ); + } ); + + QUnit.test( "#2046 - jQuery.fn.load( String, Function ) with ajaxSetup on dataType json", 1, function( assert ) { + var done = assert.async(); + + jQuery.ajaxSetup( { + dataType: "json" + } ); + jQuery( document ).ajaxComplete( function( e, xml, s ) { + assert.strictEqual( s.dataType, "html", "Verify the load() dataType was html" ); + jQuery( document ).off( "ajaxComplete" ); + done(); + } ); + jQuery( "#first" ).load( "data/test3.html" ); + } ); + + QUnit.test( "#10524 - jQuery.fn.load() - data specified in ajaxSettings is merged in", 1, function( assert ) { + var done = assert.async(); + + var data = { + "baz": 1 + }; + jQuery.ajaxSetup( { + data: { + "foo": "bar" + } + } ); + jQuery( "#foo" ).load( "data/echoQuery.php", data ); + jQuery( document ).ajaxComplete( function( event, jqXHR, options ) { + assert.ok( ~options.data.indexOf( "foo=bar" ), "Data from ajaxSettings was used" ); + done(); + } ); + } ); + +// //----------- jQuery.post() + + QUnit.test( "jQuery.post() - data", 3, function( assert ) { + var done = assert.async(); + + jQuery.when( + jQuery.post( + url( "data/name.php" ), + { + xml: "5-2", + length: 3 + }, + function( xml ) { + jQuery( "math", xml ).each( function() { + assert.strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + assert.strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + } ); + } + ), + jQuery.ajax( { + url: url( "data/echoData.php" ), + type: "POST", + data: { + "test": { + "length": 7, + "foo": "bar" + } + }, + success: function( data ) { + assert.strictEqual( data, "test%5Blength%5D=7&test%5Bfoo%5D=bar", "Check if a sub-object with a length param is serialized correctly" ); + } + } ) + ).always( function() { + done(); + } ); + } ); + + QUnit.test( "jQuery.post( String, Hash, Function ) - simple with xml", 4, function( assert ) { + var done = assert.async(); + + jQuery.when( + jQuery.post( + url( "data/name.php" ), + { + "xml": "5-2" + }, + function( xml ) { + jQuery( "math", xml ).each( function() { + assert.strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + assert.strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + } ); + } + ), + jQuery.post( url( "data/name.php?xml=5-2" ), {}, function( xml ) { + jQuery( "math", xml ).each( function() { + assert.strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + assert.strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + } ); + } ) + ).always( function() { + done(); + } ); + } ); + + QUnit.test( "jQuery[get|post]( options ) - simple with xml", 2, function( assert ) { + var done = assert.async(); + + jQuery.when.apply( jQuery, + jQuery.map( [ "get", "post" ], function( method ) { + return jQuery[ method ]( { + url: url( "data/name.php" ), + data: { + "xml": "5-2" + }, + success: function( xml ) { + jQuery( "math", xml ).each( function() { + assert.strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + } ); + } + } ); + } ) + ).always( function() { + done(); + } ); + } ); + +//----------- jQuery.active + + QUnit.test( "jQuery.active", function( assert ) { + assert.expect( 1 ); + assert.ok( jQuery.active === 0, "ajax active counter should be zero: " + jQuery.active ); + } ); + +} )(); diff --git a/dashboard-ui/bower_components/jquery/test/unit/attributes.js b/dashboard-ui/bower_components/jquery/test/unit/attributes.js new file mode 100644 index 0000000000..8b31b72a6e --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/attributes.js @@ -0,0 +1,1522 @@ +QUnit.module( "attributes", { + teardown: moduleTeardown +} ); + +function bareObj( value ) { + return value; +} + +function functionReturningObj( value ) { + return function() { + return value; + }; +} + +/* + ======== local reference ======= + bareObj and functionReturningObj can be used to test passing functions to setters + See testVal below for an example + + bareObj( value ); + This function returns whatever value is passed in + + functionReturningObj( value ); + Returns a function that returns the value +*/ + +QUnit.test( "jQuery.propFix integrity test", function( assert ) { + assert.expect( 1 ); + + // This must be maintained and equal jQuery.attrFix when appropriate + // Ensure that accidental or erroneous property + // overwrites don't occur + // This is simply for better code coverage and future proofing. + var props = { + "tabindex": "tabIndex", + "readonly": "readOnly", + "for": "htmlFor", + "class": "className", + "maxlength": "maxLength", + "cellspacing": "cellSpacing", + "cellpadding": "cellPadding", + "rowspan": "rowSpan", + "colspan": "colSpan", + "usemap": "useMap", + "frameborder": "frameBorder", + "contenteditable": "contentEditable" + }; + + assert.deepEqual( props, jQuery.propFix, "jQuery.propFix passes integrity check" ); +} ); + +QUnit.test( "attr(String)", function( assert ) { + assert.expect( 50 ); + + var extras, body, $body, + select, optgroup, option, $img, styleElem, + $button, $form, $a; + + assert.equal( jQuery( "#text1" ).attr( "type" ), "text", "Check for type attribute" ); + assert.equal( jQuery( "#radio1" ).attr( "type" ), "radio", "Check for type attribute" ); + assert.equal( jQuery( "#check1" ).attr( "type" ), "checkbox", "Check for type attribute" ); + assert.equal( jQuery( "#simon1" ).attr( "rel" ), "bookmark", "Check for rel attribute" ); + assert.equal( jQuery( "#google" ).attr( "title" ), "Google!", "Check for title attribute" ); + assert.equal( jQuery( "#mark" ).attr( "hreflang" ), "en", "Check for hreflang attribute" ); + assert.equal( jQuery( "#en" ).attr( "lang" ), "en", "Check for lang attribute" ); + assert.equal( jQuery( "#simon" ).attr( "class" ), "blog link", "Check for class attribute" ); + assert.equal( jQuery( "#name" ).attr( "name" ), "name", "Check for name attribute" ); + assert.equal( jQuery( "#text1" ).attr( "name" ), "action", "Check for name attribute" ); + assert.ok( jQuery( "#form" ).attr( "action" ).indexOf( "formaction" ) >= 0, "Check for action attribute" ); + assert.equal( jQuery( "#text1" ).attr( "value", "t" ).attr( "value" ), "t", "Check setting the value attribute" ); + assert.equal( jQuery( "#text1" ).attr( "value", "" ).attr( "value" ), "", "Check setting the value attribute to empty string" ); + assert.equal( jQuery( "
        " ).attr( "value" ), "t", "Check setting custom attr named 'value' on a div" ); + assert.equal( jQuery( "#form" ).attr( "blah", "blah" ).attr( "blah" ), "blah", "Set non-existent attribute on a form" ); + assert.equal( jQuery( "#foo" ).attr( "height" ), undefined, "Non existent height attribute should return undefined" ); + + // [7472] & [3113] (form contains an input with name="action" or name="id") + extras = jQuery( "" ).appendTo( "#testForm" ); + assert.equal( jQuery( "#form" ).attr( "action", "newformaction" ).attr( "action" ), "newformaction", "Check that action attribute was changed" ); + assert.equal( jQuery( "#testForm" ).attr( "target" ), undefined, "Retrieving target does not equal the input with name=target" ); + assert.equal( jQuery( "#testForm" ).attr( "target", "newTarget" ).attr( "target" ), "newTarget", "Set target successfully on a form" ); + assert.equal( jQuery( "#testForm" ).removeAttr( "id" ).attr( "id" ), undefined, "Retrieving id does not equal the input with name=id after id is removed [#7472]" ); + + // Bug #3685 (form contains input with name="name") + assert.equal( jQuery( "#testForm" ).attr( "name" ), undefined, "Retrieving name does not retrieve input with name=name" ); + extras.remove(); + + assert.equal( jQuery( "#text1" ).attr( "maxlength" ), "30", "Check for maxlength attribute" ); + assert.equal( jQuery( "#text1" ).attr( "maxLength" ), "30", "Check for maxLength attribute" ); + assert.equal( jQuery( "#area1" ).attr( "maxLength" ), "30", "Check for maxLength attribute" ); + + // using innerHTML in IE causes href attribute to be serialized to the full path + jQuery( "" ).attr( { + "id": "tAnchor5", + "href": "#5" + } ).appendTo( "#qunit-fixture" ); + assert.equal( jQuery( "#tAnchor5" ).attr( "href" ), "#5", "Check for non-absolute href (an anchor)" ); + jQuery( "" ).appendTo( "#qunit-fixture" ); + assert.equal( jQuery( "#tAnchor5" ).prop( "href" ), jQuery( "#tAnchor6" ).prop( "href" ), "Check for absolute href prop on an anchor" ); + + jQuery( "" ).appendTo( "#qunit-fixture" ); + assert.equal( jQuery( "#tAnchor5" ).prop( "href" ), jQuery( "#scriptSrc" ).prop( "src" ), "Check for absolute src prop on a script" ); + + // list attribute is readonly by default in browsers that support it + jQuery( "#list-test" ).attr( "list", "datalist" ); + assert.equal( jQuery( "#list-test" ).attr( "list" ), "datalist", "Check setting list attribute" ); + + // Related to [5574] and [5683] + body = document.body; + $body = jQuery( body ); + + assert.strictEqual( $body.attr( "foo" ), undefined, "Make sure that a non existent attribute returns undefined" ); + + body.setAttribute( "foo", "baz" ); + assert.equal( $body.attr( "foo" ), "baz", "Make sure the dom attribute is retrieved when no expando is found" ); + + $body.attr( "foo", "cool" ); + assert.equal( $body.attr( "foo" ), "cool", "Make sure that setting works well when both expando and dom attribute are available" ); + + body.removeAttribute( "foo" ); // Cleanup + + select = document.createElement( "select" ); + optgroup = document.createElement( "optgroup" ); + option = document.createElement( "option" ); + + optgroup.appendChild( option ); + select.appendChild( optgroup ); + + assert.equal( jQuery( option ).prop( "selected" ), true, "Make sure that a single option is selected, even when in an optgroup." ); + + $img = jQuery( "" ).appendTo( "body" ); + assert.equal( $img.attr( "width" ), "215", "Retrieve width attribute an an element with display:none." ); + assert.equal( $img.attr( "height" ), "53", "Retrieve height attribute an an element with display:none." ); + + // Check for style support + styleElem = jQuery( "
        " ).appendTo( "#qunit-fixture" ).css( { + background: "url(UPPERlower.gif)" + } ); + assert.ok( !!~styleElem.attr( "style" ).indexOf( "UPPERlower.gif" ), "Check style attribute getter" ); + assert.ok( !!~styleElem.attr( "style", "position:absolute;" ).attr( "style" ).indexOf( "absolute" ), "Check style setter" ); + + // Check value on button element (#1954) + $button = jQuery( "" ).insertAfter( "#button" ); + assert.strictEqual( $button.attr( "value" ), undefined, "Absence of value attribute on a button" ); + assert.equal( $button.attr( "value", "foobar" ).attr( "value" ), "foobar", "Value attribute on a button does not return innerHTML" ); + assert.equal( $button.attr( "value", "baz" ).html(), "text", "Setting the value attribute does not change innerHTML" ); + + // Attributes with a colon on a table element (#1591) + assert.equal( jQuery( "#table" ).attr( "test:attrib" ), undefined, "Retrieving a non-existent attribute on a table with a colon does not throw an error." ); + assert.equal( jQuery( "#table" ).attr( "test:attrib", "foobar" ).attr( "test:attrib" ), "foobar", "Setting an attribute on a table with a colon does not throw an error." ); + + $form = jQuery( "
        " ).appendTo( "#qunit-fixture" ); + assert.equal( $form.attr( "class" ), "something", "Retrieve the class attribute on a form." ); + + $a = jQuery( "
        Click" ).appendTo( "#qunit-fixture" ); + assert.equal( $a.attr( "onclick" ), "something()", "Retrieve ^on attribute without anonymous function wrapper." ); + + assert.ok( jQuery( "
        " ).attr( "doesntexist" ) === undefined, "Make sure undefined is returned when no attribute is found." ); + assert.ok( jQuery( "
        " ).attr( "title" ) === undefined, "Make sure undefined is returned when no attribute is found." ); + assert.equal( jQuery( "
        " ).attr( "title", "something" ).attr( "title" ), "something", "Set the title attribute." ); + assert.ok( jQuery().attr( "doesntexist" ) === undefined, "Make sure undefined is returned when no element is there." ); + assert.equal( jQuery( "
        " ).attr( "value" ), undefined, "An unset value on a div returns undefined." ); + assert.strictEqual( jQuery( "" ).attr( "value" ), undefined, "An unset value on a select returns undefined." ); + + $form = jQuery( "#form" ).attr( "enctype", "multipart/form-data" ); + assert.equal( $form.prop( "enctype" ), "multipart/form-data", "Set the enctype of a form (encoding in IE6/7 #6743)" ); + +} ); + +QUnit.test( "attr(String) on cloned elements, #9646", function( assert ) { + assert.expect( 4 ); + + var div, + input = jQuery( "" ); + + input.attr( "name" ); + + assert.strictEqual( input.clone( true ).attr( "name", "test" )[ 0 ].name, "test", "Name attribute should be changed on cloned element" ); + + div = jQuery( "
        " ); + div.attr( "id" ); + + assert.strictEqual( div.clone( true ).attr( "id", "test" )[ 0 ].id, "test", "Id attribute should be changed on cloned element" ); + + input = jQuery( "" ); + input.attr( "value" ); + + assert.strictEqual( input.clone( true ).attr( "value", "test" )[ 0 ].value, "test", "Value attribute should be changed on cloned element" ); + + assert.strictEqual( input.clone( true ).attr( "value", 42 )[ 0 ].value, "42", "Value attribute should be changed on cloned element" ); +} ); + +QUnit.test( "attr(String) in XML Files", function( assert ) { + assert.expect( 3 ); + var xml = createDashboardXML(); + assert.equal( jQuery( "locations", xml ).attr( "class" ), "foo", "Check class attribute in XML document" ); + assert.equal( jQuery( "location", xml ).attr( "for" ), "bar", "Check for attribute in XML document" ); + assert.equal( jQuery( "location", xml ).attr( "checked" ), "different", "Check that hooks are not attached in XML document" ); +} ); + +QUnit.test( "attr(String, Function)", function( assert ) { + assert.expect( 2 ); + + assert.equal( + jQuery( "#text1" ).attr( "value", function() { + return this.id; + } ).attr( "value" ), + "text1", + "Set value from id" + ); + + assert.equal( + jQuery( "#text1" ).attr( "title", function( i ) { + return i; + } ).attr( "title" ), + "0", + "Set value with an index" + ); +} ); + +QUnit.test( "attr(Hash)", function( assert ) { + assert.expect( 3 ); + var pass = true; + jQuery( "div" ).attr( { + "foo": "baz", + "zoo": "ping" + } ).each( function() { + if ( this.getAttribute( "foo" ) !== "baz" && this.getAttribute( "zoo" ) !== "ping" ) { + pass = false; + } + } ); + + assert.ok( pass, "Set Multiple Attributes" ); + + assert.equal( + jQuery( "#text1" ).attr( { + "value": function() { + return this[ "id" ]; + } } ).attr( "value" ), + "text1", + "Set attribute to computed value #1" + ); + + assert.equal( + jQuery( "#text1" ).attr( { + "title": function( i ) { + return i; + } + } ).attr( "title" ), + "0", + "Set attribute to computed value #2" + ); +} ); + +QUnit.test( "attr(String, Object)", function( assert ) { + assert.expect( 71 ); + + var $input, $text, $details, + attributeNode, commentNode, textNode, obj, + table, td, j, type, + check, thrown, button, $radio, $radios, $svg, + div = jQuery( "div" ).attr( "foo", "bar" ), + i = 0, + fail = false; + + for ( ; i < div.length; i++ ) { + if ( div[ i ].getAttribute( "foo" ) !== "bar" ) { + fail = i; + break; + } + } + + assert.equal( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" ); + + assert.ok( + jQuery( "#foo" ).attr( { + "width": null + } ), + "Try to set an attribute to nothing" + ); + + jQuery( "#name" ).attr( "name", "something" ); + assert.equal( jQuery( "#name" ).attr( "name" ), "something", "Set name attribute" ); + jQuery( "#name" ).attr( "name", null ); + assert.equal( jQuery( "#name" ).attr( "name" ), undefined, "Remove name attribute" ); + + $input = jQuery( "", { + name: "something", + id: "specified" + } ); + assert.equal( $input.attr( "name" ), "something", "Check element creation gets/sets the name attribute." ); + assert.equal( $input.attr( "id" ), "specified", "Check element creation gets/sets the id attribute." ); + + // As of fixing #11115, we only guarantee boolean property update for checked and selected + $input = jQuery( "" ).attr( "checked", true ); + assert.equal( $input.prop( "checked" ), true, "Setting checked updates property (verified by .prop)" ); + assert.equal( $input[ 0 ].checked, true, "Setting checked updates property (verified by native property)" ); + $input = jQuery( "" ); + $select1.val( valueObj( 4 ) ); + assert.equal( $select1.val(), "4", "Should be possible to set the val() to a newly created option" ); + + // using contents will get comments regular, text, and comment nodes + j = jQuery( "#nonnodes" ).contents(); + j.val( valueObj( "asdf" ) ); + assert.equal( j.val(), "asdf", "Check node,textnode,comment with val()" ); + j.removeAttr( "value" ); + + $select.val( valueObj( [ "1", "2" ] ) ); + assert.deepEqual( $select.val(), [ "1", "2" ], "Should set array of values" ); +}; + +QUnit.test( "val(String/Number)", function( assert ) { + testVal( bareObj, assert ); +} ); + +QUnit.test( "val(Function)", function( assert ) { + testVal( functionReturningObj, assert ); +} ); + +QUnit.test( "val(Array of Numbers) (Bug #7123)", function( assert ) { + assert.expect( 4 ); + jQuery( "#form" ).append( "" ); + var elements = jQuery( "input[name=arrayTest]" ).val( [ 1, 2 ] ); + assert.ok( elements[ 0 ].checked, "First element was checked" ); + assert.ok( elements[ 1 ].checked, "Second element was checked" ); + assert.ok( !elements[ 2 ].checked, "Third element was unchecked" ); + assert.ok( !elements[ 3 ].checked, "Fourth element remained unchecked" ); + + elements.remove(); +} ); + +QUnit.test( "val(Function) with incoming value", function( assert ) { + assert.expect( 10 ); + + var oldVal = jQuery( "#text1" ).val(); + + jQuery( "#text1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); + return "test"; + } ); + + assert.equal( document.getElementById( "text1" ).value, "test", "Check for modified (via val(String)) value of input element" ); + + oldVal = jQuery( "#text1" ).val(); + + jQuery( "#text1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); + return 67; + } ); + + assert.equal( document.getElementById( "text1" ).value, "67", "Check for modified (via val(Number)) value of input element" ); + + oldVal = jQuery( "#select1" ).val(); + + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); + return "3"; + } ); + + assert.equal( jQuery( "#select1" ).val(), "3", "Check for modified (via val(String)) value of select element" ); + + oldVal = jQuery( "#select1" ).val(); + + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); + return 2; + } ); + + assert.equal( jQuery( "#select1" ).val(), "2", "Check for modified (via val(Number)) value of select element" ); + + jQuery( "#select1" ).append( "" ); + + oldVal = jQuery( "#select1" ).val(); + + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); + return 4; + } ); + + assert.equal( jQuery( "#select1" ).val(), "4", "Should be possible to set the val() to a newly created option" ); +} ); + +// testing if a form.reset() breaks a subsequent call to a select element's .val() (in IE only) +QUnit.test( "val(select) after form.reset() (Bug #2551)", function( assert ) { + assert.expect( 3 ); + + jQuery( "
        " ).appendTo( "#qunit-fixture" ); + + jQuery( "#kkk" ).val( "gf" ); + + document[ "kk" ].reset(); + + assert.equal( jQuery( "#kkk" )[ 0 ].value, "cf", "Check value of select after form reset." ); + assert.equal( jQuery( "#kkk" ).val(), "cf", "Check value of select after form reset." ); + + // re-verify the multi-select is not broken (after form.reset) by our fix for single-select + assert.deepEqual( jQuery( "#select3" ).val(), [ "1", "2" ], "Call val() on a multiple='multiple' select" ); + + jQuery( "#kk" ).remove(); +} ); + +var testAddClass = function( valueObj, assert ) { + assert.expect( 9 ); + + var pass, j, i, + div = jQuery( "#qunit-fixture div" ); + div.addClass( valueObj( "test" ) ); + pass = true; + for ( i = 0; i < div.length; i++ ) { + if ( !~div.get( i ).className.indexOf( "test" ) ) { + pass = false; + } + } + assert.ok( pass, "Add Class" ); + + // using contents will get regular, text, and comment nodes + j = jQuery( "#nonnodes" ).contents(); + j.addClass( valueObj( "asdf" ) ); + assert.ok( j.hasClass( "asdf" ), "Check node,textnode,comment for addClass" ); + + div = jQuery( "
        " ); + + div.addClass( valueObj( "test" ) ); + assert.equal( div.attr( "class" ), "test", "Make sure there's no extra whitespace." ); + + div.attr( "class", " foo" ); + div.addClass( valueObj( "test" ) ); + assert.equal( div.attr( "class" ), "foo test", "Make sure there's no extra whitespace." ); + + div.attr( "class", "foo" ); + div.addClass( valueObj( "bar baz" ) ); + assert.equal( div.attr( "class" ), "foo bar baz", "Make sure there isn't too much trimming." ); + + div.removeClass(); + div.addClass( valueObj( "foo" ) ).addClass( valueObj( "foo" ) ); + assert.equal( div.attr( "class" ), "foo", "Do not add the same class twice in separate calls." ); + + div.addClass( valueObj( "fo" ) ); + assert.equal( div.attr( "class" ), "foo fo", "Adding a similar class does not get interrupted." ); + div.removeClass().addClass( "wrap2" ); + assert.ok( div.addClass( "wrap" ).hasClass( "wrap" ), "Can add similarly named classes" ); + + div.removeClass(); + div.addClass( valueObj( "bar bar" ) ); + assert.equal( div.attr( "class" ), "bar", "Do not add the same class twice in the same call." ); +}; + +QUnit.test( "addClass(String)", function( assert ) { + testAddClass( bareObj, assert ); +} ); + +QUnit.test( "addClass(Function)", function( assert ) { + testAddClass( functionReturningObj, assert ); +} ); + +QUnit.test( "addClass(Function) with incoming value", function( assert ) { + assert.expect( 52 ); + var pass, i, + div = jQuery( "#qunit-fixture div" ), + old = div.map( function() { + return jQuery( this ).attr( "class" ) || ""; + } ); + + div.addClass( function( i, val ) { + if ( this.id !== "_firebugConsole" ) { + assert.equal( val, old[ i ], "Make sure the incoming value is correct." ); + return "test"; + } + } ); + + pass = true; + for ( i = 0; i < div.length; i++ ) { + if ( div.get( i ).className.indexOf( "test" ) === -1 ) { + pass = false; + } + } + assert.ok( pass, "Add Class" ); +} ); + +var testRemoveClass = function( valueObj, assert ) { + assert.expect( 8 ); + + var $set = jQuery( "#qunit-fixture div" ), + div = document.createElement( "div" ); + + $set.addClass( "test" ).removeClass( valueObj( "test" ) ); + + assert.ok( !$set.is( ".test" ), "Remove Class" ); + + $set.addClass( "test" ).addClass( "foo" ).addClass( "bar" ); + $set.removeClass( valueObj( "test" ) ).removeClass( valueObj( "bar" ) ).removeClass( valueObj( "foo" ) ); + + assert.ok( !$set.is( ".test,.bar,.foo" ), "Remove multiple classes" ); + + // Make sure that a null value doesn't cause problems + $set.eq( 0 ).addClass( "expected" ).removeClass( valueObj( null ) ); + assert.ok( $set.eq( 0 ).is( ".expected" ), "Null value passed to removeClass" ); + + $set.eq( 0 ).addClass( "expected" ).removeClass( valueObj( "" ) ); + assert.ok( $set.eq( 0 ).is( ".expected" ), "Empty string passed to removeClass" ); + + // using contents will get regular, text, and comment nodes + $set = jQuery( "#nonnodes" ).contents(); + $set.removeClass( valueObj( "asdf" ) ); + assert.ok( !$set.hasClass( "asdf" ), "Check node,textnode,comment for removeClass" ); + + jQuery( div ).removeClass( valueObj( "foo" ) ); + assert.strictEqual( jQuery( div ).attr( "class" ), undefined, "removeClass doesn't create a class attribute" ); + + div.className = " test foo "; + + jQuery( div ).removeClass( valueObj( "foo" ) ); + assert.equal( div.className, "test", "Make sure remaining className is trimmed." ); + + div.className = " test "; + + jQuery( div ).removeClass( valueObj( "test" ) ); + assert.equal( div.className, "", "Make sure there is nothing left after everything is removed." ); +}; + +QUnit.test( "removeClass(String) - simple", function( assert ) { + testRemoveClass( bareObj, assert ); +} ); + +QUnit.test( "removeClass(Function) - simple", function( assert ) { + testRemoveClass( functionReturningObj, assert ); +} ); + +QUnit.test( "removeClass(Function) with incoming value", function( assert ) { + assert.expect( 52 ); + + var $divs = jQuery( "#qunit-fixture div" ).addClass( "test" ), old = $divs.map( function() { + return jQuery( this ).attr( "class" ); + } ); + + $divs.removeClass( function( i, val ) { + if ( this.id !== "_firebugConsole" ) { + assert.equal( val, old[ i ], "Make sure the incoming value is correct." ); + return "test"; + } + } ); + + assert.ok( !$divs.is( ".test" ), "Remove Class" ); +} ); + +QUnit.test( "removeClass() removes duplicates", function( assert ) { + assert.expect( 1 ); + + var $div = jQuery( jQuery.parseHTML( "
        " ) ); + + $div.removeClass( "x" ); + + assert.ok( !$div.hasClass( "x" ), "Element with multiple same classes does not escape the wrath of removeClass()" ); +} ); + +QUnit.test( "removeClass(undefined) is a no-op", function( assert ) { + assert.expect( 1 ); + + var $div = jQuery( "
        " ); + $div.removeClass( undefined ); + + assert.ok( $div.hasClass( "base" ) && $div.hasClass( "second" ), "Element still has classes after removeClass(undefined)" ); +} ); + +var testToggleClass = function( valueObj, assert ) { + assert.expect( 19 ); + + var e = jQuery( "#firstp" ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + e.toggleClass( valueObj( "test" ) ); + assert.ok( e.is( ".test" ), "Assert class present" ); + e.toggleClass( valueObj( "test" ) ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + + // class name with a boolean + e.toggleClass( valueObj( "test" ), false ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + e.toggleClass( valueObj( "test" ), false ); + assert.ok( !e.is( ".test" ), "Assert class still not present" ); + e.toggleClass( valueObj( "test" ), true ); + assert.ok( e.is( ".test" ), "Assert class present" ); + e.toggleClass( valueObj( "test" ), true ); + assert.ok( e.is( ".test" ), "Assert class still present" ); + e.toggleClass( valueObj( "test" ), false ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + + // multiple class names + e.addClass( "testA testB" ); + assert.ok( e.is( ".testA.testB" ), "Assert 2 different classes present" ); + e.toggleClass( valueObj( "testB testC" ) ); + assert.ok( ( e.is( ".testA.testC" ) && !e.is( ".testB" ) ), "Assert 1 class added, 1 class removed, and 1 class kept" ); + e.toggleClass( valueObj( "testA testC" ) ); + assert.ok( ( !e.is( ".testA" ) && !e.is( ".testB" ) && !e.is( ".testC" ) ), "Assert no class present" ); + + // toggleClass storage + e.toggleClass( true ); + assert.ok( e[ 0 ].className === "", "Assert class is empty (data was empty)" ); + e.addClass( "testD testE" ); + assert.ok( e.is( ".testD.testE" ), "Assert class present" ); + e.toggleClass(); + assert.ok( !e.is( ".testD.testE" ), "Assert class not present" ); + assert.ok( jQuery._data( e[ 0 ], "__className__" ) === "testD testE", "Assert data was stored" ); + e.toggleClass(); + assert.ok( e.is( ".testD.testE" ), "Assert class present (restored from data)" ); + e.toggleClass( false ); + assert.ok( !e.is( ".testD.testE" ), "Assert class not present" ); + e.toggleClass( true ); + assert.ok( e.is( ".testD.testE" ), "Assert class present (restored from data)" ); + e.toggleClass(); + e.toggleClass( false ); + e.toggleClass(); + assert.ok( e.is( ".testD.testE" ), "Assert class present (restored from data)" ); + + // Cleanup + e.removeClass( "testD" ); + assert.expectJqData( this, e[ 0 ], "__className__" ); +}; + +QUnit.test( "toggleClass(String|boolean|undefined[, boolean])", function( assert ) { + testToggleClass( bareObj, assert ); +} ); + +QUnit.test( "toggleClass(Function[, boolean])", function( assert ) { + testToggleClass( functionReturningObj, assert ); +} ); + +QUnit.test( "toggleClass(Function[, boolean]) with incoming value", function( assert ) { + assert.expect( 14 ); + + var e = jQuery( "#firstp" ), + old = e.attr( "class" ) || ""; + + assert.ok( !e.is( ".test" ), "Assert class not present" ); + + e.toggleClass( function( i, val ) { + assert.equal( old, val, "Make sure the incoming value is correct." ); + return "test"; + } ); + assert.ok( e.is( ".test" ), "Assert class present" ); + + old = e.attr( "class" ); + + e.toggleClass( function( i, val ) { + assert.equal( old, val, "Make sure the incoming value is correct." ); + return "test"; + } ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + + old = e.attr( "class" ) || ""; + + // class name with a boolean + e.toggleClass( function( i, val, state ) { + assert.equal( old, val, "Make sure the incoming value is correct." ); + assert.equal( state, false, "Make sure that the state is passed in." ); + return "test"; + }, false ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); + + old = e.attr( "class" ) || ""; + + e.toggleClass( function( i, val, state ) { + assert.equal( old, val, "Make sure the incoming value is correct." ); + assert.equal( state, true, "Make sure that the state is passed in." ); + return "test"; + }, true ); + assert.ok( e.is( ".test" ), "Assert class present" ); + + old = e.attr( "class" ); + + e.toggleClass( function( i, val, state ) { + assert.equal( old, val, "Make sure the incoming value is correct." ); + assert.equal( state, false, "Make sure that the state is passed in." ); + return "test"; + }, false ); + assert.ok( !e.is( ".test" ), "Assert class not present" ); +} ); + +QUnit.test( "addClass, removeClass, hasClass", function( assert ) { + assert.expect( 17 ); + + var jq = jQuery( "

        Hi

        " ), x = jq[ 0 ]; + + jq.addClass( "hi" ); + assert.equal( x.className, "hi", "Check single added class" ); + + jq.addClass( "foo bar" ); + assert.equal( x.className, "hi foo bar", "Check more added classes" ); + + jq.removeClass(); + assert.equal( x.className, "", "Remove all classes" ); + + jq.addClass( "hi foo bar" ); + jq.removeClass( "foo" ); + assert.equal( x.className, "hi bar", "Check removal of one class" ); + + assert.ok( jq.hasClass( "hi" ), "Check has1" ); + assert.ok( jq.hasClass( "bar" ), "Check has2" ); + + jq = jQuery( "

        " ); + + assert.ok( jq.hasClass( "class1" ), "Check hasClass with line feed" ); + assert.ok( jq.is( ".class1" ), "Check is with line feed" ); + assert.ok( jq.hasClass( "class2" ), "Check hasClass with tab" ); + assert.ok( jq.is( ".class2" ), "Check is with tab" ); + assert.ok( jq.hasClass( "cla.ss3" ), "Check hasClass with dot" ); + assert.ok( jq.hasClass( "class4" ), "Check hasClass with carriage return" ); + assert.ok( jq.is( ".class4" ), "Check is with carriage return" ); + + jq.removeClass( "class2" ); + assert.ok( jq.hasClass( "class2" ) === false, "Check the class has been properly removed" ); + jq.removeClass( "cla" ); + assert.ok( jq.hasClass( "cla.ss3" ), "Check the dotted class has not been removed" ); + jq.removeClass( "cla.ss3" ); + assert.ok( jq.hasClass( "cla.ss3" ) === false, "Check the dotted class has been removed" ); + jq.removeClass( "class4" ); + assert.ok( jq.hasClass( "class4" ) === false, "Check the class has been properly removed" ); +} ); + +QUnit.test( "addClass, removeClass, hasClass on many elements", function( assert ) { + assert.expect( 19 ); + + var elem = jQuery( "

        p0

        p1

        p2

        " ); + + elem.addClass( "hi" ); + assert.equal( elem[ 0 ].className, "hi", "Check single added class" ); + assert.equal( elem[ 1 ].className, "hi", "Check single added class" ); + assert.equal( elem[ 2 ].className, "hi", "Check single added class" ); + + elem.addClass( "foo bar" ); + assert.equal( elem[ 0 ].className, "hi foo bar", "Check more added classes" ); + assert.equal( elem[ 1 ].className, "hi foo bar", "Check more added classes" ); + assert.equal( elem[ 2 ].className, "hi foo bar", "Check more added classes" ); + + elem.removeClass(); + assert.equal( elem[ 0 ].className, "", "Remove all classes" ); + assert.equal( elem[ 1 ].className, "", "Remove all classes" ); + assert.equal( elem[ 2 ].className, "", "Remove all classes" ); + + elem.addClass( "hi foo bar" ); + elem.removeClass( "foo" ); + assert.equal( elem[ 0 ].className, "hi bar", "Check removal of one class" ); + assert.equal( elem[ 1 ].className, "hi bar", "Check removal of one class" ); + assert.equal( elem[ 2 ].className, "hi bar", "Check removal of one class" ); + + assert.ok( elem.hasClass( "hi" ), "Check has1" ); + assert.ok( elem.hasClass( "bar" ), "Check has2" ); + + assert.ok( jQuery( "

        p0

        p1

        p2

        " ).hasClass( "hi" ), + "Did find a class in the first element" ); + assert.ok( jQuery( "

        p0

        p1

        p2

        " ).hasClass( "hi" ), + "Did find a class in the second element" ); + assert.ok( jQuery( "

        p0

        p1

        p2

        " ).hasClass( "hi" ), + "Did find a class in the last element" ); + + assert.ok( jQuery( "

        p0

        p1

        p2

        " ).hasClass( "hi" ), + "Did find a class when present in all elements" ); + + assert.ok( !jQuery( "

        p0

        p1

        p2

        " ).hasClass( "hi" ), + "Did not find a class when not present" ); +} ); + +QUnit.test( "contents().hasClass() returns correct values", function( assert ) { + assert.expect( 2 ); + + var $div = jQuery( "
        text
        " ), + $contents = $div.contents(); + + assert.ok( $contents.hasClass( "foo" ), "Found 'foo' in $contents" ); + assert.ok( !$contents.hasClass( "undefined" ), "Did not find 'undefined' in $contents (correctly)" ); +} ); + +QUnit.test( "hasClass correctly interprets non-space separators (#13835)", function( assert ) { + assert.expect( 4 ); + + var + map = { + tab: " ", + "line-feed": " ", + "form-feed": " ", + "carriage-return": " " + }, + classes = jQuery.map( map, function( separator, label ) { + return " " + separator + label + separator + " "; + } ), + $div = jQuery( "
        " ); + + jQuery.each( map, function( label ) { + assert.ok( $div.hasClass( label ), label.replace( "-", " " ) ); + } ); +} ); + +QUnit.test( "coords returns correct values in IE6/IE7, see #10828", function( assert ) { + assert.expect( 1 ); + + var area, + map = jQuery( "" ); + + area = map.html( "a" ).find( "area" ); + assert.equal( area.attr( "coords" ), "0,0,0,0", "did not retrieve coords correctly" ); +} ); + +QUnit.test( "should not throw at $(option).val() (#14686)", function( assert ) { + assert.expect( 1 ); + + try { + jQuery( "" ).val(); + assert.equal( val.length, 0, "Empty option should have no value" ); + + val = jQuery( "" ).val(); + assert.equal( val.length, 0, "insignificant white-space returned for value" ); + + val = jQuery( "" ).val(); + assert.equal( val.length, 4, "insignificant white-space returned for value" ); +} ); + +QUnit.test( "SVG class manipulation (gh-2199)", function( assert ) { + assert.expect( 12 ); + + function createSVGElement( nodeName ) { + return document.createElementNS( "http://www.w3.org/2000/svg", nodeName ); + } + + jQuery.each( [ + "svg", + "rect", + "g" + ], function() { + var elem = jQuery( createSVGElement( this ) ); + + elem.addClass( "awesome" ); + assert.ok( elem.hasClass( "awesome" ), "SVG element (" + this + ") has added class" ); + + elem.removeClass( "awesome" ); + assert.ok( !elem.hasClass( "awesome" ), "SVG element (" + this + ") removes the class" ); + + elem.toggleClass( "awesome" ); + assert.ok( elem.hasClass( "awesome" ), "SVG element (" + this + ") toggles the class on" ); + + elem.toggleClass( "awesome" ); + assert.ok( !elem.hasClass( "awesome" ), "SVG element (" + this + ") toggles the class off" ); + } ); +} ); diff --git a/dashboard-ui/bower_components/jquery/test/unit/basic.js b/dashboard-ui/bower_components/jquery/test/unit/basic.js new file mode 100644 index 0000000000..25e86d1a35 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/basic.js @@ -0,0 +1,302 @@ +QUnit.module( "basic", { teardown: moduleTeardown } ); + +if ( jQuery.ajax ) { +QUnit.test( "ajax", function( assert ) { + assert.expect( 4 ); + + var done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); + + jQuery.ajax( { + type: "GET", + url: url( "data/name.php?name=foo" ), + success: function( msg ) { + assert.strictEqual( msg, "bar", "Check for GET" ); + done.pop()(); + } + } ); + + jQuery.ajax( { + type: "POST", + url: url( "data/name.php" ), + data: "name=peter", + success: function( msg ) { + assert.strictEqual( msg, "pan", "Check for POST" ); + done.pop()(); + } + } ); + + jQuery( "#first" ).load( url( "data/name.html" ), function() { + assert.ok( /^ERROR/.test( jQuery( "#first" ).text() ), + "Check if content was injected into the DOM" ); + done.pop()(); + } ); +} ); +} + +QUnit.test( "attributes", function( assert ) { + assert.expect( 6 ); + + var a = jQuery( "" ).appendTo( "#qunit-fixture" ), + input = jQuery( "" ).appendTo( "#qunit-fixture" ); + + assert.strictEqual( a.attr( "foo", "bar" ).attr( "foo" ), "bar", ".attr getter/setter" ); + assert.strictEqual( a.removeAttr( "foo" ).attr( "foo" ), undefined, ".removeAttr" ); + assert.strictEqual( a.prop( "href", "#5" ).prop( "href" ), + location.href.replace( /\#.*$/, "" ) + "#5", + ".prop getter/setter" ); + + a.addClass( "abc def ghj" ).removeClass( "def ghj" ); + assert.strictEqual( a.hasClass( "abc" ), true, ".(add|remove|has)Class, class present" ); + assert.strictEqual( a.hasClass( "def" ), false, ".(add|remove|has)Class, class missing" ); + + assert.strictEqual( input.val( "xyz" ).val(), "xyz", ".val getter/setter" ); +} ); + +if ( jQuery.css ) { +QUnit.test( "css", function( assert ) { + assert.expect( 3 ); + + var div = jQuery( "
        " ).appendTo( "#qunit-fixture" ); + + assert.strictEqual( div.css( "width", "50px" ).css( "width" ), "50px", ".css getter/setter" ); + + div.hide(); + assert.strictEqual( div.css( "display" ), "none", "div hidden" ); + div.show(); + assert.strictEqual( div.css( "display" ), "block", "div shown" ); +} ); +} + +QUnit.test( "core", function( assert ) { + assert.expect( 28 ); + + var elem = jQuery( "
        " ); + + assert.strictEqual( elem.length, 2, "Correct number of elements" ); + assert.strictEqual( jQuery.trim( " hello " ), "hello", "jQuery.trim" ); + + assert.strictEqual( jQuery.type( null ), "null", "jQuery.type(null)" ); + assert.strictEqual( jQuery.type( undefined ), "undefined", "jQuery.type(undefined)" ); + assert.strictEqual( jQuery.type( "a" ), "string", "jQuery.type(String)" ); + + assert.ok( jQuery.isPlainObject( { "a": 2 } ), "jQuery.isPlainObject(object)" ); + assert.ok( !jQuery.isPlainObject( "foo" ), "jQuery.isPlainObject(String)" ); + + assert.ok( jQuery.isFunction( jQuery.noop ), "jQuery.isFunction(jQuery.noop)" ); + assert.ok( !jQuery.isFunction( 2 ), "jQuery.isFunction(Number)" ); + + assert.ok( jQuery.isNumeric( "-2" ), "jQuery.isNumeric(String representing a number)" ); + assert.ok( !jQuery.isNumeric( "" ), "jQuery.isNumeric(\"\")" ); + + assert.ok( jQuery.isXMLDoc( jQuery.parseXML( + "" + ) ), "jQuery.isXMLDoc" ); + + assert.ok( jQuery.isWindow( window ), "jQuery.isWindow(window)" ); + assert.ok( !jQuery.isWindow( 2 ), "jQuery.isWindow(Number)" ); + + assert.strictEqual( jQuery.inArray( 3, [ "a", 6, false, 3, {} ] ), 3, "jQuery.inArray - true" ); + assert.strictEqual( + jQuery.inArray( 3, [ "a", 6, false, "3", {} ] ), + -1, + "jQuery.inArray - false" + ); + + assert.strictEqual( elem.get( 1 ), elem[ 1 ], ".get" ); + assert.strictEqual( elem.first()[ 0 ], elem[ 0 ], ".first" ); + assert.strictEqual( elem.last()[ 0 ], elem[ 1 ], ".last" ); + + assert.deepEqual( jQuery.map( [ "a", "b", "c" ], function( v, k ) { + return k + v; + } ), [ "0a", "1b", "2c" ], "jQuery.map" ); + + assert.deepEqual( jQuery.merge( [ 1, 2 ], [ "a", "b" ] ), [ 1, 2, "a", "b" ], "jQuery.merge" ); + + assert.deepEqual( jQuery.grep( [ 1, 2, 3 ], function( value ) { + return value % 2 !== 0; + } ), [ 1, 3 ], "jQuery.grep" ); + + assert.deepEqual( jQuery.extend( { a: 2 }, { b: 3 } ), { a: 2, b: 3 }, "jQuery.extend" ); + + jQuery.each( [ 0, 2 ], function( k, v ) { + assert.strictEqual( k * 2, v, "jQuery.each" ); + } ); + + assert.deepEqual( jQuery.makeArray( { 0: "a", 1: "b", 2: "c", length: 3 } ), + [ "a", "b", "c" ], "jQuery.makeArray" ); + + assert.strictEqual( jQuery.parseHTML( "
        " ).length, + 2, "jQuery.parseHTML" ); + + assert.deepEqual( jQuery.parseJSON( "{\"a\": 2}" ), { a: 2 }, "jQuery.parseJON" ); +} ); + +QUnit.test( "data", function( assert ) { + assert.expect( 4 ); + + var elem = jQuery( "
        " ).appendTo( "#qunit-fixture" ); + + assert.ok( !jQuery.hasData( elem[ 0 ] ), "jQuery.hasData - false" ); + assert.strictEqual( elem.data( "a", "b" ).data( "a" ), "b", ".data getter/setter" ); + assert.strictEqual( elem.data( "c" ), "d", ".data from data-* attributes" ); + assert.ok( jQuery.hasData( elem[ 0 ] ), "jQuery.hasData - true" ); +} ); + +QUnit.test( "dimensions", function( assert ) { + assert.expect( 3 ); + + var elem = jQuery( + "
        " + ).appendTo( "#qunit-fixture" ); + + assert.strictEqual( elem.width( 50 ).width(), 50, ".width getter/setter" ); + assert.strictEqual( elem.innerWidth(), 64, ".innerWidth getter" ); + assert.strictEqual( elem.outerWidth(), 68, ".outerWidth getter" ); +} ); + +QUnit.test( "event", function( assert ) { + assert.expect( 1 ); + + var elem = jQuery( "
        " ).appendTo( "#qunit-fixture" ); + + elem + .on( "click", function() { + assert.ok( false, "click should not fire" ); + } ) + .off( "click" ) + .trigger( "click" ) + .on( "click", function() { + assert.ok( true, "click should fire" ); + } ) + .trigger( "click" ); +} ); + +QUnit.test( "manipulation", function( assert ) { + assert.expect( 5 ); + + var child, + elem1 = jQuery( "
        " ).appendTo( "#qunit-fixture" ), + elem2 = jQuery( "
        " ).appendTo( "#qunit-fixture" ); + + assert.strictEqual( elem1.text( "foo" ).text(), "foo", ".html getter/setter" ); + + assert.strictEqual( + + // Support: IE 8 only + // IE 8 prints tag names in upper case. + elem1.html( "" ).html().toLowerCase(), + "", + ".html getter/setter" + ); + + assert.strictEqual( elem1.append( elem2 )[ 0 ].childNodes[ 1 ], elem2[ 0 ], ".append" ); + assert.strictEqual( elem1.prepend( elem2 )[ 0 ].childNodes[ 0 ], elem2[ 0 ], ".prepend" ); + + child = elem1.find( "span" ); + child.after( "" ); + child.before( "" ); + + assert.strictEqual( + + // Support: IE 8 only + // IE 8 prints tag names in upper case. + elem1.html().toLowerCase(), + "
        ", + ".after/.before" + ); +} ); + +QUnit.test( "offset", function( assert ) { + assert.expect( 3 ); + + var parent = jQuery( "
        " ).appendTo( "#qunit-fixture" ), + elem = jQuery( "
        " ).appendTo( parent ); + + assert.strictEqual( elem.offset().top, 25, ".offset getter" ); + assert.strictEqual( elem.position().top, 5, ".position getter" ); + assert.strictEqual( elem.offsetParent()[ 0 ], parent[ 0 ], ".offsetParent" ); +} ); + +QUnit.test( "selector", function( assert ) { + assert.expect( 2 ); + + var elem = jQuery( "
        " ) + .appendTo( "#qunit-fixture" ); + + assert.strictEqual( elem.find( ".a a" ).length, 0, ".find - no result" ); + assert.strictEqual( elem.find( "span.b a" )[ 0 ].nodeName, "A", ".find - one result" ); +} ); + +QUnit.test( "serialize", function( assert ) { + assert.expect( 2 ); + + var params = { "someName": [ 1, 2, 3 ], "regularThing": "blah" }; + assert.strictEqual( jQuery.param( params ), + "someName%5B%5D=1&someName%5B%5D=2&someName%5B%5D=3®ularThing=blah", + "jQuery.param" ); + + assert.strictEqual( jQuery( "#form" ).serialize(), + "action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search" + + "&select1=&select2=3&select3=1&select3=2&select5=3", + "form serialization as query string" ); +} ); + +QUnit.test( "traversing", function( assert ) { + assert.expect( 12 ); + + var elem = jQuery( "
        foo
        " ) + .appendTo( "#qunit-fixture" ); + + assert.strictEqual( elem.find( "em" ).parent()[ 0 ].nodeName, "B", ".parent" ); + assert.strictEqual( elem.find( "em" ).parents()[ 1 ].nodeName, "A", ".parents" ); + assert.strictEqual( elem.find( "em" ).parentsUntil( "div" ).length, 2, ".parentsUntil" ); + assert.strictEqual( elem.find( "i" ).next()[ 0 ].nodeName, "SPAN", ".next" ); + assert.strictEqual( elem.find( "i" ).prev()[ 0 ].nodeName, "A", ".prev" ); + assert.strictEqual( elem.find( "a" ).nextAll()[ 1 ].nodeName, "SPAN", ".nextAll" ); + assert.strictEqual( elem.find( "span" ).prevAll()[ 1 ].nodeName, "A", ".prevAll" ); + assert.strictEqual( elem.find( "a" ).nextUntil( "span" ).length, 1, ".nextUntil" ); + assert.strictEqual( elem.find( "span" ).prevUntil( "a" ).length, 1, ".prevUntil" ); + assert.strictEqual( elem.find( "i" ).siblings().length, 2, ".siblings" ); + assert.strictEqual( elem.children()[ 2 ].nodeName, "SPAN", ".children" ); + assert.strictEqual( elem.contents()[ 3 ].nodeType, 3, ".contents" ); +} ); + +QUnit.test( "wrap", function( assert ) { + assert.expect( 3 ); + + var elem = jQuery( "
        " ); + + elem.find( "b" ).wrap( "" ); + + assert.strictEqual( + + // Support: IE 8 only + // IE 8 prints tag names in upper case. + elem.html().toLowerCase(), + "", + ".wrap" + ); + + elem.find( "span" ).wrapInner( "" ); + + assert.strictEqual( + + // Support: IE 8 only + // IE 8 prints tag names in upper case. + elem.html().toLowerCase(), + "", + ".wrapInner" + ); + + elem.find( "a" ).wrapAll( "" ); + + assert.strictEqual( + + // Support: IE 8 only + // IE 8 prints tag names in upper case. + elem.html().toLowerCase(), + "", + ".wrapAll" + ); + +} ); diff --git a/dashboard-ui/bower_components/jquery/test/unit/callbacks.js b/dashboard-ui/bower_components/jquery/test/unit/callbacks.js new file mode 100644 index 0000000000..0bae02a876 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/callbacks.js @@ -0,0 +1,358 @@ +QUnit.module( "callbacks", { + teardown: moduleTeardown +} ); + +( function() { + +var output, + addToOutput = function( string ) { + return function() { + output += string; + }; + }, + outputA = addToOutput( "A" ), + outputB = addToOutput( "B" ), + outputC = addToOutput( "C" ), + tests = { + "": "XABC X XABCABCC X XBB X XABA X XX", + "once": "XABC X X X X X XABA X XX", + "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC XX", + "unique": "XABC X XABCA X XBB X XAB X X", + "stopOnFalse": "XABC X XABCABCC X XBB X XA X XX", + "once memory": "XABC XABC X XA X XA XABA XC XX", + "once unique": "XABC X X X X X XAB X X", + "once stopOnFalse": "XABC X X X X X XA X XX", + "memory unique": "XABC XA XABCA XA XBB XB XAB XC X", + "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X XX", + "unique stopOnFalse": "XABC X XABCA X XBB X XA X X" + }, + filters = { + "no filter": undefined, + "filter": function( fn ) { + return function() { + return fn.apply( this, arguments ); + }; + } + }; + + function showFlags( flags ) { + if ( typeof flags === "string" ) { + return "'" + flags + "'"; + } + var output = [], key; + for ( key in flags ) { + output.push( "'" + key + "': " + flags[ key ] ); + } + return "{ " + output.join( ", " ) + " }"; + } + +jQuery.each( tests, function( strFlags, resultString ) { + + var objectFlags = {}; + + jQuery.each( strFlags.split( " " ), function() { + if ( this.length ) { + objectFlags[ this ] = true; + } + } ); + + jQuery.each( filters, function( filterLabel ) { + + jQuery.each( { + "string": strFlags, + "object": objectFlags + }, function( flagsTypes, flags ) { + + QUnit.test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function( assert ) { + + assert.expect( 28 ); + + var cblist, + results = resultString.split( /\s+/ ); + + // Basic binding and firing + output = "X"; + cblist = jQuery.Callbacks( flags ); + assert.strictEqual( cblist.locked(), false, ".locked() initially false" ); + assert.strictEqual( cblist.disabled(), false, ".disabled() initially false" ); + assert.strictEqual( cblist.fired(), false, ".fired() initially false" ); + cblist.add(function( str ) { + output += str; + }); + assert.strictEqual( cblist.fired(), false, ".fired() still false after .add" ); + cblist.fire( "A" ); + assert.strictEqual( output, "XA", "Basic binding and firing" ); + assert.strictEqual( cblist.fired(), true, ".fired() detects firing" ); + output = "X"; + cblist.disable(); + cblist.add(function( str ) { + output += str; + }); + assert.strictEqual( output, "X", "Adding a callback after disabling" ); + cblist.fire("A"); + assert.strictEqual( output, "X", "Firing after disabling" ); + assert.strictEqual( cblist.disabled(), true, ".disabled() becomes true" ); + assert.strictEqual( cblist.locked(), true, "disabling locks" ); + + // Emptying while firing (#13517) + cblist = jQuery.Callbacks( flags ); + cblist.add( cblist.empty ); + cblist.add( function() { + assert.ok( false, "not emptied" ); + } ); + cblist.fire(); + + // Disabling while firing + cblist = jQuery.Callbacks( flags ); + cblist.add( cblist.disable ); + cblist.add( function() { + assert.ok( false, "not disabled" ); + } ); + cblist.fire(); + + // Basic binding and firing (context, arguments) + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add(function() { + assert.equal( this, window, "Basic binding and firing (context)" ); + output += Array.prototype.join.call( arguments, "" ); + }); + cblist.fireWith( window, [ "A", "B" ] ); + assert.strictEqual( output, "XAB", "Basic binding and firing (arguments)" ); + + // fireWith with no arguments + output = ""; + cblist = jQuery.Callbacks( flags ); + cblist.add(function() { + assert.equal( this, window, "fireWith with no arguments (context is window)" ); + assert.strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" ); + }); + cblist.fireWith(); + + // Basic binding, removing and firing + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add( outputA, outputB, outputC ); + cblist.remove( outputB, outputC ); + cblist.fire(); + assert.strictEqual( output, "XA", "Basic binding, removing and firing" ); + + // Empty + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add( outputA ); + cblist.add( outputB ); + cblist.add( outputC ); + cblist.empty(); + cblist.fire(); + assert.strictEqual( output, "X", "Empty" ); + + // Locking + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add(function( str ) { + output += str; + }); + cblist.lock(); + cblist.add(function( str ) { + output += str; + }); + cblist.fire("A"); + cblist.add(function( str ) { + output += str; + }); + assert.strictEqual( output, "X", "Lock early" ); + assert.strictEqual( cblist.locked(), true, "Locking reflected in accessor" ); + + // Ordering + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add(function() { + cblist.add( outputC ); + outputA(); + }, outputB ); + cblist.fire(); + assert.strictEqual( output, results.shift(), "Proper ordering" ); + + // Add and fire again + output = "X"; + cblist.add(function() { + cblist.add( outputC ); + outputA(); + }, outputB ); + assert.strictEqual( output, results.shift(), "Add after fire" ); + + output = "X"; + cblist.fire(); + assert.strictEqual( output, results.shift(), "Fire again" ); + + // Multiple fire + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add(function( str ) { + output += str; + }); + cblist.fire("A"); + assert.strictEqual( output, "XA", "Multiple fire (first fire)" ); + output = "X"; + cblist.add(function( str ) { + output += str; + }); + assert.strictEqual( output, results.shift(), "Multiple fire (first new callback)" ); + output = "X"; + cblist.fire("B"); + assert.strictEqual( output, results.shift(), "Multiple fire (second fire)" ); + output = "X"; + cblist.add(function( str ) { + output += str; + }); + assert.strictEqual( output, results.shift(), "Multiple fire (second new callback)" ); + + // Return false + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add( outputA, function() { return false; }, outputB ); + cblist.add( outputA ); + cblist.fire(); + assert.strictEqual( output, results.shift(), "Callback returning false" ); + + // Add another callback (to control lists with memory do not fire anymore) + output = "X"; + cblist.add( outputC ); + assert.strictEqual( output, results.shift(), "Adding a callback after one returned false" ); + + // Callbacks are not iterated + output = ""; + function handler() { + output += "X"; + } + handler.method = function() { + output += "!"; + }; + cblist = jQuery.Callbacks( flags ); + cblist.add( handler ); + cblist.add( handler ); + cblist.fire(); + assert.strictEqual( output, results.shift(), "No callback iteration" ); + } ); + } ); + } ); +} ); + +} )(); + +QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert ) { + + assert.expect( 1 ); + + var options = { + "unique": true + }, + cb = jQuery.Callbacks( options ), + count = 0, + fn = function() { + assert.ok( !( count++ ), "called once" ); + }; + options[ "unique" ] = false; + cb.add( fn, fn ); + cb.fire(); +} ); + +QUnit.test( "jQuery.Callbacks.fireWith - arguments are copied", function( assert ) { + + assert.expect( 1 ); + + var cb = jQuery.Callbacks( "memory" ), + args = [ "hello" ]; + + cb.fireWith( null, args ); + args[ 0 ] = "world"; + + cb.add( function( hello ) { + assert.strictEqual( hello, "hello", "arguments are copied internally" ); + } ); +} ); + +QUnit.test( "jQuery.Callbacks.remove - should remove all instances", function( assert ) { + + assert.expect( 1 ); + + var cb = jQuery.Callbacks(); + + function fn() { + assert.ok( false, "function wasn't removed" ); + } + + cb.add( fn, fn, function() { + assert.ok( true, "end of test" ); + } ).remove( fn ).fire(); +} ); + +QUnit.test( "jQuery.Callbacks.has", function( assert ) { + + assert.expect( 13 ); + + var cb = jQuery.Callbacks(); + function getA() { + return "A"; + } + function getB() { + return "B"; + } + function getC() { + return "C"; + } + cb.add( getA, getB, getC ); + assert.strictEqual( cb.has(), true, "No arguments to .has() returns whether callback function(s) are attached or not" ); + assert.strictEqual( cb.has( getA ), true, "Check if a specific callback function is in the Callbacks list" ); + + cb.remove( getB ); + assert.strictEqual( cb.has( getB ), false, "Remove a specific callback function and make sure its no longer there" ); + assert.strictEqual( cb.has( getA ), true, "Remove a specific callback function and make sure other callback function is still there" ); + + cb.empty(); + assert.strictEqual( cb.has(), false, "Empty list and make sure there are no callback function(s)" ); + assert.strictEqual( cb.has( getA ), false, "Check for a specific function in an empty() list" ); + + cb.add( getA, getB, function() { + assert.strictEqual( cb.has(), true, "Check if list has callback function(s) from within a callback function" ); + assert.strictEqual( cb.has( getA ), true, "Check if list has a specific callback from within a callback function" ); + } ).fire(); + + assert.strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" ); + + cb.disable(); + assert.strictEqual( cb.has(), false, "disabled() list has no callback functions (returns false)" ); + assert.strictEqual( cb.has( getA ), false, "Check for a specific function in a disabled() list" ); + + cb = jQuery.Callbacks( "unique" ); + cb.add( getA ); + cb.add( getA ); + assert.strictEqual( cb.has(), true, "Check if unique list has callback function(s) attached" ); + cb.lock(); + assert.strictEqual( cb.has(), false, "locked() list is empty and returns false" ); +} ); + +QUnit.test( "jQuery.Callbacks() - adding a string doesn't cause a stack overflow", function( assert ) { + + assert.expect( 1 ); + + jQuery.Callbacks().add( "hello world" ); + + assert.ok( true, "no stack overflow" ); +} ); + +QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", function( assert ) { + + assert.expect( 1 ); + + var cb = jQuery.Callbacks(), + fired = false, + shot = function() { fired = true; }; + + cb.disable(); + cb.empty(); + cb.add( shot ); + cb.fire(); + assert.ok( !fired, "Disabled callback function didn't fire" ); +} ); diff --git a/dashboard-ui/bower_components/jquery/test/unit/core.js b/dashboard-ui/bower_components/jquery/test/unit/core.js new file mode 100644 index 0000000000..a9e93989c5 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/core.js @@ -0,0 +1,1711 @@ +QUnit.module( "core", { teardown: moduleTeardown } ); + +QUnit.test( "Basic requirements", function( assert ) { + assert.expect( 7 ); + assert.ok( Array.prototype.push, "Array.push()" ); + assert.ok( Function.prototype.apply, "Function.apply()" ); + assert.ok( document.getElementById, "getElementById" ); + assert.ok( document.getElementsByTagName, "getElementsByTagName" ); + assert.ok( RegExp, "RegExp" ); + assert.ok( jQuery, "jQuery" ); + assert.ok( $, "$" ); +} ); + +QUnit.test( "jQuery()", function( assert ) { + + var elem, i, + obj = jQuery( "div" ), + code = jQuery( "" ), + img = jQuery( "" ), + div = jQuery( "

        " ), + exec = false, + expected = 23, + attrObj = { + "text": "test", + "class": "test2", + "id": "test3" + }; + + // The $(html, props) signature can stealth-call any $.fn method, check for a + // few here but beware of modular builds where these methods may be excluded. + if ( jQuery.fn.click ) { + expected++; + attrObj[ "click" ] = function() { assert.ok( exec, "Click executed." ); }; + } + if ( jQuery.fn.width ) { + expected++; + attrObj[ "width" ] = 10; + } + if ( jQuery.fn.offset ) { + expected++; + attrObj[ "offset" ] = { "top": 1, "left": 1 }; + } + if ( jQuery.fn.css ) { + expected += 2; + attrObj[ "css" ] = { "paddingLeft": 1, "paddingRight": 1 }; + } + if ( jQuery.fn.attr ) { + expected++; + attrObj.attr = { "desired": "very" }; + } + + assert.expect( expected ); + + // Basic constructor's behavior + assert.equal( jQuery().length, 0, "jQuery() === jQuery([])" ); + assert.equal( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" ); + assert.equal( jQuery(null).length, 0, "jQuery(null) === jQuery([])" ); + assert.equal( jQuery("").length, 0, "jQuery('') === jQuery([])" ); + assert.equal( jQuery("#").length, 0, "jQuery('#') === jQuery([])" ); + + assert.equal( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" ); + + // can actually yield more than one, when iframes are included, the window is an array as well + assert.equal( jQuery( window ).length, 1, "Correct number of elements generated for jQuery(window)" ); + +/* + // disabled since this test was doing nothing. i tried to fix it but i'm not sure + // what the expected behavior should even be. FF returns "\n" for the text node + // make sure this is handled + var crlfContainer = jQuery('

        \r\n

        '); + var x = crlfContainer.contents().get(0).nodeValue; + assert.equal( x, what???, "Check for \\r and \\n in jQuery()" ); +*/ + + /* // Disabled until we add this functionality in + var pass = true; + try { + jQuery("
        Testing
        ").appendTo(document.getElementById("iframe").contentDocument.body); + } catch(e){ + pass = false; + } + assert.ok( pass, "jQuery('<tag>') needs optional document parameter to ease cross-frame DOM wrangling, see #968" );*/ + + assert.equal( code.length, 1, "Correct number of elements generated for code" ); + assert.equal( code.parent().length, 0, "Make sure that the generated HTML has no parent." ); + + assert.equal( img.length, 1, "Correct number of elements generated for img" ); + assert.equal( img.parent().length, 0, "Make sure that the generated HTML has no parent." ); + + assert.equal( div.length, 4, "Correct number of elements generated for div hr code b" ); + assert.equal( div.parent().length, 0, "Make sure that the generated HTML has no parent." ); + + assert.equal( jQuery( [ 1, 2, 3 ] ).get( 1 ), 2, "Test passing an array to the factory" ); + + assert.equal( jQuery( document.body ).get( 0 ), jQuery( "body" ).get( 0 ), "Test passing an html node to the factory" ); + + elem = jQuery( " hello" )[ 0 ]; + assert.equal( elem.nodeName.toLowerCase(), "em", "leading space" ); + + elem = jQuery( "\n\nworld" )[ 0 ]; + assert.equal( elem.nodeName.toLowerCase(), "em", "leading newlines" ); + + elem = jQuery( "
        ", attrObj ); + + if ( jQuery.fn.width ) { + assert.equal( elem[ 0 ].style.width, "10px", "jQuery() quick setter width" ); + } + + if ( jQuery.fn.offset ) { + assert.equal( elem[ 0 ].style.top, "1px", "jQuery() quick setter offset" ); + } + + if ( jQuery.fn.css ) { + assert.equal( elem[ 0 ].style.paddingLeft, "1px", "jQuery quick setter css" ); + assert.equal( elem[ 0 ].style.paddingRight, "1px", "jQuery quick setter css" ); + } + + if ( jQuery.fn.attr ) { + assert.equal( elem[ 0 ].getAttribute( "desired" ), "very", "jQuery quick setter attr" ); + } + + assert.equal( elem[ 0 ].childNodes.length, 1, "jQuery quick setter text" ); + assert.equal( elem[ 0 ].firstChild.nodeValue, "test", "jQuery quick setter text" ); + assert.equal( elem[ 0 ].className, "test2", "jQuery() quick setter class" ); + assert.equal( elem[ 0 ].id, "test3", "jQuery() quick setter id" ); + + exec = true; + elem.trigger( "click" ); + + // manually clean up detached elements + elem.remove(); + + for ( i = 0; i < 3; ++i ) { + elem = jQuery( "" ); + } + assert.equal( elem[ 0 ].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); + + elem = jQuery( "", {} ); + assert.strictEqual( elem[ 0 ].ownerDocument, document, + "Empty attributes object is not interpreted as a document (trac-8950)" ); +} ); + +QUnit[ jQuery.find.compile ? "test" : "skip" ]( "jQuery(selector, context)", function( assert ) { + assert.expect( 3 ); + assert.deepEqual( jQuery( "div p", "#qunit-fixture" ).get(), q( "sndp", "en", "sap" ), "Basic selector with string as context" ); + assert.deepEqual( jQuery( "div p", q( "qunit-fixture" )[ 0 ] ).get(), q( "sndp", "en", "sap" ), "Basic selector with element as context" ); + assert.deepEqual( jQuery( "div p", jQuery( "#qunit-fixture" ) ).get(), q( "sndp", "en", "sap" ), "Basic selector with jQuery object as context" ); +} ); + +QUnit.test( "globalEval", function( assert ) { + assert.expect( 3 ); + Globals.register( "globalEvalTest" ); + + jQuery.globalEval( "globalEvalTest = 1;" ); + assert.equal( window.globalEvalTest, 1, "Test variable assignments are global" ); + + jQuery.globalEval( "var globalEvalTest = 2;" ); + assert.equal( window.globalEvalTest, 2, "Test variable declarations are global" ); + + jQuery.globalEval( "this.globalEvalTest = 3;" ); + assert.equal( window.globalEvalTest, 3, "Test context (this) is the window object" ); +} ); + + +QUnit.test( "globalEval with 'use strict'", function( assert ) { + assert.expect( 1 ); + Globals.register( "strictEvalTest" ); + + jQuery.globalEval( "'use strict'; var strictEvalTest = 1;" ); + assert.equal( window.strictEvalTest, 1, "Test variable declarations are global (strict mode)" ); +} ); + +// This is not run in AMD mode +if ( jQuery.noConflict ) { + QUnit.test( "noConflict", function( assert ) { + assert.expect( 7 ); + + var $$ = jQuery; + + assert.strictEqual( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" ); + assert.strictEqual( window[ "jQuery" ], $$, "Make sure jQuery wasn't touched." ); + assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." ); + + jQuery = $ = $$; + + assert.strictEqual( jQuery.noConflict( true ), $$, "noConflict returned the jQuery object" ); + assert.strictEqual( window[ "jQuery" ], originaljQuery, "Make sure jQuery was reverted." ); + assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." ); + assert.ok( $$().pushStack( [] ), "Make sure that jQuery still works." ); + + window[ "jQuery" ] = jQuery = $$; + } ); +} + +QUnit.test( "trim", function( assert ) { + assert.expect( 13 ); + + var nbsp = String.fromCharCode( 160 ); + + assert.equal( jQuery.trim( "hello " ), "hello", "trailing space" ); + assert.equal( jQuery.trim( " hello" ), "hello", "leading space" ); + assert.equal( jQuery.trim( " hello " ), "hello", "space on both sides" ); + assert.equal( jQuery.trim( " " + nbsp + "hello " + nbsp + " " ), "hello", " " ); + + assert.equal( jQuery.trim(), "", "Nothing in." ); + assert.equal( jQuery.trim( undefined ), "", "Undefined" ); + assert.equal( jQuery.trim( null ), "", "Null" ); + assert.equal( jQuery.trim( 5 ), "5", "Number" ); + assert.equal( jQuery.trim( false ), "false", "Boolean" ); + + assert.equal( jQuery.trim( " " ), "", "space should be trimmed" ); + assert.equal( jQuery.trim( "ipad\xA0" ), "ipad", "nbsp should be trimmed" ); + assert.equal( jQuery.trim( "\uFEFF" ), "", "zwsp should be trimmed" ); + assert.equal( jQuery.trim( "\uFEFF \xA0! | \uFEFF" ), "! |", "leading/trailing should be trimmed" ); +} ); + +QUnit.test( "type", function( assert ) { + assert.expect( 28 ); + + assert.equal( jQuery.type( null ), "null", "null" ); + assert.equal( jQuery.type( undefined ), "undefined", "undefined" ); + assert.equal( jQuery.type( true ), "boolean", "Boolean" ); + assert.equal( jQuery.type( false ), "boolean", "Boolean" ); + assert.equal( jQuery.type( Boolean( true ) ), "boolean", "Boolean" ); + assert.equal( jQuery.type( 0 ), "number", "Number" ); + assert.equal( jQuery.type( 1 ), "number", "Number" ); + assert.equal( jQuery.type( Number( 1 ) ), "number", "Number" ); + assert.equal( jQuery.type( "" ), "string", "String" ); + assert.equal( jQuery.type( "a" ), "string", "String" ); + assert.equal( jQuery.type( String( "a" ) ), "string", "String" ); + assert.equal( jQuery.type( {} ), "object", "Object" ); + assert.equal( jQuery.type( /foo/ ), "regexp", "RegExp" ); + assert.equal( jQuery.type( new RegExp( "asdf" ) ), "regexp", "RegExp" ); + assert.equal( jQuery.type( [ 1 ] ), "array", "Array" ); + assert.equal( jQuery.type( new Date() ), "date", "Date" ); + assert.equal( jQuery.type( new Function( "return;" ) ), "function", "Function" ); + assert.equal( jQuery.type( function() {} ), "function", "Function" ); + assert.equal( jQuery.type( new Error() ), "error", "Error" ); + assert.equal( jQuery.type( window ), "object", "Window" ); + assert.equal( jQuery.type( document ), "object", "Document" ); + assert.equal( jQuery.type( document.body ), "object", "Element" ); + assert.equal( jQuery.type( document.createTextNode( "foo" ) ), "object", "TextNode" ); + assert.equal( jQuery.type( document.getElementsByTagName( "*" ) ), "object", "NodeList" ); + + // Avoid Lint complaints + var MyString = String, + MyNumber = Number, + MyBoolean = Boolean, + MyObject = Object; + assert.equal( jQuery.type( new MyBoolean( true ) ), "boolean", "Boolean" ); + assert.equal( jQuery.type( new MyNumber( 1 ) ), "number", "Number" ); + assert.equal( jQuery.type( new MyString( "a" ) ), "string", "String" ); + assert.equal( jQuery.type( new MyObject() ), "object", "Object" ); +} ); + +QUnit.test( "type for `Symbol`", function( assert ) { + + // Prevent reference errors + if ( typeof Symbol !== "function" ) { + assert.expect( 0 ); + return; + } + + assert.expect( 2 ); + + assert.equal( jQuery.type( Symbol() ), "symbol", "Symbol" ); + assert.equal( jQuery.type( Object( Symbol() ) ), "symbol", "Symbol" ); +} ); + +QUnit.asyncTest( "isPlainObject", function( assert ) { + assert.expect( 15 ); + + var pass, iframe, doc, + fn = function() {}; + + // The use case that we want to match + assert.ok( jQuery.isPlainObject( {} ), "{}" ); + + // Not objects shouldn't be matched + assert.ok( !jQuery.isPlainObject( "" ), "string" ); + assert.ok( !jQuery.isPlainObject( 0 ) && !jQuery.isPlainObject( 1 ), "number" ); + assert.ok( !jQuery.isPlainObject( true ) && !jQuery.isPlainObject( false ), "boolean" ); + assert.ok( !jQuery.isPlainObject( null ), "null" ); + assert.ok( !jQuery.isPlainObject( undefined ), "undefined" ); + + // Arrays shouldn't be matched + assert.ok( !jQuery.isPlainObject( [] ), "array" ); + + // Instantiated objects shouldn't be matched + assert.ok( !jQuery.isPlainObject( new Date() ), "new Date" ); + + // Functions shouldn't be matched + assert.ok( !jQuery.isPlainObject( fn ), "fn" ); + + // Again, instantiated objects shouldn't be matched + assert.ok( !jQuery.isPlainObject( new fn() ), "new fn (no methods)" ); + + // Makes the function a little more realistic + // (and harder to detect, incidentally) + fn.prototype[ "someMethod" ] = function() {}; + + // Again, instantiated objects shouldn't be matched + assert.ok( !jQuery.isPlainObject( new fn() ), "new fn" ); + + // DOM Element + assert.ok( !jQuery.isPlainObject( document.createElement( "div" ) ), "DOM Element" ); + + // Window + assert.ok( !jQuery.isPlainObject( window ), "window" ); + + pass = false; + try { + jQuery.isPlainObject( window.location ); + pass = true; + } catch ( e ) {} + assert.ok( pass, "Does not throw exceptions on host objects" ); + + // Objects from other windows should be matched + Globals.register( "iframeDone" ); + window.iframeDone = function( otherObject, detail ) { + window.iframeDone = undefined; + iframe.parentNode.removeChild( iframe ); + assert.ok( jQuery.isPlainObject( new otherObject() ), "new otherObject" + ( detail ? " - " + detail : "" ) ); + QUnit.start(); + }; + + try { + iframe = jQuery( "#qunit-fixture" )[ 0 ].appendChild( document.createElement( "iframe" ) ); + doc = iframe.contentDocument || iframe.contentWindow.document; + doc.open(); + doc.write( "" ); + doc.close(); + } catch ( e ) { + window.iframeDone( Object, "iframes not supported" ); + } +} ); + +// +QUnit[ typeof Symbol === "function" ? "test" : "skip" ]( "isPlainObject(Symbol)", function( assert ) { + assert.expect( 2 ); + + assert.equal( jQuery.isPlainObject( Symbol() ), false, "Symbol" ); + assert.equal( jQuery.isPlainObject( Object( Symbol() ) ), false, "Symbol inside an object" ); +} ); + +QUnit.test( "isFunction", function( assert ) { + assert.expect( 19 ); + + var mystr, myarr, myfunction, fn, obj, nodes, first, input, a; + + // Make sure that false values return false + assert.ok( !jQuery.isFunction(), "No Value" ); + assert.ok( !jQuery.isFunction( null ), "null Value" ); + assert.ok( !jQuery.isFunction( undefined ), "undefined Value" ); + assert.ok( !jQuery.isFunction( "" ), "Empty String Value" ); + assert.ok( !jQuery.isFunction( 0 ), "0 Value" ); + + // Check built-ins + assert.ok( jQuery.isFunction( String ), "String Function(" + String + ")" ); + assert.ok( jQuery.isFunction( Array ), "Array Function(" + Array + ")" ); + assert.ok( jQuery.isFunction( Object ), "Object Function(" + Object + ")" ); + assert.ok( jQuery.isFunction( Function ), "Function Function(" + Function + ")" ); + + // When stringified, this could be misinterpreted + mystr = "function"; + assert.ok( !jQuery.isFunction( mystr ), "Function String" ); + + // When stringified, this could be misinterpreted + myarr = [ "function" ]; + assert.ok( !jQuery.isFunction( myarr ), "Function Array" ); + + // When stringified, this could be misinterpreted + myfunction = { "function": "test" }; + assert.ok( !jQuery.isFunction( myfunction ), "Function Object" ); + + // Make sure normal functions still work + fn = function() {}; + assert.ok( jQuery.isFunction( fn ), "Normal Function" ); + + obj = document.createElement( "object" ); + + // Firefox says this is a function + assert.ok( !jQuery.isFunction( obj ), "Object Element" ); + + // Since 1.3, this isn't supported (#2968) + //ok( jQuery.isFunction(obj.getAttribute), "getAttribute Function" ); + + nodes = document.body.childNodes; + + // Safari says this is a function + assert.ok( !jQuery.isFunction( nodes ), "childNodes Property" ); + + first = document.body.firstChild; + + // Normal elements are reported ok everywhere + assert.ok( !jQuery.isFunction( first ), "A normal DOM Element" ); + + input = document.createElement( "input" ); + input.type = "text"; + document.body.appendChild( input ); + + // Since 1.3, this isn't supported (#2968) + //ok( jQuery.isFunction(input.focus), "A default function property" ); + + document.body.removeChild( input ); + + a = document.createElement( "a" ); + a.href = "some-function"; + document.body.appendChild( a ); + + // This serializes with the word 'function' in it + assert.ok( !jQuery.isFunction( a ), "Anchor Element" ); + + document.body.removeChild( a ); + + // Recursive function calls have lengths and array-like properties + function callme( callback ) { + function fn( response ) { + callback( response ); + } + + assert.ok( jQuery.isFunction( fn ), "Recursive Function Call" ); + + fn( { some: "data" } ); + } + + callme( function() { + callme( function() {} ); + } ); +} ); + +QUnit.test( "isNumeric", function( assert ) { + assert.expect( 38 ); + + var t = jQuery.isNumeric, + ToString = function( value ) { + this.toString = function() { + return String( value ); + }; + }; + + assert.ok( t( "-10" ), "Negative integer string" ); + assert.ok( t( "0" ), "Zero string" ); + assert.ok( t( "5" ), "Positive integer string" ); + assert.ok( t( -16 ), "Negative integer number" ); + assert.ok( t( 0 ), "Zero integer number" ); + assert.ok( t( 32 ), "Positive integer number" ); + assert.ok( t( "040" ), "Octal integer literal string" ); + assert.ok( t( "0xFF" ), "Hexadecimal integer literal string" ); + assert.ok( t( 0xFFF ), "Hexadecimal integer literal" ); + assert.ok( t( "-1.6" ), "Negative floating point string" ); + assert.ok( t( "4.536" ), "Positive floating point string" ); + assert.ok( t( -2.6 ), "Negative floating point number" ); + assert.ok( t( 3.1415 ), "Positive floating point number" ); + assert.ok( t( 1.5999999999999999 ), "Very precise floating point number" ); + assert.ok( t( 8e5 ), "Exponential notation" ); + assert.ok( t( "123e-2" ), "Exponential notation string" ); + assert.ok( t( new ToString( "42" ) ), "Custom .toString returning number" ); + + assert.equal( t( "" ), false, "Empty string" ); + assert.equal( t( " " ), false, "Whitespace characters string" ); + assert.equal( t( "\t\t" ), false, "Tab characters string" ); + assert.equal( t( "abcdefghijklm1234567890" ), false, "Alphanumeric character string" ); + assert.equal( t( "xabcdefx" ), false, "Non-numeric character string" ); + assert.equal( t( true ), false, "Boolean true literal" ); + assert.equal( t( false ), false, "Boolean false literal" ); + assert.equal( t( "bcfed5.2" ), false, "Number with preceding non-numeric characters" ); + assert.equal( t( "7.2acdgs" ), false, "Number with trailling non-numeric characters" ); + assert.equal( t( undefined ), false, "Undefined value" ); + assert.equal( t( null ), false, "Null value" ); + assert.equal( t( NaN ), false, "NaN value" ); + assert.equal( t( Infinity ), false, "Infinity primitive" ); + assert.equal( t( Number.POSITIVE_INFINITY ), false, "Positive Infinity" ); + assert.equal( t( Number.NEGATIVE_INFINITY ), false, "Negative Infinity" ); + assert.equal( t( new ToString( "Devo" ) ), false, "Custom .toString returning non-number" ); + assert.equal( t( {} ), false, "Empty object" ); + assert.equal( t( [] ), false, "Empty array" ); + assert.equal( t( [ 42 ] ), false, "Array with one number" ); + assert.equal( t( function() {} ), false, "Instance of a function" ); + assert.equal( t( new Date() ), false, "Instance of a Date" ); +} ); + +QUnit[ typeof Symbol === "function" ? "test" : "skip" ]( "isNumeric(Symbol)", function( assert ) { + assert.expect( 2 ); + + assert.equal( jQuery.isNumeric( Symbol() ), false, "Symbol" ); + assert.equal( jQuery.isNumeric( Object( Symbol() ) ), false, "Symbol inside an object" ); +} ); + +QUnit.test( "isXMLDoc - HTML", function( assert ) { + assert.expect( 4 ); + + assert.ok( !jQuery.isXMLDoc( document ), "HTML document" ); + assert.ok( !jQuery.isXMLDoc( document.documentElement ), "HTML documentElement" ); + assert.ok( !jQuery.isXMLDoc( document.body ), "HTML Body Element" ); + + var body, + iframe = document.createElement( "iframe" ); + document.body.appendChild( iframe ); + + try { + body = jQuery( iframe ).contents()[ 0 ]; + + try { + assert.ok( !jQuery.isXMLDoc( body ), "Iframe body element" ); + } catch ( e ) { + assert.ok( false, "Iframe body element exception" ); + } + + } catch ( e ) { + assert.ok( true, "Iframe body element - iframe not working correctly" ); + } + + document.body.removeChild( iframe ); +} ); + +QUnit.test( "XSS via location.hash", function( assert ) { + assert.expect( 1 ); + + QUnit.stop(); + jQuery[ "_check9521" ] = function( x ) { + assert.ok( x, "script called from #id-like selector with inline handler" ); + jQuery( "#check9521" ).remove(); + delete jQuery[ "_check9521" ]; + QUnit.start(); + }; + try { + + // This throws an error because it's processed like an id + jQuery( "#" ).appendTo( "#qunit-fixture" ); + } catch ( err ) { + jQuery[ "_check9521" ]( true ); + } +} ); + +QUnit.test( "isXMLDoc - XML", function( assert ) { + assert.expect( 3 ); + var xml = createDashboardXML(); + assert.ok( jQuery.isXMLDoc( xml ), "XML document" ); + assert.ok( jQuery.isXMLDoc( xml.documentElement ), "XML documentElement" ); + assert.ok( jQuery.isXMLDoc( jQuery( "tab", xml )[ 0 ] ), "XML Tab Element" ); +} ); + +QUnit.test( "isWindow", function( assert ) { + assert.expect( 14 ); + + assert.ok( jQuery.isWindow( window ), "window" ); + assert.ok( jQuery.isWindow( document.getElementsByTagName( "iframe" )[ 0 ].contentWindow ), "iframe.contentWindow" ); + assert.ok( !jQuery.isWindow(), "empty" ); + assert.ok( !jQuery.isWindow( null ), "null" ); + assert.ok( !jQuery.isWindow( undefined ), "undefined" ); + assert.ok( !jQuery.isWindow( document ), "document" ); + assert.ok( !jQuery.isWindow( document.documentElement ), "documentElement" ); + assert.ok( !jQuery.isWindow( "" ), "string" ); + assert.ok( !jQuery.isWindow( 1 ), "number" ); + assert.ok( !jQuery.isWindow( true ), "boolean" ); + assert.ok( !jQuery.isWindow( {} ), "object" ); + assert.ok( !jQuery.isWindow( { setInterval: function() {} } ), "fake window" ); + assert.ok( !jQuery.isWindow( /window/ ), "regexp" ); + assert.ok( !jQuery.isWindow( function() {} ), "function" ); +} ); + +QUnit.test( "jQuery('html')", function( assert ) { + assert.expect( 18 ); + + var s, div, j; + + jQuery[ "foo" ] = false; + s = jQuery( "" )[ 0 ]; + assert.ok( s, "Creating a script" ); + assert.ok( !jQuery[ "foo" ], "Make sure the script wasn't executed prematurely" ); + jQuery( "body" ).append( "" ); + assert.ok( jQuery[ "foo" ], "Executing a scripts contents in the right context" ); + + // Test multi-line HTML + div = jQuery( "
        \r\nsome text\n

        some p

        \nmore text\r\n
        " )[ 0 ]; + assert.equal( div.nodeName.toUpperCase(), "DIV", "Make sure we're getting a div." ); + assert.equal( div.firstChild.nodeType, 3, "Text node." ); + assert.equal( div.lastChild.nodeType, 3, "Text node." ); + assert.equal( div.childNodes[ 1 ].nodeType, 1, "Paragraph." ); + assert.equal( div.childNodes[ 1 ].firstChild.nodeType, 3, "Paragraph text." ); + + assert.ok( jQuery( "" )[ 0 ], "Creating a link" ); + + assert.ok( !jQuery( ""; + assert.equal( jQuery.parseHTML( html ).length, 0, "Ignore scripts by default" ); + assert.equal( jQuery.parseHTML( html, true )[0].nodeName.toLowerCase(), "script", "Preserve scripts when requested" ); + + html += "
        "; + assert.equal( jQuery.parseHTML( html )[0].nodeName.toLowerCase(), "div", "Preserve non-script nodes" ); + assert.equal( jQuery.parseHTML( html, true )[0].nodeName.toLowerCase(), "script", "Preserve script position"); + + assert.equal( jQuery.parseHTML("text")[0].nodeType, 3, "Parsing text returns a text node" ); + assert.equal( jQuery.parseHTML( "\t
        " )[0].nodeValue, "\t", "Preserve leading whitespace" ); + + assert.equal( jQuery.parseHTML("
        ")[0].nodeType, 3, "Leading spaces are treated as text nodes (#11290)" ); + + html = jQuery.parseHTML( "
        test div
        " ); + + assert.equal( html[ 0 ].parentNode.nodeType, 11, "parentNode should be documentFragment" ); + assert.equal( html[ 0 ].innerHTML, "test div", "Content should be preserved" ); + + assert.equal( jQuery.parseHTML("").length, 1, "Incorrect html-strings should not break anything" ); + assert.equal( jQuery.parseHTML("")[ 1 ].parentNode.nodeType, 11, + "parentNode should be documentFragment for wrapMap (variable in manipulation module) elements too" ); + assert.ok( jQuery.parseHTML("<#if>

        This is a test.

        <#/if>") || true, "Garbage input should not cause error" ); +}); + +if ( jQuery.support.createHTMLDocument && !/opera.*version\/12\.1/i.test( navigator.userAgent ) ) { + QUnit.asyncTest( "jQuery.parseHTML", function( assert ) { + assert.expect( 1 ); + + Globals.register( "parseHTMLError" ); + + jQuery.globalEval( "parseHTMLError = false;" ); + jQuery.parseHTML( "" ); + + window.setTimeout( function() { + QUnit.start(); + assert.equal( window.parseHTMLError, false, "onerror eventhandler has not been called." ); + }, 2000 ); + } ); +} + +QUnit.test( "jQuery.parseJSON", function( assert ) { + assert.expect( 20 ); + + assert.strictEqual( jQuery.parseJSON( null ), null, "primitive null" ); + assert.strictEqual( jQuery.parseJSON( "0.88" ), 0.88, "Number" ); + assert.strictEqual( + jQuery.parseJSON( "\" \\\" \\\\ \\/ \\b \\f \\n \\r \\t \\u007E \\u263a \"" ), + " \" \\ / \b \f \n \r \t ~ \u263A ", + "String escapes" + ); + assert.deepEqual( jQuery.parseJSON( "{}" ), {}, "Empty object" ); + assert.deepEqual( jQuery.parseJSON( "{\"test\":1}" ), { "test": 1 }, "Plain object" ); + assert.deepEqual( jQuery.parseJSON( "[0]" ), [ 0 ], "Simple array" ); + + assert.deepEqual( + jQuery.parseJSON( "[ \"string\", -4.2, 2.7180e0, 3.14E-1, {}, [], true, false, null ]" ), + [ "string", -4.2, 2.718, 0.314, {}, [], true, false, null ], + "Array of all data types" + ); + assert.deepEqual( + jQuery.parseJSON( "{ \"string\": \"\", \"number\": 4.2e+1, \"object\": {}," + + "\"array\": [[]], \"boolean\": [ true, false ], \"null\": null }" ), + { string: "", number: 42, object: {}, array: [ [] ], "boolean": [ true, false ], "null": null }, + "Dictionary of all data types" + ); + + assert.deepEqual( jQuery.parseJSON( "\n{\"test\":1}\t" ), { "test": 1 }, + "Leading and trailing whitespace are ignored" ); + + assert.throws( function() { + jQuery.parseJSON(); + }, null, "Undefined raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "" ); + }, null, "Empty string raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "''" ); + }, null, "Single-quoted string raises an error" ); + /* + + // Broken on IE8 + assert.throws(function() { + jQuery.parseJSON("\" \\a \""); + }, null, "Invalid string escape raises an error" ); + + // Broken on IE8, Safari 5.1 Windows + assert.throws(function() { + jQuery.parseJSON("\"\t\""); + }, null, "Unescaped control character raises an error" ); + + // Broken on IE8 + assert.throws(function() { + jQuery.parseJSON(".123"); + }, null, "Number with no integer component raises an error" ); + + */ + assert.throws( function() { + var result = jQuery.parseJSON( "0101" ); + + // Support: IE9+ + // Ensure base-10 interpretation on browsers that erroneously accept leading-zero numbers + if ( result === 101 ) { + throw new Error( "close enough" ); + } + }, null, "Leading-zero number raises an error or is parsed as decimal" ); + assert.throws( function() { + jQuery.parseJSON( "{a:1}" ); + }, null, "Unquoted property raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "{'a':1}" ); + }, null, "Single-quoted property raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "[,]" ); + }, null, "Array element elision raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "{},[]" ); + }, null, "Comma expression raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "[]\n,{}" ); + }, null, "Newline-containing comma expression raises an error" ); + assert.throws( function() { + jQuery.parseJSON( "\"\"\n\"\"" ); + }, null, "Automatic semicolon insertion raises an error" ); + + assert.strictEqual( jQuery.parseJSON( [ 0 ] ), 0, "Input cast to string" ); +} ); + +QUnit.test( "jQuery.parseXML", function( assert ) { + assert.expect( 8 ); + + var xml, tmp; + try { + xml = jQuery.parseXML( "

        A well-formed xml string

        " ); + tmp = xml.getElementsByTagName( "p" )[ 0 ]; + assert.ok( !!tmp, "

        present in document" ); + tmp = tmp.getElementsByTagName( "b" )[ 0 ]; + assert.ok( !!tmp, " present in document" ); + assert.strictEqual( tmp.childNodes[ 0 ].nodeValue, "well-formed", " text is as expected" ); + } catch ( e ) { + assert.strictEqual( e, undefined, "unexpected error" ); + } + try { + xml = jQuery.parseXML( "

        Not a <well-formed xml string

        " ); + assert.ok( false, "invalid xml not detected" ); + } catch ( e ) { + assert.strictEqual( e.message, "Invalid XML:

        Not a <well-formed xml string

        ", "invalid xml detected" ); + } + try { + xml = jQuery.parseXML( "" ); + assert.strictEqual( xml, null, "empty string => null document" ); + xml = jQuery.parseXML(); + assert.strictEqual( xml, null, "undefined string => null document" ); + xml = jQuery.parseXML( null ); + assert.strictEqual( xml, null, "null string => null document" ); + xml = jQuery.parseXML( true ); + assert.strictEqual( xml, null, "non-string => null document" ); + } catch ( e ) { + assert.ok( false, "empty input throws exception" ); + } +} ); + +QUnit.test( "jQuery.camelCase()", function( assert ) { + + var tests = { + "foo-bar": "fooBar", + "foo-bar-baz": "fooBarBaz", + "girl-u-want": "girlUWant", + "the-4th-dimension": "the4thDimension", + "-o-tannenbaum": "OTannenbaum", + "-moz-illa": "MozIlla", + "-ms-take": "msTake" + }; + + assert.expect( 7 ); + + jQuery.each( tests, function( key, val ) { + assert.equal( jQuery.camelCase( key ), val, "Converts: " + key + " => " + val ); + } ); +} ); + +testIframeWithCallback( + "Conditional compilation compatibility (#13274)", + "core/cc_on.html", + function( cc_on, errors, $, assert ) { + assert.expect( 3 ); + assert.ok( true, "JScript conditional compilation " + ( cc_on ? "supported" : "not supported" ) ); + assert.deepEqual( errors, [], "No errors" ); + assert.ok( $(), "jQuery executes" ); + } +); + +// iOS7 doesn't fire the load event if the long-loading iframe gets its source reset to about:blank. +// This makes this test fail but it doesn't seem to cause any real-life problems so blacklisting +// this test there is preferred to complicating the hard-to-test core/ready code further. +if ( !/iphone os 7_/i.test( navigator.userAgent ) ) { + testIframeWithCallback( + "document ready when jQuery loaded asynchronously (#13655)", + "core/dynamic_ready.html", + function( ready, assert ) { + assert.expect( 1 ); + assert.equal( true, ready, "document ready correctly fired when jQuery is loaded after DOMContentLoaded" ); + } + ); +} + +testIframeWithCallback( + "Tolerating alias-masked DOM properties (#14074)", + "core/aliased.html", + function( errors, assert ) { + assert.expect( 1 ); + assert.deepEqual( errors, [], "jQuery loaded" ); + } +); + +testIframeWithCallback( + "Don't call window.onready (#14802)", + "core/onready.html", + function( error, assert ) { + assert.expect( 1 ); + assert.equal( error, false, "no call to user-defined onready" ); + } +); + +QUnit.test( "Iterability of jQuery objects (gh-1693)", function( assert ) { + /* jshint unused: false */ + assert.expect( 1 ); + + var i, elem, result; + + if ( typeof Symbol === "function" ) { + + elem = jQuery( "
        " ); + result = ""; + + try { + eval( "for ( i of elem ) { result += i.nodeName; }" ); + } catch ( e ) {} + assert.equal( result, "DIVSPANA", "for-of works on jQuery objects" ); + } else { + assert.ok( true, "The browser doesn't support Symbols" ); + } +} ); diff --git a/dashboard-ui/bower_components/jquery/test/unit/css.js b/dashboard-ui/bower_components/jquery/test/unit/css.js new file mode 100644 index 0000000000..c2213b2482 --- /dev/null +++ b/dashboard-ui/bower_components/jquery/test/unit/css.js @@ -0,0 +1,1298 @@ +if ( jQuery.css ) { + +QUnit.module( "css", { teardown: moduleTeardown } ); + +QUnit.test( "css(String|Hash)", function( assert ) { + assert.expect( 42 ); + + assert.equal( jQuery( "#qunit-fixture" ).css( "display" ), "block", "Check for css property \"display\"" ); + + var $child, div, div2, width, height, child, prctval, checkval, old; + + $child = jQuery( "#nothiddendivchild" ).css( { "width": "20%", "height": "20%" } ); + assert.notEqual( $child.css( "width" ), "20px", "Retrieving a width percentage on the child of a hidden div returns percentage" ); + assert.notEqual( $child.css( "height" ), "20px", "Retrieving a height percentage on the child of a hidden div returns percentage" ); + + div = jQuery( "
        " ); + + // These should be "auto" (or some better value) + // temporarily provide "0px" for backwards compat + assert.equal( div.css( "width" ), "0px", "Width on disconnected node." ); + assert.equal( div.css( "height" ), "0px", "Height on disconnected node." ); + + div.css( { "width": 4, "height": 4 } ); + + assert.equal( div.css( "width" ), "4px", "Width on disconnected node." ); + assert.equal( div.css( "height" ), "4px", "Height on disconnected node." ); + + div2 = jQuery( "
        " ); + clone = element.clone(); + assert.equal( clone[ 0 ].defaultValue, "foo", "Textarea defaultValue cloned correctly" ); +} ); + +QUnit.test( "clone(multiple selected options) (Bug #8129)", function( assert ) { + + assert.expect( 1 ); + + var element = jQuery( "" ); + + function getSelectedOptions( collection ) { + return collection.find( "option" ).filter( function( option ) { + return option.selected; + } ); + } + + assert.equal( + getSelectedOptions( element.clone() ).length, + getSelectedOptions( element ).length, + "Multiple selected options cloned correctly" + ); +} ); + +QUnit.test( "clone() on XML nodes", function( assert ) { + + assert.expect( 2 ); + + var xml = createDashboardXML(), + root = jQuery( xml.documentElement ).clone(), + origTab = jQuery( "tab", xml ).eq( 0 ), + cloneTab = jQuery( "tab", root ).eq( 0 ); + + origTab.text( "origval" ); + cloneTab.text( "cloneval" ); + assert.equal( origTab.text(), "origval", "Check original XML node was correctly set" ); + assert.equal( cloneTab.text(), "cloneval", "Check cloned XML node was correctly set" ); +} ); + +QUnit.test( "clone() on local XML nodes with html5 nodename", function( assert ) { + + assert.expect( 2 ); + + var $xmlDoc = jQuery( jQuery.parseXML( "" ) ), + $meter = $xmlDoc.find( "meter" ).clone(); + + assert.equal( $meter[ 0 ].nodeName, "meter", "Check if nodeName was not changed due to cloning" ); + assert.equal( $meter[ 0 ].nodeType, 1, "Check if nodeType is not changed due to cloning" ); +} ); + +QUnit.test( "html(undefined)", function( assert ) { + + assert.expect( 1 ); + + assert.equal( jQuery( "#foo" ).html( "test" ).html( undefined ).html().toLowerCase(), "test", ".html(undefined) is chainable (#5571)" ); +} ); + +QUnit.test( "html() on empty set", function( assert ) { + + assert.expect( 1 ); + + assert.strictEqual( jQuery().html(), undefined, ".html() returns undefined for empty sets (#11962)" ); +} ); + +function childNodeNames( node ) { + return jQuery.map( node.childNodes, function( child ) { + return child.nodeName.toUpperCase(); + } ).join( " " ); +} + +function testHtml( valueObj, assert ) { + assert.expect( 40 ); + + var actual, expected, tmp, + div = jQuery( "
        " ), + fixture = jQuery( "#qunit-fixture" ); + + div.html( valueObj( "
        " ) ); + assert.equal( div.children().length, 2, "Found children" ); + assert.equal( div.children().children().length, 1, "Found grandchild" ); + + actual = []; expected = []; + tmp = jQuery( "" ).html( valueObj( "area" ) ).each( function() { + expected.push( "AREA" ); + actual.push( childNodeNames( this ) ); + } ); + assert.equal( expected.length, 1, "Expecting one parent" ); + assert.deepEqual( actual, expected, "Found the inserted area element" ); + + assert.equal( div.html( valueObj( 5 ) ).html(), "5", "Setting a number as html" ); + assert.equal( div.html( valueObj( 0 ) ).html(), "0", "Setting a zero as html" ); + assert.equal( div.html( valueObj( Infinity ) ).html(), "Infinity", "Setting Infinity as html" ); + assert.equal( div.html( valueObj( NaN ) ).html(), "", "Setting NaN as html" ); + assert.equal( div.html( valueObj( 1e2 ) ).html(), "100", "Setting exponential number notation as html" ); + + div.html( valueObj( " &" ) ); + assert.equal( + div[ 0 ].innerHTML.replace( /\xA0/, " " ), + " &", + "Entities are passed through correctly" + ); + + tmp = "<div>hello1</div>"; + assert.equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html" ); + tmp = "x" + tmp; + assert.equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html, leading x" ); + tmp = " " + tmp.slice( 1 ); + assert.equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html, leading space" ); + + actual = []; expected = []; tmp = {}; + jQuery( "#nonnodes" ).contents().html( valueObj( "bold" ) ).each( function() { + var html = jQuery( this ).html(); + tmp[ this.nodeType ] = true; + expected.push( this.nodeType === 1 ? "bold" : undefined ); + actual.push( html ? html.toLowerCase() : html ); + } ); + assert.deepEqual( actual, expected, "Set containing element, text node, comment" ); + assert.ok( tmp[ 1 ], "element" ); + assert.ok( tmp[ 3 ], "text node" ); + assert.ok( tmp[ 8 ], "comment" ); + + actual = []; expected = []; + fixture.children( "div" ).html( valueObj( "test" ) ).each( function() { + expected.push( "B" ); + actual.push( childNodeNames( this ) ); + } ); + assert.equal( expected.length, 7, "Expecting many parents" ); + assert.deepEqual( actual, expected, "Correct childNodes after setting HTML" ); + + actual = []; expected = []; + fixture.html( valueObj( "" ) ).each( function() { + expected.push( "STYLE" ); + actual.push( childNodeNames( this ) ); + } ); + assert.equal( expected.length, 1, "Expecting one parent" ); + assert.deepEqual( actual, expected, "Found the inserted style element" ); + + fixture.html( valueObj( "" )[ 0 ]; + elem.checked = false; + assert.equal( jQuery( elem ).clone().attr( "id", "clone" )[ 0 ].checked, false, "Checked false state correctly cloned" ); + + elem = jQuery.parseHTML( "" )[ 0 ]; + elem.checked = true; + assert.equal( jQuery( elem ).clone().attr( "id", "clone" )[ 0 ].checked, true, "Checked true state correctly cloned" ); +} ); + +QUnit.test( "manipulate mixed jQuery and text (#12384, #12346)", function( assert ) { + + assert.expect( 2 ); + + var div = jQuery( "
        a
        " ).append( " ", jQuery( "b" ), " ", jQuery( "c" ) ), + nbsp = String.fromCharCode( 160 ); + + assert.equal( div.text(), "a" + nbsp + "b" + nbsp + "c", "Appending mixed jQuery with text nodes" ); + + div = jQuery( "
        " ) + .find( "div" ) + .after( "

        a

        ", "

        b

        " ) + .parent(); + assert.equal( div.find( "*" ).length, 3, "added 2 paragraphs after inner div" ); +} ); + +QUnit.test( "script evaluation (#11795)", function( assert ) { + + assert.expect( 13 ); + + var scriptsIn, scriptsOut, + fixture = jQuery( "#qunit-fixture" ).empty(), + objGlobal = ( function() { + return this; + } )(), + isOk = objGlobal.ok, + notOk = function() { + var args = arguments; + args[ 0 ] = !args[ 0 ]; + return isOk.apply( this, args ); + }; + + objGlobal.ok = notOk; + scriptsIn = jQuery( [ + "", + "", + "", + "", + "
        ", + "", + "", + "", + "", + "
        " + ].join( "" ) ); + scriptsIn.appendTo( jQuery( "
        " ) ); + objGlobal.ok = isOk; + + scriptsOut = fixture.append( scriptsIn ).find( "script" ); + assert.equal( scriptsOut[ 0 ].type, "something/else", "Non-evaluated type." ); + assert.equal( scriptsOut[ 1 ].type, "text/javascript", "Evaluated type." ); + assert.deepEqual( scriptsOut.get(), fixture.find( "script" ).get(), "All script tags remain." ); + + objGlobal.ok = notOk; + scriptsOut = scriptsOut.add( scriptsOut.clone() ).appendTo( fixture.find( "div" ) ); + assert.deepEqual( fixture.find( "div script" ).get(), scriptsOut.get(), "Scripts cloned without reevaluation" ); + fixture.append( scriptsOut.detach() ); + assert.deepEqual( fixture.children( "script" ).get(), scriptsOut.get(), "Scripts detached without reevaluation" ); + objGlobal.ok = isOk; + + if ( jQuery.ajax ) { + Globals.register( "testBar" ); + jQuery( "#qunit-fixture" ).append( ""; + + jQuery.htmlPrefilter = function( html ) { + invocations++; + assert.equal( html, expectedArgument, "Expected input" ); + + // Remove - + - + - - + - + + + - - - - +