diff -Nru jquery-1.11.3+dfsg/AUTHORS.txt jquery-3.2.1/AUTHORS.txt --- jquery-1.11.3+dfsg/AUTHORS.txt 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/AUTHORS.txt 2017-03-20 19:00:06.000000000 +0000 @@ -6,10 +6,10 @@ Stefan Petre Yehuda Katz Corey Jewett -Klaus Hartl +Klaus Hartl Franck Marcia Jörn Zaefferer -Paul Bakaus +Paul Bakaus Brandon Aaron Mike Alsup Dave Methvin @@ -36,7 +36,7 @@ Ben Alman James Padolsey David Petersen -Batiste Bieler +Batiste Bieler Alexander Farkas Rick Waldron Filipe Fortes @@ -47,7 +47,7 @@ Michael Monteleone Noah Sloan Tom Viner -Douglas Neiner +Douglas Neiner Adam J. Sontag Dave Reed Ralph Whitbeck @@ -57,7 +57,7 @@ unknown temp01 Heungsub Lee -Colin Snover +Colin Snover Ryan W Tenney Pinhook Ron Otten @@ -69,7 +69,7 @@ Russell Holbrook Julian Aubourg Gianni Alessandro Chiappetta -Scott Jehl +Scott Jehl James Burke Jonas Pfenniger Xavi Ramirez @@ -77,11 +77,11 @@ Sylvester Keil Brandon Sterne Mathias Bynens -Timmy Willison -Corey Frang +Timmy Willison <4timmywil@gmail.com> +Corey Frang Digitalxero Anton Kovalyov -David Murdoch +David Murdoch Josh Varner Charles McNulty Jordan Boesch @@ -139,7 +139,7 @@ Elijah Manor Daniel Chatfield Nikita Govorov -Wesley Walser +Wesley Walser Mike Pennisi Markus Staab Dave Riddle @@ -170,6 +170,8 @@ Rod Vagg Bennett Sorbo Sebastian Burkhard +Zachary Adam Kaplan +nanto_vi nanto Danil Somsikov Ryunosuke SATO @@ -177,41 +179,123 @@ Adam Coulombe Andrew Plummer Mark Raddatz +Isaac Z. Schlueter +Karl Sieburg +Pascal Borreli +Nguyen Phuc Lam Dmitry Gusev Michał Gołębiowski -Nguyen Phuc Lam +Li Xudong +Steven Benner Tom H Fuertes -Brandon Johnson +Renato Oliveira dos Santos +ros3cin Jason Bedard Kyle Robinson Young -Renato Oliveira dos Santos Chris Talkington Eddie Monge Terry Jones Jason Merino Jeremy Dunck Chris Price +Guy Bedford Amey Sakhadeo +Mike Sidorov Anthony Ryan Dominik D. Geyer George Kats Lihan Li Ronny Springer -Marian Sollmann -Corey Frang Chris Antaki -Noah Hamann +Marian Sollmann +njhamann +Ilya Kantor David Hong +John Paul Jakob Stoeck -Christopher Jones +Christopher Jones Forbes Lindesay -John Paul S. Andrew Sheppard Leonardo Balter Roman Reiß Benjy Cui Rodrigo Rosenfeld Rosas John Hoven +Philip Jägenstedt Christian Kosmowski Liang Peng TJ VanToll +Senya Pugach +Aurelio De Rosa +Nazar Mokrynskyi +Amit Merchant +Jason Bedard +Arthur Verschaeve +Dan Hart +Bin Xin +David Corbacho +Veaceslav Grimalschi +Daniel Husar +Frederic Hemberger +Ben Toews +Aditya Raghavan +Victor Homyakov +Shivaji Varma +Nicolas HENRY +Anne-Gaelle Colom +George Mauer +Leonardo Braga +Stephen Edgar +Thomas Tortorini +Winston Howes +Jon Hester +Alexander O'Mara +Bastian Buchholz +Arthur Stolyar +Calvin Metcalf +Mu Haibao +Richard McDaniel +Chris Rebert +Gabriel Schulhof +Gilad Peleg +Martin Naumann +Marek Lewandowski +Bruno Pérel +Reed Loden +Daniel Nill +Yongwoo Jeon +Sean Henderson +Richard Kraaijenhagen +Connor Atherton +Gary Ye +Christian Grete +Liza Ramo +Julian Alexander Murillo +Joelle Fleurantin +Jae Sung Park +Jun Sun +Josh Soref +Henry Wong +Jon Dufresne +Martijn W. van der Lee +Devin Wilson +Steve Mao +Zack Hall +Bernhard M. Wiedemann +Todor Prikumov +Jha Naman +William Robinet +Alexander Lisianoi +Vitaliy Terziev +Joe Trumbull +Alexander K +Damian Senn +Ralin Chimev +Felipe Sateler +Christophe Tafani-Dereeper +Manoj Kumar +David Broder-Rodgers +Alex Louden +Alex Padilla +南漂一卒 +karan-96 diff -Nru jquery-1.11.3+dfsg/.babelrc jquery-3.2.1/.babelrc --- jquery-1.11.3+dfsg/.babelrc 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.babelrc 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} diff -Nru jquery-1.11.3+dfsg/bower.json jquery-3.2.1/bower.json --- jquery-1.11.3+dfsg/bower.json 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/bower.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -{ - "name": "jquery", - "version": "1.11.3", - "main": "dist/jquery.js", - "license": "MIT", - "ignore": [ - "**/.*", - "build", - "dist/cdn", - "speed", - "test", - "*.md", - "AUTHORS.txt", - "Gruntfile.js", - "package.json" - ], - "devDependencies": { - "sizzle": "2.1.1-jquery.2.1.2", - "requirejs": "2.1.10", - "qunit": "1.14.0", - "sinon": "1.8.1" - }, - "keywords": [ - "jquery", - "javascript", - "library" - ] -} diff -Nru jquery-1.11.3+dfsg/.bowerrc jquery-3.2.1/.bowerrc --- jquery-1.11.3+dfsg/.bowerrc 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.bowerrc 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/build/release/cdn.js jquery-3.2.1/build/release/cdn.js --- jquery-1.11.3+dfsg/build/release/cdn.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/release/cdn.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,118 @@ +var + fs = require( "fs" ), + shell = require( "shelljs" ), + path = require( "path" ), + + cdnFolder = "dist/cdn", + + releaseFiles = { + "jquery-VER.js": "dist/jquery.js", + "jquery-VER.min.js": "dist/jquery.min.js", + "jquery-VER.min.map": "dist/jquery.min.map", + "jquery-VER.slim.js": "dist/jquery.slim.js", + "jquery-VER.slim.min.js": "dist/jquery.slim.min.js", + "jquery-VER.slim.min.map": "dist/jquery.slim.min.map" + }, + + googleFilesCDN = [ + "jquery.js", "jquery.min.js", "jquery.min.map", + "jquery.slim.js", "jquery.slim.min.js", "jquery.slim.min.map" + ], + + msFilesCDN = [ + "jquery-VER.js", "jquery-VER.min.js", "jquery-VER.min.map", + "jquery-VER.slim.js", "jquery-VER.slim.min.js", "jquery-VER.slim.min.map" + ]; + +/** + * Generates copies for the CDNs + */ +function makeReleaseCopies( Release ) { + shell.mkdir( "-p", cdnFolder ); + + Object.keys( releaseFiles ).forEach( function( key ) { + var text, + builtFile = releaseFiles[ key ], + unpathedFile = key.replace( /VER/g, Release.newVersion ), + releaseFile = cdnFolder + "/" + unpathedFile; + + if ( /\.map$/.test( releaseFile ) ) { + + // Map files need to reference the new uncompressed name; + // assume that all files reside in the same directory. + // "file":"jquery.min.js" ... "sources":["jquery.js"] + text = fs.readFileSync( builtFile, "utf8" ) + .replace( /"file":"([^"]+)"/, + "\"file\":\"" + unpathedFile.replace( /\.min\.map/, ".min.js\"" ) ) + .replace( /"sources":\["([^"]+)"\]/, + "\"sources\":[\"" + unpathedFile.replace( /\.min\.map/, ".js" ) + "\"]" ); + fs.writeFileSync( releaseFile, text ); + } else if ( builtFile !== releaseFile ) { + shell.cp( "-f", builtFile, releaseFile ); + } + } ); +} + +function makeArchives( Release, callback ) { + + Release.chdir( Release.dir.repo ); + + function makeArchive( cdn, files, callback ) { + if ( Release.preRelease ) { + console.log( "Skipping archive creation for " + cdn + "; this is a beta release." ); + callback(); + return; + } + + console.log( "Creating production archive for " + cdn ); + + var sum, + archiver = require( "archiver" )( "zip" ), + md5file = cdnFolder + "/" + cdn + "-md5.txt", + output = fs.createWriteStream( + cdnFolder + "/" + cdn + "-jquery-" + Release.newVersion + ".zip" + ), + rver = /VER/; + + output.on( "close", callback ); + + output.on( "error", function( err ) { + throw err; + } ); + + archiver.pipe( output ); + + files = files.map( function( item ) { + return "dist" + ( rver.test( item ) ? "/cdn" : "" ) + "/" + + item.replace( rver, Release.newVersion ); + } ); + + sum = Release.exec( "md5 -r " + files.join( " " ), "Error retrieving md5sum" ); + fs.writeFileSync( md5file, sum ); + files.push( md5file ); + + files.forEach( function( file ) { + archiver.append( fs.createReadStream( file ), + { name: path.basename( file ) } ); + } ); + + archiver.finalize(); + } + + function buildGoogleCDN( callback ) { + makeArchive( "googlecdn", googleFilesCDN, callback ); + } + + function buildMicrosoftCDN( callback ) { + makeArchive( "mscdn", msFilesCDN, callback ); + } + + buildGoogleCDN( function() { + buildMicrosoftCDN( callback ); + } ); +} + +module.exports = { + makeReleaseCopies: makeReleaseCopies, + makeArchives: makeArchives +}; diff -Nru jquery-1.11.3+dfsg/build/release/dist.js jquery-3.2.1/build/release/dist.js --- jquery-1.11.3+dfsg/build/release/dist.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/release/dist.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,159 @@ +module.exports = function( Release, files, complete ) { + + var + fs = require( "fs" ), + shell = require( "shelljs" ), + pkg = require( Release.dir.repo + "/package.json" ), + distRemote = Release.remote + + // For local and github dists + .replace( /jquery(\.git|$)/, "jquery-dist$1" ), + + // These files are included with the distribution + extras = [ + "src", + "LICENSE.txt", + "AUTHORS.txt", + "package.json" + ]; + + /** + * Clone the distribution repo + */ + function clone() { + Release.chdir( Release.dir.base ); + Release.dir.dist = Release.dir.base + "/dist"; + + console.log( "Using distribution repo: ", distRemote ); + Release.exec( "git clone " + distRemote + " " + Release.dir.dist, + "Error cloning repo." ); + + // Distribution always works on master + Release.chdir( Release.dir.dist ); + Release.exec( "git checkout master", "Error checking out branch." ); + console.log(); + } + + /** + * Generate bower file for jquery-dist + */ + function generateBower() { + return JSON.stringify( { + name: pkg.name, + main: pkg.main, + license: "MIT", + ignore: [ + "package.json" + ], + keywords: pkg.keywords + }, null, 2 ); + } + + /** + * Replace the version in the README + * @param {string} readme + */ + function editReadme( readme ) { + var rprev = new RegExp( Release.prevVersion, "g" ); + return readme.replace( rprev, Release.newVersion ); + } + + /** + * Copy necessary files over to the dist repo + */ + function copy() { + + // Copy dist files + var distFolder = Release.dir.dist + "/dist", + externalFolder = Release.dir.dist + "/external", + readme = fs.readFileSync( Release.dir.dist + "/README.md", "utf8" ), + rmIgnore = files + .concat( [ + "README.md", + "node_modules" + ] ) + .map( function( file ) { + return Release.dir.dist + "/" + file; + } ); + + shell.config.globOptions = { + ignore: rmIgnore + }; + + // Remove extraneous files before copy + shell.rm( "-rf", Release.dir.dist + "/**/*" ); + + shell.mkdir( "-p", distFolder ); + files.forEach( function( file ) { + shell.cp( "-f", Release.dir.repo + "/" + file, distFolder ); + } ); + + // Copy Sizzle + shell.mkdir( "-p", externalFolder ); + shell.cp( "-rf", Release.dir.repo + "/external/sizzle", externalFolder ); + + // Copy other files + extras.forEach( function( file ) { + shell.cp( "-rf", Release.dir.repo + "/" + file, Release.dir.dist ); + } ); + + // Remove the wrapper from the dist repo + shell.rm( "-f", Release.dir.dist + "/src/wrapper.js" ); + + // Write generated bower file + fs.writeFileSync( Release.dir.dist + "/bower.json", generateBower() ); + + fs.writeFileSync( Release.dir.dist + "/README.md", editReadme( readme ) ); + + console.log( "Files ready to add." ); + console.log( "Edit the dist README.md to include the latest blog post link." ); + } + + /** + * Add, commit, and tag the dist files + */ + function commit() { + console.log( "Adding files to dist..." ); + Release.exec( "git add -A", "Error adding files." ); + Release.exec( + "git commit -m \"Release " + Release.newVersion + "\"", + "Error committing files." + ); + console.log(); + + console.log( "Tagging release on dist..." ); + Release.exec( "git tag " + Release.newVersion, + "Error tagging " + Release.newVersion + " on dist repo." ); + Release.tagTime = Release.exec( "git log -1 --format=\"%ad\"", + "Error getting tag timestamp." ).trim(); + } + + /** + * Push files to dist repo + */ + function push() { + Release.chdir( Release.dir.dist ); + + console.log( "Pushing release to dist repo..." ); + Release.exec( "git push " + distRemote + " master --tags", + "Error pushing master and tags to git repo." ); + + // Set repo for npm publish + Release.dir.origRepo = Release.dir.repo; + Release.dir.repo = Release.dir.dist; + } + + Release.walk( [ + Release._section( "Copy files to distribution repo" ), + clone, + copy, + Release.confirmReview, + + Release._section( "Add, commit, and tag files in distribution repo" ), + commit, + Release.confirmReview, + + Release._section( "Pushing files to distribution repo" ), + push + ], complete ); +}; diff -Nru jquery-1.11.3+dfsg/build/release/ensure-sizzle.js jquery-3.2.1/build/release/ensure-sizzle.js --- jquery-1.11.3+dfsg/build/release/ensure-sizzle.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/release/ensure-sizzle.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,52 @@ +var fs = require( "fs" ), + npm = require( "npm" ), + chalk = require( "chalk" ), + sizzleLoc = __dirname + "/../../external/sizzle/dist/sizzle.js", + rversion = /Engine v(\d+\.\d+\.\d+(?:-[-\.\d\w]+)?)/; + +/** + * Retrieve the latest tag of Sizzle from npm + * @param {Function(string)} callback + */ +function getLatestSizzle( callback ) { + npm.load( function( err, npm ) { + if ( err ) { + throw err; + } + npm.commands.info( [ "sizzle", "version" ], function( err, info ) { + if ( err ) { + throw err; + } + callback( Object.keys( info )[ 0 ] ); + } ); + } ); +} + +/** + * Ensure the /src folder has the latest tag of Sizzle + * @param {Object} Release + * @param {Function} callback + */ +function ensureSizzle( Release, callback ) { + console.log(); + console.log( "Checking Sizzle version..." ); + getLatestSizzle( function( latest ) { + var match = rversion.exec( fs.readFileSync( sizzleLoc, "utf8" ) ), + version = match ? match[ 1 ] : "Not Found"; + + if ( version !== latest ) { + + // colors is inherited from jquery-release + console.log( + "The Sizzle version in the src folder (" + chalk.red( version ) + + ") is not the latest tag (" + chalk.green( latest ) + ")." + ); + Release.confirm( callback ); + } else { + console.log( "Sizzle is latest (" + chalk.green( latest ) + ")" ); + callback(); + } + } ); +} + +module.exports = ensureSizzle; diff -Nru jquery-1.11.3+dfsg/build/release.js jquery-3.2.1/build/release.js --- jquery-1.11.3+dfsg/build/release.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/build/release.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,113 +1,45 @@ +var fs = require( "fs" ); + module.exports = function( Release ) { var - fs = require( "fs" ), - shell = require( "shelljs" ), - - devFile = "dist/jquery.js", - minFile = "dist/jquery.min.js", - mapFile = "dist/jquery.min.map", - - cdnFolder = "dist/cdn", - - releaseFiles = { - "jquery-VER.js": devFile, - "jquery-VER.min.js": minFile, - "jquery-VER.min.map": mapFile - }, - - googleFilesCDN = [ - "jquery.js", "jquery.min.js", "jquery.min.map" + files = [ + "dist/jquery.js", + "dist/jquery.min.js", + "dist/jquery.min.map", + "dist/jquery.slim.js", + "dist/jquery.slim.min.js", + "dist/jquery.slim.min.map", + "src/core.js" ], + cdn = require( "./release/cdn" ), + dist = require( "./release/dist" ), + ensureSizzle = require( "./release/ensure-sizzle" ), - msFilesCDN = [ - "jquery-VER.js", "jquery-VER.min.js", "jquery-VER.min.map" - ], - - _complete = Release.complete; - - /** - * Generates copies for the CDNs - */ - function makeReleaseCopies() { - shell.mkdir( "-p", cdnFolder ); - - Object.keys( releaseFiles ).forEach(function( key ) { - var text, - builtFile = releaseFiles[ key ], - unpathedFile = key.replace( /VER/g, Release.newVersion ), - releaseFile = cdnFolder + "/" + unpathedFile; - - if ( /\.map$/.test( releaseFile ) ) { - // Map files need to reference the new uncompressed name; - // assume that all files reside in the same directory. - // "file":"jquery.min.js","sources":["jquery.js"] - text = fs.readFileSync( builtFile, "utf8" ) - .replace( /"file":"([^"]+)","sources":\["([^"]+)"\]/, - "\"file\":\"" + unpathedFile.replace( /\.min\.map/, ".min.js" ) + - "\",\"sources\":[\"" + unpathedFile.replace( /\.min\.map/, ".js" ) + "\"]" ); - fs.writeFileSync( releaseFile, text ); - } else if ( /\.min\.js$/.test( releaseFile ) ) { - // Remove the source map comment; it causes way too many problems. - // Keep the map file in case DevTools allow manual association. - text = fs.readFileSync( builtFile, "utf8" ) - .replace( /\/\/# sourceMappingURL=\S+/, "" ); - fs.writeFileSync( releaseFile, text ); - } else if ( builtFile !== releaseFile ) { - shell.cp( "-f", builtFile, releaseFile ); - } - }); - } - - function buildGoogleCDN() { - makeArchive( "googlecdn", googleFilesCDN ); - } - - function buildMicrosoftCDN() { - makeArchive( "mscdn", msFilesCDN ); - } - - function makeArchive( cdn, files ) { - if ( Release.preRelease ) { - console.log( "Skipping archive creation for " + cdn + "; this is a beta release." ); - return; - } + npmTags = Release.npmTags; - console.log( "Creating production archive for " + cdn ); - - var archiver = require( "archiver" )( "zip" ), - md5file = cdnFolder + "/" + cdn + "-md5.txt", - output = fs.createWriteStream( cdnFolder + "/" + cdn + "-jquery-" + Release.newVersion + ".zip" ); - - output.on( "error", function( err ) { - throw err; - }); - - archiver.pipe( output ); - - files = files.map(function( item ) { - return cdnFolder + "/" + item.replace( /VER/g, Release.newVersion ); - }); - - shell.exec( "md5sum", files, function( code, stdout ) { - fs.writeFileSync( md5file, stdout ); - files.push( md5file ); - - files.forEach(function( file ) { - archiver.append( fs.createReadStream( file ), { name: file } ); - }); + Release.define( { + npmPublish: true, + issueTracker: "github", - archiver.finalize(); - }); - } + /** + * Ensure the repo is in a proper state before release + * @param {Function} callback + */ + checkRepoState: function( callback ) { + ensureSizzle( Release, callback ); + }, - Release.define({ - npmPublish: true, - npmTags: function() { - return [ "1.x" ]; + /** + * Set the version in the src folder for distributing AMD + */ + _setSrcVersion: function() { + var corePath = __dirname + "/../src/core.js", + contents = fs.readFileSync( corePath, "utf8" ); + contents = contents.replace( /@VERSION/g, Release.newVersion ); + fs.writeFileSync( corePath, contents, "utf8" ); }, - issueTracker: "trac", - contributorReportId: 508, + /** * Generates any release artifacts that should be included in the release. * The callback must be invoked with an array of files that should be @@ -116,48 +48,43 @@ */ generateArtifacts: function( callback ) { Release.exec( "grunt", "Grunt command failed" ); - makeReleaseCopies(); - callback([ "dist/jquery.js", "dist/jquery.min.js", "dist/jquery.min.map" ]); + Release.exec( + "grunt custom:-ajax,-effects --filename=jquery.slim.js && " + + "grunt remove_map_comment --filename=jquery.slim.js", + "Grunt custom failed" + ); + cdn.makeReleaseCopies( Release ); + Release._setSrcVersion(); + callback( files ); }, + /** - * Release completion + * Acts as insertion point for restoring Release.dir.repo + * It was changed to reuse npm publish code in jquery-release + * for publishing the distribution repo instead */ - complete: function() { - // Build CDN archives async - buildGoogleCDN(); - buildMicrosoftCDN(); - _complete(); + npmTags: function() { + + // origRepo is not defined if dist was skipped + Release.dir.repo = Release.dir.origRepo || Release.dir.repo; + return npmTags(); }, + /** - * Our trac milestones are different than the new version - * @example - * - * // For Release.newVersion equal to 2.1.0 or 1.11.0 - * Release._tracMilestone(); - * // => 1.11/2.1 - * - * // For Release.newVersion equal to 2.1.1 or 1.11.1 - * Release._tracMilestone(); - * // => 1.11.1/2.1.1 + * Publish to distribution repo and npm + * @param {Function} callback */ - tracMilestone: function() { - var otherVersion, - m = Release.newVersion.split( "." ), - major = m[0] | 0, - minor = m[1] | 0, - patch = m[2] | 0 ? "." + m[2] : "", - version = major + "." + minor + patch; - if ( major === 1) { - otherVersion = "2." + ( minor - 10 ) + patch; - return version + "/" + otherVersion; - } - otherVersion = "1." + ( minor + 10 ) + patch; - return otherVersion + "/" + version; + dist: function( callback ) { + cdn.makeArchives( Release, function() { + dist( Release, files, callback ); + } ); } - }); + } ); }; module.exports.dependencies = [ - "archiver@0.5.2", - "shelljs@0.2.6" + "archiver@1.3.0", + "shelljs@0.7.7", + "npm@4.4.1", + "chalk@1.1.3" ]; diff -Nru jquery-1.11.3+dfsg/build/release-notes.js jquery-3.2.1/build/release-notes.js --- jquery-1.11.3+dfsg/build/release-notes.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/build/release-notes.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -#!/usr/bin/env node -/* - * jQuery Release Note Generator - */ - -var http = require("http"), - extract = /(.*?)<[^"]+"component">\s*(\S+)/g, - version = process.argv[2]; - -if ( !/^\d+\.\d+/.test( version ) ) { - console.error( "Invalid version number: " + version ); - process.exit( 1 ); -} - -http.request({ - host: "bugs.jquery.com", - port: 80, - method: "GET", - path: "/query?status=closed&resolution=fixed&max=400&component=!web&order=component&milestone=" + version -}, function( res ) { - var data = []; - - res.on( "data", function( chunk ) { - data.push( chunk ); - }); - - res.on( "end", function() { - var match, cur, cat, - file = data.join(""); - - while ( (match = extract.exec( file )) ) { - if ( "#" + match[1] !== match[2] ) { - cat = match[3]; - - if ( !cur || cur !== cat ) { - if ( cur ) { - console.log(""); - } - cur = cat; - console.log( "

" + cat.charAt(0).toUpperCase() + cat.slice(1) + "

" ); - console.log("
"); - } - - }); -}).end(); diff -Nru jquery-1.11.3+dfsg/build/tasks/build.js jquery-3.2.1/build/tasks/build.js --- jquery-1.11.3+dfsg/build/tasks/build.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/build/tasks/build.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,6 +1,7 @@ /** * Special concat/build task to handle various jQuery build requirements - * Concats AMD modules, removes their definitions, and includes/excludes specified modules + * Concats AMD modules, removes their definitions, + * and includes/excludes specified modules */ module.exports = function( grunt ) { @@ -9,24 +10,39 @@ var fs = require( "fs" ), requirejs = require( "requirejs" ), + Insight = require( "insight" ), + pkg = require( "../../package.json" ), srcFolder = __dirname + "/../../src/", - rdefineEnd = /\}\);[^}\w]*$/, + rdefineEnd = /\}\s*?\);[^}\w]*$/, + read = function( fileName ) { + return grunt.file.read( srcFolder + fileName ); + }, + + // Catch `// @CODE` and subsequent comment lines event if they don't start + // in the first column. + wrapper = read( "wrapper.js" ).split( /[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/ ), + config = { baseUrl: "src", name: "jquery", - out: "dist/jquery.js", + + // Allow strict mode + useStrict: true, + // We have multiple minify steps optimize: "none", + // Include dependencies loaded with require findNestedDependencies: true, + + // Avoid inserting define() placeholder + skipModuleInsertion: true, + // Avoid breaking semicolons inserted by r.js skipSemiColonInsertion: true, wrap: { - startFile: "src/intro.js", - endFile: "src/outro.js" - }, - paths: { - sizzle: "sizzle/dist/sizzle" + start: wrapper[ 0 ].replace( /\/\*\s*eslint(?: |-).*\s*\*\/\n/, "" ), + end: wrapper[ 1 ] }, rawText: {}, onBuildWrite: convert @@ -35,7 +51,8 @@ /** * Strip all definitions generated by requirejs * Convert "var" modules to var declarations - * "var module" means the module only contains a return statement that should be converted to a var declaration + * "var module" means the module only contains a return + * statement that should be converted to a var declaration * This is indicated by including the file in any "var" folder * @param {String} name * @param {String} path @@ -43,31 +60,36 @@ */ function convert( name, path, contents ) { var amdName; + // Convert var modules - if ( /.\/var\//.test( path ) ) { + if ( /.\/var\//.test( path.replace( process.cwd(), "" ) ) ) { contents = contents - .replace( /define\([\w\W]*?return/, "var " + (/var\/([\w-]+)/.exec(name)[1]) + " =" ) + .replace( + /define\([\w\W]*?return/, + "var " + + ( /var\/([\w-]+)/.exec( name )[ 1 ] ) + + " =" + ) .replace( rdefineEnd, "" ); // Sizzle treatment - } else if ( /^sizzle$/.test( name ) ) { + } else if ( /\/sizzle$/.test( name ) ) { contents = "var Sizzle =\n" + contents + // Remove EXPOSE lines from Sizzle .replace( /\/\/\s*EXPOSE[\w\W]*\/\/\s*EXPOSE/, "return Sizzle;" ); } else { - // Ignore jQuery's exports (the only necessary one) - if ( name !== "jquery" ) { - contents = contents - .replace( /\s*return\s+[^\}]+(\}\);[^\w\}]*)$/, "$1" ) - // Multiple exports - .replace( /\s*exports\.\w+\s*=\s*\w+;/g, "" ); - } + contents = contents + .replace( /\s*return\s+[^\}]+(\}\s*?\);[^\w\}]*)$/, "$1" ) + + // Multiple exports + .replace( /\s*exports\.\w+\s*=\s*\w+;/g, "" ); // Remove define wrappers, closure ends, and empty declarations contents = contents - .replace( /define\([^{]*?{/, "" ) + .replace( /define\([^{]*?{\s*(?:("|')use strict\1(?:;|))?/, "" ) .replace( rdefineEnd, "" ); // Remove anything wrapped with @@ -79,15 +101,17 @@ // Remove empty definitions contents = contents - .replace( /define\(\[[^\]]+\]\)[\W\n]+$/, "" ); + .replace( /define\(\[[^\]]*\]\)[\W\n]+$/, "" ); } + // AMD Name - if ( (amdName = grunt.option( "amd" )) != null && /^exports\/amd$/.test( name ) ) { - if (amdName) { + if ( ( amdName = grunt.option( "amd" ) ) != null && /^exports\/amd$/.test( name ) ) { + if ( amdName ) { grunt.log.writeln( "Naming jQuery with AMD name: " + amdName ); } else { grunt.log.writeln( "AMD name now anonymous" ); } + // Remove the comma for anonymous defines contents = contents .replace( /(\s*)"jquery"(\,\s*)/, amdName ? "$1\"" + amdName + "\"$2" : "" ); @@ -98,78 +122,107 @@ grunt.registerMultiTask( "build", - "Concatenate source, remove sub AMD definitions, (include/exclude modules with +/- flags), embed date/version", + "Concatenate source, remove sub AMD definitions, " + + "(include/exclude modules with +/- flags), embed date/version", function() { var flag, index, done = this.async(), flags = this.flags, optIn = flags[ "*" ], - name = this.data.dest, + name = grunt.option( "filename" ), minimum = this.data.minimum, removeWith = this.data.removeWith, excluded = [], included = [], version = grunt.config( "pkg.version" ), + /** * Recursively calls the excluder to remove on all modules in the list * @param {Array} list - * @param {String} [prepend] Prepend this to the module name. Indicates we're walking a directory + * @param {String} [prepend] Prepend this to the module name. + * Indicates we're walking a directory */ excludeList = function( list, prepend ) { if ( list ) { prepend = prepend ? prepend + "/" : ""; - list.forEach(function( module ) { + list.forEach( function( module ) { + // Exclude var modules as well if ( module === "var" ) { - excludeList( fs.readdirSync( srcFolder + prepend + module ), prepend + module ); + excludeList( + fs.readdirSync( srcFolder + prepend + module ), prepend + module + ); return; } if ( prepend ) { + // Skip if this is not a js file and we're walking files in a dir - if ( !(module = /([\w-\/]+)\.js$/.exec( module )) ) { + if ( !( module = /([\w-\/]+)\.js$/.exec( module ) ) ) { return; } + // Prepend folder name if passed // Remove .js extension - module = prepend + module[1]; + module = prepend + module[ 1 ]; } // Avoid infinite recursion if ( excluded.indexOf( module ) === -1 ) { excluder( "-" + module ); } - }); + } ); } }, + /** * Adds the specified module to the excluded or included list, depending on the flag - * @param {String} flag A module path relative to the src directory starting with + or - to indicate whether it should included or excluded + * @param {String} flag A module path relative to + * the src directory starting with + or - to indicate + * whether it should included or excluded */ excluder = function( flag ) { - var m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ), + var additional, + m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ), exclude = m[ 1 ] === "-", module = m[ 2 ]; if ( exclude ) { + // Can't exclude certain modules if ( minimum.indexOf( module ) === -1 ) { + // Add to excluded if ( excluded.indexOf( module ) === -1 ) { grunt.log.writeln( flag ); excluded.push( module ); + // Exclude all files in the folder of the same name // These are the removable dependencies // It's fine if the directory is not there try { excludeList( fs.readdirSync( srcFolder + module ), module ); - } catch( e ) { + } catch ( e ) { grunt.verbose.writeln( e ); } } + + additional = removeWith[ module ]; + // Check removeWith list - excludeList( removeWith[ module ] ); + if ( additional ) { + excludeList( additional.remove || additional ); + if ( additional.include ) { + included = included.concat( additional.include ); + grunt.log.writeln( "+" + additional.include ); + } + } } else { - grunt.log.error( "Module \"" + module + "\" is a mimimum requirement."); + grunt.log.error( "Module \"" + module + "\" is a minimum requirement." ); + if ( module === "selector" ) { + grunt.log.error( + "If you meant to replace Sizzle, use -sizzle instead." + ); + } } } else { grunt.log.writeln( flag ); @@ -177,6 +230,11 @@ } }; + // Filename can be passed to the command line using + // command line options + // e.g. grunt build --filename=jquery-custom.js + name = name ? ( "dist/" + name ) : this.data.dest; + // append commit id to version if ( process.env.COMMIT ) { version += " " + process.env.COMMIT; @@ -192,15 +250,24 @@ // * none (implicit exclude) // *:* all (implicit include) // *:*:-css all except css and dependents (explicit > implicit) - // *:*:-css:+effects same (excludes effects because explicit include is trumped by explicit exclude of dependency) - // *:+effects none except effects and its dependencies (explicit include trumps implicit exclude of dependency) + // *:*:-css:+effects same (excludes effects because explicit include is + // trumped by explicit exclude of dependency) + // *:+effects none except effects and its dependencies + // (explicit include trumps implicit exclude of dependency) delete flags[ "*" ]; for ( flag in flags ) { excluder( flag ); } + // Handle Sizzle exclusion + // Replace with selector-native + if ( ( index = excluded.indexOf( "sizzle" ) ) > -1 ) { + config.rawText.selector = "define(['./selector-native']);"; + excluded.splice( index, 1 ); + } + // Replace exports/global with a noop noConflict - if ( (index = excluded.indexOf( "exports/global" )) > -1 ) { + if ( ( index = excluded.indexOf( "exports/global" ) ) > -1 ) { config.rawText[ "exports/global" ] = "define(['../core']," + "function( jQuery ) {\njQuery.noConflict = function() {};\n});"; excluded.splice( index, 1 ); @@ -212,9 +279,11 @@ // append excluded modules to version if ( excluded.length ) { version += " -" + excluded.join( ",-" ); + // set pkg.version to version with excludes, so minified file picks it up grunt.config.set( "pkg.version", version ); grunt.verbose.writeln( "Version changed to " + version ); + // Have to use shallow or core will get excluded since it is a dependency config.excludeShallow = excluded; } @@ -226,8 +295,10 @@ */ config.out = function( compiled ) { compiled = compiled + // Embed Version .replace( /@VERSION/g, version ) + // Embed Date // yyyy-mm-ddThh:mmZ .replace( /@DATE/g, ( new Date() ).toISOString().replace( /:\d+\.\d+Z$/, "Z" ) ); @@ -238,8 +309,11 @@ // Turn off opt-in if necessary if ( !optIn ) { + // Overwrite the default inclusions with the explicit ones provided - config.rawText.jquery = "define([" + (included.length ? included.join(",") : "") + "]);"; + config.rawText.jquery = "define([" + + ( included.length ? included.join( "," ) : "" ) + + "]);"; } // Trace dependencies and concatenate files @@ -249,8 +323,8 @@ done(); }, function( err ) { done( err ); - }); - }); + } ); + } ); // Special "alias" task to make custom build creation less grawlix-y // Translation example @@ -262,10 +336,47 @@ // grunt build:*:*:+ajax:-dimensions:-effects:-offset grunt.registerTask( "custom", function() { var args = this.args, - modules = args.length ? args[ 0 ].replace( /,/g, ":" ) : ""; + modules = args.length ? args[ 0 ].replace( /,/g, ":" ) : "", + done = this.async(), + insight = new Insight( { + trackingCode: "UA-1076265-4", + pkg: pkg + } ); + + function exec( trackingAllowed ) { + var tracks = args.length ? args[ 0 ].split( "," ) : []; + var defaultPath = [ "build", "custom" ]; + + tracks = tracks.map( function( track ) { + return track.replace( /\//g, "+" ); + } ); + + if ( trackingAllowed ) { + + // Track individuals + tracks.forEach( function( module ) { + var path = defaultPath.concat( [ "individual" ], module ); + + insight.track.apply( insight, path ); + } ); + + // Track full command + insight.track.apply( insight, defaultPath.concat( [ "full" ], tracks ) ); + } + + grunt.task.run( [ "build:*:*" + ( modules ? ":" + modules : "" ), "uglify", "dist" ] ); + done(); + } grunt.log.writeln( "Creating custom build...\n" ); - grunt.task.run([ "build:*:*" + (modules ? ":" + modules : ""), "uglify", "dist" ]); - }); + // Ask for permission the first time + if ( insight.optOut === undefined ) { + insight.askPermission( null, function( error, result ) { + exec( result ); + } ); + } else { + exec( !insight.optOut ); + } + } ); }; diff -Nru jquery-1.11.3+dfsg/build/tasks/dist.js jquery-3.2.1/build/tasks/dist.js --- jquery-1.11.3+dfsg/build/tasks/dist.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/build/tasks/dist.js 2017-03-20 19:00:06.000000000 +0000 @@ -2,11 +2,12 @@ "use strict"; - var fs = require( "fs" ), + var fs = require( "fs" ), + filename = grunt.option( "filename" ), distpaths = [ - "dist/jquery.js", - "dist/jquery.min.map", - "dist/jquery.min.js" + "dist/" + filename, + "dist/" + filename.replace( ".js", ".min.map" ), + "dist/" + filename.replace( ".js", ".min.js" ) ]; // Process files for distribution @@ -21,14 +22,14 @@ flags = Object.keys( this.flags ); // Combine all output target paths - paths = [].concat( stored, flags ).filter(function( path ) { + paths = [].concat( stored, flags ).filter( function( path ) { return path !== "*"; - }); + } ); // Ensure the dist files are pure ASCII nonascii = false; - distpaths.forEach(function( filename ) { + distpaths.forEach( function( filename ) { var i, c, text = fs.readFileSync( filename, "utf8" ); @@ -53,7 +54,7 @@ } // Optionally copy dist files to other locations - paths.forEach(function( path ) { + paths.forEach( function( path ) { var created; if ( !/\/$/.test( path ) ) { @@ -63,9 +64,9 @@ created = path + filename.replace( "dist/", "" ); grunt.file.write( created, text ); grunt.log.writeln( "File '" + created + "' created." ); - }); - }); + } ); + } ); return !nonascii; - }); + } ); }; diff -Nru jquery-1.11.3+dfsg/build/tasks/lib/spawn_test.js jquery-3.2.1/build/tasks/lib/spawn_test.js --- jquery-1.11.3+dfsg/build/tasks/lib/spawn_test.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/tasks/lib/spawn_test.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,14 @@ +"use strict"; + +// Run Node with provided parameters: the first one being the Grunt +// done function and latter ones being files to be tested. +// See the comment in ../node_smoke_tests.js for more information. +module.exports = function spawnTest( done ) { + var testPaths = [].slice.call( arguments, 1 ), + spawn = require( "cross-spawn" ); + + spawn( "node", testPaths, { stdio: "inherit" } ) + .on( "close", function( code ) { + done( code === 0 ); + } ); +}; diff -Nru jquery-1.11.3+dfsg/build/tasks/node_smoke_tests.js jquery-3.2.1/build/tasks/node_smoke_tests.js --- jquery-1.11.3+dfsg/build/tasks/node_smoke_tests.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/tasks/node_smoke_tests.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,32 @@ +module.exports = function( grunt ) { + + "use strict"; + + var fs = require( "fs" ), + spawnTest = require( "./lib/spawn_test.js" ), + testsDir = "./test/node_smoke_tests/", + nodeSmokeTests = [ "babel:nodeSmokeTests" ]; + + // Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes. + // All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code + // on success or another one on failure. Spawning in sub-processes is + // important so that the tests & the main process don't interfere with + // each other, e.g. so that they don't share the require cache. + + fs.readdirSync( testsDir ) + .filter( function( testFilePath ) { + return fs.statSync( testsDir + testFilePath ).isFile() && + /\.js$/.test( testFilePath ); + } ) + .forEach( function( testFilePath ) { + var taskName = "node_" + testFilePath.replace( /\.js$/, "" ); + + grunt.registerTask( taskName, function() { + spawnTest( this.async(), "test/node_smoke_tests/" + testFilePath ); + } ); + + nodeSmokeTests.push( taskName ); + } ); + + grunt.registerTask( "node_smoke_tests", nodeSmokeTests ); +}; diff -Nru jquery-1.11.3+dfsg/build/tasks/promises_aplus_tests.js jquery-3.2.1/build/tasks/promises_aplus_tests.js --- jquery-1.11.3+dfsg/build/tasks/promises_aplus_tests.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/tasks/promises_aplus_tests.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,23 @@ +module.exports = function( grunt ) { + + "use strict"; + + var spawnTest = require( "./lib/spawn_test.js" ); + + grunt.registerTask( "promises_aplus_tests", + [ "promises_aplus_tests:deferred", "promises_aplus_tests:when" ] ); + + grunt.registerTask( "promises_aplus_tests:deferred", function() { + spawnTest( this.async(), + "./node_modules/.bin/promises-aplus-tests", + "test/promises_aplus_adapters/deferred.js" + ); + } ); + + grunt.registerTask( "promises_aplus_tests:when", function() { + spawnTest( this.async(), + "./node_modules/.bin/promises-aplus-tests", + "test/promises_aplus_adapters/when.js" + ); + } ); +}; diff -Nru jquery-1.11.3+dfsg/build/tasks/sourcemap.js jquery-3.2.1/build/tasks/sourcemap.js --- jquery-1.11.3+dfsg/build/tasks/sourcemap.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/build/tasks/sourcemap.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,15 @@ +var fs = require( "fs" ); + +module.exports = function( grunt ) { + var config = grunt.config( "uglify.all.files" ); + grunt.registerTask( "remove_map_comment", function() { + var minLoc = grunt.config.process( Object.keys( config )[ 0 ] ); + + // Remove the source map comment; it causes way too many problems. + // The map file is still generated for manual associations + // https://github.com/jquery/jquery/issues/1707 + var text = fs.readFileSync( minLoc, "utf8" ) + .replace( /\/\/# sourceMappingURL=\S+/, "" ); + fs.writeFileSync( minLoc, text ); + } ); +}; diff -Nru jquery-1.11.3+dfsg/build/tasks/testswarm.js jquery-3.2.1/build/tasks/testswarm.js --- jquery-1.11.3+dfsg/build/tasks/testswarm.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/build/tasks/testswarm.js 2017-03-20 19:00:06.000000000 +0000 @@ -3,7 +3,7 @@ "use strict"; grunt.registerTask( "testswarm", function( commit, configFile, projectName, browserSets, - timeout ) { + timeout, testMode ) { var jobName, config, tests, testswarm = require( "testswarm" ), runs = {}, @@ -14,11 +14,12 @@ config = grunt.file.readJSON( configFile )[ projectName ]; browserSets = browserSets || config.browserSets; if ( browserSets[ 0 ] === "[" ) { + // We got an array, parse it browserSets = JSON.parse( browserSets ); } timeout = timeout || 1000 * 60 * 15; - tests = grunt.config([ this.name, "tests" ]); + tests = grunt.config( [ this.name, "tests" ] ); if ( pull ) { jobName = "Pull " + commit.substr( 0, 10 ) + ""; } - tests.forEach(function( test ) { - runs[ test ] = config.testUrl + commit + "/test/index.html?module=" + test; - }); + if ( testMode === "basic" ) { + runs.basic = config.testUrl + commit + "/test/index.html?module=basic"; + } else { + tests.forEach( function( test ) { + runs[ test ] = config.testUrl + commit + "/test/index.html?module=" + test; + } ); + } - testswarm.createClient({ + testswarm.createClient( { url: config.swarmUrl } ) .addReporter( testswarm.reporters.cli ) .auth( { id: config.authUsername, token: config.authToken - }) + } ) .addjob( { name: jobName, @@ -54,5 +59,5 @@ done( passed ); } ); - }); + } ); }; diff -Nru jquery-1.11.3+dfsg/CONTRIBUTING.md jquery-3.2.1/CONTRIBUTING.md --- jquery-1.11.3+dfsg/CONTRIBUTING.md 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/CONTRIBUTING.md 2017-03-20 19:00:06.000000000 +0000 @@ -1,89 +1,71 @@ # Contributing to jQuery 1. [Getting Involved](#getting-involved) -2. [Discussion](#discussion) +2. [Questions and Discussion](#questions-and-discussion) 3. [How To Report Bugs](#how-to-report-bugs) -4. [Core Style Guide](#jquery-core-style-guide) -5. [Tips For Bug Patching](#tips-for-bug-patching) - +4. [Tips for Bug Patching](#tips-for-bug-patching) +Note: This is the code development repository for *jQuery Core* only. Before opening an issue or making a pull request, be sure you're in the right place. +* jQuery plugin issues should be reported to the author of the plugin. +* jQuery Core API documentation issues can be filed [at the API repo](https://github.com/jquery/api.jquery.com/issues). +* Bugs or suggestions for other jQuery organization projects should be filed in [their respective repos](https://github.com/jquery/). ## Getting Involved -There are a number of ways to get involved with the development of jQuery core. Even if you've never contributed code to an Open Source project before, we're always looking for help identifying bugs, writing and reducing test cases and documentation. +[API design principles](https://github.com/jquery/jquery/wiki/API-design-guidelines) + +We're always looking for help [identifying bugs](#how-to-report-bugs), writing and reducing test cases, and improving documentation. And although new features are rare, anything passing our [guidelines](https://github.com/jquery/jquery/wiki/Adding-new-features) will be considered. -This is the best way to contribute to jQuery core. Please read through the full guide detailing [How to Report Bugs](#how-to-report-bugs). +More information on how to contribute to this and other jQuery organization projects is at [contribute.jquery.org](https://contribute.jquery.org), including a short guide with tips, tricks, and ideas on [getting started with open source](https://contribute.jquery.org/open-source/). Please review our [commit & pull request guide](https://contribute.jquery.org/commits-and-pull-requests/) and [style guides](https://contribute.jquery.org/style-guide/) for instructions on how to maintain a fork and submit patches. Before we can merge any pull request, we'll also need you to sign our [contributor license agreement](https://contribute.jquery.org/cla/). -## Discussion + +## Questions and Discussion ### Forum and IRC -The jQuery core development team frequently tracks posts on the [jQuery Development Forum](http://forum.jquery.com/developing-jquery-core). If you have longer posts or questions please feel free to post them there. If you think you've found a bug please [file it in the bug tracker](#how-to-report-bugs). +jQuery is so popular that many developers have knowledge of its capabilities and limitations. Most questions about using jQuery can be answered on popular forums such as [Stack Overflow](https://stackoverflow.com). Please start there when you have questions, even if you think you've found a bug. -Additionally most of the jQuery core development team can be found in the [#jquery-dev](http://webchat.freenode.net/?channels=jquery-dev) IRC channel on irc.freenode.net. +The jQuery Core team watches the [jQuery Development Forum](https://forum.jquery.com/developing-jquery-core). If you have longer posts or questions that can't be answered in places such as Stack Overflow, please feel free to post them there. If you think you've found a bug, please [file it in the bug tracker](#how-to-report-bugs). The Core team can be found in the [#jquery-dev](https://webchat.freenode.net/?channels=jquery-dev) IRC channel on irc.freenode.net. ### Weekly Status Meetings -Every week (unless otherwise noted) the jQuery core dev team has a meeting to discuss the progress of current work and to bring forward possible new blocker bugs for discussion. - -The meeting is held in the [#jquery-meeting](http://webchat.freenode.net/?channels=jquery-meeting) IRC channel on irc.freenode.net at [Noon EST](http://www.timeanddate.com/worldclock/fixedtime.html?month=1&day=17&year=2011&hour=12&min=0&sec=0&p1=43) on Mondays. +The jQuery Core team has a weekly meeting to discuss the progress of current work. The meeting is held in the [#jquery-meeting](https://webchat.freenode.net/?channels=jquery-meeting) IRC channel on irc.freenode.net at [Noon EST](https://www.timeanddate.com/worldclock/fixedtime.html?month=1&day=17&year=2011&hour=12&min=0&sec=0&p1=43) on Mondays. -[Past Meeting Notes](https://docs.google.com/document/d/1MrLFvoxW7GMlH9KK-bwypn77cC98jUnz7sMW1rg_TP4/edit?hl=en) +[jQuery Core Meeting Notes](https://meetings.jquery.org/category/core/) ## How to Report Bugs ### Make sure it is a jQuery bug -Many bugs reported to our bug tracker are actually bugs in user code, not in jQuery code. Keep in mind that just because your code throws an error and the console points to a line number inside of jQuery, this does *not* mean the bug is a jQuery bug; more often than not, these errors result from providing incorrect arguments when calling a jQuery function. +Most bugs reported to our bug tracker are actually bugs in user code, not in jQuery code. Keep in mind that just because your code throws an error inside of jQuery, this does *not* mean the bug is a jQuery bug. -If you are new to jQuery, it is usually a much better idea to ask for help first in the [Using jQuery Forum](http://forum.jquery.com/using-jquery) or the [jQuery IRC channel](http://webchat.freenode.net/?channels=%23jquery). You will get much quicker support, and you will help avoid tying up the jQuery team with invalid bug reports. These same resources can also be useful if you want to confirm that your bug is indeed a bug in jQuery before filing any tickets. +Ask for help first in the [Using jQuery Forum](https://forum.jquery.com/using-jquery) or another discussion forum like [Stack Overflow](https://stackoverflow.com/). You will get much quicker support, and you will help avoid tying up the jQuery team with invalid bug reports. - -### Disable any browser extensions +### Disable browser extensions Make sure you have reproduced the bug with all browser extensions and add-ons disabled, as these can sometimes cause things to break in interesting and unpredictable ways. Try using incognito, stealth or anonymous browsing modes. - ### Try the latest version of jQuery -Bugs in old versions of jQuery may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the [latest build](http://code.jquery.com/jquery.js). - -### Try an older version of jQuery +Bugs in old versions of jQuery may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the [latest build](https://code.jquery.com/jquery.js). We cannot fix bugs in older released files, if a bug has been fixed in a subsequent version of jQuery the site should upgrade. -Sometimes, bugs are introduced in newer versions of jQuery that do not exist in previous versions. When possible, it can be useful to try testing with an older release. +### Simplify the test case -### Reduce, reduce, reduce! +When experiencing a problem, [reduce your code](https://webkit.org/quality/reduction.html) to the bare minimum required to reproduce the issue. This makes it *much* easier to isolate and fix the offending code. Bugs reported without reduced test cases take on average 9001% longer to fix than bugs that are submitted with them, so you really should try to do this if at all possible. -When you are experiencing a problem, the most useful thing you can possibly do is to [reduce your code](http://webkit.org/quality/reduction.html) to the bare minimum required to reproduce the issue. This makes it *much* easier to isolate and fix the offending code. Bugs that are reported without reduced test cases take on average 9001% longer to fix than bugs that are submitted with them, so you really should try to do this if at all possible. +### Search for related or duplicate issues -## jQuery Core Style Guide +Go to the [jQuery Core issue tracker](https://github.com/jquery/jquery/issues) and make sure the problem hasn't already been reported. If not, create a new issue there and include your test case. -See: [jQuery's Style Guides](http://contribute.jquery.org/style-guide/) ## Tips For Bug Patching - -### Environment: localhost w/ PHP, Node & Grunt - -Starting in jQuery 1.8, a newly overhauled development workflow has been introduced. In this new system, we rely on node & gruntjs to automate the building and validation of source code—while you write code. - -The Ajax tests still depend on PHP running locally*, so make sure you have the following installed: - -* Some kind of localhost server program that supports PHP (any will do) -* Node.js -* NPM (comes with the latest version of Node.js) -* Grunt (install with: `npm install grunt -g` - - -Maintaining a list of platform specific instructions is outside of the scope of this document and there is plenty of existing documentation for the above technologies. - -* The PHP dependency will soon be shed in favor of an all-node solution. - +We *love* when people contribute back to the project by patching the bugs they find. Since jQuery is used by so many people, we are cautious about the patches we accept and want to be sure they don't have a negative impact on the millions of people using jQuery each day. For that reason it can take a while for any suggested patch to work its way through the review and release process. The reward for you is knowing that the problem you fixed will improve things for millions of sites and billions of visits per day. ### Build a Local Copy of jQuery -Create a fork of the jQuery repo on github at http://github.com/jquery/jquery +Create a fork of the jQuery repo on github at https://github.com/jquery/jquery Change directory to your web root directory, whatever that might be: @@ -115,10 +97,10 @@ $ git pull upstream master ``` -Run the Grunt tools: +Run the build script ```bash -$ grunt && grunt watch +$ npm run build ``` Now open the jQuery test suite in a browser at http://localhost/test. If there is a port, be sure to include it. @@ -126,89 +108,38 @@ Success! You just built and tested jQuery! -### Fix a bug from a ticket filed at bugs.jquery.com: - -**NEVER write your patches to the master branch** - it gets messy (I say this from experience!) - -**ALWAYS USE A "TOPIC" BRANCH!** Like so (#### = the ticket #)... - -Make sure you start with your up-to-date master: - -```bash -$ git checkout master -``` - -Create and checkout a new branch that includes the ticket # - -```bash -$ git checkout -b bug_#### - -# ( Explanation: this useful command will: -# "checkout" a "-b" (branch) by the name of "bug_####" -# or create it if it doesn't exist ) -``` - -Now you're on branch: bug_#### - -Determine the module/file you'll be working in... - -Open up the corresponding /test/unit/?????.js and add the initial failing unit tests. This may seem awkward at first, but in the long run it will make sense. To truly and efficiently patch a bug, you need to be working against that bug. - -Next, open the module files and make your changes - -Run http://localhost/test --> **ALL TESTS MUST PASS** - -Once you're satisfied with your patch... - -Stage the files to be tracked: - -```bash -$ git add filename -# (you can use "git status" to list the files you've changed) -``` - +### Test Suite Tips... -( I recommend NEVER, EVER using "git add . " ) +During the process of writing your patch, you will run the test suite MANY times. You can speed up the process by narrowing the running test suite down to the module you are testing by either double clicking the title of the test or appending it to the url. The following examples assume you're working on a local repo, hosted on your localhost server. -Once you've staged all of your changed files, go ahead and commit them +Example: -```bash -$ git commit -m "Brief description of fix. Fixes #0000" -``` +http://localhost/test/?module=css -For a multiple line commit message, leave off the `-m "description"`. +This will only run the "css" module tests. This will significantly speed up your development and debugging. -You will then be led into vi (or the text editor that you have set up) to complete your commit message. +**ALWAYS RUN THE FULL SUITE BEFORE COMMITTING AND PUSHING A PATCH!** -Then, push your branch with the bug fix commits to your github fork -```bash -$ git push origin -u bug_#### -``` +#### Loading changes on the test page -Before you tackle your next bug patch, return to the master: +Rather than rebuilding jQuery with `grunt` every time you make a change, you can use the included `grunt watch` task to rebuild distribution files whenever a file is saved. ```bash -$ git checkout master +$ grunt watch ``` +Alternatively, you can **load tests in AMD** to avoid the need for rebuilding altogether. +Click "Load with AMD" after loading the test page. -### Test Suite Tips... -During the process of writing your patch, you will run the test suite MANY times. You can speed up the process by narrowing the running test suite down to the module you are testing by either double clicking the title of the test or appending it to the url. The following examples assume you're working on a local repo, hosted on your localhost server. +### Repo organization -Example: - -http://localhost/test/?filter=css - -This will only run the "css" module tests. This will significantly speed up your development and debugging. - -**ALWAYS RUN THE FULL SUITE BEFORE COMMITTING AND PUSHING A PATCH!** +The jQuery source is organized with AMD modules and then concatenated and compiled at build time. +jQuery also contains some special modules we call "var modules", which are placed in folders named "var". At build time, these small modules are compiled to simple var statements. This makes it easy for us to share variables across modules. Browse the "src" folder for examples. ### Browser support -Remember that jQuery supports multiple browsers and their versions; any contributed code must work in all of them. You can refer to the [browser support page](http://jquery.com/browser-support/) for the current list of supported browsers. - -Note that browser support differs depending on whether you are targeting the `master` or `1.x-master` branch. +Remember that jQuery supports multiple browsers and their versions; any contributed code must work in all of them. You can refer to the [browser support page](https://jquery.com/browser-support/) for the current list of supported browsers. diff -Nru jquery-1.11.3+dfsg/debian/build.js jquery-3.2.1/debian/build.js --- jquery-1.11.3+dfsg/debian/build.js 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/build.js 2017-09-02 23:36:32.000000000 +0000 @@ -11,11 +11,11 @@ // Avoid breaking semicolons inserted by r.js skipSemiColonInsertion: true, wrap: { - startFile: "src/intro.js", - endFile: "src/outro.js" + startFile: "start.js", + endFile: "end.js" }, paths: { - sizzle: "sizzle/dist/sizzle" + sizzle: "../external/sizzle/dist/sizzle" }, rawText: {}, /** @@ -28,7 +28,7 @@ * @param {String} contents The contents to be written (including their AMD wrappers) */ onBuildWrite: function( name, path, contents ) { - var rdefineEnd = /\}\);[^}\w]*$/; + var rdefineEnd = /\}\s*?\);[^}\w]*$/; var amdName; // Convert var modules if ( /.\/var\//.test( path ) ) { @@ -36,12 +36,15 @@ .replace( /define\([\w\W]*?return/, "var " + (/var\/([\w-]+)/.exec(name)[1]) + " =" ) .replace( rdefineEnd, "" ); // Sizzle treatment - } else if ( /^sizzle$/.test( name ) ) { + } else if ( /\/sizzle$/.test( name ) ) { contents = "var Sizzle =\n" + contents // Remove EXPOSE lines from Sizzle .replace( /\/\/\s*EXPOSE[\w\W]*\/\/\s*EXPOSE/, "return Sizzle;" ); } else { + contents = contents + .replace( /\s*return\s+[^\}]+(\}\s*?\);[^\w\}]*)$/, "$1" ) + // Ignore jQuery's exports (the only necessary one) if ( name !== "jquery" ) { @@ -49,11 +52,13 @@ .replace( /\s*return\s+[^\}]+(\}\);[^\w\}]*)$/, "$1" ) // Multiple exports .replace( /\s*exports\.\w+\s*=\s*\w+;/g, "" ); + } else { + contents = contents.replace(/return.*;/, ''); } // Remove define wrappers, closure ends, and empty declarations contents = contents - .replace( /define\([^{]*?{/, "" ) + .replace( /define\([^{]*?{\s*(?:("|')use strict\1(?:;|))?/, "" ) .replace( rdefineEnd, "" ); // Remove anything wrapped with diff -Nru jquery-1.11.3+dfsg/debian/changelog jquery-3.2.1/debian/changelog --- jquery-1.11.3+dfsg/debian/changelog 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/changelog 2020-11-02 19:17:09.000000000 +0000 @@ -1,3 +1,137 @@ +jquery (3.2.1-1~16.04.sav0) xenial; urgency=medium + + * Backport to Xenial + + -- Rob Savoury Mon, 02 Nov 2020 11:17:09 -0800 + +jquery (3.2.1-1) unstable; urgency=medium + + [ Antonio Terceiro ] + + * Drop myself from Uploaders:. I have no intention of working in this + package anymore. + + [ Marcelo Jorge Vieira ] + + * New upstream version 3.2.1 + * Changed section from 'web' to 'javascript' + * Drop Steve Kemp from uploaders + * Bump Standards-Version to 4.0.0 (no changes) + + -- Marcelo Jorge Vieira Sat, 02 Sep 2017 21:14:01 -0300 + +jquery (3.1.1-2) unstable; urgency=medium + + * debian/rules: adapt path to r.js after a change in nodejs-requirejs + (Closes: #847740) + + -- Antonio Terceiro Sun, 11 Dec 2016 13:18:53 -0200 + +jquery (3.1.1-1) unstable; urgency=medium + + * Uploading jQuery 3.x to unstable + * New upstream version 3.1.1 + * debian/rules, debian/build.js: adapt Debian build to changes in upstream + build + * Bump Standards-Version to 3.9.8; no changes needed. + + -- Antonio Terceiro Sun, 16 Oct 2016 14:34:46 -0200 + +jquery (3.0.0~beta1-1) experimental; urgency=medium + + * New upstream release + - Drop `compat` branch, which has also been dropped upstream. + See http://blog.jquery.com/2016/01/14/jquery-3-0-beta-released/ + for details + - Removed embedded copies of external libraries (of which some didn't have + proper sources and only provided minified code): + - external/npo + - external/qunit + - external/qunit-assert-step + - external/requirejs + - external/sinon + * Drop the version number mangling to add a `+dfsg` suffix. First the + changes from upstream are not due to the DFSG, but are removing pre-built + Javascript files, which is not a problem according to the DFSG, but a + policy. Second, if the package is in the Debian main component, obviously + it complies with the DFSG. Anyway, the files removed are documented in + debian/copyright. + - debian/watch: remove version mangling options. + - debian/rules: updated version number parsing + - debian/tests/check-against-upstream-build: updated version number parsing + * debian/build.js: adapt to changes in upstream build system + * debian/rules: change date formatting to cope with changes in output + of `date --iso-8601=m` starting with coreutils 8.25 + * debian/control: + - bump Standards-Version to 3.9.7; no changes needed + - use https URLs in Vcs-* + * debian/tests/check-against-upstream-build: download upstream build over + https + * debian/rules: add simple build-time tests on override_dh_auto_test + + -- Antonio Terceiro Sat, 09 Apr 2016 14:30:31 -0300 + +jquery (3.0.0~alpha1+dfsg-2) experimental; urgency=medium + + * remove unused lintian overrides + * debian/minify: remove `//# sourceMappingURL=..` magic comment, as uptream + does (Closes: #799825) + + -- Antonio Terceiro Wed, 23 Sep 2015 09:33:43 -0300 + +jquery (3.0.0~alpha1+dfsg-1) experimental; urgency=medium + + * New upstream release. Includes: + - the regular release (successor to jQuery 2.x) in + /usr/share/javascript/jquery/ + - the "compat" branch (successor to jquery 1.x) in + /usr/share/javascript/jquery-compat/ + * debian/watch: + - also look for alpha/beta versions + - automate adding +dfsg to downloaded upstream tarballs + - call debian/prepare-tarball to prepare the tarball used as upstream + source. See debian/README.source.md. + * Added DEP-8 tests: + - debian/tests/check-against-upstream-build: checks that our build matches + upstream's. + + -- Antonio Terceiro Wed, 02 Sep 2015 11:01:01 -0300 + +jquery (1.12.3-1) unstable; urgency=medium + + * New upstream release + - debian/build.js: port applicable upstream changes in + build/tasks/build.js since previous version + - Bundled copies of external libraries removed: + - external/npo + - external/qunit + - external/qunit-assert-step + - external/requirejs + - external/sinon + * Drop the version number mangling to add a `+dfsg` suffix. First the + changes from upstream are not due to the DFSG, but are removing pre-built + Javascript files, which is not a problem according to the DFSG, but a + policy. Second, if the package is in the Debian main component, obviously + it complies with the DFSG. Anyway, the files removed are documented in + debian/copyright. + - debian/watch: remove version mangling options. + * Copy and adapt autopkgtest tests from experimental branch + - debian/tests/check-against-upstream-build: use https instead of http for + retrieving upstream release + * debian/rules: + - cope with removal of upstream version mangling + - change date formatting to cope with changes in output of `date + --iso-8601=m` starting with coreutils 8.25 + - drop workaround for bug in upstream build that has been fixed + - add a simple build-time test under override_dh_auto_test + * debian/control: + - Bump Standards-Version to 3.9.7, no changes needed + - Use https in Vcs-* URLs + * debian/copyright: + - cope with the location change for sizzle + + -- Antonio Terceiro Sat, 09 Apr 2016 10:55:14 -0300 + jquery (1.11.3+dfsg-4) unstable; urgency=medium * debian/rules: remove `//# sourceMappingURL=..` magic comment from minified diff -Nru jquery-1.11.3+dfsg/debian/control jquery-3.2.1/debian/control --- jquery-1.11.3+dfsg/debian/control 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/control 2017-09-03 00:14:01.000000000 +0000 @@ -1,18 +1,16 @@ Source: jquery -Section: web +Section: javascript Priority: optional Maintainer: Debian Javascript Maintainers -Uploaders: Marcelo Jorge Vieira (metal) , - Steve Kemp , - Antonio Terceiro +Uploaders: Marcelo Jorge Vieira Build-Depends: debhelper (>= 9~), node-requirejs, node-source-map, node-uglify, nodejs, -Standards-Version: 3.9.6 +Standards-Version: 4.0.0 Homepage: http://jquery.com/ -Vcs-Git: git://anonscm.debian.org/pkg-javascript/jquery.git +Vcs-Git: https://anonscm.debian.org/git/pkg-javascript/jquery.git Vcs-Browser: https://anonscm.debian.org/cgit/pkg-javascript/jquery.git Package: libjs-jquery diff -Nru jquery-1.11.3+dfsg/debian/copyright jquery-3.2.1/debian/copyright --- jquery-1.11.3+dfsg/debian/copyright 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/copyright 2017-09-02 23:36:32.000000000 +0000 @@ -2,7 +2,7 @@ Upstream-Name: jQuery Source: http://jquery.com/ Comment: For more details on developers please see http://docs.jquery.com/Contributors -Files-Excluded: dist +Files-Excluded: dist external/npo external/qunit external/qunit-assert-step external/requirejs external/sinon Files: * Copyright: 2005-2011 John Resig, Brandon Aaron & Jörn Zaefferer @@ -12,13 +12,14 @@ Copyright: 2011, The Dojo Foundation License: MIT or BSD-3-clause or GPL-2 -Files: src/sizzle/* +Files: external/sizzle/* Copyright: 2011, The Dojo Foundation License: MIT or BSD-3-clause or GPL-2 Files: debian/* Copyright: 2008 Steve Kemp 2010 Marcelo Jorge Vieira + 2015-2016 Antonio Terceiro License: GPL-2 or MIT License: GPL-2 diff -Nru jquery-1.11.3+dfsg/debian/gbp.conf jquery-3.2.1/debian/gbp.conf --- jquery-1.11.3+dfsg/debian/gbp.conf 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -[DEFAULT] -debian-branch = debian/1.x diff -Nru jquery-1.11.3+dfsg/debian/install jquery-3.2.1/debian/install --- jquery-1.11.3+dfsg/debian/install 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/install 2017-09-02 23:36:32.000000000 +0000 @@ -1,2 +1,2 @@ -dist/*.js /usr/share/javascript/jquery -dist/*.map /usr/share/javascript/jquery +dist/*.js /usr/share/javascript/jquery +dist/*.map /usr/share/javascript/jquery diff -Nru jquery-1.11.3+dfsg/debian/links jquery-3.2.1/debian/links --- jquery-1.11.3+dfsg/debian/links 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/links 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -/usr/share/javascript/jquery/jquery.min.js /usr/share/javascript/jquery/jquery.lite.js -/usr/share/javascript/jquery/jquery.min.js /usr/share/javascript/jquery/jquery.pack.js diff -Nru jquery-1.11.3+dfsg/debian/minify jquery-3.2.1/debian/minify --- jquery-1.11.3+dfsg/debian/minify 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/debian/minify 2017-09-02 23:36:32.000000000 +0000 @@ -0,0 +1,14 @@ +#!/bin/sh + +output="$1" + +set -x + +uglifyjs \ + --source-map ${output%%.js}.min.map \ + --source-map-url jquery.min.map \ + --output ${output%%.js}.min.js \ + "$output" + +# remove sourceMappingURL comment, as upstream does +sed -i -e '/\/\/# sourceMappingURL=\S\+/ d' ${output%%.js}.min.js diff -Nru jquery-1.11.3+dfsg/debian/patches/fixedTests.diff jquery-3.2.1/debian/patches/fixedTests.diff --- jquery-1.11.3+dfsg/debian/patches/fixedTests.diff 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/debian/patches/fixedTests.diff 2017-09-02 23:46:52.000000000 +0000 @@ -0,0 +1,26 @@ +--- a/test/index.html ++++ b/test/index.html +@@ -3,7 +3,7 @@ + + + jQuery Test Suite +- ++ + + + + + +- +- +- +- +- ++ ++ ++ + + + diff -Nru jquery-1.11.3+dfsg/debian/release-check jquery-3.2.1/debian/release-check --- jquery-1.11.3+dfsg/debian/release-check 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/release-check 2017-09-02 23:36:32.000000000 +0000 @@ -2,25 +2,9 @@ set -e - -cachedir=$HOME/.cache/jquery-debian -mkdir -p $cachedir -version=$(dpkg-parsechangelog -SVersion | cut -d + -f 1) -if [ ! -f $cachedir/jquery-${version}.js ]; then - wget --directory-prefix=$cachedir http://code.jquery.com/jquery-${version}.js -fi - -./debian/rules dist/jquery.js +./debian/rules override_dh_auto_build rc=0 -diff --ignore-blank-line \ - --ignore-matching-lines=Date:.*Z \ - -u $cachedir/jquery-${version}.js dist/jquery.js || rc=$? +./debian/tests/check-against-upstream-build dist/jquery.js || rc=$? +./debian/tests/check-minification dist/jquery.min.js || rc=$? ./debian/rules clean - -if [ "$rc" -ne 0 ]; then - printf "Proceed? [y/N]" - read proceed - if [ "$proceed" != y -a "$proceed" != Y ]; then - exit 1 - fi -fi +exit $rc diff -Nru jquery-1.11.3+dfsg/debian/rules jquery-3.2.1/debian/rules --- jquery-1.11.3+dfsg/debian/rules 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/rules 2017-09-03 00:07:21.000000000 +0000 @@ -1,8 +1,8 @@ #!/usr/bin/make -f source = $(shell find src/ -name '*.js') -timestamp = $(shell date --iso-8601=minutes --utc --date="$(shell dpkg-parsechangelog -S Date)" | sed -e 's/+0000/Z/') -version = $(shell dpkg-parsechangelog -SVersion | cut -d + -f 1) +timestamp = $(shell date --iso-8601=minutes --utc --date="$(shell dpkg-parsechangelog -S Date)" | sed -e 's/+00:\?00/Z/') +version = $(shell dpkg-parsechangelog -SVersion | cut -d - -f 1 | sed 's/~/-/') override_dh_auto_build: dist/jquery.js dist/jquery.min.js dist/jquery.min.map dh_auto_build @@ -10,22 +10,30 @@ build.js: debian/build.js cp $< $@ -dist/jquery.js: build.js $(source) - nodejs /usr/lib/nodejs/r.js -o build.js +dist/jquery.js: start.js end.js build.js $(source) + nodejs /usr/lib/nodejs/requirejs/r.js -o build.js sed -i -e 's/@DATE/$(timestamp)/; s/@VERSION/$(version)/' $@ - sed -i -e 's/\/\/"use strict";/\/\//' $@ + @echo "Checking syntax of $@ ..." + nodejs --check $@ || (mv $@ $@.failed; false) + +start.js: src/wrapper.js + sed -e '/^\/\*\s*eslint-/d; /^\/\/ @CODE/,$$ d' $< > $@ || ($(RM) $@; false) + +end.js: src/wrapper.js + sed -e '1,/^\/\/ @CODE/ d; /\/\/ build.js inserts compiled jQuery here/d' $< > $@ || ($(RM) $@; false) dist/jquery.min.js dist/jquery.min.map: dist/jquery.js - uglifyjs \ - --source-map dist/jquery.min.map \ - --source-map-url jquery.min.map \ - --output dist/jquery.min.js \ - $^ - sed -i -e '/\/\/# sourceMappingURL=\S\+/ d' dist/jquery.min.js + ./debian/minify $^ + +override_dh_auto_test: + nodejs --check dist/jquery.js + nodejs --check dist/jquery.min.js + ./debian/tests/check-minification dist/jquery.min.js override_dh_auto_clean: $(RM) -rf dist/ $(RM) build.js + $(RM) start.js end.js dh_auto_clean %: diff -Nru jquery-1.11.3+dfsg/debian/source.lintian-overrides jquery-3.2.1/debian/source.lintian-overrides --- jquery-1.11.3+dfsg/debian/source.lintian-overrides 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/source.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -jquery source: license-problem-json-evil debian/README.Debian diff -Nru jquery-1.11.3+dfsg/debian/tests/check-against-upstream-build jquery-3.2.1/debian/tests/check-against-upstream-build --- jquery-1.11.3+dfsg/debian/tests/check-against-upstream-build 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/debian/tests/check-against-upstream-build 2017-09-02 23:36:32.000000000 +0000 @@ -0,0 +1,30 @@ +#!/bin/sh + +exec 2>&1 + +set -ex + +version=$(dpkg-parsechangelog -SVersion | cut -d - -f 1 | sed 's/~/-/') + +build="$1" +if [ -z "$build" ]; then + build='/usr/share/javascript/jquery/jquery.js' +fi + +upstream_cache="$ADTTMP" +if [ -z "$upstream_cache" ]; then + upstream_cache=$HOME/.cache/jquery-debian + mkdir -p "$upstream_cache" +fi +upstream_build=$upstream_cache/jquery-${version}.js + +if [ ! -f "$upstream_build" ]; then + wget --output-document="$upstream_build" \ + https://code.jquery.com/jquery-${version}.js +fi + +diff --ignore-blank-lines \ + --ignore-matching-lines=Date:.*Z \ + --ignore-matching-lines='^\s*"use strict";\s*$' \ + -u "$upstream_build" "$build" + diff -Nru jquery-1.11.3+dfsg/debian/tests/check-minification jquery-3.2.1/debian/tests/check-minification --- jquery-1.11.3+dfsg/debian/tests/check-minification 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/debian/tests/check-minification 2017-09-02 23:36:32.000000000 +0000 @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +rc=0 + +if [ $# -eq 0 ]; then + eval set -- /usr/share/javascript/jquery/jquery.min.js +fi + +for minjs in "$@"; do + if grep -q '^..# sourceMappingURL=' $minjs; then + echo "E: $minjs contains '//# sourceMappingURL=.*'" + rc=1 + fi +done + +exit $rc diff -Nru jquery-1.11.3+dfsg/debian/tests/control jquery-3.2.1/debian/tests/control --- jquery-1.11.3+dfsg/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/debian/tests/control 2017-09-02 23:36:32.000000000 +0000 @@ -0,0 +1,2 @@ +Tests: check-against-upstream-build, check-minification +Depends: @, wget, ca-certificates diff -Nru jquery-1.11.3+dfsg/debian/watch jquery-3.2.1/debian/watch --- jquery-1.11.3+dfsg/debian/watch 2015-09-23 12:32:05.000000000 +0000 +++ jquery-3.2.1/debian/watch 2017-09-02 23:36:32.000000000 +0000 @@ -1,4 +1,3 @@ version=3 -opts="dversionmangle=s/[+]dfsg(.?\d+)?$//" \ -https://github.com/jquery/jquery/releases \ - .*/(1\.[\d\.]+).tar.gz +opts="uversionmangle=s/-/~/;" \ +https://github.com/jquery/jquery/releases .*/([0-9][0-9a-z.-]+)\.tar\.gz diff -Nru jquery-1.11.3+dfsg/.editorconfig jquery-3.2.1/.editorconfig --- jquery-1.11.3+dfsg/.editorconfig 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.editorconfig 2017-03-20 19:00:06.000000000 +0000 @@ -3,41 +3,14 @@ root = true - [*] +indent_style = tab end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -# Tabs in JS unless otherwise specified -[**.js] -indent_style = tab - -[Makefile] -indent_style = tab - - -[speed/**.html] -indent_style = tab - -[speed/**.css] -indent_style = tab - -[speed/benchmarker.js] +[package.json] indent_style = space indent_size = 2 - -[test/**.xml] -indent_style = tab - -[test/**.php] -indent_style = tab - -[test/**.html] -indent_style = tab - -[test/**.css] -indent_style = space -indent_size = 8 diff -Nru jquery-1.11.3+dfsg/.eslintignore jquery-3.2.1/.eslintignore --- jquery-1.11.3+dfsg/.eslintignore 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.eslintignore 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,14 @@ +external +node_modules +*.min.js +dist/** +!dist/jquery.js +test/data/jquery-1.9.1.js +test/data/badcall.js +test/data/badjson.js +test/data/json_obj.js +test/data/readywaitasset.js +test/data/readywaitloader.js +test/data/support/csp.js +test/data/support/getComputedSupport.js +test/node_smoke_tests/lib/ensure_iterability.js diff -Nru jquery-1.11.3+dfsg/.eslintrc-browser.json jquery-3.2.1/.eslintrc-browser.json --- jquery-1.11.3+dfsg/.eslintrc-browser.json 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.eslintrc-browser.json 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,31 @@ +{ + "root": true, + + "extends": "jquery", + + // Support: IE <=9 only, Android <=4.0 only + // The above browsers are failing a lot of tests in the ES5 + // test suite at http://test262.ecmascript.org. + "parserOptions": { + "ecmaVersion": 3 + }, + + // The browser env is not enabled on purpose so that code takes + // all browser-only globals from window instead of assuming + // they're available as globals. This makes it possible to use + // jQuery with tools like jsdom which provide a custom window + // implementation. + "env": {}, + + "globals": { + "window": true, + "jQuery": true, + "define": true, + "module": true, + "noGlobal": true + }, + + "rules": { + "strict": ["error", "function"] + } +} diff -Nru jquery-1.11.3+dfsg/.eslintrc.json jquery-3.2.1/.eslintrc.json --- jquery-1.11.3+dfsg/.eslintrc.json 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.eslintrc.json 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,5 @@ +{ + "root": true, + + "extends": "./.eslintrc-node.json" +} diff -Nru jquery-1.11.3+dfsg/.eslintrc-node.json jquery-3.2.1/.eslintrc-node.json --- jquery-1.11.3+dfsg/.eslintrc-node.json 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.eslintrc-node.json 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,13 @@ +{ + "root": true, + + "extends": "jquery", + + "parserOptions": { + "ecmaVersion": 5 + }, + + "env": { + "node": true + } +} diff -Nru jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.js jquery-3.2.1/external/sizzle/dist/sizzle.js --- jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/external/sizzle/dist/sizzle.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,2272 @@ +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +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 hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // 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 ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + 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 ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return 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']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[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 (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[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[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && 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.replace( rwhitespace, " " ) + " " ).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, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + 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 + + // ...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 ] || + + // 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 ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + 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; + } + + // 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; + } + } + } + } + } + + // 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( 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 ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( 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 negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + 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; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( 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, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "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 ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // 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 ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + 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 + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +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 multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +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( 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( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // 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 || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // 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 ); + } + } + } + + // `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++]) ) { + 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, match /* 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 ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // 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 ) { + + // 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" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + 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 ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +// EXPOSE +var _sizzle = window.Sizzle; + +Sizzle.noConflict = function() { + if ( window.Sizzle === Sizzle ) { + window.Sizzle = _sizzle; + } + + return Sizzle; +}; + +if ( typeof define === "function" && define.amd ) { + define(function() { return Sizzle; }); +// Sizzle requires that there be a global window in Common-JS like environments +} else if ( typeof module !== "undefined" && module.exports ) { + module.exports = Sizzle; +} else { + window.Sizzle = Sizzle; +} +// EXPOSE + +})( window ); diff -Nru jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.min.js jquery-3.2.1/external/sizzle/dist/sizzle.min.js --- jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.min.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/external/sizzle/dist/sizzle.min.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,3 @@ +/*! Sizzle v2.3.3 | (c) jQuery Foundation, Inc. | jquery.org/license */ +!function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null});var Aa=a.Sizzle;ga.noConflict=function(){return a.Sizzle===ga&&(a.Sizzle=Aa),ga},"function"==typeof define&&define.amd?define(function(){return ga}):"undefined"!=typeof module&&module.exports?module.exports=ga:a.Sizzle=ga}(window); +//# sourceMappingURL=sizzle.min.map \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.min.map jquery-3.2.1/external/sizzle/dist/sizzle.min.map --- jquery-1.11.3+dfsg/external/sizzle/dist/sizzle.min.map 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/external/sizzle/dist/sizzle.min.map 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1 @@ +{"version":3,"sources":["sizzle.js"],"names":["window","i","support","Expr","getText","isXML","tokenize","compile","select","outermostContext","sortInput","hasDuplicate","setDocument","document","docElem","documentIsHTML","rbuggyQSA","rbuggyMatches","matches","contains","expando","Date","preferredDoc","dirruns","done","classCache","createCache","tokenCache","compilerCache","sortOrder","a","b","hasOwn","hasOwnProperty","arr","pop","push_native","push","slice","indexOf","list","elem","len","length","booleans","whitespace","identifier","attributes","pseudos","rwhitespace","RegExp","rtrim","rcomma","rcombinators","rattributeQuotes","rpseudo","ridentifier","matchExpr","ID","CLASS","TAG","ATTR","PSEUDO","CHILD","bool","needsContext","rinputs","rheader","rnative","rquickExpr","rsibling","runescape","funescape","_","escaped","escapedWhitespace","high","String","fromCharCode","rcssescape","fcssescape","ch","asCodePoint","charCodeAt","toString","unloadHandler","disabledAncestor","addCombinator","disabled","dir","next","apply","call","childNodes","nodeType","e","target","els","j","Sizzle","selector","context","results","seed","m","nid","match","groups","newSelector","newContext","ownerDocument","exec","getElementById","id","getElementsByTagName","getElementsByClassName","qsa","test","nodeName","toLowerCase","getAttribute","replace","setAttribute","toSelector","join","testContext","parentNode","querySelectorAll","qsaError","removeAttribute","keys","cache","key","value","cacheLength","shift","markFunction","fn","assert","el","createElement","removeChild","addHandle","attrs","handler","split","attrHandle","siblingCheck","cur","diff","sourceIndex","nextSibling","createInputPseudo","type","name","createButtonPseudo","createDisabledPseudo","isDisabled","createPositionalPseudo","argument","matchIndexes","documentElement","node","hasCompare","subWindow","doc","defaultView","top","addEventListener","attachEvent","className","appendChild","createComment","getById","getElementsByName","filter","attrId","find","getAttributeNode","elems","tag","tmp","innerHTML","input","matchesSelector","webkitMatchesSelector","mozMatchesSelector","oMatchesSelector","msMatchesSelector","disconnectedMatch","compareDocumentPosition","adown","bup","compare","sortDetached","aup","ap","bp","unshift","expr","elements","ret","attr","val","undefined","specified","escape","sel","error","msg","Error","uniqueSort","duplicates","detectDuplicates","sortStable","sort","splice","textContent","firstChild","nodeValue","selectors","createPseudo","relative",">","first"," ","+","~","preFilter","excess","unquoted","nodeNameSelector","pattern","operator","check","result","what","last","simple","forward","ofType","xml","uniqueCache","outerCache","nodeIndex","start","parent","useCache","lastChild","uniqueID","pseudo","args","setFilters","idx","matched","not","matcher","unmatched","has","text","innerText","lang","elemLang","hash","location","root","focus","activeElement","hasFocus","href","tabIndex","enabled","checked","selected","selectedIndex","empty","header","button","eq","even","odd","lt","gt","radio","checkbox","file","password","image","submit","reset","prototype","filters","parseOnly","tokens","soFar","preFilters","cached","combinator","base","skip","checkNonElements","doneName","oldCache","newCache","elementMatcher","matchers","multipleContexts","contexts","condense","map","newUnmatched","mapped","setMatcher","postFilter","postFinder","postSelector","temp","preMap","postMap","preexisting","matcherIn","matcherOut","matcherFromTokens","checkContext","leadingRelative","implicitRelative","matchContext","matchAnyContext","concat","matcherFromGroupMatchers","elementMatchers","setMatchers","bySet","byElement","superMatcher","outermost","matchedCount","setMatched","contextBackup","dirrunsUnique","Math","random","token","compiled","defaultValue","_sizzle","noConflict","define","amd","module","exports"],"mappings":";CAUA,SAAWA,GAEX,GAAIC,GACHC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAGAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAGAC,EAAU,SAAW,EAAI,GAAIC,MAC7BC,EAAetB,EAAOa,SACtBU,EAAU,EACVC,EAAO,EACPC,EAAaC,KACbC,EAAaD,KACbE,EAAgBF,KAChBG,EAAY,SAAUC,EAAGC,GAIxB,MAHKD,KAAMC,IACVpB,GAAe,GAET,GAIRqB,KAAcC,eACdC,KACAC,EAAMD,EAAIC,IACVC,EAAcF,EAAIG,KAClBA,EAAOH,EAAIG,KACXC,EAAQJ,EAAII,MAGZC,EAAU,SAAUC,EAAMC,GAGzB,IAFA,GAAIxC,GAAI,EACPyC,EAAMF,EAAKG,OACJ1C,EAAIyC,EAAKzC,IAChB,GAAKuC,EAAKvC,KAAOwC,EAChB,MAAOxC,EAGT,WAGD2C,EAAW,6HAKXC,EAAa,sBAGbC,EAAa,gCAGbC,EAAa,MAAQF,EAAa,KAAOC,EAAa,OAASD,EAE9D,gBAAkBA,EAElB,2DAA6DC,EAAa,OAASD,EACnF,OAEDG,EAAU,KAAOF,EAAa,wFAKAC,EAAa,eAM3CE,EAAc,GAAIC,QAAQL,EAAa,IAAK,KAC5CM,EAAQ,GAAID,QAAQ,IAAML,EAAa,8BAAgCA,EAAa,KAAM,KAE1FO,EAAS,GAAIF,QAAQ,IAAML,EAAa,KAAOA,EAAa,KAC5DQ,EAAe,GAAIH,QAAQ,IAAML,EAAa,WAAaA,EAAa,IAAMA,EAAa,KAE3FS,EAAmB,GAAIJ,QAAQ,IAAML,EAAa,iBAAmBA,EAAa,OAAQ,KAE1FU,EAAU,GAAIL,QAAQF,GACtBQ,EAAc,GAAIN,QAAQ,IAAMJ,EAAa,KAE7CW,GACCC,GAAM,GAAIR,QAAQ,MAAQJ,EAAa,KACvCa,MAAS,GAAIT,QAAQ,QAAUJ,EAAa,KAC5Cc,IAAO,GAAIV,QAAQ,KAAOJ,EAAa,SACvCe,KAAQ,GAAIX,QAAQ,IAAMH,GAC1Be,OAAU,GAAIZ,QAAQ,IAAMF,GAC5Be,MAAS,GAAIb,QAAQ,yDAA2DL,EAC/E,+BAAiCA,EAAa,cAAgBA,EAC9D,aAAeA,EAAa,SAAU,KACvCmB,KAAQ,GAAId,QAAQ,OAASN,EAAW,KAAM,KAG9CqB,aAAgB,GAAIf,QAAQ,IAAML,EAAa,mDAC9CA,EAAa,mBAAqBA,EAAa,mBAAoB,MAGrEqB,EAAU,sCACVC,EAAU,SAEVC,EAAU,yBAGVC,EAAa,mCAEbC,EAAW,OAIXC,EAAY,GAAIrB,QAAQ,qBAAuBL,EAAa,MAAQA,EAAa,OAAQ,MACzF2B,GAAY,SAAUC,EAAGC,EAASC,GACjC,GAAIC,GAAO,KAAOF,EAAU,KAI5B,OAAOE,KAASA,GAAQD,EACvBD,EACAE,EAAO,EAENC,OAAOC,aAAcF,EAAO,OAE5BC,OAAOC,aAAcF,GAAQ,GAAK,MAAe,KAAPA,EAAe,QAK5DG,GAAa,sDACbC,GAAa,SAAUC,EAAIC,GAC1B,MAAKA,GAGQ,OAAPD,EACG,SAIDA,EAAG3C,MAAO,MAAU,KAAO2C,EAAGE,WAAYF,EAAGtC,OAAS,GAAIyC,SAAU,IAAO,IAI5E,KAAOH,GAOfI,GAAgB,WACfzE,KAGD0E,GAAmBC,GAClB,SAAU9C,GACT,MAAOA,GAAK+C,YAAa,IAAS,QAAU/C,IAAQ,SAAWA,MAE9DgD,IAAK,aAAcC,KAAM,UAI7B,KACCrD,EAAKsD,MACHzD,EAAMI,EAAMsD,KAAMtE,EAAauE,YAChCvE,EAAauE,YAId3D,EAAKZ,EAAauE,WAAWlD,QAASmD,SACrC,MAAQC,IACT1D,GAASsD,MAAOzD,EAAIS,OAGnB,SAAUqD,EAAQC,GACjB7D,EAAYuD,MAAOK,EAAQ1D,EAAMsD,KAAKK,KAKvC,SAAUD,EAAQC,GACjB,GAAIC,GAAIF,EAAOrD,OACd1C,EAAI,CAEL,OAAS+F,EAAOE,KAAOD,EAAIhG,MAC3B+F,EAAOrD,OAASuD,EAAI,IAKvB,QAASC,IAAQC,EAAUC,EAASC,EAASC,GAC5C,GAAIC,GAAGvG,EAAGwC,EAAMgE,EAAKC,EAAOC,EAAQC,EACnCC,EAAaR,GAAWA,EAAQS,cAGhChB,EAAWO,EAAUA,EAAQP,SAAW,CAKzC,IAHAQ,EAAUA,MAGe,gBAAbF,KAA0BA,GACxB,IAAbN,GAA+B,IAAbA,GAA+B,KAAbA,EAEpC,MAAOQ,EAIR,KAAMC,KAEEF,EAAUA,EAAQS,eAAiBT,EAAU/E,KAAmBT,GACtED,EAAayF,GAEdA,EAAUA,GAAWxF,EAEhBE,GAAiB,CAIrB,GAAkB,KAAb+E,IAAoBY,EAAQrC,EAAW0C,KAAMX,IAGjD,GAAMI,EAAIE,EAAM,IAGf,GAAkB,IAAbZ,EAAiB,CACrB,KAAMrD,EAAO4D,EAAQW,eAAgBR,IAUpC,MAAOF,EALP,IAAK7D,EAAKwE,KAAOT,EAEhB,MADAF,GAAQjE,KAAMI,GACP6D,MAYT,IAAKO,IAAepE,EAAOoE,EAAWG,eAAgBR,KACrDrF,EAAUkF,EAAS5D,IACnBA,EAAKwE,KAAOT,EAGZ,MADAF,GAAQjE,KAAMI,GACP6D,MAKH,CAAA,GAAKI,EAAM,GAEjB,MADArE,GAAKsD,MAAOW,EAASD,EAAQa,qBAAsBd,IAC5CE,CAGD,KAAME,EAAIE,EAAM,KAAOxG,EAAQiH,wBACrCd,EAAQc,uBAGR,MADA9E,GAAKsD,MAAOW,EAASD,EAAQc,uBAAwBX,IAC9CF,EAKT,GAAKpG,EAAQkH,MACXxF,EAAewE,EAAW,QACzBpF,IAAcA,EAAUqG,KAAMjB,IAAc,CAE9C,GAAkB,IAAbN,EACJe,EAAaR,EACbO,EAAcR,MAMR,IAAwC,WAAnCC,EAAQiB,SAASC,cAA6B,EAGnDd,EAAMJ,EAAQmB,aAAc,OACjCf,EAAMA,EAAIgB,QAAS1C,GAAYC,IAE/BqB,EAAQqB,aAAc,KAAOjB,EAAMrF,GAIpCuF,EAASrG,EAAU8F,GACnBnG,EAAI0G,EAAOhE,MACX,OAAQ1C,IACP0G,EAAO1G,GAAK,IAAMwG,EAAM,IAAMkB,GAAYhB,EAAO1G,GAElD2G,GAAcD,EAAOiB,KAAM,KAG3Bf,EAAavC,EAAS+C,KAAMjB,IAAcyB,GAAaxB,EAAQyB,aAC9DzB,EAGF,GAAKO,EACJ,IAIC,MAHAvE,GAAKsD,MAAOW,EACXO,EAAWkB,iBAAkBnB,IAEvBN,EACN,MAAQ0B,IACR,QACIvB,IAAQrF,GACZiF,EAAQ4B,gBAAiB,QAS/B,MAAOzH,GAAQ4F,EAASqB,QAAStE,EAAO,MAAQkD,EAASC,EAASC,GASnE,QAAS7E,MACR,GAAIwG,KAEJ,SAASC,GAAOC,EAAKC,GAMpB,MAJKH,GAAK7F,KAAM+F,EAAM,KAAQjI,EAAKmI,mBAE3BH,GAAOD,EAAKK,SAEZJ,EAAOC,EAAM,KAAQC,EAE9B,MAAOF,GAOR,QAASK,IAAcC,GAEtB,MADAA,GAAIrH,IAAY,EACTqH,EAOR,QAASC,IAAQD,GAChB,GAAIE,GAAK9H,EAAS+H,cAAc,WAEhC,KACC,QAASH,EAAIE,GACZ,MAAO5C,GACR,OAAO,EACN,QAEI4C,EAAGb,YACPa,EAAGb,WAAWe,YAAaF,GAG5BA,EAAK,MASP,QAASG,IAAWC,EAAOC,GAC1B,GAAI9G,GAAM6G,EAAME,MAAM,KACrBhJ,EAAIiC,EAAIS,MAET,OAAQ1C,IACPE,EAAK+I,WAAYhH,EAAIjC,IAAO+I,EAU9B,QAASG,IAAcrH,EAAGC,GACzB,GAAIqH,GAAMrH,GAAKD,EACduH,EAAOD,GAAsB,IAAftH,EAAEgE,UAAiC,IAAf/D,EAAE+D,UACnChE,EAAEwH,YAAcvH,EAAEuH,WAGpB,IAAKD,EACJ,MAAOA,EAIR,IAAKD,EACJ,MAASA,EAAMA,EAAIG,YAClB,GAAKH,IAAQrH,EACZ,QAKH,OAAOD,GAAI,KAOZ,QAAS0H,IAAmBC,GAC3B,MAAO,UAAUhH,GAChB,GAAIiH,GAAOjH,EAAK6E,SAASC,aACzB,OAAgB,UAATmC,GAAoBjH,EAAKgH,OAASA,GAQ3C,QAASE,IAAoBF,GAC5B,MAAO,UAAUhH,GAChB,GAAIiH,GAAOjH,EAAK6E,SAASC,aACzB,QAAiB,UAATmC,GAA6B,WAATA,IAAsBjH,EAAKgH,OAASA,GAQlE,QAASG,IAAsBpE,GAG9B,MAAO,UAAU/C,GAKhB,MAAK,QAAUA,GASTA,EAAKqF,YAAcrF,EAAK+C,YAAa,EAGpC,SAAW/C,GACV,SAAWA,GAAKqF,WACbrF,EAAKqF,WAAWtC,WAAaA,EAE7B/C,EAAK+C,WAAaA,EAMpB/C,EAAKoH,aAAerE,GAI1B/C,EAAKoH,cAAgBrE,GACpBF,GAAkB7C,KAAW+C,EAGzB/C,EAAK+C,WAAaA,EAKd,SAAW/C,IACfA,EAAK+C,WAAaA,GAY5B,QAASsE,IAAwBrB,GAChC,MAAOD,IAAa,SAAUuB,GAE7B,MADAA,IAAYA,EACLvB,GAAa,SAAUjC,EAAMrF,GACnC,GAAIgF,GACH8D,EAAevB,KAAQlC,EAAK5D,OAAQoH,GACpC9J,EAAI+J,EAAarH,MAGlB,OAAQ1C,IACFsG,EAAOL,EAAI8D,EAAa/J,MAC5BsG,EAAKL,KAAOhF,EAAQgF,GAAKK,EAAKL,SAYnC,QAAS2B,IAAaxB,GACrB,MAAOA,IAAmD,mBAAjCA,GAAQa,sBAAwCb,EAI1EnG,EAAUiG,GAAOjG,WAOjBG,EAAQ8F,GAAO9F,MAAQ,SAAUoC,GAGhC,GAAIwH,GAAkBxH,IAASA,EAAKqE,eAAiBrE,GAAMwH,eAC3D,SAAOA,GAA+C,SAA7BA,EAAgB3C,UAQ1C1G,EAAcuF,GAAOvF,YAAc,SAAUsJ,GAC5C,GAAIC,GAAYC,EACfC,EAAMH,EAAOA,EAAKpD,eAAiBoD,EAAO5I,CAG3C,OAAK+I,KAAQxJ,GAA6B,IAAjBwJ,EAAIvE,UAAmBuE,EAAIJ,iBAKpDpJ,EAAWwJ,EACXvJ,EAAUD,EAASoJ,gBACnBlJ,GAAkBV,EAAOQ,GAIpBS,IAAiBT,IACpBuJ,EAAYvJ,EAASyJ,cAAgBF,EAAUG,MAAQH,IAGnDA,EAAUI,iBACdJ,EAAUI,iBAAkB,SAAUnF,IAAe,GAG1C+E,EAAUK,aACrBL,EAAUK,YAAa,WAAYpF,KAUrCnF,EAAQ6C,WAAa2F,GAAO,SAAUC,GAErC,MADAA,GAAG+B,UAAY,KACP/B,EAAGnB,aAAa,eAOzBtH,EAAQgH,qBAAuBwB,GAAO,SAAUC,GAE/C,MADAA,GAAGgC,YAAa9J,EAAS+J,cAAc,MAC/BjC,EAAGzB,qBAAqB,KAAKvE,SAItCzC,EAAQiH,uBAAyB/C,EAAQiD,KAAMxG,EAASsG,wBAMxDjH,EAAQ2K,QAAUnC,GAAO,SAAUC,GAElC,MADA7H,GAAQ6J,YAAahC,GAAK1B,GAAK7F,GACvBP,EAASiK,oBAAsBjK,EAASiK,kBAAmB1J,GAAUuB,SAIzEzC,EAAQ2K,SACZ1K,EAAK4K,OAAW,GAAI,SAAU9D,GAC7B,GAAI+D,GAAS/D,EAAGQ,QAASlD,EAAWC,GACpC,OAAO,UAAU/B,GAChB,MAAOA,GAAK+E,aAAa,QAAUwD,IAGrC7K,EAAK8K,KAAS,GAAI,SAAUhE,EAAIZ,GAC/B,GAAuC,mBAA3BA,GAAQW,gBAAkCjG,EAAiB,CACtE,GAAI0B,GAAO4D,EAAQW,eAAgBC,EACnC,OAAOxE,IAASA,UAIlBtC,EAAK4K,OAAW,GAAK,SAAU9D,GAC9B,GAAI+D,GAAS/D,EAAGQ,QAASlD,EAAWC,GACpC,OAAO,UAAU/B,GAChB,GAAIyH,GAAwC,mBAA1BzH,GAAKyI,kBACtBzI,EAAKyI,iBAAiB,KACvB,OAAOhB,IAAQA,EAAK7B,QAAU2C,IAMhC7K,EAAK8K,KAAS,GAAI,SAAUhE,EAAIZ,GAC/B,GAAuC,mBAA3BA,GAAQW,gBAAkCjG,EAAiB,CACtE,GAAImJ,GAAMjK,EAAGkL,EACZ1I,EAAO4D,EAAQW,eAAgBC,EAEhC,IAAKxE,EAAO,CAIX,GADAyH,EAAOzH,EAAKyI,iBAAiB,MACxBhB,GAAQA,EAAK7B,QAAUpB,EAC3B,OAASxE,EAIV0I,GAAQ9E,EAAQyE,kBAAmB7D,GACnChH,EAAI,CACJ,OAASwC,EAAO0I,EAAMlL,KAErB,GADAiK,EAAOzH,EAAKyI,iBAAiB,MACxBhB,GAAQA,EAAK7B,QAAUpB,EAC3B,OAASxE,GAKZ,YAMHtC,EAAK8K,KAAU,IAAI/K,EAAQgH,qBAC1B,SAAUkE,EAAK/E,GACd,MAA6C,mBAAjCA,GAAQa,qBACZb,EAAQa,qBAAsBkE,GAG1BlL,EAAQkH,IACZf,EAAQ0B,iBAAkBqD,GAD3B,QAKR,SAAUA,EAAK/E,GACd,GAAI5D,GACH4I,KACApL,EAAI,EAEJqG,EAAUD,EAAQa,qBAAsBkE,EAGzC,IAAa,MAARA,EAAc,CAClB,MAAS3I,EAAO6D,EAAQrG,KACA,IAAlBwC,EAAKqD,UACTuF,EAAIhJ,KAAMI,EAIZ,OAAO4I,GAER,MAAO/E,IAITnG,EAAK8K,KAAY,MAAI/K,EAAQiH,wBAA0B,SAAUuD,EAAWrE,GAC3E,GAA+C,mBAAnCA,GAAQc,wBAA0CpG,EAC7D,MAAOsF,GAAQc,uBAAwBuD,IAUzCzJ,KAOAD,MAEMd,EAAQkH,IAAMhD,EAAQiD,KAAMxG,EAASkH,qBAG1CW,GAAO,SAAUC,GAMhB7H,EAAQ6J,YAAahC,GAAK2C,UAAY,UAAYlK,EAAU,qBAC1CA,EAAU,kEAOvBuH,EAAGZ,iBAAiB,wBAAwBpF,QAChD3B,EAAUqB,KAAM,SAAWQ,EAAa,gBAKnC8F,EAAGZ,iBAAiB,cAAcpF,QACvC3B,EAAUqB,KAAM,MAAQQ,EAAa,aAAeD,EAAW,KAI1D+F,EAAGZ,iBAAkB,QAAU3G,EAAU,MAAOuB,QACrD3B,EAAUqB,KAAK,MAMVsG,EAAGZ,iBAAiB,YAAYpF,QACrC3B,EAAUqB,KAAK,YAMVsG,EAAGZ,iBAAkB,KAAO3G,EAAU,MAAOuB,QAClD3B,EAAUqB,KAAK,cAIjBqG,GAAO,SAAUC,GAChBA,EAAG2C,UAAY,mFAKf,IAAIC,GAAQ1K,EAAS+H,cAAc,QACnC2C,GAAM7D,aAAc,OAAQ,UAC5BiB,EAAGgC,YAAaY,GAAQ7D,aAAc,OAAQ,KAIzCiB,EAAGZ,iBAAiB,YAAYpF,QACpC3B,EAAUqB,KAAM,OAASQ,EAAa,eAKS,IAA3C8F,EAAGZ,iBAAiB,YAAYpF,QACpC3B,EAAUqB,KAAM,WAAY,aAK7BvB,EAAQ6J,YAAahC,GAAKnD,UAAW,EACY,IAA5CmD,EAAGZ,iBAAiB,aAAapF,QACrC3B,EAAUqB,KAAM,WAAY,aAI7BsG,EAAGZ,iBAAiB,QACpB/G,EAAUqB,KAAK,YAIXnC,EAAQsL,gBAAkBpH,EAAQiD,KAAOnG,EAAUJ,EAAQI,SAChEJ,EAAQ2K,uBACR3K,EAAQ4K,oBACR5K,EAAQ6K,kBACR7K,EAAQ8K,qBAERlD,GAAO,SAAUC,GAGhBzI,EAAQ2L,kBAAoB3K,EAAQ0E,KAAM+C,EAAI,KAI9CzH,EAAQ0E,KAAM+C,EAAI,aAClB1H,EAAcoB,KAAM,KAAMW,KAI5BhC,EAAYA,EAAU2B,QAAU,GAAIO,QAAQlC,EAAU4G,KAAK,MAC3D3G,EAAgBA,EAAc0B,QAAU,GAAIO,QAAQjC,EAAc2G,KAAK,MAIvEuC,EAAa/F,EAAQiD,KAAMvG,EAAQgL,yBAKnC3K,EAAWgJ,GAAc/F,EAAQiD,KAAMvG,EAAQK,UAC9C,SAAUW,EAAGC,GACZ,GAAIgK,GAAuB,IAAfjK,EAAEgE,SAAiBhE,EAAEmI,gBAAkBnI,EAClDkK,EAAMjK,GAAKA,EAAE+F,UACd,OAAOhG,KAAMkK,MAAWA,GAAwB,IAAjBA,EAAIlG,YAClCiG,EAAM5K,SACL4K,EAAM5K,SAAU6K,GAChBlK,EAAEgK,yBAA8D,GAAnChK,EAAEgK,wBAAyBE,MAG3D,SAAUlK,EAAGC,GACZ,GAAKA,EACJ,MAASA,EAAIA,EAAE+F,WACd,GAAK/F,IAAMD,EACV,OAAO,CAIV,QAAO,GAOTD,EAAYsI,EACZ,SAAUrI,EAAGC,GAGZ,GAAKD,IAAMC,EAEV,MADApB,IAAe,EACR,CAIR,IAAIsL,IAAWnK,EAAEgK,yBAA2B/J,EAAE+J,uBAC9C,OAAKG,GACGA,GAIRA,GAAYnK,EAAEgF,eAAiBhF,MAAUC,EAAE+E,eAAiB/E,GAC3DD,EAAEgK,wBAAyB/J,GAG3B,EAGc,EAAVkK,IACF/L,EAAQgM,cAAgBnK,EAAE+J,wBAAyBhK,KAAQmK,EAGxDnK,IAAMjB,GAAYiB,EAAEgF,gBAAkBxF,GAAgBH,EAASG,EAAcQ,MAG7EC,IAAMlB,GAAYkB,EAAE+E,gBAAkBxF,GAAgBH,EAASG,EAAcS,GAC1E,EAIDrB,EACJ6B,EAAS7B,EAAWoB,GAAMS,EAAS7B,EAAWqB,GAChD,EAGe,EAAVkK,KAAmB,IAE3B,SAAUnK,EAAGC,GAEZ,GAAKD,IAAMC,EAEV,MADApB,IAAe,EACR,CAGR,IAAIyI,GACHnJ,EAAI,EACJkM,EAAMrK,EAAEgG,WACRkE,EAAMjK,EAAE+F,WACRsE,GAAOtK,GACPuK,GAAOtK,EAGR,KAAMoK,IAAQH,EACb,MAAOlK,KAAMjB,KACZkB,IAAMlB,EAAW,EACjBsL,KACAH,EAAM,EACNtL,EACE6B,EAAS7B,EAAWoB,GAAMS,EAAS7B,EAAWqB,GAChD,CAGK,IAAKoK,IAAQH,EACnB,MAAO7C,IAAcrH,EAAGC,EAIzBqH,GAAMtH,CACN,OAASsH,EAAMA,EAAItB,WAClBsE,EAAGE,QAASlD,EAEbA,GAAMrH,CACN,OAASqH,EAAMA,EAAItB,WAClBuE,EAAGC,QAASlD,EAIb,OAAQgD,EAAGnM,KAAOoM,EAAGpM,GACpBA,GAGD,OAAOA,GAENkJ,GAAciD,EAAGnM,GAAIoM,EAAGpM,IAGxBmM,EAAGnM,KAAOqB,KACV+K,EAAGpM,KAAOqB,EAAe,EACzB,GAGKT,GA3YCA,GA8YTsF,GAAOjF,QAAU,SAAUqL,EAAMC,GAChC,MAAOrG,IAAQoG,EAAM,KAAM,KAAMC,IAGlCrG,GAAOqF,gBAAkB,SAAU/I,EAAM8J,GASxC,IAPO9J,EAAKqE,eAAiBrE,KAAW5B,GACvCD,EAAa6B,GAId8J,EAAOA,EAAK9E,QAASnE,EAAkB,UAElCpD,EAAQsL,iBAAmBzK,IAC9Ba,EAAe2K,EAAO,QACpBtL,IAAkBA,EAAcoG,KAAMkF,OACtCvL,IAAkBA,EAAUqG,KAAMkF,IAErC,IACC,GAAIE,GAAMvL,EAAQ0E,KAAMnD,EAAM8J,EAG9B,IAAKE,GAAOvM,EAAQ2L,mBAGlBpJ,EAAK5B,UAAuC,KAA3B4B,EAAK5B,SAASiF,SAChC,MAAO2G,GAEP,MAAO1G,IAGV,MAAOI,IAAQoG,EAAM1L,EAAU,MAAQ4B,IAASE,OAAS,GAG1DwD,GAAOhF,SAAW,SAAUkF,EAAS5D,GAKpC,OAHO4D,EAAQS,eAAiBT,KAAcxF,GAC7CD,EAAayF,GAEPlF,EAAUkF,EAAS5D,IAG3B0D,GAAOuG,KAAO,SAAUjK,EAAMiH,IAEtBjH,EAAKqE,eAAiBrE,KAAW5B,GACvCD,EAAa6B,EAGd,IAAIgG,GAAKtI,EAAK+I,WAAYQ,EAAKnC,eAE9BoF,EAAMlE,GAAMzG,EAAO4D,KAAMzF,EAAK+I,WAAYQ,EAAKnC,eAC9CkB,EAAIhG,EAAMiH,GAAO3I,GACjB6L,MAEF,OAAeA,UAARD,EACNA,EACAzM,EAAQ6C,aAAehC,EACtB0B,EAAK+E,aAAckC,IAClBiD,EAAMlK,EAAKyI,iBAAiBxB,KAAUiD,EAAIE,UAC1CF,EAAItE,MACJ,MAGJlC,GAAO2G,OAAS,SAAUC,GACzB,OAAQA,EAAM,IAAItF,QAAS1C,GAAYC,KAGxCmB,GAAO6G,MAAQ,SAAUC,GACxB,KAAM,IAAIC,OAAO,0CAA4CD,IAO9D9G,GAAOgH,WAAa,SAAU7G,GAC7B,GAAI7D,GACH2K,KACAlH,EAAI,EACJjG,EAAI,CAOL,IAJAU,GAAgBT,EAAQmN,iBACxB3M,GAAaR,EAAQoN,YAAchH,EAAQhE,MAAO,GAClDgE,EAAQiH,KAAM1L,GAETlB,EAAe,CACnB,MAAS8B,EAAO6D,EAAQrG,KAClBwC,IAAS6D,EAASrG,KACtBiG,EAAIkH,EAAW/K,KAAMpC,GAGvB,OAAQiG,IACPI,EAAQkH,OAAQJ,EAAYlH,GAAK,GAQnC,MAFAxF,GAAY,KAEL4F,GAORlG,EAAU+F,GAAO/F,QAAU,SAAUqC,GACpC,GAAIyH,GACHuC,EAAM,GACNxM,EAAI,EACJ6F,EAAWrD,EAAKqD,QAEjB,IAAMA,GAMC,GAAkB,IAAbA,GAA+B,IAAbA,GAA+B,KAAbA,EAAkB,CAGjE,GAAiC,gBAArBrD,GAAKgL,YAChB,MAAOhL,GAAKgL,WAGZ,KAAMhL,EAAOA,EAAKiL,WAAYjL,EAAMA,EAAOA,EAAK8G,YAC/CkD,GAAOrM,EAASqC,OAGZ,IAAkB,IAAbqD,GAA+B,IAAbA,EAC7B,MAAOrD,GAAKkL,cAhBZ,OAASzD,EAAOzH,EAAKxC,KAEpBwM,GAAOrM,EAAS8J,EAkBlB,OAAOuC,IAGRtM,EAAOgG,GAAOyH,WAGbtF,YAAa,GAEbuF,aAAcrF,GAEd9B,MAAOjD,EAEPyF,cAEA+B,QAEA6C,UACCC,KAAOtI,IAAK,aAAcuI,OAAO,GACjCC,KAAOxI,IAAK,cACZyI,KAAOzI,IAAK,kBAAmBuI,OAAO,GACtCG,KAAO1I,IAAK,oBAGb2I,WACCvK,KAAQ,SAAU6C,GAUjB,MATAA,GAAM,GAAKA,EAAM,GAAGe,QAASlD,EAAWC,IAGxCkC,EAAM,IAAOA,EAAM,IAAMA,EAAM,IAAMA,EAAM,IAAM,IAAKe,QAASlD,EAAWC,IAExD,OAAbkC,EAAM,KACVA,EAAM,GAAK,IAAMA,EAAM,GAAK,KAGtBA,EAAMpE,MAAO,EAAG,IAGxByB,MAAS,SAAU2C,GA6BlB,MAlBAA,GAAM,GAAKA,EAAM,GAAGa,cAEY,QAA3Bb,EAAM,GAAGpE,MAAO,EAAG,IAEjBoE,EAAM,IACXP,GAAO6G,MAAOtG,EAAM,IAKrBA,EAAM,KAAQA,EAAM,GAAKA,EAAM,IAAMA,EAAM,IAAM,GAAK,GAAmB,SAAbA,EAAM,IAA8B,QAAbA,EAAM,KACzFA,EAAM,KAAUA,EAAM,GAAKA,EAAM,IAAqB,QAAbA,EAAM,KAGpCA,EAAM,IACjBP,GAAO6G,MAAOtG,EAAM,IAGdA,GAGR5C,OAAU,SAAU4C,GACnB,GAAI2H,GACHC,GAAY5H,EAAM,IAAMA,EAAM,EAE/B,OAAKjD,GAAiB,MAAE4D,KAAMX,EAAM,IAC5B,MAIHA,EAAM,GACVA,EAAM,GAAKA,EAAM,IAAMA,EAAM,IAAM,GAGxB4H,GAAY/K,EAAQ8D,KAAMiH,KAEpCD,EAAS/N,EAAUgO,GAAU,MAE7BD,EAASC,EAAS/L,QAAS,IAAK+L,EAAS3L,OAAS0L,GAAWC,EAAS3L,UAGvE+D,EAAM,GAAKA,EAAM,GAAGpE,MAAO,EAAG+L,GAC9B3H,EAAM,GAAK4H,EAAShM,MAAO,EAAG+L,IAIxB3H,EAAMpE,MAAO,EAAG,MAIzByI,QAECnH,IAAO,SAAU2K,GAChB,GAAIjH,GAAWiH,EAAiB9G,QAASlD,EAAWC,IAAY+C,aAChE,OAA4B,MAArBgH,EACN,WAAa,OAAO,GACpB,SAAU9L,GACT,MAAOA,GAAK6E,UAAY7E,EAAK6E,SAASC,gBAAkBD,IAI3D3D,MAAS,SAAU+G,GAClB,GAAI8D,GAAU/M,EAAYiJ,EAAY,IAEtC,OAAO8D,KACLA,EAAU,GAAItL,QAAQ,MAAQL,EAAa,IAAM6H,EAAY,IAAM7H,EAAa,SACjFpB,EAAYiJ,EAAW,SAAUjI,GAChC,MAAO+L,GAAQnH,KAAgC,gBAAnB5E,GAAKiI,WAA0BjI,EAAKiI,WAA0C,mBAAtBjI,GAAK+E,cAAgC/E,EAAK+E,aAAa,UAAY,OAI1J3D,KAAQ,SAAU6F,EAAM+E,EAAUC,GACjC,MAAO,UAAUjM,GAChB,GAAIkM,GAASxI,GAAOuG,KAAMjK,EAAMiH,EAEhC,OAAe,OAAViF,EACgB,OAAbF,GAEFA,IAINE,GAAU,GAEU,MAAbF,EAAmBE,IAAWD,EACvB,OAAbD,EAAoBE,IAAWD,EAClB,OAAbD,EAAoBC,GAAqC,IAA5BC,EAAOpM,QAASmM,GAChC,OAAbD,EAAoBC,GAASC,EAAOpM,QAASmM,MAChC,OAAbD,EAAoBC,GAASC,EAAOrM,OAAQoM,EAAM/L,UAAa+L,EAClD,OAAbD,GAAsB,IAAME,EAAOlH,QAASxE,EAAa,KAAQ,KAAMV,QAASmM,MACnE,OAAbD,IAAoBE,IAAWD,GAASC,EAAOrM,MAAO,EAAGoM,EAAM/L,OAAS,KAAQ+L,EAAQ,QAK3F3K,MAAS,SAAU0F,EAAMmF,EAAM7E,EAAUiE,EAAOa,GAC/C,GAAIC,GAAgC,QAAvBrF,EAAKnH,MAAO,EAAG,GAC3ByM,EAA+B,SAArBtF,EAAKnH,UACf0M,EAAkB,YAATJ,CAEV,OAAiB,KAAVZ,GAAwB,IAATa,EAGrB,SAAUpM,GACT,QAASA,EAAKqF,YAGf,SAAUrF,EAAM4D,EAAS4I,GACxB,GAAI9G,GAAO+G,EAAaC,EAAYjF,EAAMkF,EAAWC,EACpD5J,EAAMqJ,IAAWC,EAAU,cAAgB,kBAC3CO,EAAS7M,EAAKqF,WACd4B,EAAOsF,GAAUvM,EAAK6E,SAASC,cAC/BgI,GAAYN,IAAQD,EACpB3F,GAAO,CAER,IAAKiG,EAAS,CAGb,GAAKR,EAAS,CACb,MAAQrJ,EAAM,CACbyE,EAAOzH,CACP,OAASyH,EAAOA,EAAMzE,GACrB,GAAKuJ,EACJ9E,EAAK5C,SAASC,gBAAkBmC,EACd,IAAlBQ,EAAKpE,SAEL,OAAO,CAITuJ,GAAQ5J,EAAe,SAATgE,IAAoB4F,GAAS,cAE5C,OAAO,EAMR,GAHAA,GAAUN,EAAUO,EAAO5B,WAAa4B,EAAOE,WAG1CT,GAAWQ,EAAW,CAK1BrF,EAAOoF,EACPH,EAAajF,EAAM9I,KAAc8I,EAAM9I,OAIvC8N,EAAcC,EAAYjF,EAAKuF,YAC7BN,EAAYjF,EAAKuF,cAEnBtH,EAAQ+G,EAAazF,OACrB2F,EAAYjH,EAAO,KAAQ5G,GAAW4G,EAAO,GAC7CkB,EAAO+F,GAAajH,EAAO,GAC3B+B,EAAOkF,GAAaE,EAAOzJ,WAAYuJ,EAEvC,OAASlF,IAASkF,GAAalF,GAAQA,EAAMzE,KAG3C4D,EAAO+F,EAAY,IAAMC,EAAMlN,MAGhC,GAAuB,IAAlB+H,EAAKpE,YAAoBuD,GAAQa,IAASzH,EAAO,CACrDyM,EAAazF,IAAWlI,EAAS6N,EAAW/F,EAC5C,YAuBF,IAjBKkG,IAEJrF,EAAOzH,EACP0M,EAAajF,EAAM9I,KAAc8I,EAAM9I,OAIvC8N,EAAcC,EAAYjF,EAAKuF,YAC7BN,EAAYjF,EAAKuF,cAEnBtH,EAAQ+G,EAAazF,OACrB2F,EAAYjH,EAAO,KAAQ5G,GAAW4G,EAAO,GAC7CkB,EAAO+F,GAKH/F,KAAS,EAEb,MAASa,IAASkF,GAAalF,GAAQA,EAAMzE,KAC3C4D,EAAO+F,EAAY,IAAMC,EAAMlN,MAEhC,IAAO6M,EACN9E,EAAK5C,SAASC,gBAAkBmC,EACd,IAAlBQ,EAAKpE,aACHuD,IAGGkG,IACJJ,EAAajF,EAAM9I,KAAc8I,EAAM9I,OAIvC8N,EAAcC,EAAYjF,EAAKuF,YAC7BN,EAAYjF,EAAKuF,cAEnBP,EAAazF,IAAWlI,EAAS8H,IAG7Ba,IAASzH,GACb,KASL,OADA4G,IAAQwF,EACDxF,IAAS2E,GAAW3E,EAAO2E,IAAU,GAAK3E,EAAO2E,GAAS,KAKrElK,OAAU,SAAU4L,EAAQ3F,GAK3B,GAAI4F,GACHlH,EAAKtI,EAAK6C,QAAS0M,IAAYvP,EAAKyP,WAAYF,EAAOnI,gBACtDpB,GAAO6G,MAAO,uBAAyB0C,EAKzC,OAAKjH,GAAIrH,GACDqH,EAAIsB,GAIPtB,EAAG9F,OAAS,GAChBgN,GAASD,EAAQA,EAAQ,GAAI3F,GACtB5J,EAAKyP,WAAW3N,eAAgByN,EAAOnI,eAC7CiB,GAAa,SAAUjC,EAAMrF,GAC5B,GAAI2O,GACHC,EAAUrH,EAAIlC,EAAMwD,GACpB9J,EAAI6P,EAAQnN,MACb,OAAQ1C,IACP4P,EAAMtN,EAASgE,EAAMuJ,EAAQ7P,IAC7BsG,EAAMsJ,KAAW3O,EAAS2O,GAAQC,EAAQ7P,MAG5C,SAAUwC,GACT,MAAOgG,GAAIhG,EAAM,EAAGkN,KAIhBlH,IAITzF,SAEC+M,IAAOvH,GAAa,SAAUpC,GAI7B,GAAImF,MACHjF,KACA0J,EAAUzP,EAAS6F,EAASqB,QAAStE,EAAO,MAE7C,OAAO6M,GAAS5O,GACfoH,GAAa,SAAUjC,EAAMrF,EAASmF,EAAS4I,GAC9C,GAAIxM,GACHwN,EAAYD,EAASzJ,EAAM,KAAM0I,MACjChP,EAAIsG,EAAK5D,MAGV,OAAQ1C,KACDwC,EAAOwN,EAAUhQ,MACtBsG,EAAKtG,KAAOiB,EAAQjB,GAAKwC,MAI5B,SAAUA,EAAM4D,EAAS4I,GAKxB,MAJA1D,GAAM,GAAK9I,EACXuN,EAASzE,EAAO,KAAM0D,EAAK3I,GAE3BiF,EAAM,GAAK,MACHjF,EAAQnE,SAInB+N,IAAO1H,GAAa,SAAUpC,GAC7B,MAAO,UAAU3D,GAChB,MAAO0D,IAAQC,EAAU3D,GAAOE,OAAS,KAI3CxB,SAAYqH,GAAa,SAAU2H,GAElC,MADAA,GAAOA,EAAK1I,QAASlD,EAAWC,IACzB,SAAU/B,GAChB,OAASA,EAAKgL,aAAehL,EAAK2N,WAAahQ,EAASqC,IAASF,QAAS4N,SAW5EE,KAAQ7H,GAAc,SAAU6H,GAM/B,MAJM7M,GAAY6D,KAAKgJ,GAAQ,KAC9BlK,GAAO6G,MAAO,qBAAuBqD,GAEtCA,EAAOA,EAAK5I,QAASlD,EAAWC,IAAY+C,cACrC,SAAU9E,GAChB,GAAI6N,EACJ,GACC,IAAMA,EAAWvP,EAChB0B,EAAK4N,KACL5N,EAAK+E,aAAa,aAAe/E,EAAK+E,aAAa,QAGnD,MADA8I,GAAWA,EAAS/I,cACb+I,IAAaD,GAA2C,IAAnCC,EAAS/N,QAAS8N,EAAO,YAE5C5N,EAAOA,EAAKqF,aAAiC,IAAlBrF,EAAKqD,SAC3C,QAAO,KAKTE,OAAU,SAAUvD,GACnB,GAAI8N,GAAOvQ,EAAOwQ,UAAYxQ,EAAOwQ,SAASD,IAC9C,OAAOA,IAAQA,EAAKjO,MAAO,KAAQG,EAAKwE,IAGzCwJ,KAAQ,SAAUhO,GACjB,MAAOA,KAAS3B,GAGjB4P,MAAS,SAAUjO,GAClB,MAAOA,KAAS5B,EAAS8P,iBAAmB9P,EAAS+P,UAAY/P,EAAS+P,gBAAkBnO,EAAKgH,MAAQhH,EAAKoO,OAASpO,EAAKqO,WAI7HC,QAAWnH,IAAsB,GACjCpE,SAAYoE,IAAsB,GAElCoH,QAAW,SAAUvO,GAGpB,GAAI6E,GAAW7E,EAAK6E,SAASC,aAC7B,OAAqB,UAAbD,KAA0B7E,EAAKuO,SAA0B,WAAb1J,KAA2B7E,EAAKwO,UAGrFA,SAAY,SAAUxO,GAOrB,MAJKA,GAAKqF,YACTrF,EAAKqF,WAAWoJ,cAGVzO,EAAKwO,YAAa,GAI1BE,MAAS,SAAU1O,GAKlB,IAAMA,EAAOA,EAAKiL,WAAYjL,EAAMA,EAAOA,EAAK8G,YAC/C,GAAK9G,EAAKqD,SAAW,EACpB,OAAO,CAGT,QAAO,GAGRwJ,OAAU,SAAU7M,GACnB,OAAQtC,EAAK6C,QAAe,MAAGP,IAIhC2O,OAAU,SAAU3O,GACnB,MAAO0B,GAAQkD,KAAM5E,EAAK6E,WAG3BiE,MAAS,SAAU9I,GAClB,MAAOyB,GAAQmD,KAAM5E,EAAK6E,WAG3B+J,OAAU,SAAU5O,GACnB,GAAIiH,GAAOjH,EAAK6E,SAASC,aACzB,OAAgB,UAATmC,GAAkC,WAAdjH,EAAKgH,MAA8B,WAATC,GAGtDyG,KAAQ,SAAU1N,GACjB,GAAIiK,EACJ,OAAuC,UAAhCjK,EAAK6E,SAASC,eACN,SAAd9E,EAAKgH,OAImC,OAArCiD,EAAOjK,EAAK+E,aAAa,UAA2C,SAAvBkF,EAAKnF,gBAIvDyG,MAASlE,GAAuB,WAC/B,OAAS,KAGV+E,KAAQ/E,GAAuB,SAAUE,EAAcrH,GACtD,OAASA,EAAS,KAGnB2O,GAAMxH,GAAuB,SAAUE,EAAcrH,EAAQoH,GAC5D,OAASA,EAAW,EAAIA,EAAWpH,EAASoH,KAG7CwH,KAAQzH,GAAuB,SAAUE,EAAcrH,GAEtD,IADA,GAAI1C,GAAI,EACAA,EAAI0C,EAAQ1C,GAAK,EACxB+J,EAAa3H,KAAMpC,EAEpB,OAAO+J,KAGRwH,IAAO1H,GAAuB,SAAUE,EAAcrH,GAErD,IADA,GAAI1C,GAAI,EACAA,EAAI0C,EAAQ1C,GAAK,EACxB+J,EAAa3H,KAAMpC,EAEpB,OAAO+J,KAGRyH,GAAM3H,GAAuB,SAAUE,EAAcrH,EAAQoH,GAE5D,IADA,GAAI9J,GAAI8J,EAAW,EAAIA,EAAWpH,EAASoH,IACjC9J,GAAK,GACd+J,EAAa3H,KAAMpC,EAEpB,OAAO+J,KAGR0H,GAAM5H,GAAuB,SAAUE,EAAcrH,EAAQoH,GAE5D,IADA,GAAI9J,GAAI8J,EAAW,EAAIA,EAAWpH,EAASoH,IACjC9J,EAAI0C,GACbqH,EAAa3H,KAAMpC,EAEpB,OAAO+J,OAKV7J,EAAK6C,QAAa,IAAI7C,EAAK6C,QAAY,EAGvC,KAAM/C,KAAO0R,OAAO,EAAMC,UAAU,EAAMC,MAAM,EAAMC,UAAU,EAAMC,OAAO,GAC5E5R,EAAK6C,QAAS/C,GAAMuJ,GAAmBvJ,EAExC,KAAMA,KAAO+R,QAAQ,EAAMC,OAAO,GACjC9R,EAAK6C,QAAS/C,GAAM0J,GAAoB1J,EAIzC,SAAS2P,OACTA,GAAWsC,UAAY/R,EAAKgS,QAAUhS,EAAK6C,QAC3C7C,EAAKyP,WAAa,GAAIA,IAEtBtP,EAAW6F,GAAO7F,SAAW,SAAU8F,EAAUgM,GAChD,GAAItC,GAASpJ,EAAO2L,EAAQ5I,EAC3B6I,EAAO3L,EAAQ4L,EACfC,EAAS7Q,EAAYyE,EAAW,IAEjC,IAAKoM,EACJ,MAAOJ,GAAY,EAAII,EAAOlQ,MAAO,EAGtCgQ,GAAQlM,EACRO,KACA4L,EAAapS,EAAKiO,SAElB,OAAQkE,EAAQ,CAGTxC,KAAYpJ,EAAQtD,EAAO2D,KAAMuL,MACjC5L,IAEJ4L,EAAQA,EAAMhQ,MAAOoE,EAAM,GAAG/D,SAAY2P,GAE3C3L,EAAOtE,KAAOgQ,OAGfvC,GAAU,GAGJpJ,EAAQrD,EAAa0D,KAAMuL,MAChCxC,EAAUpJ,EAAM6B,QAChB8J,EAAOhQ,MACNgG,MAAOyH,EAEPrG,KAAM/C,EAAM,GAAGe,QAAStE,EAAO,OAEhCmP,EAAQA,EAAMhQ,MAAOwN,EAAQnN,QAI9B,KAAM8G,IAAQtJ,GAAK4K,SACZrE,EAAQjD,EAAWgG,GAAO1C,KAAMuL,KAAcC,EAAY9I,MAC9D/C,EAAQ6L,EAAY9I,GAAQ/C,MAC7BoJ,EAAUpJ,EAAM6B,QAChB8J,EAAOhQ,MACNgG,MAAOyH,EACPrG,KAAMA,EACNvI,QAASwF,IAEV4L,EAAQA,EAAMhQ,MAAOwN,EAAQnN,QAI/B,KAAMmN,EACL,MAOF,MAAOsC,GACNE,EAAM3P,OACN2P,EACCnM,GAAO6G,MAAO5G,GAEdzE,EAAYyE,EAAUO,GAASrE,MAAO,GAGzC,SAASqF,IAAY0K,GAIpB,IAHA,GAAIpS,GAAI,EACPyC,EAAM2P,EAAO1P,OACbyD,EAAW,GACJnG,EAAIyC,EAAKzC,IAChBmG,GAAYiM,EAAOpS,GAAGoI,KAEvB,OAAOjC,GAGR,QAASb,IAAeyK,EAASyC,EAAYC,GAC5C,GAAIjN,GAAMgN,EAAWhN,IACpBkN,EAAOF,EAAW/M,KAClB0C,EAAMuK,GAAQlN,EACdmN,EAAmBF,GAAgB,eAARtK,EAC3ByK,EAAWrR,GAEZ,OAAOiR,GAAWzE,MAEjB,SAAUvL,EAAM4D,EAAS4I,GACxB,MAASxM,EAAOA,EAAMgD,GACrB,GAAuB,IAAlBhD,EAAKqD,UAAkB8M,EAC3B,MAAO5C,GAASvN,EAAM4D,EAAS4I,EAGjC,QAAO,GAIR,SAAUxM,EAAM4D,EAAS4I,GACxB,GAAI6D,GAAU5D,EAAaC,EAC1B4D,GAAaxR,EAASsR,EAGvB,IAAK5D,GACJ,MAASxM,EAAOA,EAAMgD,GACrB,IAAuB,IAAlBhD,EAAKqD,UAAkB8M,IACtB5C,EAASvN,EAAM4D,EAAS4I,GAC5B,OAAO,MAKV,OAASxM,EAAOA,EAAMgD,GACrB,GAAuB,IAAlBhD,EAAKqD,UAAkB8M,EAO3B,GANAzD,EAAa1M,EAAMrB,KAAcqB,EAAMrB,OAIvC8N,EAAcC,EAAY1M,EAAKgN,YAAeN,EAAY1M,EAAKgN,cAE1DkD,GAAQA,IAASlQ,EAAK6E,SAASC,cACnC9E,EAAOA,EAAMgD,IAAShD,MAChB,CAAA,IAAMqQ,EAAW5D,EAAa9G,KACpC0K,EAAU,KAAQvR,GAAWuR,EAAU,KAAQD,EAG/C,MAAQE,GAAU,GAAMD,EAAU,EAMlC,IAHA5D,EAAa9G,GAAQ2K,EAGfA,EAAU,GAAM/C,EAASvN,EAAM4D,EAAS4I,GAC7C,OAAO,EAMZ,OAAO,GAIV,QAAS+D,IAAgBC,GACxB,MAAOA,GAAStQ,OAAS,EACxB,SAAUF,EAAM4D,EAAS4I,GACxB,GAAIhP,GAAIgT,EAAStQ,MACjB,OAAQ1C,IACP,IAAMgT,EAAShT,GAAIwC,EAAM4D,EAAS4I,GACjC,OAAO,CAGT,QAAO,GAERgE,EAAS,GAGX,QAASC,IAAkB9M,EAAU+M,EAAU7M,GAG9C,IAFA,GAAIrG,GAAI,EACPyC,EAAMyQ,EAASxQ,OACR1C,EAAIyC,EAAKzC,IAChBkG,GAAQC,EAAU+M,EAASlT,GAAIqG,EAEhC,OAAOA,GAGR,QAAS8M,IAAUnD,EAAWoD,EAAKtI,EAAQ1E,EAAS4I,GAOnD,IANA,GAAIxM,GACH6Q,KACArT,EAAI,EACJyC,EAAMuN,EAAUtN,OAChB4Q,EAAgB,MAAPF,EAEFpT,EAAIyC,EAAKzC,KACVwC,EAAOwN,EAAUhQ,MAChB8K,IAAUA,EAAQtI,EAAM4D,EAAS4I,KACtCqE,EAAajR,KAAMI,GACd8Q,GACJF,EAAIhR,KAAMpC,IAMd,OAAOqT,GAGR,QAASE,IAAYpF,EAAWhI,EAAU4J,EAASyD,EAAYC,EAAYC,GAO1E,MANKF,KAAeA,EAAYrS,KAC/BqS,EAAaD,GAAYC,IAErBC,IAAeA,EAAYtS,KAC/BsS,EAAaF,GAAYE,EAAYC,IAE/BnL,GAAa,SAAUjC,EAAMD,EAASD,EAAS4I,GACrD,GAAI2E,GAAM3T,EAAGwC,EACZoR,KACAC,KACAC,EAAczN,EAAQ3D,OAGtBwI,EAAQ5E,GAAQ2M,GAAkB9M,GAAY,IAAKC,EAAQP,UAAaO,GAAYA,MAGpF2N,GAAY5F,IAAe7H,GAASH,EAEnC+E,EADAiI,GAAUjI,EAAO0I,EAAQzF,EAAW/H,EAAS4I,GAG9CgF,EAAajE,EAEZ0D,IAAgBnN,EAAO6H,EAAY2F,GAAeN,MAMjDnN,EACD0N,CAQF,IALKhE,GACJA,EAASgE,EAAWC,EAAY5N,EAAS4I,GAIrCwE,EAAa,CACjBG,EAAOR,GAAUa,EAAYH,GAC7BL,EAAYG,KAAUvN,EAAS4I,GAG/BhP,EAAI2T,EAAKjR,MACT,OAAQ1C,KACDwC,EAAOmR,EAAK3T,MACjBgU,EAAYH,EAAQ7T,MAAS+T,EAAWF,EAAQ7T,IAAOwC,IAK1D,GAAK8D,GACJ,GAAKmN,GAActF,EAAY,CAC9B,GAAKsF,EAAa,CAEjBE,KACA3T,EAAIgU,EAAWtR,MACf,OAAQ1C,KACDwC,EAAOwR,EAAWhU,KAEvB2T,EAAKvR,KAAO2R,EAAU/T,GAAKwC,EAG7BiR,GAAY,KAAOO,KAAkBL,EAAM3E,GAI5ChP,EAAIgU,EAAWtR,MACf,OAAQ1C,KACDwC,EAAOwR,EAAWhU,MACtB2T,EAAOF,EAAanR,EAASgE,EAAM9D,GAASoR,EAAO5T,SAEpDsG,EAAKqN,KAAUtN,EAAQsN,GAAQnR,SAOlCwR,GAAab,GACZa,IAAe3N,EACd2N,EAAWzG,OAAQuG,EAAaE,EAAWtR,QAC3CsR,GAEGP,EACJA,EAAY,KAAMpN,EAAS2N,EAAYhF,GAEvC5M,EAAKsD,MAAOW,EAAS2N,KAMzB,QAASC,IAAmB7B,GAwB3B,IAvBA,GAAI8B,GAAcnE,EAAS9J,EAC1BxD,EAAM2P,EAAO1P,OACbyR,EAAkBjU,EAAK2N,SAAUuE,EAAO,GAAG5I,MAC3C4K,EAAmBD,GAAmBjU,EAAK2N,SAAS,KACpD7N,EAAImU,EAAkB,EAAI,EAG1BE,EAAe/O,GAAe,SAAU9C,GACvC,MAAOA,KAAS0R,GACdE,GAAkB,GACrBE,EAAkBhP,GAAe,SAAU9C,GAC1C,MAAOF,GAAS4R,EAAc1R,OAC5B4R,GAAkB,GACrBpB,GAAa,SAAUxQ,EAAM4D,EAAS4I,GACrC,GAAIxC,IAAS2H,IAAqBnF,GAAO5I,IAAY5F,MACnD0T,EAAe9N,GAASP,SACxBwO,EAAc7R,EAAM4D,EAAS4I,GAC7BsF,EAAiB9R,EAAM4D,EAAS4I,GAGlC,OADAkF,GAAe,KACR1H,IAGDxM,EAAIyC,EAAKzC,IAChB,GAAM+P,EAAU7P,EAAK2N,SAAUuE,EAAOpS,GAAGwJ,MACxCwJ,GAAa1N,GAAcyN,GAAgBC,GAAYjD,QACjD,CAIN,GAHAA,EAAU7P,EAAK4K,OAAQsH,EAAOpS,GAAGwJ,MAAO9D,MAAO,KAAM0M,EAAOpS,GAAGiB,SAG1D8O,EAAS5O,GAAY,CAGzB,IADA8E,IAAMjG,EACEiG,EAAIxD,EAAKwD,IAChB,GAAK/F,EAAK2N,SAAUuE,EAAOnM,GAAGuD,MAC7B,KAGF,OAAO+J,IACNvT,EAAI,GAAK+S,GAAgBC,GACzBhT,EAAI,GAAK0H,GAER0K,EAAO/P,MAAO,EAAGrC,EAAI,GAAIuU,QAASnM,MAAgC,MAAzBgK,EAAQpS,EAAI,GAAIwJ,KAAe,IAAM,MAC7EhC,QAAStE,EAAO,MAClB6M,EACA/P,EAAIiG,GAAKgO,GAAmB7B,EAAO/P,MAAOrC,EAAGiG,IAC7CA,EAAIxD,GAAOwR,GAAoB7B,EAASA,EAAO/P,MAAO4D,IACtDA,EAAIxD,GAAOiF,GAAY0K,IAGzBY,EAAS5Q,KAAM2N,GAIjB,MAAOgD,IAAgBC,GAGxB,QAASwB,IAA0BC,EAAiBC,GACnD,GAAIC,GAAQD,EAAYhS,OAAS,EAChCkS,EAAYH,EAAgB/R,OAAS,EACrCmS,EAAe,SAAUvO,EAAMF,EAAS4I,EAAK3I,EAASyO,GACrD,GAAItS,GAAMyD,EAAG8J,EACZgF,EAAe,EACf/U,EAAI,IACJgQ,EAAY1J,MACZ0O,KACAC,EAAgBzU,EAEhB0K,EAAQ5E,GAAQsO,GAAa1U,EAAK8K,KAAU,IAAG,IAAK8J,GAEpDI,EAAiB5T,GAA4B,MAAjB2T,EAAwB,EAAIE,KAAKC,UAAY,GACzE3S,EAAMyI,EAAMxI,MASb,KAPKoS,IACJtU,EAAmB4F,IAAYxF,GAAYwF,GAAW0O,GAM/C9U,IAAMyC,GAA4B,OAApBD,EAAO0I,EAAMlL,IAAaA,IAAM,CACrD,GAAK4U,GAAapS,EAAO,CACxByD,EAAI,EACEG,GAAW5D,EAAKqE,gBAAkBjG,IACvCD,EAAa6B,GACbwM,GAAOlO,EAER,OAASiP,EAAU0E,EAAgBxO,KAClC,GAAK8J,EAASvN,EAAM4D,GAAWxF,EAAUoO,GAAO,CAC/C3I,EAAQjE,KAAMI,EACd,OAGGsS,IACJxT,EAAU4T,GAKPP,KAEEnS,GAAQuN,GAAWvN,IACxBuS,IAIIzO,GACJ0J,EAAU5N,KAAMI,IAgBnB,GATAuS,GAAgB/U,EASX2U,GAAS3U,IAAM+U,EAAe,CAClC9O,EAAI,CACJ,OAAS8J,EAAU2E,EAAYzO,KAC9B8J,EAASC,EAAWgF,EAAY5O,EAAS4I,EAG1C,IAAK1I,EAAO,CAEX,GAAKyO,EAAe,EACnB,MAAQ/U,IACAgQ,EAAUhQ,IAAMgV,EAAWhV,KACjCgV,EAAWhV,GAAKkC,EAAIyD,KAAMU,GAM7B2O,GAAa7B,GAAU6B,GAIxB5S,EAAKsD,MAAOW,EAAS2O,GAGhBF,IAAcxO,GAAQ0O,EAAWtS,OAAS,GAC5CqS,EAAeL,EAAYhS,OAAW,GAExCwD,GAAOgH,WAAY7G,GAUrB,MALKyO,KACJxT,EAAU4T,EACV1U,EAAmByU,GAGbjF,EAGT,OAAO2E,GACNpM,GAAcsM,GACdA,EAGFvU,EAAU4F,GAAO5F,QAAU,SAAU6F,EAAUM,GAC9C,GAAIzG,GACH0U,KACAD,KACAlC,EAAS5Q,EAAewE,EAAW,IAEpC,KAAMoM,EAAS,CAER9L,IACLA,EAAQpG,EAAU8F,IAEnBnG,EAAIyG,EAAM/D,MACV,OAAQ1C,IACPuS,EAAS0B,GAAmBxN,EAAMzG,IAC7BuS,EAAQpR,GACZuT,EAAYtS,KAAMmQ,GAElBkC,EAAgBrS,KAAMmQ,EAKxBA,GAAS5Q,EAAewE,EAAUqO,GAA0BC,EAAiBC,IAG7EnC,EAAOpM,SAAWA,EAEnB,MAAOoM,IAYRhS,EAAS2F,GAAO3F,OAAS,SAAU4F,EAAUC,EAASC,EAASC,GAC9D,GAAItG,GAAGoS,EAAQiD,EAAO7L,EAAMwB,EAC3BsK,EAA+B,kBAAbnP,IAA2BA,EAC7CM,GAASH,GAAQjG,EAAW8F,EAAWmP,EAASnP,UAAYA,EAM7D,IAJAE,EAAUA,MAIY,IAAjBI,EAAM/D,OAAe,CAIzB,GADA0P,EAAS3L,EAAM,GAAKA,EAAM,GAAGpE,MAAO,GAC/B+P,EAAO1P,OAAS,GAAkC,QAA5B2S,EAAQjD,EAAO,IAAI5I,MACvB,IAArBpD,EAAQP,UAAkB/E,GAAkBZ,EAAK2N,SAAUuE,EAAO,GAAG5I,MAAS,CAG/E,GADApD,GAAYlG,EAAK8K,KAAS,GAAGqK,EAAMpU,QAAQ,GAAGuG,QAAQlD,EAAWC,IAAY6B,QAAkB,IACzFA,EACL,MAAOC,EAGIiP,KACXlP,EAAUA,EAAQyB,YAGnB1B,EAAWA,EAAS9D,MAAO+P,EAAO9J,QAAQF,MAAM1F,QAIjD1C,EAAIwD,EAAwB,aAAE4D,KAAMjB,GAAa,EAAIiM,EAAO1P,MAC5D,OAAQ1C,IAAM,CAIb,GAHAqV,EAAQjD,EAAOpS,GAGVE,EAAK2N,SAAWrE,EAAO6L,EAAM7L,MACjC,KAED,KAAMwB,EAAO9K,EAAK8K,KAAMxB,MAEjBlD,EAAO0E,EACZqK,EAAMpU,QAAQ,GAAGuG,QAASlD,EAAWC,IACrCF,EAAS+C,KAAMgL,EAAO,GAAG5I,OAAU5B,GAAaxB,EAAQyB,aAAgBzB,IACpE,CAKJ,GAFAgM,EAAO7E,OAAQvN,EAAG,GAClBmG,EAAWG,EAAK5D,QAAUgF,GAAY0K,IAChCjM,EAEL,MADA/D,GAAKsD,MAAOW,EAASC,GACdD,CAGR,SAeJ,OAPEiP,GAAYhV,EAAS6F,EAAUM,IAChCH,EACAF,GACCtF,EACDuF,GACCD,GAAW/B,EAAS+C,KAAMjB,IAAcyB,GAAaxB,EAAQyB,aAAgBzB,GAExEC,GAMRpG,EAAQoN,WAAalM,EAAQ6H,MAAM,IAAIsE,KAAM1L,GAAY+F,KAAK,MAAQxG,EAItElB,EAAQmN,mBAAqB1M,EAG7BC,IAIAV,EAAQgM,aAAexD,GAAO,SAAUC,GAEvC,MAA0E,GAAnEA,EAAGmD,wBAAyBjL,EAAS+H,cAAc,eAMrDF,GAAO,SAAUC,GAEtB,MADAA,GAAG2C,UAAY,mBAC+B,MAAvC3C,EAAG+E,WAAWlG,aAAa,WAElCsB,GAAW,yBAA0B,SAAUrG,EAAMiH,EAAMrJ,GAC1D,IAAMA,EACL,MAAOoC,GAAK+E,aAAckC,EAA6B,SAAvBA,EAAKnC,cAA2B,EAAI,KAOjErH,EAAQ6C,YAAe2F,GAAO,SAAUC,GAG7C,MAFAA,GAAG2C,UAAY,WACf3C,EAAG+E,WAAWhG,aAAc,QAAS,IACY,KAA1CiB,EAAG+E,WAAWlG,aAAc,YAEnCsB,GAAW,QAAS,SAAUrG,EAAMiH,EAAMrJ,GACzC,IAAMA,GAAyC,UAAhCoC,EAAK6E,SAASC,cAC5B,MAAO9E,GAAK+S,eAOT9M,GAAO,SAAUC,GACtB,MAAsC,OAA/BA,EAAGnB,aAAa,eAEvBsB,GAAWlG,EAAU,SAAUH,EAAMiH,EAAMrJ,GAC1C,GAAIsM,EACJ,KAAMtM,EACL,MAAOoC,GAAMiH,MAAW,EAAOA,EAAKnC,eACjCoF,EAAMlK,EAAKyI,iBAAkBxB,KAAWiD,EAAIE,UAC7CF,EAAItE,MACL,MAMJ,IAAIoN,IAAUzV,EAAOmG,MAErBA,IAAOuP,WAAa,WAKnB,MAJK1V,GAAOmG,SAAWA,KACtBnG,EAAOmG,OAASsP,IAGVtP,IAGe,kBAAXwP,SAAyBA,OAAOC,IAC3CD,OAAO,WAAa,MAAOxP,MAEE,mBAAX0P,SAA0BA,OAAOC,QACnDD,OAAOC,QAAU3P,GAEjBnG,EAAOmG,OAASA,IAIbnG","file":"sizzle.min.js"} \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/external/sizzle/LICENSE.txt jquery-3.2.1/external/sizzle/LICENSE.txt --- jquery-1.11.3+dfsg/external/sizzle/LICENSE.txt 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/external/sizzle/LICENSE.txt 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,36 @@ +Copyright jQuery Foundation and other contributors, https://jquery.org/ + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/jquery/sizzle + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +All files located in the node_modules and external directories are +externally maintained libraries used by this software which have their +own licenses; we recommend you read them, as their terms may differ from +the terms above. diff -Nru jquery-1.11.3+dfsg/.github/ISSUE_TEMPLATE.md jquery-3.2.1/.github/ISSUE_TEMPLATE.md --- jquery-1.11.3+dfsg/.github/ISSUE_TEMPLATE.md 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.github/ISSUE_TEMPLATE.md 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,24 @@ + + +### Description ### + + +### Link to test case ### + diff -Nru jquery-1.11.3+dfsg/.github/PULL_REQUEST_TEMPLATE.md jquery-3.2.1/.github/PULL_REQUEST_TEMPLATE.md --- jquery-1.11.3+dfsg/.github/PULL_REQUEST_TEMPLATE.md 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.github/PULL_REQUEST_TEMPLATE.md 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,20 @@ +### Summary ### + + + +### Checklist ### + + +* [ ] All authors have signed the CLA at https://cla.js.foundation/jquery/jquery +* [ ] New tests have been added to show the fix or feature works +* [ ] Grunt build and unit tests pass locally with these changes +* [ ] If needed, a docs issue/PR was created at https://github.com/jquery/api.jquery.com + + diff -Nru jquery-1.11.3+dfsg/.gitignore jquery-3.2.1/.gitignore --- jquery-1.11.3+dfsg/.gitignore 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.gitignore 2017-03-20 19:00:06.000000000 +0000 @@ -8,6 +8,12 @@ .bower.json .sizecache.json -/dist -/bower_components +npm-debug.log* + +# Ignore everything in dist folder except for eslint config +/dist/* +!/dist/.eslintrc.json + /node_modules + +/test/node_smoke_tests/lib/ensure_iterability.js diff -Nru jquery-1.11.3+dfsg/Gruntfile.js jquery-3.2.1/Gruntfile.js --- jquery-1.11.3+dfsg/Gruntfile.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/Gruntfile.js 2017-03-20 19:00:06.000000000 +0000 @@ -2,24 +2,27 @@ "use strict"; function readOptionalJSON( filepath ) { - var data = {}; + var stripJSONComments = require( "strip-json-comments" ), + data = {}; try { - data = grunt.file.readJSON( filepath ); + data = JSON.parse( stripJSONComments( + fs.readFileSync( filepath, { encoding: "utf8" } ) + ) ); } catch ( e ) {} return data; } - var gzip = require( "gzip-js" ), - srcHintOptions = readOptionalJSON( "src/.jshintrc" ); + var fs = require( "fs" ), + gzip = require( "gzip-js" ); - // The concatenated file won't pass onevar - // But our modules can - delete srcHintOptions.onevar; + if ( !grunt.option( "filename" ) ) { + grunt.option( "filename", "jquery.js" ); + } - grunt.initConfig({ + grunt.initConfig( { pkg: grunt.file.readJSON( "package.json" ), dst: readOptionalJSON( "dist/.destination.json" ), - compare_size: { + "compare_size": { files: [ "dist/jquery.js", "dist/jquery.min.js" ], options: { compress: { @@ -30,6 +33,18 @@ cache: "build/.sizecache.json" } }, + babel: { + options: { + sourceMap: "inline", + retainLines: true + }, + nodeSmokeTests: { + files: { + "test/node_smoke_tests/lib/ensure_iterability.js": + "test/node_smoke_tests/lib/ensure_iterability_es6.js" + } + } + }, build: { all: { dest: "dist/jquery.js", @@ -37,102 +52,131 @@ "core", "selector" ], + + // Exclude specified modules if the module matching the key is removed removeWith: { ajax: [ "manipulation/_evalUrl", "event/ajax" ], callbacks: [ "deferred" ], - css: [ "effects", "dimensions", "offset" ] + css: [ "effects", "dimensions", "offset" ], + "css/showHide": [ "effects" ], + deferred: { + remove: [ "ajax", "effects", "queue", "core/ready" ], + include: [ "core/ready-no-deferred" ] + }, + sizzle: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ] } } }, - bowercopy: { - options: { - clean: true - }, - src: { - files: { - "src/sizzle/dist": "sizzle/dist", - "src/sizzle/test/data": "sizzle/test/data", - "src/sizzle/test/unit": "sizzle/test/unit", - "src/sizzle/test/index.html": "sizzle/test/index.html", - "src/sizzle/test/jquery.js": "sizzle/test/jquery.js" - } - }, - tests: { + npmcopy: { + all: { options: { - destPrefix: "test/libs" + destPrefix: "external" }, files: { - "qunit": "qunit/qunit", - "require.js": "requirejs/require.js", - "sinon/fake_timers.js": "sinon/lib/sinon/util/fake_timers.js", - "sinon/timers_ie.js": "sinon/lib/sinon/util/timers_ie.js" + "sizzle/dist": "sizzle/dist", + "sizzle/LICENSE.txt": "sizzle/LICENSE.txt", + + "npo/npo.js": "native-promise-only/npo.js", + + "qunit/qunit.js": "qunitjs/qunit/qunit.js", + "qunit/qunit.css": "qunitjs/qunit/qunit.css", + "qunit/LICENSE.txt": "qunitjs/LICENSE.txt", + + "qunit-assert-step/qunit-assert-step.js": + "qunit-assert-step/qunit-assert-step.js", + "qunit-assert-step/MIT-LICENSE.txt": + "qunit-assert-step/MIT-LICENSE.txt", + + "requirejs/require.js": "requirejs/require.js", + + "sinon/sinon.js": "sinon/pkg/sinon.js", + "sinon/LICENSE.txt": "sinon/LICENSE" } } }, jsonlint: { pkg: { src: [ "package.json" ] - }, - - bower: { - src: [ "bower.json" ] } }, - jshint: { - all: { - src: [ - "src/**/*.js", "Gruntfile.js", "test/**/*.js", "build/**/*.js" - ], - options: { - jshintrc: true - } + eslint: { + options: { + + // See https://github.com/sindresorhus/grunt-eslint/issues/119 + quiet: true }, + + // We have to explicitly declare "src" property otherwise "newer" + // task wouldn't work properly :/ dist: { - src: "dist/jquery.js", - options: srcHintOptions + src: "dist/jquery.js" + }, + dev: { + src: [ "src/**/*.js", "Gruntfile.js", "test/**/*.js", "build/**/*.js" ] } }, - jscs: { - src: "src/**/*.js", - gruntfile: "Gruntfile.js", - - // Right know, check only test helpers - test: [ "test/data/testrunner.js", "test/data/testinit.js" ], - release: "build/*.js", - tasks: "build/tasks/*.js" - }, testswarm: { - tests: "ajax attributes callbacks core css data deferred dimensions effects event manipulation offset queue selector serialize support traversing".split( " " ) + tests: [ + + // A special module with basic tests, meant for + // not fully supported environments like Android 2.3, + // jsdom or PhantomJS. We run it everywhere, though, + // to make sure tests are not broken. + "basic", + + "ajax", + "animation", + "attributes", + "callbacks", + "core", + "css", + "data", + "deferred", + "deprecated", + "dimensions", + "effects", + "event", + "manipulation", + "offset", + "queue", + "selector", + "serialize", + "support", + "traversing", + "tween" + ] }, watch: { - files: [ "<%= jshint.all.src %>" ], - tasks: "dev" + files: [ "<%= eslint.dev.src %>" ], + tasks: [ "dev" ] }, uglify: { all: { files: { - "dist/jquery.min.js": [ "dist/jquery.js" ] + "dist/<%= grunt.option('filename').replace('.js', '.min.js') %>": + "dist/<%= grunt.option('filename') %>" }, options: { preserveComments: false, - sourceMap: "dist/jquery.min.map", - sourceMappingURL: "jquery.min.map", + sourceMap: true, + ASCIIOnly: true, + sourceMapName: + "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>", report: "min", beautify: { - ascii_only: true + "ascii_only": true }, banner: "/*! jQuery v<%= pkg.version %> | " + - "(c) 2005, <%= grunt.template.today('yyyy') %> jQuery Foundation, Inc. | " + - "jquery.org/license */", + "(c) JS Foundation and other contributors | jquery.org/license */", compress: { - hoist_funs: false, + "hoist_funs": false, loops: false, unused: false } } } } - }); + } ); // Load grunt tasks from NPM packages require( "load-grunt-tasks" )( grunt ); @@ -140,12 +184,50 @@ // Integrate jQuery specific tasks grunt.loadTasks( "build/tasks" ); - grunt.registerTask( "bower", "bowercopy" ); - grunt.registerTask( "lint", [ "jshint", "jscs" ] ); - - // Short list as a high frequency watch task - grunt.registerTask( "dev", [ "build:*:*", "lint" ] ); + grunt.registerTask( "lint", [ + "jsonlint", - // Default grunt - grunt.registerTask( "default", [ "jsonlint", "dev", "uglify", "dist:*", "compare_size" ] ); + // Running the full eslint task without breaking it down to targets + // would run the dist target first which would point to errors in the built + // file, making it harder to fix them. We want to check the built file only + // if we already know the source files pass the linter. + "eslint:dev", + "eslint:dist" + ] ); + + grunt.registerTask( "lint:newer", [ + "newer:jsonlint", + + // Don't replace it with just the task; see the above comment. + "newer:eslint:dev", + "newer:eslint:dist" + ] ); + + grunt.registerTask( "test:fast", "node_smoke_tests" ); + grunt.registerTask( "test:slow", "promises_aplus_tests" ); + + grunt.registerTask( "test", [ + "test:fast", + "test:slow" + ] ); + + grunt.registerTask( "dev", [ + "build:*:*", + "newer:eslint:dev", + "newer:uglify", + "remove_map_comment", + "dist:*", + "compare_size" + ] ); + + grunt.registerTask( "default", [ + "eslint:dev", + "build:*:*", + "uglify", + "remove_map_comment", + "dist:*", + "eslint:dist", + "test:fast", + "compare_size" + ] ); }; diff -Nru jquery-1.11.3+dfsg/.jscsrc jquery-3.2.1/.jscsrc --- jquery-1.11.3+dfsg/.jscsrc 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.jscsrc 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -{ - "preset": "jquery", - - "excludeFiles": [ "src/intro.js", "src/outro.js", "src/sizzle/**/*" ] -} diff -Nru jquery-1.11.3+dfsg/.jshintignore jquery-3.2.1/.jshintignore --- jquery-1.11.3+dfsg/.jshintignore 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.jshintignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -src/intro.js -src/outro.js -src/sizzle/**/* -test/libs/**/* -test/data/jquery-1.9.1.js -test/data/badcall.js -test/data/badjson.js -test/data/json_obj.js -test/data/readywaitasset.js -test/data/readywaitloader.js -test/data/support/csp.js -test/data/support/getComputedSupport.js diff -Nru jquery-1.11.3+dfsg/.jshintrc jquery-3.2.1/.jshintrc --- jquery-1.11.3+dfsg/.jshintrc 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.jshintrc 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -{ - "boss": true, - "curly": true, - "eqeqeq": true, - "eqnull": true, - "expr": true, - "immed": true, - "noarg": true, - "onevar": true, - "quotmark": "double", - "smarttabs": true, - "trailing": true, - "undef": true, - "unused": true, - - "node": true -} \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/LICENSE.txt jquery-3.2.1/LICENSE.txt --- jquery-1.11.3+dfsg/LICENSE.txt 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/LICENSE.txt 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,36 @@ +Copyright JS Foundation and other contributors, https://js.foundation/ + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/jquery/jquery + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +All files located in the node_modules and external directories are +externally maintained libraries used by this software which have their +own licenses; we recommend you read them, as their terms may differ from +the terms above. diff -Nru jquery-1.11.3+dfsg/.mailmap jquery-3.2.1/.mailmap --- jquery-1.11.3+dfsg/.mailmap 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.mailmap 2017-03-20 19:00:06.000000000 +0000 @@ -6,16 +6,16 @@ Andrew E Monat Anton Matzneller Anton Matzneller -Batiste Bieler +Batiste Bieler Benjamin Truyman Brandon Aaron Carl Danley Carl Fürstenberg Carl Fürstenberg Charles McNulty -Christopher Jones -Colin Snover -Corey Frang +Christopher Jones cjqed +Colin Snover +Corey Frang Dan Heberden Daniel Chatfield Daniel Gálvez @@ -24,7 +24,9 @@ Dave Reed David Fox David Hong +David Murdoch Devin Cooper +Douglas Neiner Dmitry Gusev Earle Castledine Erick Ruiz de Chávez @@ -54,6 +56,7 @@ Jörn Zaefferer Jörn Zaefferer Karl Swedberg +Klaus Hartl Kris Borchers Lee Carpenter Li Xudong @@ -67,10 +70,9 @@ Michał Gołębiowski Michał Gołębiowski Mike Alsup -Noah Hamann -David Hong Nguyen Phuc Lam Oleg Gaidarenko +Paul Bakaus Rafaël Blais Masson Richard D. Worth Rick Waldron @@ -80,15 +82,20 @@ Ron Otten Sai Lung Wong Scott González -Scott Jehl +Scott Jehl Sebastian Burkhard -Timmy Willison -Timmy Willison +Senya Pugach +Thomas Tortorini Mr21 +Timmy Willison <4timmywil@gmail.com> +Timmy Willison <4timmywil@gmail.com> +Timmy Willison <4timmywil@gmail.com> +Timmy Willison <4timmywil@gmail.com> Timo Tijhof TJ Holowaychuk Tom H Fuertes Tom H Fuertes Tom H Fuertes Tom Viner +Wesley Walser Xavi Ramirez Xavier Montillet Yehuda Katz diff -Nru jquery-1.11.3+dfsg/MIT-LICENSE.txt jquery-3.2.1/MIT-LICENSE.txt --- jquery-1.11.3+dfsg/MIT-LICENSE.txt 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/MIT-LICENSE.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -Copyright 2014 jQuery Foundation and other contributors -http://jquery.com/ - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff -Nru jquery-1.11.3+dfsg/.npmignore jquery-3.2.1/.npmignore --- jquery-1.11.3+dfsg/.npmignore 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/.npmignore 2017-03-20 19:00:06.000000000 +0000 @@ -1,14 +1,16 @@ -.jshintignore -.jshintrc +.eslintignore +.eslintrc.json /.editorconfig /.gitattributes -/.jscs.json /.mailmap /.travis.yml /build -/dist/cdn /speed /test /Gruntfile.js + +/external/qunit +/external/requirejs +/external/sinon diff -Nru jquery-1.11.3+dfsg/.npmrc jquery-3.2.1/.npmrc --- jquery-1.11.3+dfsg/.npmrc 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/.npmrc 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1 @@ +save-exact=true diff -Nru jquery-1.11.3+dfsg/package.json jquery-3.2.1/package.json --- jquery-1.11.3+dfsg/package.json 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/package.json 2017-03-20 19:00:06.000000000 +0000 @@ -2,12 +2,12 @@ "name": "jquery", "title": "jQuery", "description": "JavaScript library for DOM operations", - "version": "1.11.3", + "version": "3.2.1", "main": "dist/jquery.js", - "homepage": "http://jquery.com", + "homepage": "https://jquery.com", "author": { - "name": "jQuery Foundation and other contributors", - "url": "https://github.com/jquery/jquery/blob/1.11.3/AUTHORS.txt" + "name": "JS Foundation and other contributors", + "url": "https://github.com/jquery/jquery/blob/3.2.1/AUTHORS.txt" }, "repository": { "type": "git", @@ -20,35 +20,78 @@ "library" ], "bugs": { - "url": "http://bugs.jquery.com" + "url": "https://github.com/jquery/jquery/issues" }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/jquery/jquery/blob/1.11.3/MIT-LICENSE.txt" - } - ], + "license": "MIT", "dependencies": {}, "devDependencies": { - "commitplease": "2.0.0", - "grunt": "0.4.2", - "grunt-bowercopy": "0.7.1", - "grunt-cli": "0.1.13", - "grunt-compare-size": "0.4.0", - "grunt-contrib-jshint": "0.8.0", - "grunt-contrib-uglify": "0.3.2", - "grunt-contrib-watch": "0.5.3", - "grunt-git-authors": "1.2.0", - "grunt-jscs-checker": "0.4.1", - "grunt-jsonlint": "1.0.4", + "babel-preset-es2015": "6.6.0", + "commitplease": "2.6.1", + "core-js": "2.2.2", + "cross-spawn": "2.2.3", + "eslint-config-jquery": "1.0.0", + "grunt": "1.0.1", + "grunt-babel": "6.0.0", + "grunt-cli": "1.2.0", + "grunt-compare-size": "0.4.2", + "grunt-contrib-uglify": "1.0.1", + "grunt-contrib-watch": "1.0.0", + "grunt-eslint": "19.0.0", + "grunt-git-authors": "3.2.0", + "grunt-jsonlint": "1.0.7", + "grunt-newer": "1.2.0", + "grunt-npmcopy": "0.1.0", "gzip-js": "0.3.2", - "load-grunt-tasks": "0.3.0", - "requirejs": "2.1.10", + "husky": "0.11.4", + "insight": "0.8.1", + "jsdom": "5.6.1", + "load-grunt-tasks": "3.5.0", + "native-promise-only": "0.8.1", + "promises-aplus-tests": "2.1.2", + "q": "1.4.1", + "qunit-assert-step": "1.0.3", + "qunitjs": "1.23.1", + "requirejs": "2.2.0", + "sinon": "1.17.3", + "sizzle": "2.3.3", + "strip-json-comments": "2.0.1", "testswarm": "1.1.0" }, "scripts": { "build": "npm install && grunt", "start": "grunt watch", - "test": "grunt" + "test": "grunt && grunt test:slow", + "precommit": "grunt lint:newer", + "commitmsg": "node node_modules/commitplease" + }, + "commitplease": { + "nohook": true, + "components": [ + "Docs", + "Tests", + "Build", + "Support", + "Release", + "Core", + "Ajax", + "Attributes", + "Callbacks", + "CSS", + "Data", + "Deferred", + "Deprecated", + "Dimensions", + "Effects", + "Event", + "Manipulation", + "Offset", + "Queue", + "Selector", + "Serialize", + "Traversing", + "Wrap" + ], + "markerPattern": "^((clos|fix|resolv)(e[sd]|ing))|^(refs?)", + "ticketPattern": "^((Closes|Fixes) ([a-zA-Z]{2,}-)[0-9]+)|^(Refs? [^#])" } } diff -Nru jquery-1.11.3+dfsg/README.md jquery-3.2.1/README.md --- jquery-1.11.3+dfsg/README.md 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/README.md 2017-03-20 19:00:06.000000000 +0000 @@ -1,4 +1,4 @@ -[jQuery](http://jquery.com/) - New Wave JavaScript +[jQuery](https://jquery.com/) — New Wave JavaScript ================================================== Contribution Guides @@ -6,27 +6,26 @@ In the spirit of open source software development, jQuery always encourages community code contribution. To help you get started and before you jump into writing code, be sure to read these important contribution guidelines thoroughly: -1. [Getting Involved](http://contribute.jquery.org/) -2. [Core Style Guide](http://contribute.jquery.org/style-guide/js/) -3. [Writing Code for jQuery Foundation Projects](http://contribute.jquery.org/code/) +1. [Getting Involved](https://contribute.jquery.org/) +2. [Core Style Guide](https://contribute.jquery.org/style-guide/js/) +3. [Writing Code for jQuery Foundation Projects](https://contribute.jquery.org/code/) Environments in which to use jQuery -------------------------------------- -- [Browser support](http://jquery.com/browser-support/) differs between the master (2.x) branch and the 1.x-master branch. Specifically, 2.x does not support legacy browsers such as IE6-8. The jQuery team continues to provide support for legacy browsers on the 1.x-master branch. Use the latest 1.x release if support for those browsers is required. See [browser support](http://jquery.com/browser-support/) for more info. -- To use jQuery in Node, browser extensions, and other non-browser environments, use only **2.x** releases. 1.x does not support these environments. +- [Browser support](https://jquery.com/browser-support/) +- jQuery also supports Node, browser extensions, and other non-browser environments. What you need to build your own jQuery -------------------------------------- -In order to build jQuery, you need to have Node.js/npm latest and git 1.7 or later. -(Earlier versions might work OK, but are not tested.) +In order to build jQuery, you need to have the latest Node.js/npm and git 1.7 or later. Earlier versions might work, but are not supported. -For Windows you have to download and install [git](http://git-scm.com/downloads) and [Node.js](http://nodejs.org/download/). +For Windows, you have to download and install [git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/en/download/). -Mac OS users should install [Homebrew](http://mxcl.github.com/homebrew/). Once Homebrew is installed, run `brew install git` to install git, +OS X users should install [Homebrew](http://brew.sh/). Once Homebrew is installed, run `brew install git` to install git, and `brew install node` to install Node.js. Linux/BSD users should use their appropriate package managers to install git and Node.js, or build from source @@ -48,17 +47,17 @@ ``` The built version of jQuery will be put in the `dist/` subdirectory, along with the minified copy and associated map file. -If you want create custom build or help with jQuery development, it would be better to install [grunt command line interface](https://github.com/gruntjs/grunt-cli) as a global package: +If you want to create custom build or help with jQuery development, it would be better to install [grunt command line interface](https://github.com/gruntjs/grunt-cli) as a global package: ``` npm install -g grunt-cli ``` Make sure you have `grunt` installed by testing: ``` -grunt -v +grunt -V ``` -Now by running `grunt` command, in the jquery directory, you could build full version of jQuery, just like with `npm run build` command: +Now by running the `grunt` command, in the jquery directory, you can build a full version of jQuery, just like with an `npm run build` command: ``` grunt ``` @@ -82,12 +81,15 @@ - **ajax/xhr**: The XMLHTTPRequest AJAX transport only. - **ajax/script**: The ` - - - - - - - diff -Nru jquery-1.11.3+dfsg/src/sizzle/test/data/testinit.js jquery-3.2.1/src/sizzle/test/data/testinit.js --- jquery-1.11.3+dfsg/src/sizzle/test/data/testinit.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/src/sizzle/test/data/testinit.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -var fireNative, - jQuery = this.jQuery || "jQuery", // For testing .noConflict() - $ = this.$ || "$", - originaljQuery = jQuery, - original$ = $; - -(function() { - // Config parameter to force basic code paths - QUnit.config.urlConfig.push({ - id: "basic", - label: "Bypass optimizations", - tooltip: "Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition" - }); - if ( QUnit.urlParams.basic ) { - document.querySelectorAll = null; - document.documentElement.contains = null; - document.documentElement.compareDocumentPosition = null; - // Return array of length two to pass assertion - // But support should be false as its not native - document.getElementsByClassName = function() { return [ 0, 1 ]; }; - } -})(); - -/** - * Returns an array of elements with the given IDs - * @example q("main", "foo", "bar") - * @result [
, , ] - */ -function q() { - 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", "baar"]); - * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar' - */ -function t( a, b, c ) { - var f = Sizzle(b), - s = "", - i = 0; - - for ( ; i < f.length; i++ ) { - s += ( s && "," ) + '"' + f[ i ].id + '"'; - } - - deepEqual(f, q.apply( q, c ), a + " (" + b + ")"); -} - -/** - * 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 value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000); -} - -var createWithFriesXML = function() { - var string = ' \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - 1 \ - \ - \ - \ - \ - foo \ - \ - \ - \ - \ - \ - \ - '; - - return jQuery.parseXML( string ); -}; - -fireNative = document.createEvent ? - function( node, type ) { - var event = document.createEvent("HTMLEvents"); - event.initEvent( type, true, true ); - node.dispatchEvent( event ); - } : - function( node, type ) { - var event = document.createEventObject(); - node.fireEvent( "on" + type, event ); - }; - -function testIframeWithCallback( title, fileName, func ) { - test( title, function() { - var iframe; - - stop(); - window.iframeCallback = function() { - var self = this, - args = arguments; - setTimeout(function() { - window.iframeCallback = undefined; - iframe.remove(); - func.apply( self, args ); - func = function() {}; - start(); - }, 0 ); - }; - iframe = jQuery( "
" ).css({ position: "absolute", width: "500px", left: "-600px" }) - .append( jQuery( " -
- - -
-
- -
- - - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- -
-
hi there
-
-
-
-
-
-
-
- -
-
-
- - -
- - -
- - -
C
-
-
- -
-
    -
  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 - - - - - - - - -
​ -
- -
- - diff -Nru jquery-1.11.3+dfsg/src/sizzle/test/jquery.js jquery-3.2.1/src/sizzle/test/jquery.js --- jquery-1.11.3+dfsg/src/sizzle/test/jquery.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/src/sizzle/test/jquery.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,9597 +0,0 @@ -/*! - * 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(" @@ -20,14 +21,14 @@ $(function () { clearTimeout( timeoutId ); if ( !timeoutFired ) { - window.parent.iframeCallback( true ); + startIframeTest( true ); } }); }); timeoutId = setTimeout(function () { timeoutFired = true; - window.parent.iframeCallback( false ); + startIframeTest( false ); }, 10000); }); diff -Nru jquery-1.11.3+dfsg/test/data/core/onready.html jquery-3.2.1/test/data/core/onready.html --- jquery-1.11.3+dfsg/test/data/core/onready.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/core/onready.html 2017-03-20 19:00:06.000000000 +0000 @@ -8,6 +8,7 @@ window.onready = function() { error = "Called window.onready"; }; + @@ -16,7 +17,7 @@ diff -Nru jquery-1.11.3+dfsg/test/data/css/cssWidthBeforeDocReady.html jquery-3.2.1/test/data/css/cssWidthBeforeDocReady.html --- jquery-1.11.3+dfsg/test/data/css/cssWidthBeforeDocReady.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/css/cssWidthBeforeDocReady.html 2017-03-20 19:00:06.000000000 +0000 @@ -4,8 +4,6 @@ +
+
diff -Nru jquery-1.11.3+dfsg/test/data/dimensions/documentSmall.html jquery-3.2.1/test/data/dimensions/documentSmall.html --- jquery-1.11.3+dfsg/test/data/dimensions/documentSmall.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/dimensions/documentSmall.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ - - - - - - - -
- -
- - diff -Nru jquery-1.11.3+dfsg/test/data/evalScript.php jquery-3.2.1/test/data/evalScript.php --- jquery-1.11.3+dfsg/test/data/evalScript.php 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/evalScript.php 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -ok( "" === "GET", "request method is " ); \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/test/data/event/focusElem.html jquery-3.2.1/test/data/event/focusElem.html --- jquery-1.11.3+dfsg/test/data/event/focusElem.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/focusElem.html 2017-03-20 19:00:06.000000000 +0000 @@ -5,12 +5,13 @@ .focus() (activeElement access #13393) + diff -Nru jquery-1.11.3+dfsg/test/data/event/focusinCrossFrame.html jquery-3.2.1/test/data/event/focusinCrossFrame.html --- jquery-1.11.3+dfsg/test/data/event/focusinCrossFrame.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/focusinCrossFrame.html 2017-03-20 19:00:06.000000000 +0000 @@ -5,13 +5,14 @@ focusin event cross-frame (#14180) + diff -Nru jquery-1.11.3+dfsg/test/data/event/interactiveReady.html jquery-3.2.1/test/data/event/interactiveReady.html --- jquery-1.11.3+dfsg/test/data/event/interactiveReady.html 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/data/event/interactiveReady.html 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,24 @@ + + + + +Test case for gh-2100 + + + + + + + + + +
+ + diff -Nru jquery-1.11.3+dfsg/test/data/event/longLoadScript.php jquery-3.2.1/test/data/event/longLoadScript.php --- jquery-1.11.3+dfsg/test/data/event/longLoadScript.php 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/longLoadScript.php 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ - \ No newline at end of file diff -Nru jquery-1.11.3+dfsg/test/data/event/onbeforeunload.html jquery-3.2.1/test/data/event/onbeforeunload.html --- jquery-1.11.3+dfsg/test/data/event/onbeforeunload.html 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/data/event/onbeforeunload.html 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + diff -Nru jquery-1.11.3+dfsg/test/data/event/promiseReady.html jquery-3.2.1/test/data/event/promiseReady.html --- jquery-1.11.3+dfsg/test/data/event/promiseReady.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/promiseReady.html 2017-03-20 19:00:06.000000000 +0000 @@ -4,10 +4,11 @@ Test case for jQuery ticket #11470 + diff -Nru jquery-1.11.3+dfsg/test/data/event/syncReady.html jquery-3.2.1/test/data/event/syncReady.html --- jquery-1.11.3+dfsg/test/data/event/syncReady.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/syncReady.html 2017-03-20 19:00:06.000000000 +0000 @@ -4,12 +4,13 @@ Test case for jQuery ticket #10067 + @@ -17,7 +18,7 @@ oldIE into thinking the dom is ready, but it's not... leaving this check here for future trailblazers to attempt fixing this...--> - +
diff -Nru jquery-1.11.3+dfsg/test/data/event/triggerunload.html jquery-3.2.1/test/data/event/triggerunload.html --- jquery-1.11.3+dfsg/test/data/event/triggerunload.html 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/event/triggerunload.html 2017-03-20 19:00:06.000000000 +0000 @@ -1,6 +1,7 @@ + diff -Nru jquery-1.11.3+dfsg/test/data/iframeTest.js jquery-3.2.1/test/data/iframeTest.js --- jquery-1.11.3+dfsg/test/data/iframeTest.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/data/iframeTest.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,8 @@ + +window.startIframeTest = function() { + var args = Array.prototype.slice.call( arguments ); + + // Note: jQuery may be undefined if page did not load it + args.unshift( window.jQuery, window, document ); + window.parent.iframeCallback.apply( null, args ); +}; diff -Nru jquery-1.11.3+dfsg/test/data/jquery-1.9.1.js jquery-3.2.1/test/data/jquery-1.9.1.js --- jquery-1.11.3+dfsg/test/data/jquery-1.9.1.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/data/jquery-1.9.1.js 2017-03-20 19:00:06.000000000 +0000 @@ -11,7 +11,7 @@ * * Date: 2013-2-4 */ -(function( window, undefined ) { +( function( window, undefined ) { // Can't do this because several apps including ASP.NET trace // the stack via arguments.caller.callee and Firefox dies if @@ -19,6 +19,7 @@ // Support: Firefox 18+ //"use strict"; var + // The deferred used on DOM ready readyList, @@ -58,6 +59,7 @@ // 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 ); }, @@ -103,6 +105,7 @@ jQuery.ready(); } }, + // Clean-up method for dom ready events detach = function() { if ( document.addEventListener ) { @@ -116,6 +119,7 @@ }; jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used jquery: core_version, @@ -130,7 +134,8 @@ // Handle HTML strings if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + 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 ]; @@ -139,22 +144,23 @@ } // 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; // scripts is true for back-compat 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 ] ); @@ -170,20 +176,21 @@ // HANDLE: $(#id) } else { - elem = document.getElementById( match[2] ); + 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] ) { + 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[ 0 ] = elem; } this.context = document; @@ -203,7 +210,7 @@ // HANDLE: $(DOMElement) } else if ( selector.nodeType ) { - this.context = this[0] = selector; + this.context = this[ 0 ] = selector; this.length = 1; return this; @@ -271,6 +278,7 @@ }, ready: function( fn ) { + // Add the callback jQuery.ready.promise().done( fn ); @@ -292,17 +300,17 @@ eq: function( i ) { var len = this.length, j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); }, map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { return callback.call( elem, i, elem ); - })); + } ) ); }, end: function() { - return this.prevObject || this.constructor(null); + return this.prevObject || this.constructor( null ); }, // For internal use only. @@ -317,7 +325,7 @@ jQuery.extend = jQuery.fn.extend = function() { var src, copyIsArray, copy, name, options, clone, - target = arguments[0] || {}, + target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; @@ -325,13 +333,14 @@ // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; - target = arguments[1] || {}; + 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) ) { + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } @@ -342,8 +351,10 @@ } for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { + if ( ( options = arguments[ i ] ) != null ) { + // Extend the base object for ( name in options ) { src = target[ name ]; @@ -355,13 +366,13 @@ } // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = jQuery.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; + clone = src && jQuery.isArray( src ) ? src : []; } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; + clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them @@ -379,7 +390,7 @@ return target; }; -jQuery.extend({ +jQuery.extend( { noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; @@ -434,7 +445,7 @@ // Trigger any bound ready events if ( jQuery.fn.trigger ) { - jQuery( document ).trigger("ready").off("ready"); + jQuery( document ).trigger( "ready" ).off( "ready" ); } }, @@ -442,11 +453,11 @@ // 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"; + return jQuery.type( obj ) === "function"; }, isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; + return jQuery.type( obj ) === "array"; }, isWindow: function( obj ) { @@ -454,7 +465,7 @@ }, isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); + return !isNaN( parseFloat( obj ) ) && isFinite( obj ); }, type: function( obj ) { @@ -462,26 +473,29 @@ return String( obj ); } return typeof obj === "object" || typeof obj === "function" ? - class2type[ core_toString.call(obj) ] || "object" : + 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 ) ) { + 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") ) { + !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; } @@ -525,7 +539,7 @@ // Single tag if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; + return [ context.createElement( parsed[ 1 ] ) ]; } parsed = jQuery.buildFragment( [ data ], context, scripts ); @@ -536,6 +550,7 @@ }, parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); @@ -551,11 +566,12 @@ 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, "")) ) { + .replace( rvalidbraces, "" ) ) ) { return ( new Function( "return " + data ) )(); } @@ -574,13 +590,13 @@ try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); + xml = tmp.parseFromString( data, "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } - } catch( e ) { + } catch ( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { @@ -596,6 +612,7 @@ // 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 @@ -666,7 +683,7 @@ }, // Use native String.trim function wherever possible - trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + trim: core_trim && !core_trim.call( "\uFEFF\xA0" ) ? function( text ) { return text == null ? "" : @@ -685,7 +702,7 @@ var ret = results || []; if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { + if ( isArraylike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? [ arr ] : arr @@ -710,6 +727,7 @@ 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; @@ -730,7 +748,7 @@ first[ i++ ] = second[ j ]; } } else { - while ( second[j] !== undefined ) { + while ( second[ j ] !== undefined ) { first[ i++ ] = second[ j++ ]; } } @@ -835,7 +853,7 @@ if ( jQuery.type( key ) === "object" ) { chainable = true; for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + jQuery.access( elems, fn, i, key[ i ], true, emptyGet, raw ); } // Sets one value @@ -847,6 +865,7 @@ } if ( bulk ) { + // Bulk operations run against the entire set if ( raw ) { fn.call( elems, value ); @@ -863,7 +882,7 @@ if ( fn ) { for ( ; i < length; 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 ) ) ); } } } @@ -874,13 +893,13 @@ // Gets bulk ? fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; + length ? fn( elems[ 0 ], key ) : emptyGet; }, now: function() { return ( new Date() ).getTime(); } -}); +} ); jQuery.ready.promise = function( obj ) { if ( !readyList ) { @@ -891,11 +910,13 @@ // 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 ); @@ -904,6 +925,7 @@ // If IE event model is used } else { + // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent( "onreadystatechange", completed ); @@ -916,17 +938,18 @@ try { top = window.frameElement == null && document.documentElement; - } catch(e) {} + } catch ( e ) {} if ( top && top.doScroll ) { - (function doScrollCheck() { + ( function doScrollCheck() { if ( !jQuery.isReady ) { try { + // Use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch(e) { + top.doScroll( "left" ); + } catch ( e ) { return setTimeout( doScrollCheck, 50 ); } @@ -936,7 +959,7 @@ // and execute any waiting functions jQuery.ready(); } - })(); + } )(); } } } @@ -944,9 +967,9 @@ }; // Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error".split( " " ), function( i, name ) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); +} ); function isArraylike( obj ) { var length = obj.length, @@ -966,7 +989,8 @@ } // All jQuery objects should point back to these -rootjQuery = jQuery(document); +rootjQuery = jQuery( document ); + // String to Object options format cache var optionsCache = {}; @@ -975,7 +999,7 @@ var object = optionsCache[ options ] = {}; jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { object[ flag ] = true; - }); + } ); return object; } @@ -1011,20 +1035,28 @@ 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; @@ -1052,14 +1084,17 @@ } } }, + // 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 ) { + ( function add( args ) { jQuery.each( args, function( _, arg ) { var type = jQuery.type( arg ); if ( type === "function" ) { @@ -1067,15 +1102,18 @@ list.push( arg ); } } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively add( arg ); } - }); - })( arguments ); + } ); + } )( 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 ) { @@ -1085,13 +1123,15 @@ } 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 ) { + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); + // Handle firing indexes if ( firing ) { if ( index <= firingLength ) { @@ -1102,29 +1142,34 @@ } } } - }); + } ); } 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; @@ -1133,10 +1178,12 @@ } return this; }, + // Is it locked? locked: function() { return !stack; }, + // Call all callbacks with the given context and arguments fireWith: function( context, args ) { args = args || []; @@ -1150,11 +1197,13 @@ } 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; @@ -1163,14 +1212,15 @@ return self; }; -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 = { @@ -1183,12 +1233,13 @@ }, 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 action = tuple[ 0 ], 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() @@ -1198,11 +1249,12 @@ } else { newDefer[ action + "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 ) { @@ -1220,11 +1272,12 @@ 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; @@ -1233,12 +1286,12 @@ } // 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 ); @@ -1269,7 +1322,7 @@ return function( value ) { contexts[ i ] = this; values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; - if( values === progressValues ) { + if ( values === progressValues ) { deferred.notifyWith( contexts, values ); } else if ( !( --remaining ) ) { deferred.resolveWith( contexts, values ); @@ -1303,32 +1356,33 @@ return deferred.promise(); } -}); -jQuery.support = (function() { +} ); +jQuery.support = ( function() { var support, all, a, input, select, fragment, opt, eventName, isSupported, i, - div = document.createElement("div"); + 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 ]; + 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 ]; + 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", @@ -1337,19 +1391,19 @@ // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, + 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, + htmlSerialize: !!div.getElementsByTagName( "link" ).length, // Get the style information from getAttribute // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), + style: /top/.test( a.getAttribute( "style" ) ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", + hrefNormalized: a.getAttribute( "href" ) === "/a", // Make sure that element opacity exists // (IE uses filter instead) @@ -1368,11 +1422,11 @@ optSelected: opt.selected, // Tests for enctype support on a form (#6743) - enctype: !!document.createElement("form").enctype, + 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>", + 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", @@ -1399,12 +1453,12 @@ // Support: IE<9 try { delete div.test; - } catch( e ) { + } catch ( e ) { support.deleteExpando = false; } // Check if we can trust getAttribute("value") - input = document.createElement("input"); + input = document.createElement( "input" ); input.setAttribute( "value", "" ); support.input = input.getAttribute( "value" ) === ""; @@ -1433,14 +1487,14 @@ 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 }) { + 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; @@ -1451,17 +1505,18 @@ support.clearCloneStyle = div.style.backgroundClip === "content-box"; // Run tests that need a body at doc ready - jQuery(function() { + 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]; + body = document.getElementsByTagName( "body" )[ 0 ]; if ( !body ) { + // Return for frameset docs that don't have a body return; } - container = document.createElement("div"); + 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 ); @@ -1474,7 +1529,7 @@ // 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 = div.getElementsByTagName( "td" ); tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; isSupported = ( tds[ 0 ].offsetHeight === 0 ); @@ -1500,7 +1555,7 @@ // 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 = div.appendChild( document.createElement( "div" ) ); marginDiv.style.cssText = div.style.cssText = divReset; marginDiv.style.marginRight = marginDiv.style.width = "0"; div.style.width = "1px"; @@ -1510,6 +1565,7 @@ } 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 @@ -1526,6 +1582,7 @@ 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 @@ -1537,18 +1594,18 @@ // 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 */ ){ +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } @@ -1571,11 +1628,12 @@ // 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 ) { + 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 ) { @@ -1679,10 +1737,11 @@ if ( name in thisCache ) { name = [ name ]; } else { - name = name.split(" "); + name = name.split( " " ); } } } else { + // If "name" is an array of keys... // When data is initially created, via ("key", "val") signature, // keys will be converted to camelCase. @@ -1693,7 +1752,7 @@ } for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; + delete thisCache[ name[ i ] ]; } // If there is no data left in the cache, we want to continue @@ -1729,7 +1788,7 @@ } } -jQuery.extend({ +jQuery.extend( { cache: {}, // Unique for each copy of jQuery on the page @@ -1740,13 +1799,14 @@ // 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 ]; + elem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, @@ -1769,6 +1829,7 @@ // 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; @@ -1777,14 +1838,14 @@ 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; + return !noData || noData !== true && elem.getAttribute( "classid" ) === noData; } -}); +} ); -jQuery.fn.extend({ +jQuery.fn.extend( { data: function( key, value ) { var attrs, name, - elem = this[0], + elem = this[ 0 ], i = 0, data = null; @@ -1796,10 +1857,10 @@ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { attrs = elem.attributes; for ( ; i < attrs.length; i++ ) { - name = attrs[i].name; + name = attrs[ i ].name; if ( !name.indexOf( "data-" ) ) { - name = jQuery.camelCase( name.slice(5) ); + name = jQuery.camelCase( name.slice( 5 ) ); dataAttr( elem, name, data[ name ] ); } @@ -1813,32 +1874,34 @@ // Sets multiple values if ( typeof key === "object" ) { - return this.each(function() { + 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() { + this.each( function() { jQuery.data( this, key, value ); - }); + } ); }, null, value, arguments.length > 1, null, true ); }, removeData: function( key ) { - return this.each(function() { + 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 ) { @@ -1852,11 +1915,12 @@ 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 jQuery.data( elem, key, data ); @@ -1875,7 +1939,7 @@ for ( name in obj ) { // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + if ( name === "data" && jQuery.isEmptyObject( obj[ name ] ) ) { continue; } if ( name !== "toJSON" ) { @@ -1885,7 +1949,7 @@ return true; } -jQuery.extend({ +jQuery.extend( { queue: function( elem, type, data ) { var queue; @@ -1895,8 +1959,8 @@ // 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) ); + if ( !queue || jQuery.isArray( data ) ) { + queue = jQuery._data( elem, type, jQuery.makeArray( data ) ); } else { queue.push( data ); } @@ -1945,15 +2009,15 @@ _queueHooks: function( elem, type ) { var key = type + "queueHooks"; return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { + empty: jQuery.Callbacks( "once memory" ).add( function() { jQuery._removeData( elem, type + "queue" ); jQuery._removeData( elem, key ); - }) - }); + } ) + } ); } -}); +} ); -jQuery.fn.extend({ +jQuery.fn.extend( { queue: function( type, data ) { var setter = 2; @@ -1964,27 +2028,28 @@ } 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 ); - }); + } ); }, + // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { @@ -1996,11 +2061,12 @@ 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 ) { @@ -2021,7 +2087,7 @@ } type = type || "fx"; - while( i-- ) { + while ( i-- ) { tmp = jQuery._data( elements[ i ], type + "queueHooks" ); if ( tmp && tmp.empty ) { count++; @@ -2031,7 +2097,7 @@ resolve(); return defer.promise( obj ); } -}); +} ); var nodeHook, boolHook, rclass = /[\t\r\n]/g, rreturn = /\r/g, @@ -2042,15 +2108,15 @@ getSetAttribute = jQuery.support.getSetAttribute, getSetInput = jQuery.support.input; -jQuery.fn.extend({ +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() { + return this.each( function() { jQuery.removeAttr( this, name ); - }); + } ); }, prop: function( name, value ) { @@ -2059,13 +2125,14 @@ removeProp: function( name ) { name = jQuery.propFix[ name ] || name; - return this.each(function() { + 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 ) {} - }); + } catch ( e ) {} + } ); }, addClass: function( value ) { @@ -2075,12 +2142,13 @@ proceed = typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { + 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 ) || []; @@ -2093,7 +2161,7 @@ if ( cur ) { j = 0; - while ( (clazz = classes[j++]) ) { + while ( ( clazz = classes[ j++ ] ) ) { if ( cur.indexOf( " " + clazz + " " ) < 0 ) { cur += clazz + " "; } @@ -2114,15 +2182,16 @@ proceed = arguments.length === 0 || typeof value === "string" && value; if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { + 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, " " ) : @@ -2131,7 +2200,8 @@ if ( cur ) { j = 0; - while ( (clazz = classes[j++]) ) { + while ( ( clazz = classes[ j++ ] ) ) { + // Remove *all* instances while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { cur = cur.replace( " " + clazz + " ", " " ); @@ -2150,13 +2220,14 @@ 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( i ) { + jQuery( this ).toggleClass( value.call( this, i, this.className, stateVal ), stateVal ); + } ); } - return this.each(function() { + return this.each( function() { if ( type === "string" ) { + // toggle individual class names var className, i = 0, @@ -2164,7 +2235,8 @@ state = stateVal, classNames = value.match( core_rnotwhite ) || []; - while ( (className = classNames[ i++ ]) ) { + while ( ( className = classNames[ i++ ] ) ) { + // check each className given, space separated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); @@ -2173,6 +2245,7 @@ // Toggle whole class name } else if ( type === core_strundefined || type === "boolean" ) { if ( this.className ) { + // store className if set jQuery._data( this, "__className__", this.className ); } @@ -2183,7 +2256,7 @@ // falling back to the empty string if nothing was stored. this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } - }); + } ); }, hasClass: function( selector ) { @@ -2191,7 +2264,7 @@ i = 0, l = this.length; for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + if ( this[ i ].nodeType === 1 && ( " " + this[ i ].className + " " ).replace( rclass, " " ).indexOf( className ) >= 0 ) { return true; } } @@ -2201,21 +2274,23 @@ val: function( value ) { var ret, hooks, isFunction, - elem = this[0]; + 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 ) { + 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, "") : + ret.replace( rreturn, "" ) : + // handle cases where value is null/undef or number ret == null ? "" : ret; } @@ -2225,9 +2300,9 @@ isFunction = jQuery.isFunction( value ); - return this.each(function( i ) { + return this.each( function( i ) { var val, - self = jQuery(this); + self = jQuery( this ); if ( this.nodeType !== 1 ) { return; @@ -2245,25 +2320,26 @@ } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { + 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 ) { + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } - }); + } ); } -}); +} ); -jQuery.extend({ +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; @@ -2288,8 +2364,9 @@ // 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 ) && + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) && ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option @@ -2311,9 +2388,9 @@ set: function( elem, value ) { var values = jQuery.makeArray( value ); - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); + jQuery( elem ).find( "option" ).each( function() { + this.selected = jQuery.inArray( jQuery( this ).val(), values ) >= 0; + } ); if ( !values.length ) { elem.selectedIndex = -1; @@ -2351,7 +2428,7 @@ if ( value === null ) { jQuery.removeAttr( elem, name ); - } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + } else if ( hooks && notxml && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } else { @@ -2359,7 +2436,7 @@ return value; } - } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + } else if ( hooks && notxml && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } else { @@ -2383,11 +2460,12 @@ attrNames = value && value.match( core_rnotwhite ); if ( attrNames && elem.nodeType === 1 ) { - while ( (name = attrNames[i++]) ) { + 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 ) ) { @@ -2410,7 +2488,8 @@ attrHooks: { type: { set: function( elem, value ) { - if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName( elem, "input" ) ) { + // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to default in case type is set after value during creation var val = elem.value; @@ -2451,13 +2530,14 @@ 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 ) { + if ( hooks && "set" in hooks && ( ret = hooks.set( elem, value, name ) ) !== undefined ) { return ret; } else { @@ -2465,7 +2545,7 @@ } } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { return ret; } else { @@ -2477,9 +2557,10 @@ 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"); + var attributeNode = elem.getAttributeNode( "tabindex" ); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : @@ -2489,12 +2570,13 @@ } } } -}); +} ); // 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 ), @@ -2504,6 +2586,7 @@ getSetInput && getSetAttribute ? attr != null : + // oldIE fabricates an empty string for missing boolean attributes // and conflates checked/selected into attroperties ruseDefault.test( name ) ? @@ -2519,9 +2602,11 @@ }, 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 ); @@ -2548,9 +2633,11 @@ }, 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 ); } @@ -2571,11 +2658,12 @@ 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 = elem.ownerDocument.createAttribute( name ) ) ); } @@ -2599,7 +2687,7 @@ // 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.each( [ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { @@ -2607,36 +2695,36 @@ 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.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.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" @@ -2665,7 +2753,7 @@ } return null; } - }); + } ); } // IE6/7 call enctype encoding @@ -2675,24 +2763,25 @@ // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { + 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; + return elem.getAttribute( "value" ) === null ? "on" : elem.value; } }; - }); + } ); } -jQuery.each([ "radio", "checkbox" ], function() { +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 ); + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) >= 0 ); } } - }); -}); + } ); +} ); var rformElems = /^(?:input|select|textarea)$/i, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, @@ -2739,29 +2828,31 @@ } // 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 !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + return typeof jQuery !== core_strundefined && ( !e || jQuery.event.triggered !== e.type ) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; + // 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 ) || [""]; + types = ( types || "" ).match( core_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(); // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; @@ -2773,7 +2864,7 @@ special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers - handleObj = jQuery.extend({ + handleObj = jQuery.extend( { type: type, origType: origType, data: data, @@ -2781,16 +2872,17 @@ 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/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 ); @@ -2832,17 +2924,17 @@ namespaces, origType, elemData = jQuery.hasData( elem ) && jQuery._data( elem ); - if ( !elemData || !(events = elemData.events) ) { + if ( !elemData || !( events = elemData.events ) ) { return; } // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( core_rnotwhite ) || [""]; + types = ( types || "" ).match( core_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 ) { @@ -2855,7 +2947,7 @@ 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; @@ -2903,7 +2995,7 @@ 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(".") : []; + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; cur = tmp = elem = elem || document; @@ -2917,13 +3009,14 @@ return; } - if ( type.indexOf(".") >= 0 ) { + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); + namespaces = type.split( "." ); type = namespaces.shift(); namespaces.sort(); } - ontype = type.indexOf(":") < 0 && "on" + type; + 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 ] ? @@ -2931,9 +3024,9 @@ new jQuery.Event( type, typeof event === "object" && event ); event.isTrigger = true; - event.namespace = namespaces.join("."); + event.namespace = namespaces.join( "." ); event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : null; // Clean up the event in case it is being reused @@ -2967,14 +3060,14 @@ } // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { + 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() ) { + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { event.type = i > 1 ? bubbleType : @@ -2997,8 +3090,8 @@ // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + if ( ( !special._default || special._default.apply( 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. @@ -3017,6 +3110,7 @@ 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 } @@ -3044,7 +3138,7 @@ 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 @@ -3057,11 +3151,11 @@ // 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). @@ -3070,11 +3164,11 @@ event.handleObj = handleObj; event.data = handleObj.data; - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + 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(); } @@ -3100,13 +3194,13 @@ // 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") ) { + 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") ) { + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { matches = []; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; @@ -3124,7 +3218,7 @@ } } if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); + handlerQueue.push( { elem: cur, handlers: matches } ); } } } @@ -3132,7 +3226,7 @@ // 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; @@ -3185,12 +3279,12 @@ }, // 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 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 @@ -3203,7 +3297,7 @@ }, mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + 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, @@ -3236,10 +3330,12 @@ 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 ) { @@ -3249,6 +3345,7 @@ } }, focus: { + // Fire native event if possible so blur/focus sequence is correct trigger: function() { if ( this !== document.activeElement && this.focus ) { @@ -3256,6 +3353,7 @@ this.focus(); return false; } catch ( e ) { + // Support: IE<9 // If we error on focus to hidden element (#1486, #12518), // let .trigger() run the handlers @@ -3286,6 +3384,7 @@ }, 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. @@ -3330,8 +3429,9 @@ }; 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 ); } @@ -3394,6 +3494,7 @@ if ( !e ) { return; } + // If stopPropagation exists, run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); @@ -3410,7 +3511,7 @@ }; // Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ +jQuery.each( { mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { @@ -3426,7 +3527,7 @@ // 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 )) ) { + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; @@ -3434,13 +3535,14 @@ 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; @@ -3448,20 +3550,23 @@ // 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; @@ -3472,6 +3577,7 @@ }, teardown: function() { + // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; @@ -3491,6 +3597,7 @@ 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. @@ -3499,17 +3606,19 @@ 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; @@ -3519,17 +3628,17 @@ 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") ) { + if ( this !== elem || event.isSimulated || event.isTrigger || ( elem.type !== "radio" && elem.type !== "checkbox" ) ) { return event.handleObj.handler.apply( this, arguments ); } }, @@ -3544,7 +3653,7 @@ // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0, @@ -3564,18 +3673,20 @@ } } }; - }); + } ); } -jQuery.fn.extend({ +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; @@ -3587,15 +3698,18 @@ } 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; @@ -3611,16 +3725,18 @@ 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 ); @@ -3628,6 +3744,7 @@ 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( @@ -3638,6 +3755,7 @@ return this; } if ( typeof types === "object" ) { + // ( types-object [, selector] ) for ( type in types ) { this.off( type, selector, types[ type ] ); @@ -3645,6 +3763,7 @@ return this; } if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) fn = selector; selector = undefined; @@ -3652,9 +3771,9 @@ if ( fn === false ) { fn = returnFalse; } - return this.each(function() { + return this.each( function() { jQuery.event.remove( this, types, fn, selector ); - }); + } ); }, bind: function( types, data, fn ) { @@ -3668,29 +3787,30 @@ 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() { + return this.each( function() { jQuery.event.trigger( type, data, this ); - }); + } ); }, triggerHandler: function( type, data ) { - var elem = this[0]; + 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 ) { +( function( window, undefined ) { var i, cachedruns, @@ -3713,7 +3833,7 @@ sortOrder, // Instance-specific data - expando = "sizzle" + -(new Date()), + expando = "sizzle" + -( new Date() ), preferredDoc = window.document, support = {}, dirruns = 0, @@ -3731,23 +3851,24 @@ 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 ) { + 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])+", @@ -3787,6 +3908,7 @@ "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)(?:\\(" + @@ -3810,24 +3932,27 @@ 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; + slice.call( preferredDoc.documentElement.childNodes, 0 )[ 0 ].nodeType; } catch ( e ) { slice = function( i ) { var elem, results = []; - while ( (elem = this[i++]) ) { + while ( ( elem = this[ i++ ] ) ) { results.push( elem ); } return results; @@ -3852,14 +3977,16 @@ var cache, keys = []; - return (cache = function( key, value ) { + 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); - }); + return ( cache[ key ] = value ); + } ); } /** @@ -3876,13 +4003,14 @@ * @param {Function} fn Passed the created div and expects a boolean result */ function assert( fn ) { - var div = document.createElement("div"); + var div = document.createElement( "div" ); try { return fn( div ); - } catch (e) { + } catch ( e ) { return false; } finally { + // release memory in IE div = null; } @@ -3890,6 +4018,7 @@ function Sizzle( selector, context, results, seed ) { var match, elem, m, nodeType, + // QSA vars i, groups, old, nid, newContext, newSelector; @@ -3904,21 +4033,24 @@ return results; } - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + if ( ( nodeType = context.nodeType ) !== 1 && nodeType !== 9 ) { return []; } if ( !documentIsXML && !seed ) { // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { + if ( ( match = rquickExpr.exec( selector ) ) ) { + // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { + 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 ) { @@ -3929,8 +4061,9 @@ return results; } } else { + // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + if ( context.ownerDocument && ( elem = context.ownerDocument.getElementById( m ) ) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; @@ -3938,19 +4071,19 @@ } // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + } 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) ); + } 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) ) { + if ( support.qsa && !rbuggyQSA.test( selector ) ) { old = true; nid = expando; newContext = context; @@ -3963,7 +4096,7 @@ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { groups = tokenize( selector ); - if ( (old = context.getAttribute("id")) ) { + if ( ( old = context.getAttribute( "id" ) ) ) { nid = old.replace( rescape, "\\$&" ); } else { context.setAttribute( "id", nid ); @@ -3972,10 +4105,10 @@ i = groups.length; while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); + groups[ i ] = nid + toSelector( groups[ i ] ); } newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); + newSelector = groups.join( "," ); } if ( newSelector ) { @@ -3984,10 +4117,10 @@ newSelector ), 0 ) ); return results; - } catch(qsaError) { + } catch ( qsaError ) { } finally { if ( !old ) { - context.removeAttribute("id"); + context.removeAttribute( "id" ); } } } @@ -4003,9 +4136,10 @@ * @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; + var documentElement = elem && ( elem.ownerDocument || elem ).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; @@ -4030,35 +4164,38 @@ documentIsXML = isXML( doc ); // Check if getElementsByTagName("*") returns only elements - support.tagNameNoComments = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); + 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 ) { + support.attributes = assert( function( div ) { div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); + 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 ) { + support.getByClassName = assert( function( div ) { + // Opera can't find a second classname (in 9.6) div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + 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; - }); + 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 ) { + support.getByName = assert( function( div ) { + // Inject content div.id = expando + 0; div.innerHTML = "
"; @@ -4066,8 +4203,10 @@ // 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 ); @@ -4076,63 +4215,64 @@ docElem.removeChild( div ); return pass; - }); + } ); // IE6/7 return modified attributes - Expr.attrHandle = assert(function( div ) { + Expr.attrHandle = assert( function( div ) { div.innerHTML = ""; return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }) ? + div.firstChild.getAttribute( "href" ) === "#"; + } ) ? {} : { "href": function( elem ) { return elem.getAttribute( "href", 2 ); }, "type": function( elem ) { - return elem.getAttribute("type"); + return elem.getAttribute( "type" ); } }; // ID find and filter if ( support.getIdNotName ) { - Expr.find["ID"] = function( id, context ) { + 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] : []; + return m && m.parentNode ? [ m ] : []; } }; - Expr.filter["ID"] = function( id ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - return elem.getAttribute("id") === attrId; + return elem.getAttribute( "id" ) === attrId; }; }; } else { - Expr.find["ID"] = function( id, context ) { + 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] : + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode( "id" ).value === id ? + [ m ] : undefined : []; } }; - Expr.filter["ID"] = function( id ) { + Expr.filter[ "ID" ] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode( "id" ); return node && node.value === attrId; }; }; } // Tag - Expr.find["TAG"] = support.tagNameNoComments ? + Expr.find[ "TAG" ] = support.tagNameNoComments ? function( tag, context ) { if ( typeof context.getElementsByTagName !== strundefined ) { return context.getElementsByTagName( tag ); @@ -4146,7 +4286,7 @@ // Filter out possible comments if ( tag === "*" ) { - while ( (elem = results[i++]) ) { + while ( ( elem = results[ i++ ] ) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } @@ -4158,14 +4298,14 @@ }; // Name - Expr.find["NAME"] = support.getByName && function( tag, context ) { + 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 ) { + Expr.find[ "CLASS" ] = support.getByClassName && function( className, context ) { if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { return context.getElementsByClassName( className ); } @@ -4181,10 +4321,12 @@ // A support test would require too much code (would include document ready) rbuggyQSA = [ ":focus" ]; - if ( (support.qsa = isNative(doc.querySelectorAll)) ) { + if ( ( support.qsa = isNative( doc.querySelectorAll ) ) ) { + // Build QSA regex // Regex strategy adopted from Diego Perini - assert(function( div ) { + 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, @@ -4193,46 +4335,47 @@ div.innerHTML = ""; // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { + 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"); + if ( !div.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); } - }); + } ); - assert(function( div ) { + assert( function( div ) { // Opera 10-12/IE8 - ^= $= *= and empty values // Should not select anything div.innerHTML = ""; - if ( div.querySelectorAll("[i^='']").length ) { + 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 ) { + 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(",.*:"); - }); + div.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); } - if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector || + if ( ( support.matchesSelector = isNative( ( matches = docElem.matchesSelector || docElem.mozMatchesSelector || docElem.webkitMatchesSelector || docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { + docElem.msMatchesSelector ) ) ) ) { + + assert( function( div ) { - 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" ); @@ -4241,16 +4384,16 @@ // 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("|") ); + 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 ? + contains = isNative( docElem.contains ) || docElem.compareDocumentPosition ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; @@ -4258,11 +4401,11 @@ adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); + ) ); } : function( a, b ) { if ( b ) { - while ( (b = b.parentNode) ) { + while ( ( b = b.parentNode ) ) { if ( b === a ) { return true; } @@ -4281,7 +4424,7 @@ return 0; } - if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) { + 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; @@ -4324,33 +4467,34 @@ // Otherwise we need full lists of their ancestors for comparison cur = a; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { ap.unshift( cur ); } cur = b; - while ( (cur = cur.parentNode) ) { + while ( ( cur = cur.parentNode ) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { + while ( ap[ i ] === bp[ i ] ) { i++; } return i ? + // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : + siblingCheck( ap[ i ], bp[ i ] ) : // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : + 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 ); + [ 0, 0 ].sort( sortOrder ); support.detectDuplicates = hasDuplicate; return document; @@ -4361,6 +4505,7 @@ }; Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); @@ -4370,24 +4515,26 @@ 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) ) { + 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) {} + } catch ( e ) {} } - return Sizzle( expr, document, null, [elem] ).length > 0; + 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 ); @@ -4406,13 +4553,13 @@ if ( !documentIsXML ) { name = name.toLowerCase(); } - if ( (val = Expr.attrHandle[ name ]) ) { + 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 ? + return ( ( val = elem.getAttributeNode( name ) ) || elem.getAttribute( name ) ) && elem[ name ] === true ? name : val && val.specified ? val.value : null; }; @@ -4433,7 +4580,7 @@ results.sort( sortOrder ); if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { + for ( ; ( elem = results[ i ] ); i++ ) { if ( elem === results[ i - 1 ] ) { j = duplicates.push( i ); } @@ -4457,7 +4604,7 @@ // Check if b follows a if ( cur ) { - while ( (cur = cur.nextSibling) ) { + while ( ( cur = cur.nextSibling ) ) { if ( cur === b ) { return -1; } @@ -4479,27 +4626,27 @@ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; + return ( name === "input" || name === "button" ) && elem.type === type; }; } // Returns a function to use in pseudos for positionals function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { + return markFunction( function( argument ) { argument = +argument; - return markFunction(function( seed, matches ) { + 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]); + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); } } - }); - }); + } ); + } ); } /** @@ -4513,17 +4660,21 @@ nodeType = elem.nodeType; if ( !nodeType ) { + // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { + 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 ); @@ -4532,6 +4683,7 @@ } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } + // Do not include comment or processing instruction nodes return ret; @@ -4557,13 +4709,13 @@ preFilter: { "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); + 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 ); + match[ 3 ] = ( match[ 4 ] || match[ 5 ] || "" ).replace( runescape, funescape ); - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; } return match.slice( 0, 4 ); @@ -4580,22 +4732,23 @@ 7 sign of y-component 8 y of y-component */ - match[1] = match[1].toLowerCase(); + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); + 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" ); + 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] ); + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); } return match; @@ -4603,26 +4756,28 @@ "PSEUDO": function( match ) { var excess, - unquoted = !match[5] && match[2]; + unquoted = !match[ 5 ] && match[ 2 ]; - if ( matchExpr["CHILD"].test( match[0] ) ) { + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { return null; } // Accept quoted arguments as-is - if ( match[4] ) { - match[2] = match[4]; + 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 )) && + ( excess = tokenize( unquoted, true ) ) && + // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + ( 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 ); + 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) @@ -4647,10 +4802,10 @@ var pattern = classCache[ className + " " ]; return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + ( pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( className, function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }); + return pattern.test( elem.className || ( typeof elem.getAttribute !== strundefined && elem.getAttribute( "class" ) ) || "" ); + } ); }, "ATTR": function( name, operator, check ) { @@ -4702,11 +4857,12 @@ if ( simple ) { while ( dir ) { node = elem; - while ( (node = node[ dir ]) ) { + 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"; } @@ -4717,17 +4873,18 @@ // non-xml :nth-child(...) stores cache data on `parent` if ( forward && useCache ) { + // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); + outerCache = parent[ expando ] || ( parent[ expando ] = {} ); cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = cache[ 0 ] === dirruns && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; - while ( (node = ++nodeIndex && node && node[ dir ] || + while ( ( node = ++nodeIndex && node && node[ dir ] || // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { + ( diff = nodeIndex = 0 ) || start.pop() ) ) { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { @@ -4737,19 +4894,21 @@ } // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; + } 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()) ) { + 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 ]; + ( node[ expando ] || ( node[ expando ] = {} ) )[ type ] = [ dirruns, diff ]; } if ( node === elem ) { @@ -4767,6 +4926,7 @@ }, "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 @@ -4786,15 +4946,15 @@ if ( fn.length > 1 ) { args = [ pseudo, pseudo, "", argument ]; return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { + 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] ); + idx = indexOf.call( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); } - }) : + } ) : function( elem ) { return fn( elem, 0, args ); }; @@ -4805,8 +4965,10 @@ }, pseudos: { + // Potentially complex pseudos - "not": markFunction(function( selector ) { + "not": markFunction( function( selector ) { + // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators @@ -4815,36 +4977,36 @@ matcher = compile( selector.replace( rtrim, "$1" ) ); return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { + 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); + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); } } - }) : + } ) : function( elem, context, xml ) { - input[0] = elem; + input[ 0 ] = elem; matcher( input, null, xml, results ); return !results.pop(); }; - }), + } ), - "has": markFunction(function( selector ) { + "has": markFunction( function( selector ) { return function( elem ) { return Sizzle( selector, elem ).length > 0; }; - }), + } ), - "contains": markFunction(function( text ) { + "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 @@ -4854,25 +5016,26 @@ // 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 || "") ) { + 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) ) { + 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 ); + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); return false; }; - }), + } ), // Miscellaneous "target": function( elem ) { @@ -4885,7 +5048,7 @@ }, "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + return elem === document.activeElement && ( !document.hasFocus || document.hasFocus() ) && !!( elem.type || elem.href || ~elem.tabIndex ); }, // Boolean properties @@ -4898,13 +5061,15 @@ }, "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); + 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 ) { @@ -4916,6 +5081,7 @@ // 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 @@ -4930,7 +5096,7 @@ }, "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); + return !Expr.pseudos[ "empty" ]( elem ); }, // Element/input types @@ -4949,57 +5115,58 @@ "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 ); + ( ( attr = elem.getAttribute( "type" ) ) == null || attr.toLowerCase() === elem.type ); }, // Position-in-collection - "first": createPositionalPseudo(function() { + "first": createPositionalPseudo( function() { return [ 0 ]; - }), + } ), - "last": createPositionalPseudo(function( matchIndexes, length ) { + "last": createPositionalPseudo( function( matchIndexes, length ) { return [ length - 1 ]; - }), + } ), - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + "eq": createPositionalPseudo( function( matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; - }), + } ), - "even": createPositionalPseudo(function( matchIndexes, length ) { + "even": createPositionalPseudo( function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "odd": createPositionalPseudo(function( matchIndexes, length ) { + "odd": createPositionalPseudo( function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); } return matchIndexes; - }), + } ), - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + "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 ) { + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); } return matchIndexes; - }) + } ) } }; @@ -5027,10 +5194,11 @@ while ( soFar ) { // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { if ( match ) { + // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; + soFar = soFar.slice( match[ 0 ].length ) || soFar; } groups.push( tokens = [] ); } @@ -5038,20 +5206,21 @@ matched = false; // Combinators - if ( (match = rcombinators.exec( soFar )) ) { + if ( ( match = rcombinators.exec( soFar ) ) ) { matched = match.shift(); tokens.push( { value: matched, + // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) + 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 ))) ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { matched = match.shift(); tokens.push( { value: matched, @@ -5074,6 +5243,7 @@ soFar.length : soFar ? Sizzle.error( selector ) : + // Cache the tokens tokenCache( selector, groups ).slice( 0 ); } @@ -5083,7 +5253,7 @@ len = tokens.length, selector = ""; for ( ; i < len; i++ ) { - selector += tokens[i].value; + selector += tokens[ i ].value; } return selector; } @@ -5094,9 +5264,10 @@ doneName = done++; return combinator.first ? + // Check against closest ancestor/preceding element function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { return matcher( elem, context, xml ); } @@ -5110,7 +5281,7 @@ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching if ( xml ) { - while ( (elem = elem[ dir ]) ) { + while ( ( elem = elem[ dir ] ) ) { if ( elem.nodeType === 1 || checkNonElements ) { if ( matcher( elem, context, xml ) ) { return true; @@ -5118,17 +5289,17 @@ } } } else { - while ( (elem = elem[ dir ]) ) { + 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 ) { + 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 ) { + cache[ 1 ] = matcher( elem, context, xml ) || cachedruns; + if ( cache[ 1 ] === true ) { return true; } } @@ -5143,13 +5314,13 @@ function( elem, context, xml ) { var i = matchers.length; while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { + if ( !matchers[ i ]( elem, context, xml ) ) { return false; } } return true; } : - matchers[0]; + matchers[ 0 ]; } function condense( unmatched, map, filter, context, xml ) { @@ -5160,7 +5331,7 @@ mapped = map != null; for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { + if ( ( elem = unmatched[ i ] ) ) { if ( !filter || filter( elem, context, xml ) ) { newUnmatched.push( elem ); if ( mapped ) { @@ -5180,7 +5351,7 @@ if ( postFinder && !postFinder[ expando ] ) { postFinder = setMatcher( postFinder, postSelector ); } - return markFunction(function( seed, results, context, xml ) { + return markFunction( function( seed, results, context, xml ) { var temp, i, elem, preMap = [], postMap = [], @@ -5195,6 +5366,7 @@ elems, matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, postFinder || ( seed ? preFilter : preexisting || postFilter ) ? @@ -5218,8 +5390,8 @@ // 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 ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); } } } @@ -5227,25 +5399,27 @@ 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]) ) { + if ( ( elem = matcherOut[ i ] ) ) { + // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); + temp.push( ( matcherIn[ i ] = elem ) ); } } - postFinder( null, (matcherOut = []), temp, xml ); + 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 ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) { - seed[temp] = !(results[temp] = elem); + seed[ temp ] = !( results[ temp ] = elem ); } } } @@ -5263,14 +5437,14 @@ push.apply( results, matcherOut ); } } - }); + } ); } function matcherFromTokens( tokens ) { var checkContext, matcher, j, len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], + 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) @@ -5282,23 +5456,24 @@ }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? + ( 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) ]; + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + 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 ] ) { + if ( Expr.relative[ tokens[ j ].type ] ) { break; } } @@ -5307,7 +5482,7 @@ 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 && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), j < len && toSelector( tokens ) ); } @@ -5319,6 +5494,7 @@ } function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched var matcherCachedRuns = 0, bySet = setMatchers.length > 0, @@ -5331,10 +5507,12 @@ 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 ), + 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); + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ); if ( outermost ) { outermostContext = context !== document && context; @@ -5343,10 +5521,10 @@ // 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++ ) { + for ( ; ( elem = elems[ i ] ) != null; i++ ) { if ( byElement && elem ) { j = 0; - while ( (matcher = elementMatchers[j++]) ) { + while ( ( matcher = elementMatchers[ j++ ] ) ) { if ( matcher( elem, context, xml ) ) { results.push( elem ); break; @@ -5360,8 +5538,9 @@ // Track unmatched elements for set filters if ( bySet ) { + // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { + if ( ( elem = !matcher && elem ) ) { matchedCount--; } @@ -5376,16 +5555,17 @@ matchedCount += i; if ( bySet && i !== matchedCount ) { j = 0; - while ( (matcher = setMatchers[j++]) ) { + 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 ); + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); } } } @@ -5426,13 +5606,14 @@ 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] ); + cached = matcherFromTokens( group[ i ] ); if ( cached[ expando ] ) { setMatchers.push( cached ); } else { @@ -5450,7 +5631,7 @@ var i = 0, len = contexts.length; for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); + Sizzle( selector, contexts[ i ], results ); } return results; } @@ -5460,16 +5641,17 @@ 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" && + 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 ] ) { + Expr.relative[ tokens[ 1 ].type ] ) { - context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0]; + context = Expr.find[ "ID" ]( token.matches[ 0 ].replace( runescape, funescape ), context )[ 0 ]; if ( !context ) { return results; } @@ -5478,20 +5660,21 @@ } // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; while ( i-- ) { - token = tokens[i]; + token = tokens[ i ]; // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { + if ( Expr.relative[ ( type = token.type ) ] ) { break; } - if ( (find = Expr.find[ type ]) ) { + 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 = 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 ); @@ -5521,7 +5704,7 @@ } // Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; // Easy API for creating new setFilters function setFilters() {} @@ -5535,18 +5718,18 @@ Sizzle.attr = jQuery.attr; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.expr[ ":" ] = jQuery.expr.pseudos; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; - -})( window ); +} )( 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, @@ -5555,20 +5738,20 @@ prev: true }; -jQuery.fn.extend({ +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() { + return this.pushStack( jQuery( selector ).filter( function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } - }) ); + } ) ); } ret = []; @@ -5587,30 +5770,31 @@ targets = jQuery( target, this ), len = targets.length; - return this.filter(function() { + return this.filter( function() { for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { + if ( jQuery.contains( this, targets[ i ] ) ) { return true; } } - }); + } ); }, not: function( selector ) { - return this.pushStack( winnow(this, selector, false) ); + return this.pushStack( winnow( this, selector, false ) ); }, filter: function( selector ) { - return this.pushStack( winnow(this, selector, true) ); + 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( selector, this.context ).index( this[ 0 ] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, @@ -5625,10 +5809,10 @@ 0; for ( ; i < l; i++ ) { - cur = this[i]; + cur = this[ i ]; while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + if ( pos ? pos.index( cur ) > -1 : jQuery.find.matchesSelector( cur, selectors ) ) { ret.push( cur ); break; } @@ -5645,18 +5829,19 @@ // No argument, return index in parent if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + 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 ) ); + 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 ); + elem.jquery ? elem[ 0 ] : elem, this ); }, add: function( selector, context ) { @@ -5665,15 +5850,15 @@ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); - return this.pushStack( jQuery.unique(all) ); + return this.pushStack( jQuery.unique( all ) ); }, addBack: function( selector ) { return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) + this.prevObject : this.prevObject.filter( selector ) ); } -}); +} ); jQuery.fn.andSelf = jQuery.fn.addBack; @@ -5685,7 +5870,7 @@ return cur; } -jQuery.each({ +jQuery.each( { parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; @@ -5745,28 +5930,28 @@ return this.pushStack( ret ); }; -}); +} ); -jQuery.extend({ +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); + 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 )) ) { + while ( cur && cur.nodeType !== 9 && ( until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until ) ) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } - cur = cur[dir]; + cur = cur[ dir ]; } return matched; }, @@ -5782,7 +5967,7 @@ return r; } -}); +} ); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { @@ -5792,31 +5977,31 @@ qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { + 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 jQuery.grep( elements, function( elem ) { return ( elem === qualifier ) === keep; - }); + } ); } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { + var filtered = jQuery.grep( elements, function( elem ) { return elem.nodeType === 1; - }); + } ); if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); + return jQuery.filter( qualifier, filtered, !keep ); } else { qualifier = jQuery.filter( qualifier, filtered ); } } - return jQuery.grep(elements, function( elem ) { + return jQuery.grep( elements, function( elem ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); + } ); } function createSafeFragment( document ) { var list = nodeNames.split( "|" ), @@ -5835,7 +6020,7 @@ 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"), + rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, rtagName = /<([\w:]+)/, @@ -5843,6 +6028,7 @@ rhtml = /<|&#?\w+;/, rnoInnerhtml = /<(?:script|style|link)/i, manipulation_rcheckableType = /^(?:checkbox|radio)$/i, + // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rscriptType = /^$|\/(?:java|ecma)script/i, @@ -5862,40 +6048,41 @@ // 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
", "
" ] + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] }, safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + 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({ +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 ) ); + 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) ); - }); + return this.each( function( i ) { + jQuery( this ).wrapAll( html.call( this, i ) ); + } ); } - if ( this[0] ) { + if ( this[ 0 ] ) { + // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + var wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - if ( this[0].parentNode ) { - wrap.insertBefore( this[0] ); + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); } - wrap.map(function() { + wrap.map( function() { var elem = this; while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { @@ -5903,7 +6090,7 @@ } return elem; - }).append( this ); + } ).append( this ); } return this; @@ -5911,12 +6098,12 @@ wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); - }); + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); } - return this.each(function() { + return this.each( function() { var self = jQuery( this ), contents = self.contents(); @@ -5926,39 +6113,39 @@ } 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 ); - }); + return this.each( function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); + } ); }, unwrap: function() { - return this.parent().each(function() { + return this.parent().each( function() { if ( !jQuery.nodeName( this, "body" ) ) { jQuery( this ).replaceWith( this.childNodes ); } - }).end(); + } ).end(); }, append: function() { - return this.domManip(arguments, true, function( elem ) { + 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 ) { + return this.domManip( arguments, true, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { this.insertBefore( elem, this.firstChild ); } - }); + } ); }, before: function() { @@ -5966,7 +6153,7 @@ if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } - }); + } ); }, after: function() { @@ -5974,7 +6161,7 @@ if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } - }); + } ); }, // keepData is for internal use only--do not document @@ -5982,7 +6169,7 @@ var elem, i = 0; - for ( ; (elem = this[i]) != null; i++ ) { + for ( ; ( elem = this[ i ] ) != null; i++ ) { if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { if ( !keepData && elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem ) ); @@ -6004,7 +6191,8 @@ var elem, i = 0; - for ( ; (elem = this[i]) != null; i++ ) { + for ( ; ( elem = this[ i ] ) != null; i++ ) { + // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); @@ -6029,14 +6217,14 @@ 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 ) { return jQuery.access( this, function( value ) { - var elem = this[0] || {}, + var elem = this[ 0 ] || {}, i = 0, l = this.length; @@ -6050,14 +6238,15 @@ 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() ] ) { + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = value.replace( rxhtmlTag, "<$1>" ); try { - for (; i < l; i++ ) { + for ( ; i < l; i++ ) { + // Remove element nodes and prevent memory leaks - elem = this[i] || {}; + elem = this[ i ] || {}; if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; @@ -6067,7 +6256,7 @@ elem = 0; // If using innerHTML throws an exception, use the fallback method - } catch(e) {} + } catch ( e ) {} } if ( elem ) { @@ -6093,7 +6282,7 @@ jQuery( this ).remove(); parent.insertBefore( elem, next ); } - }); + } ); }, detach: function( selector ) { @@ -6111,18 +6300,18 @@ l = this.length, set = this, iNoClone = l - 1, - value = args[0], + 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 ) { + return this.each( function( index ) { var self = set.eq( index ); if ( isFunction ) { - args[0] = value.call( this, index, table ? self.html() : undefined ); + args[ 0 ] = value.call( this, index, table ? self.html() : undefined ); } self.domManip( args, table, callback ); - }); + } ); } if ( l ) { @@ -6153,9 +6342,9 @@ } callback.call( - table && jQuery.nodeName( this[i], "table" ) ? - findOrAppend( this[i], "tbody" ) : - this[i], + table && jQuery.nodeName( this[ i ], "table" ) ? + findOrAppend( this[ i ], "tbody" ) : + this[ i ], node, i ); @@ -6174,15 +6363,16 @@ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src ) { + // Hope ajax is available... - jQuery.ajax({ + 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, "" ) ); } @@ -6197,24 +6387,24 @@ return this; } -}); +} ); function findOrAppend( elem, tag ) { - return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( 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"); + 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]; + elem.type = match[ 1 ]; } else { - elem.removeAttribute("type"); + elem.removeAttribute( "type" ); } return elem; } @@ -6223,8 +6413,8 @@ function setGlobalEval( elems, refElements ) { var elem, i = 0; - for ( ; (elem = elems[i]) != null; i++ ) { - jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[ i ], "globalEval" ) ); } } @@ -6294,11 +6484,12 @@ // element in IE9, the outerHTML strategy above is not sufficient. // If the src has innerHTML and the destination does not, // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) { dest.innerHTML = src.innerHTML; } } else if ( nodeName === "input" && 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 @@ -6323,7 +6514,7 @@ } } -jQuery.each({ +jQuery.each( { appendTo: "append", prependTo: "prepend", insertBefore: "before", @@ -6338,8 +6529,8 @@ last = insert.length - 1; for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone(true); - jQuery( insert[i] )[ original ]( elems ); + 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() ); @@ -6347,7 +6538,7 @@ return this.pushStack( ret ); }; -}); +} ); function getAll( context, tag ) { var elems, elem, @@ -6357,7 +6548,7 @@ undefined; if ( !found ) { - for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + for ( found = [], elems = context.childNodes || context; ( elem = elems[ i ] ) != null; i++ ) { if ( !tag || jQuery.nodeName( elem, tag ) ) { found.push( elem ); } else { @@ -6378,12 +6569,12 @@ } } -jQuery.extend({ +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 + ">" ) ) { + 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 @@ -6392,18 +6583,19 @@ fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); } - if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + 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 ) { + 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] ); + if ( destElements[ i ] ) { + fixCloneNodeIssues( node, destElements[ i ] ); } } } @@ -6414,8 +6606,8 @@ srcElements = srcElements || getAll( elem ); destElements = destElements || getAll( clone ); - for ( i = 0; (node = srcElements[i]) != null; i++ ) { - cloneCopyEvent( node, destElements[i] ); + for ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) { + cloneCopyEvent( node, destElements[ i ] ); } } else { cloneCopyEvent( elem, clone ); @@ -6460,23 +6652,23 @@ // Convert html into DOM nodes } else { - tmp = tmp || safe.appendChild( context.createElement("div") ); + tmp = tmp || safe.appendChild( context.createElement( "div" ) ); // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; // Descend through wrappers to the right content - j = wrap[0]; + 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] ) ); + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) ); } // Remove IE's autoinserted from table fragments @@ -6487,13 +6679,13 @@ tmp.firstChild : // String was a bare or - wrap[1] === "" && !rtbody.test( elem ) ? + 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 ) { + if ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), "tbody" ) && !tbody.childNodes.length ) { elem.removeChild( tbody ); } } @@ -6527,7 +6719,7 @@ } i = 0; - while ( (elem = nodes[ i++ ]) ) { + while ( ( elem = nodes[ i++ ] ) ) { // #4087 - If origin and destination elements are the same, and this is // that element, do not do anything @@ -6548,7 +6740,7 @@ // Capture executables if ( scripts ) { j = 0; - while ( (elem = tmp[ j++ ]) ) { + while ( ( elem = tmp[ j++ ] ) ) { if ( rscriptType.test( elem.type || "" ) ) { scripts.push( elem ); } @@ -6569,7 +6761,7 @@ deleteExpando = jQuery.support.deleteExpando, special = jQuery.event.special; - for ( ; (elem = elems[i]) != null; i++ ) { + for ( ; ( elem = elems[ i ] ) != null; i++ ) { if ( acceptData || jQuery.acceptData( elem ) ) { @@ -6613,11 +6805,12 @@ } } } -}); +} ); 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]).+)/, @@ -6645,7 +6838,7 @@ } // check for vendor prefixed names - var capName = name.charAt(0).toUpperCase() + name.slice(1), + var capName = name.charAt( 0 ).toUpperCase() + name.slice( 1 ), origName = name, i = cssPrefixes.length; @@ -6660,6 +6853,7 @@ } function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem; @@ -6681,6 +6875,7 @@ 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" ) { @@ -6691,7 +6886,7 @@ // 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) ); + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay( elem.nodeName ) ); } } else { @@ -6720,7 +6915,7 @@ return elements; } -jQuery.fn.extend({ +jQuery.fn.extend( { css: function( name, value ) { return jQuery.access( this, function( elem, name, value ) { var len, styles, @@ -6752,23 +6947,25 @@ toggle: function( state ) { var bool = typeof state === "boolean"; - return this.each(function() { + return this.each( function() { if ( bool ? state : isHidden( this ) ) { jQuery( this ).show(); } else { jQuery( this ).hide(); } - }); + } ); } -}); +} ); + +jQuery.extend( { -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; @@ -6793,12 +6990,14 @@ // 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; @@ -6820,8 +7019,9 @@ 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 ) ); + if ( type === "string" && ( ret = rrelNum.exec( value ) ) ) { + value = ( ret[ 1 ] + 1 ) * ret[ 2 ] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 type = "number"; } @@ -6838,23 +7038,24 @@ // 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 ) { + 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 ) { + 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) {} + } 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 ) { + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { return ret; } @@ -6917,7 +7118,7 @@ return ret; } -}); +} ); // NOTE: we've included the "window" in window.getComputedStyle // because jsdom on node.js will break without it. @@ -7016,6 +7217,7 @@ 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; @@ -7023,20 +7225,24 @@ 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 ); @@ -7047,6 +7253,7 @@ 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 ); @@ -7072,6 +7279,7 @@ // 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 ) { @@ -7079,7 +7287,7 @@ } // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { + if ( rnumnonpx.test( val ) ) { return val; } @@ -7113,15 +7321,16 @@ // If the simple way fails, read from inside an iframe if ( display === "none" || !display ) { + // Use the already-created iframe if possible iframe = ( iframe || - jQuery("
+
+ + + +

See this blog entry for more information.

diff -Nru jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen-iframe.css jquery-3.2.1/test/integration/data/gh-1764-fullscreen-iframe.css --- jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen-iframe.css 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/integration/data/gh-1764-fullscreen-iframe.css 2017-03-20 19:00:06.000000000 +0000 @@ -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 -Nru jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen-iframe.html jquery-3.2.1/test/integration/data/gh-1764-fullscreen-iframe.html --- jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen-iframe.html 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/integration/data/gh-1764-fullscreen-iframe.html 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,21 @@ + + + + + + Test for gh-1764 - test iframe + + + + +

+
+ +
+ + + + + diff -Nru jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen.js jquery-3.2.1/test/integration/data/gh-1764-fullscreen.js --- jquery-1.11.3+dfsg/test/integration/data/gh-1764-fullscreen.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/integration/data/gh-1764-fullscreen.js 2017-03-20 19:00:06.000000000 +0000 @@ -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 -Nru jquery-1.11.3+dfsg/test/integration/gh-1764-fullscreen.html jquery-3.2.1/test/integration/gh-1764-fullscreen.html --- jquery-1.11.3+dfsg/test/integration/gh-1764-fullscreen.html 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/integration/gh-1764-fullscreen.html 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + + Test for gh-1764 + + + + + +
+
+ +
+ + + + + + diff -Nru jquery-1.11.3+dfsg/test/integration/gh-2343-ie-radio-click.html jquery-3.2.1/test/integration/gh-2343-ie-radio-click.html --- jquery-1.11.3+dfsg/test/integration/gh-2343-ie-radio-click.html 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/integration/gh-2343-ie-radio-click.html 2017-03-20 19:00:06.000000000 +0000 @@ -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 -Nru jquery-1.11.3+dfsg/test/jquery.js jquery-3.2.1/test/jquery.js --- jquery-1.11.3+dfsg/test/jquery.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/jquery.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,69 +1,56 @@ // Use the right jQuery source on the test page (and iframes) -(function() { +( function() { /* global loadTests: false */ - var src, - path = window.location.pathname.split( "test" )[ 0 ], + var path = window.location.pathname.split( "test" )[ 0 ], QUnit = window.QUnit || parent.QUnit, - require = window.require || parent.require; + require = window.require || parent.require, - // Config parameter to force basic code paths - QUnit.config.urlConfig.push({ - id: "basic", - label: "Bypass optimizations", - tooltip: "Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition; JSON.parse" - }); - if ( QUnit.urlParams.basic ) { - document.querySelectorAll = null; - document.documentElement.contains = null; - document.documentElement.compareDocumentPosition = null; - window.JSON = null; + // Default to unminified jQuery for directly-opened iframes + urlParams = QUnit ? + QUnit.urlParams : + { dev: true }, + src = urlParams.dev ? + "dist/jquery.js" : + "dist/jquery.min.js"; + + // Define configuration parameters controlling how jQuery is loaded + if ( QUnit ) { + QUnit.config.urlConfig.push( { + id: "amd", + label: "Load with AMD", + tooltip: "Load the AMD jQuery file (and its dependencies)" + } ); + QUnit.config.urlConfig.push( { + id: "dev", + label: "Load unminified", + tooltip: "Load the development (unminified) jQuery file" + } ); } - // 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: "src/sizzle/dist/sizzle" - } - }); + // Honor AMD loading on the main window (detected by seeing QUnit on it). + // This doesn't apply to iframes because they synchronously expect jQuery to be there. + if ( urlParams.amd && window.QUnit ) { + require.config( { + baseUrl: path + } ); 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"; + // Otherwise, load synchronously } else { - src = "dist/jquery.min.js"; - } + document.write( " - - - - - - - -

- 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 -Nru jquery-1.11.3+dfsg/test/unit/ajax.js jquery-3.2.1/test/unit/ajax.js --- jquery-1.11.3+dfsg/test/unit/ajax.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/ajax.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,161 +1,218 @@ -module( "ajax", { - setup: function() { - var jsonpCallback = this.jsonpCallback = jQuery.ajaxSettings.jsonpCallback; - jQuery.ajaxSettings.jsonpCallback = function() { - var callback = jsonpCallback.apply( this, arguments ); - Globals.register( callback ); - return callback; - }; - }, +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 ); -(function() { + 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 ) { + function addGlobalEvents( expected, assert ) { return function() { expected = expected || ""; jQuery( document ).on( "ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError ajaxSuccess", function( e ) { - ok( expected.indexOf(e.type) !== -1, e.type ); - }); + assert.ok( expected.indexOf( e.type ) !== -1, e.type ); + } ); }; } //----------- jQuery.ajax() - ajaxTest( "jQuery.ajax() - success callbacks", 8, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess"), - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - complete: function() { - ok( true, "complete"); + testIframe( + "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 - (url, options) syntax", 8, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess"), - create: function( options ) { - return jQuery.ajax( url("data/name.html"), options ); - }, - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - complete: function() { - ok( true, "complete" ); - } - }); + 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 (late binding)", 8, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess"), - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: true, - afterSend: function( request ) { - request.complete(function() { - ok( true, "complete" ); - }).success(function() { - ok( true, "success" ); - }).error(function() { - ok( false, "error" ); - }); - } - }); + 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 (oncomplete binding)", 8, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxSuccess"), - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: true, - complete: function( xhr ) { - xhr.complete(function() { - ok( true, "complete" ); - }).success(function() { - ok( true, "success" ); - }).error(function() { - ok( false, "error" ); - }); + ajaxTest( "jQuery.ajax() - execute js for crossOrigin when dataType option is provided", 3, + function( assert ) { + return { + create: function( options ) { + options.crossDomain = true; + options.dataType = "script"; + return jQuery.ajax( url( "data/script.php?header=ecma" ), options ); + }, + success: function() { + assert.ok( true, "success" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; } - }); + ); - ajaxTest( "jQuery.ajax() - error callbacks", 8, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError"), - url: url("data/name.php?wait=5"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - afterSend: function( request ) { - request.abort(); - }, - error: function() { - ok( true, "error" ); - }, - complete: function() { - ok( true, "complete" ); - } - }); + ajaxTest( "jQuery.ajax() - do not execute js (crossOrigin)", 2, function( assert ) { + return { + create: function( options ) { + options.crossDomain = true; + return jQuery.ajax( url( "data/script.php" ), options ); + }, + success: function() { + assert.ok( true, "success" ); + }, + fail: function() { + if ( jQuery.support.cors === false ) { + assert.ok( true, "fail" ); + } + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); - ajaxTest( "jQuery.ajax() - textStatus and errorThrown values", 4, [ - { - url: url("data/name.php?wait=5"), + 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 ) { - strictEqual( textStatus, "abort", "textStatus is 'abort' for abort" ); - strictEqual( errorThrown, "abort", "errorThrown is 'abort' for abort" ); + 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"), + url: url( "data/name.php?wait=5" ), error: function( _, textStatus, errorThrown ) { - strictEqual( textStatus, "mystatus", "textStatus is 'mystatus' for abort('mystatus')" ); - strictEqual( errorThrown, "mystatus", "errorThrown is 'mystatus' for abort('mystatus')" ); + 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"); + request.abort( "mystatus" ); } - } - ]); + } ]; + } ); - ajaxTest( "jQuery.ajax() - responseText on error", 1, { - url: url("data/errorWithText.php"), - error: function( xhr ) { - strictEqual( xhr.responseText, "plain text message", "Test jqXHR.responseText is filled for HTTP errors" ); - } - }); + 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" ); + } + }; + } ); - asyncTest( "jQuery.ajax() - retry with jQuery.ajax( this )", 2, function() { + QUnit.asyncTest( "jQuery.ajax() - retry with jQuery.ajax( this )", 2, function( assert ) { var previousUrl, firstTime = true; - jQuery.ajax({ - url: url("data/errorWithText.php"), + jQuery.ajax( { + url: url( "data/errorWithText.php" ), error: function() { if ( firstTime ) { firstTime = false; jQuery.ajax( this ); } else { - ok ( true, "Test retrying with jQuery.ajax(this) works" ); - jQuery.ajax({ - url: url("data/errorWithText.php"), + assert.ok( true, "Test retrying with jQuery.ajax(this) works" ); + jQuery.ajax( { + url: url( "data/errorWithText.php" ), data: { "x": 1 }, @@ -163,142 +220,224 @@ if ( !previousUrl ) { previousUrl = this.url; } else { - strictEqual( this.url, previousUrl, "url parameters are not re-appended" ); - start(); + 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, { - 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(""); - - strictEqual( data, tmp, "Headers were sent" ); - strictEqual( xhr.getResponseHeader("Sample-Header"), "Hello World", "Sample header received" ); - ok( data.indexOf( "undefined" ) < 0 , "Undefined header value was not sent" ); - - emptyHeader = xhr.getResponseHeader("Empty-Header"); - if ( emptyHeader === null ) { - ok( true, "Firefox doesn't support empty headers" ); - } else { - strictEqual( emptyHeader, "", "Empty header received" ); + 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: IE 9 - 11, Edge 12 - 13+ + // Not all browsers allow empty-string headers + //"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" ); } - strictEqual( xhr.getResponseHeader("Sample-Header2"), "Hello World 2", "Second sample header received" ); - } - }); - - ajaxTest( "jQuery.ajax() - Accept header", 1, { - url: url("data/headers.php?keys=accept"), - headers: { - Accept: "very wrong accept value" - }, - beforeSend: function( xhr ) { - xhr.setRequestHeader("Accept", "*/*"); - }, - success: function( data ) { - strictEqual( data, "accept: */*\n", "Test Accept header is set to last value provided" ); - } - }); + }; + } ); - ajaxTest( "jQuery.ajax() - contentType", 2, [ - { - url: url("data/headers.php?keys=content-type"), - contentType: "test", - success: function( data ) { - 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, + 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 ) { - // Some server/interpreter combinations always supply a Content-Type to scripts - data = data || "content-type: \n"; - strictEqual( data, "content-type: \n", "Test content-type is not set when options.contentType===false" ); + assert.strictEqual( data, "accept: */*\n", "Test Accept header is set to last value provided" ); } - } - ]); + }; + } ); - ajaxTest( "jQuery.ajax() - protocol-less urls", 1, { - url: "//somedomain.com", - beforeSend: function( xhr, settings ) { - equal( settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added." ); - return false; - }, - error: true - }); + 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 ) { - ajaxTest( "jQuery.ajax() - hash", 3, [ - { - url: "data/name.html#foo", + // 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 ) { - equal( settings.url, "data/name.html", "Make sure that the URL is trimmed." ); + assert.equal( settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added." ); return false; }, error: true - }, - { - url: "data/name.html?abc#foo", - beforeSend: function( xhr, settings ) { - equal( settings.url, "data/name.html?abc", "Make sure that the URL is trimmed." ); - return false; + }; + } ); + + ajaxTest( "jQuery.ajax() - hash", 4, function( assert ) { + return [ + { + url: "data/name.html#foo", + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html#foo", "Make sure that the URL has its hash." ); + return false; + }, + error: true }, - error: true - }, - { - url: "data/name.html?abc#foo", - data: { - "test": 123 + { + url: "data/name.html?abc#foo", + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html?abc#foo", "Make sure that the URL has its hash." ); + return false; + }, + error: true }, - beforeSend: function( xhr, settings ) { - equal( settings.url, "data/name.html?abc&test=123", "Make sure that the URL is trimmed." ); - return false; + { + url: "data/name.html?abc#foo", + data: { + "test": 123 + }, + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "data/name.html?abc&test=123#foo", "Make sure that the URL has its hash." ); + return false; + }, + error: true }, - error: true - } - ]); + { + url: "data/name.html?abc#brownies", + data: { + "devo": "hat" + }, + cache: false, + beforeSend: function( xhr, settings ) { + // Remove the random number, but ensure the cache-buster param is there + var url = settings.url.replace( /\d+/, "" ); + assert.equal( url, "data/name.html?abc&devo=hat&_=#brownies", "Make sure that the URL has its hash." ); + return false; + }, + error: true + } + ]; + } ); + + ajaxTest( "jQuery.ajax() - traditional param encoding", 4, function( assert ) { + return [ + { + url: "/", + traditional: true, + data: { + "devo": "hat", + "answer": 42, + "quux": "a space" + }, + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "/?devo=hat&answer=42&quux=a%20space", "Simple case" ); + return false; + }, + error: true + }, + { + url: "/", + traditional: true, + data: { + "a": [ 1, 2, 3 ], + "b[]": [ "b1", "b2" ] + }, + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "/?a=1&a=2&a=3&b%5B%5D=b1&b%5B%5D=b2", "Arrays" ); + return false; + }, + error: true + }, + { + url: "/", + traditional: true, + data: { + "a": [ [ 1, 2 ], [ 3, 4 ], 5 ] + }, + beforeSend: function( xhr, settings ) { + assert.equal( settings.url, "/?a=1%2C2&a=3%2C4&a=5", "Nested arrays" ); + return false; + }, + error: true + }, + { + url: "/", + traditional: true, + data: { + "a": [ "w", [ [ "x", "y" ], "z" ] ] + }, + cache: false, + beforeSend: function( xhr, settings ) { + var url = settings.url.replace( /\d{3,}/, "" ); + assert.equal( url, "/?a=w&a=x%2Cy%2Cz&_=", "Cache-buster" ); + return false; + }, + error: true + } + ]; + } ); - ajaxTest( "jQuery.ajax() - cross-domain detection", 7, function() { + ajaxTest( "jQuery.ajax() - cross-domain detection", 8, function( assert ) { function request( url, title, crossDomainOrOptions ) { return jQuery.extend( { dataType: "jsonp", url: url, beforeSend: function( _, s ) { - ok( crossDomainOrOptions === false ? !s.crossDomain : s.crossDomain, title ); + assert.ok( crossDomainOrOptions === false ? !s.crossDomain : s.crossDomain, title ); return false; }, error: true @@ -312,7 +451,7 @@ return [ request( - loc.protocol + "//" + loc.host + ":" + samePort, + loc.protocol + "//" + loc.hostname + ":" + samePort, "Test matching ports are not detected as cross-domain", false ), @@ -342,80 +481,104 @@ { crossDomain: true } + ), + request( + " http://otherdomain.com", + "Cross-domain url with leading space is detected as cross-domain" ) ]; - }); + } ); - ajaxTest( "jQuery.ajax() - abort", 9, { - setup: addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxError ajaxComplete"), - url: url("data/name.php?wait=5"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - afterSend: function( xhr ) { - strictEqual( xhr.readyState, 1, "XHR readyState indicates successful dispatch" ); - xhr.abort(); - strictEqual( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); - }, - error: true, - complete: function() { - ok( true, "complete" ); - } - }); + 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() - events with context", 12, function() { + 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" ); + } + }; + } ); - var context = document.createElement("div"); + ajaxTest( "jQuery.ajax() - events with context", 12, function( assert ) { + var context = document.createElement( "div" ); function event( e ) { - equal( this, context, e.type ); + assert.equal( this, context, e.type ); } function callback( msg ) { return function() { - equal( this, context, "context is preserved on callback " + msg ); + assert.equal( this, context, "context is preserved on callback " + msg ); }; } return { setup: function() { - jQuery( context ).appendTo("#foo") + jQuery( context ).appendTo( "#foo" ) .ajaxSend( event ) .ajaxComplete( event ) .ajaxError( event ) .ajaxSuccess( event ); }, - requests: [{ - url: url("data/name.html"), + requests: [ { + url: url( "data/name.html" ), context: context, - beforeSend: callback("beforeSend"), - success: callback("success"), - complete: callback("complete") + beforeSend: callback( "beforeSend" ), + success: callback( "success" ), + complete: callback( "complete" ) }, { - url: url("data/404.html"), + url: url( "data/404.html" ), context: context, - beforeSend: callback("beforeSend"), - error: callback("error"), - complete: callback("complete") - }] + beforeSend: callback( "beforeSend" ), + error: callback( "error" ), + complete: callback( "complete" ) + } ] }; - }); + } ); - ajaxTest( "jQuery.ajax() - events without context", 3, function() { + ajaxTest( "jQuery.ajax() - events without context", 3, function( assert ) { function nocallback( msg ) { return function() { - equal( typeof this.url, "string", "context is settings on callback " + msg ); + 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") + url: url( "data/404.html" ), + beforeSend: nocallback( "beforeSend" ), + error: nocallback( "error" ), + complete: nocallback( "complete" ) }; - }); + } ); - ajaxTest( "#15118 - jQuery.ajax() - function without jQuery.event", 1, function() { + ajaxTest( "#15118 - jQuery.ajax() - function without jQuery.event", 1, function( assert ) { var holder; return { url: url( "data/json.php" ), @@ -424,179 +587,218 @@ delete jQuery.event; }, complete: function() { - ok( true, "Call can be made without jQuery.event" ); + assert.ok( true, "Call can be made without jQuery.event" ); jQuery.event = holder; }, success: true }; - }); + } ); - ajaxTest( "jQuery.ajax() - context modification", 1, { - url: url("data/name.html"), - context: {}, - beforeSend: function() { - this.test = "foo"; - }, - afterSend: function() { - strictEqual( this.context.test, "foo", "Make sure the original object is maintained." ); - }, - 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() { + ajaxTest( "jQuery.ajax() - context modification through ajaxSetup", 3, function( assert ) { var obj = {}; return { setup: function() { - jQuery.ajaxSetup({ + jQuery.ajaxSetup( { context: obj - }); - strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." ); + } ); + assert.strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." ); }, - requests: [{ - url: url("data/name.html"), + requests: [ { + url: url( "data/name.html" ), success: function() { - strictEqual( this, obj, "Make sure the original object is maintained." ); + assert.strictEqual( this, obj, "Make sure the original object is maintained." ); } }, { - url: url("data/name.html"), + url: url( "data/name.html" ), context: {}, success: function() { - ok( this !== obj, "Make sure overriding context is possible." ); + assert.ok( this !== obj, "Make sure overriding context is possible." ); } - }] + } ] }; - }); + } ); - ajaxTest( "jQuery.ajax() - disabled globals", 3, { - setup: addGlobalEvents(""), - global: false, - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - complete: function() { - ok( true, "complete" ); - } - }); - - ajaxTest( "jQuery.ajax() - xml: non-namespace elements inside namespaced elements", 3, { - url: url("data/with_fries.xml"), - dataType: "xml", - success: function( resp ) { - equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); - equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); - equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); - } - }); + 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 (over JSONP)", 3, { - url: url("data/with_fries_over_jsonp.php"), - dataType: "jsonp xml", - success: function( resp ) { - equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); - equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); - equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); - } - }); + 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() - HEAD requests", 2, [ - { - url: url("data/name.html"), - type: "HEAD", - success: function( data, status, xhr ) { - ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response" ); + 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" ); } - }, - { - url: url("data/name.html"), - data: { - "whip_it": "good" + }; + } ); + + 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" ); + } }, - type: "HEAD", - success: function( data, status, xhr ) { - ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response with data" ); + { + 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, { - url: url("data/name.html"), - beforeSend: function() { - this.check = true; - }, - success: function() { - ok( this.check, "check beforeSend was executed" ); - } - }); + 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, { - create: function() { - return jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function( xhr ) { - ok( true, "beforeSend got called, canceling" ); - xhr.abort(); - }, - success: function() { - ok( false, "request didn't get canceled" ); - }, - complete: function() { - ok( false, "request didn't get canceled" ); - }, - error: function() { - ok( false, "request didn't get canceled" ); - } - }); - }, - fail: function( _, reason ) { - strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); - } - }); + 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, { - setup: function() { - Globals.register("testFoo"); - Globals.register("testBar"); - }, - dataType: "html", - url: url("data/test.html"), - success: function( data ) { - ok( data.match( /^html text/ ), "Check content for datatype html" ); - jQuery("#ap").html( data ); - strictEqual( window["testFoo"], "foo", "Check if script was evaluated for datatype html" ); - strictEqual( window["testBar"], "bar", "Check if script src was evaluated for datatype html" ); - } - }); + 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, { - url: url("data/json_obj.js"), - dataType: "text", - async: false, - success: true, - afterSend: function( xhr ) { - ok( /^\{ "data"/.test( xhr.responseText ), "check returned text" ); - } - }); + 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, { - url: url("data/json_obj.js"), - async: false, - dataType: "text", - success: true, - afterSend: function( xhr ) { - var result; - xhr.done(function( data ) { - ok( true, "success callback executed" ); - result = data; - }); - ok( /^\{ "data"/.test( result ), "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" ); + } + }; + } ); - asyncTest( "jQuery.ajax(), jQuery.get[Script|JSON](), jQuery.post(), pass-through request object", 8, function() { + 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, @@ -607,28 +809,28 @@ jQuery( document ).on( "ajaxError.passthru", function( e, xml ) { errorCount++; errorEx += ": " + xml.status; - }); + } ); jQuery( document ).one( "ajaxStop", function() { - equal( successCount, 5, "Check all ajax calls successful" ); - equal( errorCount, 0, "Check no ajax errors (status" + errorEx + ")" ); - jQuery( document ).off("ajaxError.passthru"); - start(); - }); - Globals.register("testBar"); - - ok( jQuery.get( url(target), success ), "get" ); - ok( jQuery.post( url(target), success ), "post" ); - ok( jQuery.getScript( url("data/testbar.php"), success ), "script" ); - ok( jQuery.getJSON( url("data/json_obj.js"), success ), "json" ); - ok( jQuery.ajax({ + 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() { + } ), "generic" ); + } ); - var re = /_=(.*?)(&|$)/g; + ajaxTest( "jQuery.ajax() - cache", 28, function( assert ) { + var re = /_=(.*?)(&|$)/g, + rootUrl = "data/text.php"; function request( url, title ) { return { @@ -636,10 +838,15 @@ cache: false, beforeSend: function() { var parameter, tmp; - while(( tmp = re.exec( this.url ) )) { - strictEqual( parameter, undefined, title + ": only one 'no-cache' parameter" ); + + // URL sanity check + assert.equal( this.url.indexOf( rootUrl ), 0, "root url not mangled: " + this.url ); + assert.equal( /\&.*\?/.test( this.url ), false, "parameter delimiters in order" ); + + while ( ( tmp = re.exec( this.url ) ) ) { + assert.strictEqual( parameter, undefined, title + ": only one 'no-cache' parameter" ); parameter = tmp[ 1 ]; - notStrictEqual( parameter, "tobereplaced555", title + ": parameter (if it was there) was replaced" ); + assert.notStrictEqual( parameter, "tobereplaced555", title + ": parameter (if it was there) was replaced" ); } return false; }, @@ -649,340 +856,420 @@ return [ request( - "data/text.php", - "no parameter" + rootUrl, + "no query" ), request( - "data/text.php?pizza=true", + rootUrl + "?", + "empty query" + ), + request( + rootUrl + "?pizza=true", "1 parameter" ), request( - "data/text.php?_=tobereplaced555", + rootUrl + "?_=tobereplaced555", "_= parameter" ), request( - "data/text.php?pizza=true&_=tobereplaced555", + rootUrl + "?pizza=true&_=tobereplaced555", "1 parameter and _=" ), request( - "data/text.php?_=tobereplaced555&tv=false", + rootUrl + "?_=tobereplaced555&tv=false", "_= and 1 parameter" ), request( - "data/text.php?name=David&_=tobereplaced555&washere=true", + rootUrl + "?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, [ - { - url: "data/jsonp.php?callback=?", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data.data, "JSON results returned (GET, url callback)" ); - } - }, - { - url: "data/jsonp.php?callback=??", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data.data, "JSON results returned (GET, url context-free callback)" ); - } - }, - { - url: "data/jsonp.php/??", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data.data, "JSON results returned (GET, REST-like)" ); - } - }, - { - url: "data/jsonp.php/???json=1", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - strictEqual( jQuery.type( data ), "array", "JSON results returned (GET, REST-like with param)" ); + 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, 9, { - setup: function() { - Globals.register("functionToCleanUp"); - Globals.register("XXX"); - Globals.register("jsonpResults"); - window["jsonpResults"] = function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback function)" ); - }; - }, - requests: [{ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - jsonp: "callback", - success: function( data ) { - ok( data["data"], "JSON results returned (GET, data obj callback)" ); - } - }, { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - jsonpCallback: "jsonpResults", - success: function( data ) { - ok( data.data, "JSON results returned (GET, custom callback name)" ); - } - }, { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - jsonpCallback: "functionToCleanUp", - success: function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback name to be cleaned up)" ); - 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() { - ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" ); - strictEqual( window["functionToCleanUp"], true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" ); - }); + 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)" ); + } } - }, { - url: "data/jsonp.php?callback=XXX", - dataType: "jsonp", - jsonp: false, - jsonpCallback: "XXX", - crossDomain: crossDomain, - beforeSend: function() { - ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" ); + ]; + } ); + + 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)" ); + } }, - success: function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback name with no url manipulation)" ); + { + 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 - Callback in data" + label, 2, [ - { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - data: "callback=?", - success: function( data ) { - ok( data.data, "JSON results returned (GET, data 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: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - data: "callback=??", - success: function( data ) { - ok( data.data, "JSON results returned (GET, data context-free callback)" ); - } + 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() - JSONP - POST" + label, 3, [ - { - type: "POST", - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, no callback)" ); - } + ajaxTest( "jQuery.ajax() - script, Remote with POST", 3, function( assert ) { + return { + setup: function() { + Globals.register( "testBar" ); }, - { - type: "POST", - url: "data/jsonp.php", - data: "callback=?", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, data callback)" ); - } + 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" ); }, - { - type: "POST", - url: "data/jsonp.php", - jsonp: "callback", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, data obj callback)" ); - } + 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() - JSONP" + label, 3, [ + ajaxTest( "jQuery.ajax() - script by content-type", 2, function() { + return [ { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - success: function( data ) { - ok( data.data, "JSON results returned (GET, no callback)" ); - } + url: "data/script.php", + data: { + "header": "script" + }, + success: true }, { - create: function( options ) { - var request = jQuery.ajax( options ), - promise = request.then(function( data ) { - ok( data.data, "first request: JSON results returned (GET, no callback)" ); - request = jQuery.ajax( this ).done(function( data ) { - 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/script.php", + data: { + "header": "ecma" }, - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, success: true } - ]); - - }); - - ajaxTest( "jQuery.ajax() - script, Remote", 2, { - setup: function() { - Globals.register("testBar"); - }, - url: window.location.href.replace( /[^\/]*$/, "" ) + "data/testbar.php", - dataType: "script", - success: function() { - strictEqual( window["testBar"], "bar", "Script results returned (GET, no callback)" ); - } - }); - - ajaxTest( "jQuery.ajax() - script, Remote with POST", 3, { - setup: function() { - Globals.register("testBar"); - }, - url: window.location.href.replace( /[^\/]*$/, "" ) + "data/testbar.php", - type: "POST", - dataType: "script", - success: function( data, status ) { - strictEqual( window["testBar"], "bar", "Script results returned (POST, no callback)" ); - strictEqual( status, "success", "Script results returned (POST, no callback)" ); - } - }); - - ajaxTest( "jQuery.ajax() - script, Remote with scheme-less URL", 2, { - setup: function() { - Globals.register("testBar"); - }, - url: window.location.href.replace( /[^\/]*$/, "" ).replace( /^.*?\/\//, "//" ) + "data/testbar.php", - dataType: "script", - success: function() { - strictEqual( window["testBar"], "bar", "Script results returned (GET, no callback)" ); - } - }); - - ajaxTest( "jQuery.ajax() - malformed JSON", 2, { - url: "data/badjson.js", - dataType: "json", - error: function( xhr, msg, detailedMsg ) { - strictEqual( msg, "parsererror", "A parse error occurred." ); - ok( /(invalid|error|exception)/i.test( detailedMsg ), "Detailed parsererror message provided" ); - } - }); + ]; + } ); - ajaxTest( "jQuery.ajax() - script by content-type", 2, [ - { - url: "data/script.php", + ajaxTest( "jQuery.ajax() - JSON by content-type", 5, function( assert ) { + return { + url: "data/json.php", data: { - "header": "script" + "header": "json", + "json": "array" }, - success: true - }, - { - url: "data/script.php", + 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": "ecma" + "header": "json", + "json": "array" }, - success: true - } - ]); + contents: { + "json": false + }, + success: function( text ) { + assert.strictEqual( typeof text, "string", "json wasn't auto-determined" ); + var json = JSON.parse( 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() - JSON by content-type", 5, { - url: "data/json.php", - data: { - "header": "json", - "json": "array" - }, - success: function( json ) { - ok( json.length >= 2, "Check length" ); - strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - 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() - JSON by content-type disabled with options", 6, { - url: url("data/json.php"), - data: { - "header": "json", - "json": "array" - }, - contents: { - "json": false - }, - success: function( text ) { - strictEqual( typeof text, "string", "json wasn't auto-determined" ); - var json = jQuery.parseJSON( text ); - ok( json.length >= 2, "Check length"); - strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - strictEqual( json[ 1 ]["age"], 25, "Check JSON: second, age" ); - } - }); + 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() - simple get", 1, { - type: "GET", - url: url("data/name.php?name=foo"), - success: function( msg ) { - strictEqual( msg, "bar", "Check for GET" ); - } - }); + 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, "" ); + } + }; + } ); - ajaxTest( "jQuery.ajax() - simple post", 1, { - type: "POST", - url: url("data/name.php"), - data: "name=peter", - success: function( msg ) { - strictEqual( msg, "pan", "Check for POST" ); - } - }); + ajaxTest( "jQuery.ajax() - data - x-www-form-urlencoded (gh-2658)", 1, function( assert ) { + return { + url: "bogus.html", + data: { devo: "A Beautiful World" }, + type: "post", + beforeSend: function( _, s ) { + assert.strictEqual( s.data, "devo=A+Beautiful+World", "data is '+'-encoded" ); + return false; + }, + error: true + }; + } ); - ajaxTest( "jQuery.ajax() - data option - empty bodies for non-GET requests", 1, { - url: "data/echoData.php", - data: undefined, - type: "post", - success: function( result ) { - strictEqual( result, "" ); - } - }); + ajaxTest( "jQuery.ajax() - data - text/plain (gh-2658)", 1, function( assert ) { + return { + url: "bogus.html", + data: { devo: "A Beautiful World" }, + type: "post", + contentType: "text/plain", + beforeSend: function( _, s ) { + assert.strictEqual( s.data, "devo=A%20Beautiful%20World", "data is %20-encoded" ); + return false; + }, + error: true + }; + } ); + + ajaxTest( "jQuery.ajax() - data - no processing ", 1, function( assert ) { + return { + url: "bogus.html", + data: { devo: "A Beautiful World" }, + type: "post", + contentType: "x-special-sauce", + processData: false, + beforeSend: function( _, s ) { + assert.deepEqual( s.data, { devo: "A Beautiful World" }, "data is not processed" ); + return false; + }, + error: true + }; + } ); var ifModifiedNow = new Date(); @@ -993,141 +1280,89 @@ " (no cache)": false }, function( label, cache ) { - var isOpera = !!window.opera; - - asyncTest( "jQuery.ajax() - If-Modified-Since support" + label, 3, function() { - var url = "data/if_modified_since.php?ts=" + ifModifiedNow++; - - jQuery.ajax({ - url: url, - ifModified: true, - cache: cache, - success: function( data, status ) { - strictEqual( status, "success" ); - - jQuery.ajax({ - url: url, - ifModified: true, - cache: cache, - success: function( data, status ) { - if ( data === "FAIL" ) { - ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')." ); - ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')." ); - } else { - strictEqual( status, "notmodified" ); - ok( data == null, "response body should be empty" ); - } - start(); - }, - error: function() { - // Do this because opera simply refuses to implement 304 handling :( - // A feature-driven way of detecting this would be appreciated - // See: http://gist.github.com/599419 - ok( isOpera, "error" ); - ok( isOpera, "error" ); - start(); - } - }); - }, - error: function() { - strictEqual( false, "error" ); - // Do this because opera simply refuses to implement 304 handling :( - // A feature-driven way of detecting this would be appreciated - // See: http://gist.github.com/599419 - ok( isOpera, "error" ); - start(); - } - }); - }); - - asyncTest( "jQuery.ajax() - Etag support" + label, 3, function() { - var url = "data/etag.php?ts=" + ifModifiedNow++; - - jQuery.ajax({ - url: url, - ifModified: true, - cache: cache, - success: function( data, status ) { - strictEqual( status, "success" ); - - jQuery.ajax({ + 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( data, status ) { - if ( data === "FAIL" ) { - ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-None-Match')." ); - ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-None-Match')." ); - } else { - strictEqual( status, "notmodified" ); - ok( data == null, "response body should be empty" ); - } - start(); - }, - error: function() { - // Do this because opera simply refuses to implement 304 handling :( - // A feature-driven way of detecting this would be appreciated - // See: http://gist.github.com/599419 - ok( isOpera, "error" ); - ok( isOpera, "error" ); - start(); + 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(); + } + } ); } - }); - }, - error: function() { - // Do this because opera simply refuses to implement 304 handling :( - // A feature-driven way of detecting this would be appreciated - // See: http://gist.github.com/599419 - ok( isOpera, "error" ); - start(); - } - }); - }); + } ); + } ); + } + ); } /* jQuery.each arguments end */ ); - ajaxTest( "jQuery.ajax() - failing cross-domain (non-existing)", 1, { - // see RFC 2606 - url: "http://example.invalid", - error: function( xhr, _, e ) { - ok( true, "file not found: " + xhr.status + " => " + e ); - } - }); + ajaxTest( "jQuery.ajax() - failing cross-domain (non-existing)", 1, function( assert ) { + return { - ajaxTest( "jQuery.ajax() - failing cross-domain", 1, { - url: "http://" + externalHost, - error: function( xhr, _, e ) { - ok( true, "access denied: " + xhr.status + " => " + e ); - } - }); + // see RFC 2606 + url: "http://example.invalid", + error: function( xhr, _, e ) { + assert.ok( true, "file not found: " + xhr.status + " => " + e ); + } + }; + } ); - ajaxTest( "jQuery.ajax() - atom+xml", 1, { - url: url("data/atom+xml.php"), - success: function() { - ok( true, "success" ); - } - }); + 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" ); + } + }; + } ); - asyncTest( "jQuery.ajax() - statusText", 3, function() { - jQuery.ajax( url("data/statusText.php?status=200&text=Hello") ).done(function( _, statusText, jqXHR ) { - strictEqual( statusText, "success", "callback status text ok for success" ); - 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 ) { - strictEqual( statusText, "error", "callback status text ok for error" ); - // ok( jqXHR.statusText === "World" || jQuery.browser.safari && jqXHR.statusText === "Not Found", "jqXHR status text ok for error (" + jqXHR.statusText + ")" ); - start(); - }); - }); - }); + 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(); + } ); + } ); + } ); - asyncTest( "jQuery.ajax() - statusCode", 20, function() { + QUnit.asyncTest( "jQuery.ajax() - statusCode", 20, function( assert ) { var count = 12; function countComplete() { - if ( ! --count ) { - start(); + if ( !--count ) { + QUnit.start(); } } @@ -1135,10 +1370,10 @@ name = "Test " + name + " " + ( isSuccess ? "success" : "error" ); return { 200: function() { - ok( isSuccess, name ); + assert.ok( isSuccess, name ); }, 404: function() { - ok( !isSuccess, name ); + assert.ok( !isSuccess, name ); } }; } @@ -1151,47 +1386,47 @@ }, function( uri, isSuccess ) { - jQuery.ajax( url(uri), { + jQuery.ajax( url( uri ), { statusCode: createStatusCodes( "in options", isSuccess ), complete: countComplete - }); + } ); - jQuery.ajax( url(uri), { + jQuery.ajax( url( uri ), { complete: countComplete - }).statusCode( createStatusCodes("immediately with method", isSuccess) ); + } ).statusCode( createStatusCodes( "immediately with method", isSuccess ) ); - jQuery.ajax( url(uri), { + jQuery.ajax( url( uri ), { complete: function( jqXHR ) { - jqXHR.statusCode( createStatusCodes("on complete", isSuccess) ); + jqXHR.statusCode( createStatusCodes( "on complete", isSuccess ) ); countComplete(); } - }); + } ); - jQuery.ajax( url(uri), { + jQuery.ajax( url( uri ), { complete: function( jqXHR ) { - setTimeout(function() { - jqXHR.statusCode( createStatusCodes("very late binding", isSuccess) ); + setTimeout( function() { + jqXHR.statusCode( createStatusCodes( "very late binding", isSuccess ) ); countComplete(); }, 100 ); } - }); + } ); - jQuery.ajax( url(uri), { + 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) ); + 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) ); + } ).statusCode( createStatusCodes( "all (immediately with method)", isSuccess ) ); var testString = ""; - jQuery.ajax( url(uri), { + jQuery.ajax( url( uri ), { success: function( a, b, jqXHR ) { - ok( isSuccess, "success" ); + assert.ok( isSuccess, "success" ); var statusCode = {}; statusCode[ jqXHR.status ] = function() { testString += "B"; @@ -1200,7 +1435,7 @@ testString += "A"; }, error: function( jqXHR ) { - ok( !isSuccess, "error" ); + assert.ok( !isSuccess, "error" ); var statusCode = {}; statusCode[ jqXHR.status ] = function() { testString += "B"; @@ -1209,206 +1444,239 @@ testString += "A"; }, complete: function() { - strictEqual( + 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, [ - { - url: url("data/json.php"), - converters: { - "json myJson": function( data ) { - ok( true, "converter called" ); - return data; + 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" ); } }, - dataType: "myJson", - success: function() { - ok( true, "Transitive conversion worked" ); - strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text" ); - 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 (*)" ); + } } - }, - { - url: url("data/json.php"), - converters: { - "json myJson": function( data ) { - ok( true, "converter called (*)" ); - return data; + ]; + } ); + + 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" ); } }, - contents: false, /* headers are wrong so we ignore them */ - dataType: "* myJson", - success: function() { - ok( true, "Transitive conversion worked (*)" ); - strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text (*)" ); - strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType (*)" ); + { + url: url( "data/json.php" ), + mimeType: "application/json", + success: function( json ) { + assert.ok( json.data, "Mimetype overridden using mimeType option" ); + } } - } - ]); + ]; + } ); - ajaxTest( "jQuery.ajax() - overrideMimeType", 2, [ - { - url: url("data/json.php"), - beforeSend: function( xhr ) { - xhr.overrideMimeType( "application/json" ); + 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" ); }, - success: function( json ) { - ok( json.data, "Mimetype overridden using beforeSend" ); - } - }, - { - url: url("data/json.php"), - mimeType: "application/json", - success: function( json ) { - ok( json.data, "Mimetype overridden using mimeType option" ); - } - } - ]); + dataType: "json" + }; + } ); - ajaxTest( "jQuery.ajax() - empty json gets to error callback instead of success callback.", 1, { - url: url("data/echoData.php"), - error: function( _, __, error ) { - 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( "#2688 - jQuery.ajax() - beforeSend, cancel request", 2, { - create: function() { - return jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend got called, canceling" ); - return false; - }, - success: function() { - ok( false, "request didn't get canceled" ); - }, - complete: function() { - ok( false, "request didn't get canceled" ); - }, - error: function() { - ok( false, "request didn't get canceled" ); + ajaxTest( "#2806 - jQuery.ajax() - data option - evaluate function values", 1, function( assert ) { + return { + url: "data/echoQuery.php", + data: { + key: function() { + return "value"; } - }); - }, - fail: function( _, reason ) { - strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); - } - }); - - ajaxTest( "#2806 - jQuery.ajax() - data option - evaluate function values", 1, { - url: "data/echoQuery.php", - data: { - key: function() { - return "value"; + }, + success: function( result ) { + assert.strictEqual( result, "key=value" ); } - }, - success: function( result ) { - strictEqual( result, "key=value" ); - } - }); + }; + } ); + + QUnit.test( "#7531 - jQuery.ajax() - Location object as url", function( assert ) { + assert.expect( 1 ); - test( "#7531 - jQuery.ajax() - Location object as url", 1, function () { var xhr, success = false; try { - xhr = jQuery.ajax({ + xhr = jQuery.ajax( { url: window.location - }); + } ); success = true; xhr.abort(); - } catch (e) { + } catch ( e ) { } - ok( success, "document.location did not generate exception" ); - }); + 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, { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function() { - strictEqual( this.cache, false, "cache must be false on JSON request" ); - return false; - }, - error: true - }); - }); + 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, [ - { - create: function() { - return jQuery.ajax(); - }, - done: function() { - ok( true, "With no arguments" ); - } - }, - { - create: function() { - return jQuery.ajax("data/name.html"); + 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" ); + } }, - done: function() { - ok( true, "With only string URL argument" ); - } - }, - { - create: function() { - return jQuery.ajax( "data/name.html", {}); + { + create: function() { + return jQuery.ajax( "data/name.html" ); + }, + done: function() { + assert.ok( true, "With only string URL argument" ); + } }, - done: function() { - ok( true, "With string URL param and map" ); - } - }, - { - create: function( options ) { - return jQuery.ajax( options ); + { + create: function() { + return jQuery.ajax( "data/name.html", {} ); + }, + done: function() { + assert.ok( true, "With string URL param and map" ); + } }, - url: "data/name.html", - success: function() { - ok( true, "With only 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, 2, { - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - s.callback = s.jsonpCallback; - }, - success: function() { - var previous = this; - strictEqual( previous.jsonpCallback, undefined, "jsonpCallback option is set back to default in callbacks" ); - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function() { - strictEqual( this.jsonpCallback, previous.callback, "JSONP callback name is re-used" ); - return false; - } - }); - } - }); - }); + 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 ); - test( "#9887 - jQuery.ajax() - Context with circular references (#9887)", 2, function () { var success = false, context = {}; context.field = context; @@ -1416,547 +1684,747 @@ jQuery.ajax( "non-existing", { context: context, beforeSend: function() { - ok( this === context, "context was not deep extended" ); + assert.ok( this === context, "context was not deep extended" ); return false; } - }); + } ); success = true; } catch ( e ) { console.log( e ); } - ok( success, "context with circular reference did not generate an exception" ); - }); + assert.ok( success, "context with circular reference did not generate an exception" ); + } ); jQuery.each( [ "as argument", "in settings object" ], function( inSetting, title ) { - function request( url, test ) { + function request( assert, url, test ) { return { create: function() { return jQuery.ajax( inSetting ? { url: url } : url ); }, done: function() { - ok( true, ( test || url ) + " " + title ); + assert.ok( true, ( test || url ) + " " + title ); } }; } - ajaxTest( "#10093 - jQuery.ajax() - falsy url " + title, 4, [ - request( "", "empty string" ), - request( false ), - request( null ), - request( undefined ) - ]); - - }); - - ajaxTest( "#11151 - jQuery.ajax() - parse error body", 2, { - url: url("data/errorWithJSON.php"), - dataFilter: function( string ) { - ok( false, "dataFilter called" ); - return string; - }, - error: function( jqXHR ) { - strictEqual( jqXHR.responseText, "{ \"code\": 40, \"message\": \"Bad Request\" }", "Error body properly set" ); - deepEqual( jqXHR.responseJSON, { code: 40, message: "Bad Request" }, "Error body properly parsed" ); - } - }); + 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( "#11426 - jQuery.ajax() - loading binary data shouldn't throw an exception in IE", 1, { - url: url("data/1x1.jpg"), - success: function( data ) { - ok( data === undefined || /JFIF/.test( data ), "success callback reached" ); - } - }); + 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" ); + } + }; + } ); - test( "#11743 - jQuery.ajax() - script, throws exception", 1, function() { - throws(function() { - jQuery.ajax({ - url: "data/badjson.js", - dataType: "script", - "throws": true, - // TODO find a way to test this asynchronously, too - async: false, - // Global events get confused by the exception - global: false, - success: function() { - ok( false, "Success." ); - }, - error: function() { - ok( false, "Error." ); - } - }); - }, "exception bubbled" ); - }); + 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" ); + } + }; + } ); - jQuery.each( [ "method", "type" ], function( _, globalOption ) { +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 ) { + 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 + } ); + } ); - function request( option ) { + jQuery.each( [ "method", "type" ], function( _, globalOption ) { + function request( assert, option ) { var options = { - url: url("data/echoData.php"), + url: url( "data/echoData.php" ), data: "hello", success: function( msg ) { - strictEqual( msg, "hello", "Check for POST (no override)" ); + assert.strictEqual( msg, "hello", "Check for POST (no override)" ); } }; if ( option ) { options[ option ] = "GET"; options.success = function( msg ) { - strictEqual( msg, "", "Check for no POST (overriding with " + option + ")" ); + 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, { - setup: function() { - var options = {}; - options[ globalOption ] = "POST"; - jQuery.ajaxSetup( options ); - }, - requests: [ - request("type"), - request("method"), - request() - ] - }); - - }); - - ajaxTest( "#13276 - jQuery.ajax() - compatibility between XML documents from ajax requests and parsed string", 1, { - 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 ) { - strictEqual( e, undefined, "error" ); - return; + 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 ) + ] + }; } - strictEqual( ajaxXML.find("tab").length, 3, "Parsed node was added properly" ); - } - }); + ); + } ); - ajaxTest( "#13292 - jQuery.ajax() - converter is bypassed for 204 requests", 3, { - url: "data/nocontent.php", - dataType: "testing", - converters: { - "* testing": function() { - throw "converter was called"; + 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 { + 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" ); } - }, - success: function( data, status, jqXHR ) { - strictEqual( jqXHR.status, 204, "status code is 204" ); - strictEqual( status, "nocontent", "status text is 'nocontent'" ); - strictEqual( data, undefined, "data is undefined" ); - }, - error: function( _, status, error ) { - ok( false, "error" ); - strictEqual( status, "parsererror", "Parser Error" ); - strictEqual( error, "converter was called", "Converter was called" ); - } - }); + }; + } ); - ajaxTest( "#13388 - jQuery.ajax() - responseXML", 3, { - url: url("data/with_fries.xml"), - dataType: "xml", - success: function( resp, _, jqXHR ) { - notStrictEqual( resp, undefined, "XML document exists" ); - ok( "responseXML" in jqXHR, "jqXHR.responseXML exists" ); - strictEqual( resp, jqXHR.responseXML, "jqXHR.responseXML is set correctly" ); - } - }); + 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( "#13922 - jQuery.ajax() - converter is bypassed for HEAD requests", 3, { - url: "data/json.php", - method: "HEAD", - data: { - header: "yes" - }, - converters: { - "text json": function() { - throw "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" ); } - }, - success: function( data, status ) { - ok( true, "success" ); - strictEqual( status, "nocontent", "data is undefined" ); - strictEqual( data, undefined, "data is undefined" ); - }, - error: function( _, status, error ) { - ok( false, "error" ); - strictEqual( status, "parsererror", "Parser Error" ); - strictEqual( error, "converter was called", "Converter was called" ); - } + }; } ); - ajaxTest( "#13240 - jQuery.ajax() - support non-RFC2616 methods", 1, { - url: "data/echoQuery.php", - method: "PATCH", - success: function() { - ok( true, "success" ); - }, - error: function() { - ok( false, "error" ); + 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" ); + } + }; + } ); + + testIframe( + "#14379 - jQuery.ajax() on unload", + "ajax/onunload.html", + function( assert, jQuery, window, document, status ) { + 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://" + externalHost + ":80q", + 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" + ); + } + }; + } ); - testIframeWithCallback( "#14379 - jQuery.ajax() on unload", "ajax/onunload.html", function( status ) { - expect( 1 ); - strictEqual( status, "success", "Request completed" ); - }); + 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, { - 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() { - ok( false, "error callback called" ); - }, - fail: function( _, reason ) { - strictEqual( reason, "canceled", "Request aborted by the prefilter must fail with 'canceled' status text" ); - } - }); + 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() - asyncTest( "jQuery.ajaxSetup()", 1, function() { - jQuery.ajaxSetup({ - url: url("data/name.php?name=foo"), + QUnit.asyncTest( "jQuery.ajaxSetup()", 1, function( assert ) { + jQuery.ajaxSetup( { + url: url( "data/name.php?name=foo" ), success: function( msg ) { - strictEqual( msg, "bar", "Check for GET" ); - start(); + assert.strictEqual( msg, "bar", "Check for GET" ); + QUnit.start(); } - }); + } ); jQuery.ajax(); - }); + } ); - asyncTest( "jQuery.ajaxSetup({ timeout: Number }) - with global timeout", 2, function() { + QUnit.asyncTest( "jQuery.ajaxSetup({ timeout: Number }) - with global timeout", 2, function( assert ) { var passed = 0, pass = function() { - ok( passed++ < 2, "Error callback executed" ); + assert.ok( passed++ < 2, "Error callback executed" ); if ( passed === 2 ) { - jQuery( document ).off("ajaxError.setupTest"); - start(); + jQuery( document ).off( "ajaxError.setupTest" ); + QUnit.start(); } }, fail = function( a, b ) { - ok( false, "Check for timeout failed " + a + " " + b ); - start(); + assert.ok( false, "Check for timeout failed " + a + " " + b ); + QUnit.start(); }; jQuery( document ).on( "ajaxError.setupTest", pass ); - jQuery.ajaxSetup({ + jQuery.ajaxSetup( { timeout: 1000 - }); + } ); - jQuery.ajax({ + jQuery.ajax( { type: "GET", - url: url("data/name.php?wait=5"), + url: url( "data/name.php?wait=5" ), error: pass, success: fail - }); - }); + } ); + } ); - asyncTest( "jQuery.ajaxSetup({ timeout: Number }) with localtimeout", 1, function() { - jQuery.ajaxSetup({ + QUnit.asyncTest( "jQuery.ajaxSetup({ timeout: Number }) with localtimeout", 1, function( assert ) { + jQuery.ajaxSetup( { timeout: 50 - }); - jQuery.ajax({ + } ); + jQuery.ajax( { type: "GET", timeout: 15000, - url: url("data/name.php?wait=1"), + url: url( "data/name.php?wait=1" ), error: function() { - ok( false, "Check for local timeout failed" ); - start(); + assert.ok( false, "Check for local timeout failed" ); + QUnit.start(); }, success: function() { - ok( true, "Check for local timeout" ); - start(); + assert.ok( true, "Check for local timeout" ); + QUnit.start(); } - }); - }); + } ); + } ); //----------- jQuery.domManip() - test( "#11264 - jQuery.domManip() - no side effect because of ajaxSetup or global events", 1, function() { - jQuery.ajaxSetup({ + 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() { - ok( false, "Global event triggered" ); - }); + 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( + "jQuery#load() - should resolve with correct context", 2, + function( assert ) { + var done = assert.async(); + var ps = jQuery( "

" ); + var i = 0; + + ps.appendTo( "#qunit-fixture" ); - jQuery("#qunit-fixture").append(""); + ps.load( "data/ajax/method.php", function() { + assert.strictEqual( this, ps[ i++ ] ); - jQuery( document ).off("ajaxStart ajaxStop"); - }); + if ( i === 2 ) { + done(); + } + } ); + } + ); - asyncTest( "#11402 - jQuery.domManip() - script in comments are properly evaluated", 2, function() { - jQuery("#qunit-fixture").load( "data/cleanScript.html", start ); - }); + 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() - asyncTest( "jQuery.get( String, Hash, Function ) - parse xml and use text() on nodes", 2, function() { - jQuery.get( url("data/dashboard.xml"), function( xml ) { + 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() { + jQuery( "tab", xml ).each( function() { content.push( jQuery( this ).text() ); - }); - strictEqual( content[ 0 ], "blabla", "Check first tab" ); - strictEqual( content[ 1 ], "blublu", "Check second tab" ); - start(); - }); - }); + } ); + assert.strictEqual( content[ 0 ], "blabla", "Check first tab" ); + assert.strictEqual( content[ 1 ], "blublu", "Check second tab" ); + QUnit.start(); + } ); + } ); - asyncTest( "#8277 - jQuery.get( String, Function ) - data in ajaxSettings", 1, function() { - jQuery.ajaxSetup({ + 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 ) { - ok( /helloworld$/.test( data ), "Data from ajaxSettings was used" ); - start(); - }); - }); + } ); + jQuery.get( url( "data/echoQuery.php" ), function( data ) { + assert.ok( /helloworld$/.test( data ), "Data from ajaxSettings was used" ); + QUnit.start(); + } ); + } ); //----------- jQuery.getJSON() - asyncTest( "jQuery.getJSON( String, Hash, Function ) - JSON array", 5, function() { + QUnit.asyncTest( "jQuery.getJSON( String, Hash, Function ) - JSON array", 5, function( assert ) { jQuery.getJSON( - url("data/json.php"), + url( "data/json.php" ), { "json": "array" }, function( json ) { - ok( json.length >= 2, "Check length" ); - strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - strictEqual( json[ 1 ]["age"], 25, "Check JSON: second, age" ); - start(); + 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(); } ); - }); + } ); - asyncTest( "jQuery.getJSON( String, Function ) - JSON object", 2, function() { - jQuery.getJSON( url("data/json.php"), function( json ) { - if ( json && json["data"] ) { - strictEqual( json["data"]["lang"], "en", "Check JSON: lang" ); - strictEqual( json["data"].length, 25, "Check JSON: length" ); - start(); - } - }); - }); - - asyncTest( "jQuery.getJSON() - Using Native JSON", 2, function() { - var restore = "JSON" in window, - old = window.JSON; - if ( !restore ) { - Globals.register("JSON"); - } - window.JSON = { - parse: function() { - ok( true, "Verifying that parse method was run" ); - window.JSON = old; - return true; + 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(); } - }; - jQuery.getJSON( url("data/json.php"), function( json ) { - strictEqual( json, true, "Verifying return value" ); - start(); - }); - }); + } ); + } ); - asyncTest( "jQuery.getJSON( String, Function ) - JSON object with absolute url to local content", 2, function() { + 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 ) { - strictEqual( json.data.lang, "en", "Check JSON: lang" ); - strictEqual( json.data.length, 25, "Check JSON: length" ); - start(); - }); - }); + assert.strictEqual( json.data.lang, "en", "Check JSON: lang" ); + assert.strictEqual( json.data.length, 25, "Check JSON: length" ); + QUnit.start(); + } ); + } ); //----------- jQuery.getScript() - asyncTest( "jQuery.getScript( String, Function ) - with callback", 2, function() { - Globals.register("testBar"); - jQuery.getScript( url("data/testbar.php"), function() { - strictEqual( window["testBar"], "bar", "Check if script was evaluated" ); - start(); - }); - }); - - asyncTest( "jQuery.getScript( String, Function ) - no callback", 1, function() { - Globals.register("testBar"); - jQuery.getScript( url("data/testbar.php") ).done( start ); - }); - - asyncTest( "#8082 - jQuery.getScript( String, Function ) - source as responseText", 2, function() { - Globals.register("testBar"); - jQuery.getScript( url("data/testbar.php"), function( data, _, jqXHR ) { - strictEqual( data, jqXHR.responseText, "Same-domain script requests returns the source of the script" ); - start(); - }); - }); + 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() +// //----------- jQuery.fn.load() // check if load can be called with only url - asyncTest( "jQuery.fn.load( String )", 2, function() { - jQuery.ajaxSetup({ + QUnit.test( "jQuery.fn.load( String )", 2, function( assert ) { + jQuery.ajaxSetup( { beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); + assert.strictEqual( this.type, "GET", "no data means GET request" ); } - }); - jQuery("#first").load( "data/name.html", start ); - }); - - asyncTest( "jQuery.fn.load() - 404 error callbacks", 6, function() { - addGlobalEvents("ajaxStart ajaxStop ajaxSend ajaxComplete ajaxError")(); - jQuery( document ).ajaxStop( start ); - jQuery("
").load( "data/404.html", function() { - ok( true, "complete" ); - }); - }); + } ); + 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 - asyncTest( "jQuery.fn.load( String, null )", 2, function() { - jQuery.ajaxSetup({ + QUnit.test( "jQuery.fn.load( String, null )", 2, function( assert ) { + jQuery.ajaxSetup( { beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); + assert.strictEqual( this.type, "GET", "no data means GET request" ); } - }); - jQuery("#first").load( "data/name.html", null, start ); - }); + } ); + jQuery( "#first" ).load( "data/name.html", null, assert.async() ); + } ); // check if load can be called with url and undefined data - asyncTest( "jQuery.fn.load( String, undefined )", 2, function() { - jQuery.ajaxSetup({ + QUnit.test( "jQuery.fn.load( String, undefined )", 2, function( assert ) { + jQuery.ajaxSetup( { beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); + assert.strictEqual( this.type, "GET", "no data means GET request" ); } - }); - jQuery("#first").load( "data/name.html", undefined, start ); - }); + } ); + jQuery( "#first" ).load( "data/name.html", undefined, assert.async() ); + } ); // check if load can be called with only url - asyncTest( "jQuery.fn.load( URL_SELECTOR )", 1, function() { - jQuery("#first").load( "data/test3.html div.user", function() { - strictEqual( jQuery( this ).children("div").length, 2, "Verify that specific elements were injected" ); - start(); - }); - }); + 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(); + } ); + } ); // Selector should be trimmed to avoid leading spaces (#14773) - asyncTest( "jQuery.fn.load( URL_SELECTOR with spaces )", 1, function() { - jQuery("#first").load( "data/test3.html #superuser ", function() { - strictEqual( jQuery( this ).children("div").length, 1, "Verify that specific elements were injected" ); - start(); - }); - }); - - asyncTest( "jQuery.fn.load( String, Function ) - simple: inject text into DOM", 2, function() { - jQuery("#first").load( url("data/name.html"), function() { - ok( /^ERROR/.test(jQuery("#first").text()), "Check if content was injected into the DOM" ); - start(); - }); - }); + // Selector should include any valid non-HTML whitespace (#3003) + QUnit.test( "jQuery.fn.load( URL_SELECTOR with non-HTML whitespace(#3003) )", function( assert ) { + assert.expect( 1 ); + var done = assert.async(); + jQuery( "#first" ).load( "data/test3.html #whitespace\\\\xA0 ", function() { + assert.strictEqual( jQuery( this ).children( "div" ).length, 1, "Verify that specific elements were injected" ); + done(); + } ); + } ); + + 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(); + } ); + } ); - asyncTest( "jQuery.fn.load( String, Function ) - check scripts", 7, function() { + QUnit.asyncTest( "jQuery.fn.load( String, Function ) - check scripts", 7, function( assert ) { var verifyEvaluation = function() { - strictEqual( window["testBar"], "bar", "Check if script src was evaluated after load" ); - strictEqual( jQuery("#ap").html(), "bar", "Check if script evaluation has modified DOM"); - start(); + 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() { - ok( jQuery("#first").html().match( /^html text/ ), "Check content after loading html" ); - strictEqual( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM" ); - strictEqual( window["testFoo"], "foo", "Check if script was evaluated after load" ); + 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 ); - }); - }); + } ); + } ); - asyncTest( "jQuery.fn.load( String, Function ) - check file with only a script tag", 3, function() { - Globals.register("testFoo"); + 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() { - strictEqual( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM"); - strictEqual( window["testFoo"], "foo", "Check if script was evaluated after load" ); - start(); - }); - }); + 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(); + } ); + } ); - asyncTest( "jQuery.fn.load( String, Function ) - dataFilter in ajaxSettings", 2, function() { - jQuery.ajaxSetup({ + 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 ) { - strictEqual( jQuery( this ).html(), "Hello World", "Test div was filled with filtered data" ); - strictEqual( responseText, "Hello World", "Test callback receives filtered data" ); - start(); - }); - }); + } ); + 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(); + } ); + } ); - asyncTest( "jQuery.fn.load( String, Object, Function )", 2, function() { - jQuery("
").load( url("data/params_html.php"), { + 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"); - strictEqual( $post.find("#foo").text(), "3", "Check if a hash of data is passed correctly" ); - strictEqual( $post.find("#bar").text(), "ok", "Check if a hash of data is passed correctly" ); - start(); - }); - }); - - asyncTest( "jQuery.fn.load( String, String, Function )", 2, function() { - jQuery("
").load( url("data/params_html.php"), "foo=3&bar=ok", function() { - var $get = jQuery( this ).find("#get"); - strictEqual( $get.find("#foo").text(), "3", "Check if a string of data is passed correctly" ); - strictEqual( $get.find("#bar").text(), "ok", "Check if a of data is passed correctly" ); - start(); - }); - }); + 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(); + } ); + } ); - asyncTest( "jQuery.fn.load() - callbacks get the correct parameters", 8, function() { + QUnit.test( "jQuery.fn.load() - callbacks get the correct parameters", 8, function( assert ) { var completeArgs = {}; + var done = assert.async(); - jQuery.ajaxSetup({ + 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([ + jQuery.map( [ { type: "success", url: "data/echoQuery.php?arg=pop" @@ -1967,67 +2435,73 @@ } ], function( options ) { - return jQuery.Deferred(function( defer ) { - jQuery("#foo").load( options.url, function() { + return jQuery.Deferred( function( defer ) { + jQuery( "#foo" ).load( options.url, function() { var args = arguments; - strictEqual( completeArgs[ options.url ].length, args.length, "same number of arguments (" + options.type + ")" ); + assert.strictEqual( completeArgs[ options.url ].length, args.length, "same number of arguments (" + options.type + ")" ); jQuery.each( completeArgs[ options.url ], function( i, value ) { - strictEqual( args[ i ], value, "argument #" + i + " is the same (" + options.type + ")" ); - }); + assert.strictEqual( args[ i ], value, "argument #" + i + " is the same (" + options.type + ")" ); + } ); defer.resolve(); - }); - }); - }) - ).always( start ); - }); + } ); + } ); + } ) + ).always( done ); + } ); - asyncTest( "#2046 - jQuery.fn.load( String, Function ) with ajaxSetup on dataType json", 1, function() { - jQuery.ajaxSetup({ + 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 ) { - strictEqual( s.dataType, "html", "Verify the load() dataType was html" ); - jQuery( document ).off("ajaxComplete"); - start(); - }); - jQuery("#first").load("data/test3.html"); - }); + } ); + 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(); - asyncTest( "#10524 - jQuery.fn.load() - data specified in ajaxSettings is merged in", 1, function() { var data = { "baz": 1 }; - jQuery.ajaxSetup({ + jQuery.ajaxSetup( { data: { "foo": "bar" } - }); - jQuery("#foo").load( "data/echoQuery.php", data ); - jQuery( document ).ajaxComplete(function( event, jqXHR, options ) { - ok( ~options.data.indexOf("foo=bar"), "Data from ajaxSettings was used" ); - start(); - }); - }); + } ); + 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() +// //----------- jQuery.post() + + QUnit.test( "jQuery.post() - data", 3, function( assert ) { + var done = assert.async(); - asyncTest( "jQuery.post() - data", 3, function() { jQuery.when( jQuery.post( - url("data/name.php"), + url( "data/name.php" ), { xml: "5-2", length: 3 }, function( xml ) { - jQuery( "math", xml ).each(function() { - strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - strictEqual( jQuery( "result", this ).text(), "3", "Check for 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"), + jQuery.ajax( { + url: url( "data/echoData.php" ), type: "POST", data: { "test": { @@ -2036,43 +2510,68 @@ } }, success: function( data ) { - strictEqual( data, "test%5Blength%5D=7&test%5Bfoo%5D=bar", "Check if a sub-object with a length param is serialized correctly" ); + 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() { - start(); - }); - }); + } ) + ).always( function() { + done(); + } ); + } ); + + QUnit.test( "jQuery.post( String, Hash, Function ) - simple with xml", 4, function( assert ) { + var done = assert.async(); - asyncTest( "jQuery.post( String, Hash, Function ) - simple with xml", 4, function() { jQuery.when( jQuery.post( - url("data/name.php"), + url( "data/name.php" ), { "xml": "5-2" }, function( xml ) { - jQuery( "math", xml ).each(function() { - strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - strictEqual( jQuery( "result", this ).text(), "3", "Check for 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() { - strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); - }); - }) - ).always(function() { - start(); - }); - }); + 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 - test( "jQuery.active", 1, function() { - ok( jQuery.active === 0, "ajax active counter should be zero: " + 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 -Nru jquery-1.11.3+dfsg/test/unit/animation.js jquery-3.2.1/test/unit/animation.js --- jquery-1.11.3+dfsg/test/unit/animation.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/unit/animation.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,263 @@ +( function() { + +// Can't test what ain't there +if ( !jQuery.fx ) { + return; +} + +var oldRaf = window.requestAnimationFrame, + defaultPrefilter = jQuery.Animation.prefilters[ 0 ], + defaultTweener = jQuery.Animation.tweeners[ "*" ][ 0 ], + startTime = 505877050; + +// This module tests jQuery.Animation and the corresponding 1.8+ effects APIs +QUnit.module( "animation", { + setup: function() { + window.requestAnimationFrame = null; + this.sandbox = sinon.sandbox.create(); + this.clock = this.sandbox.useFakeTimers( startTime ); + this._oldInterval = jQuery.fx.interval; + jQuery.fx.step = {}; + jQuery.fx.interval = 10; + jQuery.now = Date.now; + jQuery.Animation.prefilters = [ defaultPrefilter ]; + jQuery.Animation.tweeners = { "*": [ defaultTweener ] }; + }, + teardown: function() { + this.sandbox.restore(); + jQuery.now = Date.now; + jQuery.fx.stop(); + jQuery.fx.interval = this._oldInterval; + window.requestAnimationFrame = oldRaf; + return moduleTeardown.apply( this, arguments ); + } +} ); + +QUnit.test( "Animation( subject, props, opts ) - shape", function( assert ) { + assert.expect( 20 ); + + var subject = { test: 0 }, + props = { test: 1 }, + opts = { queue: "fx", duration: 100 }, + animation = jQuery.Animation( subject, props, opts ); + + assert.equal( + animation.elem, + subject, + ".elem is set to the exact object passed" + ); + assert.equal( + animation.originalOptions, + opts, + ".originalOptions is set to options passed" + ); + assert.equal( + animation.originalProperties, + props, + ".originalProperties is set to props passed" + ); + + assert.notEqual( animation.props, props, ".props is not the original however" ); + assert.deepEqual( animation.props, props, ".props is a copy of the original" ); + + assert.deepEqual( animation.opts, { + duration: 100, + queue: "fx", + specialEasing: { test: undefined }, + easing: jQuery.easing._default + }, ".options is filled with default easing and specialEasing" ); + + assert.equal( animation.startTime, startTime, "startTime was set" ); + assert.equal( animation.duration, 100, ".duration is set" ); + + assert.equal( animation.tweens.length, 1, ".tweens has one Tween" ); + assert.equal( typeof animation.tweens[ 0 ].run, "function", "which has a .run function" ); + + assert.equal( typeof animation.createTween, "function", ".createTween is a function" ); + assert.equal( typeof animation.stop, "function", ".stop is a function" ); + + assert.equal( typeof animation.done, "function", ".done is a function" ); + assert.equal( typeof animation.fail, "function", ".fail is a function" ); + assert.equal( typeof animation.always, "function", ".always is a function" ); + assert.equal( typeof animation.progress, "function", ".progress is a function" ); + + assert.equal( jQuery.timers.length, 1, "Added a timers function" ); + assert.equal( jQuery.timers[ 0 ].elem, subject, "...with .elem as the subject" ); + assert.equal( jQuery.timers[ 0 ].anim, animation, "...with .anim as the animation" ); + assert.equal( jQuery.timers[ 0 ].queue, opts.queue, "...with .queue" ); + + // Cleanup after ourselves by ticking to the end + this.clock.tick( 100 ); +} ); + +QUnit.test( "Animation.prefilter( fn ) - calls prefilter after defaultPrefilter", + function( assert ) { + assert.expect( 1 ); + + var prefilter = this.sandbox.stub(), + defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 ); + + jQuery.Animation.prefilter( prefilter ); + + jQuery.Animation( {}, {}, {} ); + assert.ok( prefilter.calledAfter( defaultSpy ), "our prefilter called after" ); + } +); + +QUnit.test( "Animation.prefilter( fn, true ) - calls prefilter before defaultPrefilter", + function( assert ) { + assert.expect( 1 ); + + var prefilter = this.sandbox.stub(), + defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 ); + + jQuery.Animation.prefilter( prefilter, true ); + + jQuery.Animation( {}, {}, {} ); + assert.ok( prefilter.calledBefore( defaultSpy ), "our prefilter called before" ); + } +); + +QUnit.test( "Animation.prefilter - prefilter return hooks", function( assert ) { + assert.expect( 34 ); + + var animation, realAnimation, element, + sandbox = this.sandbox, + ourAnimation = { stop: this.sandbox.spy() }, + target = { height: 50 }, + props = { height: 100 }, + opts = { duration: 100 }, + prefilter = this.sandbox.spy( function() { + realAnimation = this; + sandbox.spy( realAnimation, "createTween" ); + + assert.deepEqual( realAnimation.originalProperties, props, "originalProperties" ); + assert.equal( arguments[ 0 ], this.elem, "first param elem" ); + assert.equal( arguments[ 1 ], this.props, "second param props" ); + assert.equal( arguments[ 2 ], this.opts, "third param opts" ); + return ourAnimation; + } ), + defaultSpy = sandbox.spy( jQuery.Animation.prefilters, 0 ), + queueSpy = sandbox.spy( function( next ) { + next(); + } ), + TweenSpy = sandbox.spy( jQuery, "Tween" ); + + jQuery.Animation.prefilter( prefilter, true ); + + sandbox.stub( jQuery.fx, "timer" ); + + animation = jQuery.Animation( target, props, opts ); + + assert.equal( prefilter.callCount, 1, "Called prefilter" ); + + assert.equal( + defaultSpy.callCount, + 0, + "Returning something from a prefilter caused remaining prefilters to not run" + ); + assert.equal( jQuery.fx.timer.callCount, 0, "Returning something never queues a timer" ); + assert.equal( + animation, + ourAnimation, + "Returning something returned it from jQuery.Animation" + ); + assert.equal( + realAnimation.createTween.callCount, + 0, + "Returning something never creates tweens" + ); + assert.equal( TweenSpy.callCount, 0, "Returning something never creates tweens" ); + + // Test overridden usage on queues: + prefilter.reset(); + element = jQuery( "
" ) + .css( "height", 50 ) + .animate( props, 100 ) + .queue( queueSpy ) + .animate( props, 100 ) + .queue( queueSpy ) + .animate( props, 100 ) + .queue( queueSpy ); + + assert.equal( prefilter.callCount, 1, "Called prefilter" ); + assert.equal( queueSpy.callCount, 0, "Next function in queue not called" ); + + realAnimation.opts.complete.call( realAnimation.elem ); + assert.equal( queueSpy.callCount, 1, "Next function in queue called after complete" ); + + assert.equal( prefilter.callCount, 2, "Called prefilter again - animation #2" ); + assert.equal( ourAnimation.stop.callCount, 0, ".stop() on our animation hasn't been called" ); + + element.stop(); + assert.equal( ourAnimation.stop.callCount, 1, ".stop() called ourAnimation.stop()" ); + assert.ok( + !ourAnimation.stop.args[ 0 ][ 0 ], + ".stop( falsy ) (undefined or false are both valid)" + ); + + assert.equal( queueSpy.callCount, 2, "Next queue function called" ); + assert.ok( queueSpy.calledAfter( ourAnimation.stop ), "After our animation was told to stop" ); + + // ourAnimation.stop.reset(); + assert.equal( prefilter.callCount, 3, "Got the next animation" ); + + ourAnimation.stop.reset(); + + // do not clear queue, gotoEnd + element.stop( false, true ); + assert.ok( ourAnimation.stop.calledWith( true ), ".stop(true) calls .stop(true)" ); + assert.ok( queueSpy.calledAfter( ourAnimation.stop ), + "and the next queue function ran after we were told" ); +} ); + +QUnit.test( "Animation.tweener( fn ) - unshifts a * tweener", function( assert ) { + assert.expect( 2 ); + var starTweeners = jQuery.Animation.tweeners[ "*" ]; + + jQuery.Animation.tweener( jQuery.noop ); + assert.equal( starTweeners.length, 2 ); + assert.deepEqual( starTweeners, [ jQuery.noop, defaultTweener ] ); +} ); + +QUnit.test( "Animation.tweener( 'prop', fn ) - unshifts a 'prop' tweener", function( assert ) { + assert.expect( 4 ); + var tweeners = jQuery.Animation.tweeners, + fn = function() {}; + + jQuery.Animation.tweener( "prop", jQuery.noop ); + assert.equal( tweeners.prop.length, 1 ); + assert.deepEqual( tweeners.prop, [ jQuery.noop ] ); + + jQuery.Animation.tweener( "prop", fn ); + assert.equal( tweeners.prop.length, 2 ); + assert.deepEqual( tweeners.prop, [ fn, jQuery.noop ] ); +} ); + +QUnit.test( + "Animation.tweener( 'list of props', fn ) - unshifts a tweener to each prop", + function( assert ) { + assert.expect( 2 ); + var tweeners = jQuery.Animation.tweeners, + fn = function() {}; + + jQuery.Animation.tweener( "list of props", jQuery.noop ); + assert.deepEqual( tweeners, { + list: [ jQuery.noop ], + of: [ jQuery.noop ], + props: [ jQuery.noop ], + "*": [ defaultTweener ] + } ); + + // Test with extra whitespaces + jQuery.Animation.tweener( " list\t of \tprops\n*", fn ); + assert.deepEqual( tweeners, { + list: [ fn, jQuery.noop ], + of: [ fn, jQuery.noop ], + props: [ fn, jQuery.noop ], + "*": [ fn, defaultTweener ] + } ); + } +); + +} )(); diff -Nru jquery-1.11.3+dfsg/test/unit/attributes.js jquery-3.2.1/test/unit/attributes.js --- jquery-1.11.3+dfsg/test/unit/attributes.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/attributes.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,6 +1,6 @@ -module( "attributes", { +QUnit.module( "attributes", { teardown: moduleTeardown -}); +} ); function bareObj( value ) { return value; @@ -24,8 +24,8 @@ Returns a function that returns the value */ -test( "jQuery.propFix integrity test", function() { - expect( 1 ); +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 @@ -46,581 +46,599 @@ "contenteditable": "contentEditable" }; - if ( !jQuery.support.enctype ) { - props.enctype = "encoding"; - } - - deepEqual( props, jQuery.propFix, "jQuery.propFix passes integrity check" ); -}); + assert.deepEqual( props, jQuery.propFix, "jQuery.propFix passes integrity check" ); +} ); -test( "attr(String)", function() { - expect( 50 ); +QUnit.test( "attr(String)", function( assert ) { + assert.expect( 50 ); var extras, body, $body, select, optgroup, option, $img, styleElem, $button, $form, $a; - equal( jQuery("#text1").attr("type"), "text", "Check for type attribute" ); - equal( jQuery("#radio1").attr("type"), "radio", "Check for type attribute" ); - equal( jQuery("#check1").attr("type"), "checkbox", "Check for type attribute" ); - equal( jQuery("#simon1").attr("rel"), "bookmark", "Check for rel attribute" ); - equal( jQuery("#google").attr("title"), "Google!", "Check for title attribute" ); - equal( jQuery("#mark").attr("hreflang"), "en", "Check for hreflang attribute" ); - equal( jQuery("#en").attr("lang"), "en", "Check for lang attribute" ); - equal( jQuery("#simon").attr("class"), "blog link", "Check for class attribute" ); - equal( jQuery("#name").attr("name"), "name", "Check for name attribute" ); - equal( jQuery("#text1").attr("name"), "action", "Check for name attribute" ); - ok( jQuery("#form").attr("action").indexOf("formaction") >= 0, "Check for action attribute" ); - equal( jQuery("#text1").attr("value", "t").attr("value"), "t", "Check setting the value attribute" ); - equal( jQuery("#text1").attr("value", "").attr("value"), "", "Check setting the value attribute to empty string" ); - equal( jQuery("
").attr("value"), "t", "Check setting custom attr named 'value' on a div" ); - equal( jQuery("#form").attr("blah", "blah").attr("blah"), "blah", "Set non-existent attribute on a form" ); - equal( jQuery("#foo").attr("height"), undefined, "Non existent height attribute should return undefined" ); + 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"); - equal( jQuery("#form").attr("action","newformaction").attr("action"), "newformaction", "Check that action attribute was changed" ); - equal( jQuery("#testForm").attr("target"), undefined, "Retrieving target does not equal the input with name=target" ); - equal( jQuery("#testForm").attr("target", "newTarget").attr("target"), "newTarget", "Set target successfully on a form" ); - equal( jQuery("#testForm").removeAttr("id").attr("id"), undefined, "Retrieving id does not equal the input with name=id after id is removed [#7472]" ); + 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") - equal( jQuery("#testForm").attr("name"), undefined, "Retrieving name does not retrieve input with name=name" ); + assert.equal( jQuery( "#testForm" ).attr( "name" ), undefined, "Retrieving name does not retrieve input with name=name" ); extras.remove(); - equal( jQuery("#text1").attr("maxlength"), "30", "Check for maxlength attribute" ); - equal( jQuery("#text1").attr("maxLength"), "30", "Check for maxLength attribute" ); - equal( jQuery("#area1").attr("maxLength"), "30", "Check for maxLength attribute" ); + 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({ + jQuery( "" ).attr( { "id": "tAnchor5", "href": "#5" - }).appendTo("#qunit-fixture"); - equal( jQuery("#tAnchor5").attr("href"), "#5", "Check for non-absolute href (an anchor)" ); - jQuery("").appendTo("#qunit-fixture"); - equal( jQuery("#tAnchor5").prop("href"), jQuery("#tAnchor6").prop("href"), "Check for absolute href prop on an anchor" ); + } ).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"); - equal( jQuery("#tAnchor5").prop("href"), jQuery("#scriptSrc").prop("src"), "Check for absolute src prop on a script" ); + 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" ); - equal( jQuery("#list-test").attr("list"), "datalist", "Check setting list attribute" ); + 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 ); - strictEqual( $body.attr("foo"), undefined, "Make sure that a non existent attribute returns undefined" ); + assert.strictEqual( $body.attr( "foo" ), undefined, "Make sure that a non existent attribute returns undefined" ); body.setAttribute( "foo", "baz" ); - equal( $body.attr("foo"), "baz", "Make sure the dom attribute is retrieved when no expando is found" ); + assert.equal( $body.attr( "foo" ), "baz", "Make sure the dom attribute is retrieved when no expando is found" ); - $body.attr( "foo","cool" ); - equal( $body.attr("foo"), "cool", "Make sure that setting works well when both expando and dom attribute are available" ); + $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 + body.removeAttribute( "foo" ); // Cleanup - select = document.createElement("select"); - optgroup = document.createElement("optgroup"); - option = document.createElement("option"); + select = document.createElement( "select" ); + optgroup = document.createElement( "optgroup" ); + option = document.createElement( "option" ); optgroup.appendChild( option ); select.appendChild( optgroup ); - equal( jQuery( option ).prop("selected"), true, "Make sure that a single option is selected, even when in an 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"); - equal( $img.attr("width"), "215", "Retrieve width attribute an an element with display:none." ); - equal( $img.attr("height"), "53", "Retrieve height attribute an an element with display:none." ); + $img = jQuery( "" ).appendTo( "body" ); + assert.equal( $img.attr( "width" ), "215", "Retrieve width attribute on an element with display:none." ); + assert.equal( $img.attr( "height" ), "53", "Retrieve height attribute on an element with display:none." ); // Check for style support - styleElem = jQuery("
").appendTo("#qunit-fixture").css({ + styleElem = jQuery( "
" ).appendTo( "#qunit-fixture" ).css( { background: "url(UPPERlower.gif)" - }); - ok( !!~styleElem.attr("style").indexOf("UPPERlower.gif"), "Check style attribute getter" ); - ok( !!~styleElem.attr("style", "position:absolute;").attr("style").indexOf("absolute"), "Check style setter" ); + } ); + 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"); - strictEqual( $button.attr("value"), undefined, "Absence of value attribute on a button" ); - equal( $button.attr( "value", "foobar" ).attr("value"), "foobar", "Value attribute on a button does not return innerHTML" ); - equal( $button.attr("value", "baz").html(), "text", "Setting the value attribute does not change innerHTML" ); + $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) - equal( jQuery("#table").attr("test:attrib"), undefined, "Retrieving a non-existent attribute on a table with a colon does not throw an error." ); - 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." ); + 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"); - equal( $form.attr("class"), "something", "Retrieve the class attribute on a form." ); + $form = jQuery( "
" ).appendTo( "#qunit-fixture" ); + assert.equal( $form.attr( "class" ), "something", "Retrieve the class attribute on a form." ); - $a = jQuery("
Click").appendTo("#qunit-fixture"); - equal( $a.attr("onclick"), "something()", "Retrieve ^on attribute without anonymous function wrapper." ); + $a = jQuery( "Click" ).appendTo( "#qunit-fixture" ); + assert.equal( $a.attr( "onclick" ), "something()", "Retrieve ^on attribute without anonymous function wrapper." ); - ok( jQuery("
").attr("doesntexist") === undefined, "Make sure undefined is returned when no attribute is found." ); - ok( jQuery("
").attr("title") === undefined, "Make sure undefined is returned when no attribute is found." ); - equal( jQuery("
").attr( "title", "something" ).attr("title"), "something", "Set the title attribute." ); - ok( jQuery().attr("doesntexist") === undefined, "Make sure undefined is returned when no element is there." ); - equal( jQuery("
").attr("value"), undefined, "An unset value on a div returns undefined." ); - strictEqual( jQuery("").attr("value"), undefined, "An unset value on a select returns undefined." ); + 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" ); - equal( $form.prop("enctype"), "multipart/form-data", "Set the enctype of a form (encoding in IE6/7 #6743)" ); + $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)" ); -}); +} ); -test( "attr(String) on cloned elements, #9646", function() { - expect( 4 ); +QUnit.test( "attr(String) on cloned elements, #9646", function( assert ) { + assert.expect( 4 ); var div, - input = jQuery(""); + input = jQuery( "" ); - input.attr("name"); + input.attr( "name" ); - strictEqual( input.clone( true ).attr( "name", "test" )[ 0 ].name, "test", "Name attribute should be changed on cloned element" ); + assert.strictEqual( input.clone( true ).attr( "name", "test" )[ 0 ].name, "test", "Name attribute should be changed on cloned element" ); - div = jQuery("
"); - div.attr("id"); + div = jQuery( "
" ); + div.attr( "id" ); - strictEqual( div.clone( true ).attr( "id", "test" )[ 0 ].id, "test", "Id attribute should be changed on cloned element" ); + assert.strictEqual( div.clone( true ).attr( "id", "test" )[ 0 ].id, "test", "Id attribute should be changed on cloned element" ); - input = jQuery(""); - input.attr("value"); + input = jQuery( "" ); + input.attr( "value" ); - 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", "test" )[ 0 ].value, "test", "Value attribute should be changed on cloned element" ); - strictEqual( input.clone( true ).attr( "value", 42 )[ 0 ].value, "42", "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" ); +} ); -test( "attr(String) in XML Files", function() { - expect( 3 ); +QUnit.test( "attr(String) in XML Files", function( assert ) { + assert.expect( 3 ); var xml = createDashboardXML(); - equal( jQuery( "locations", xml ).attr("class"), "foo", "Check class attribute in XML document" ); - equal( jQuery( "location", xml ).attr("for"), "bar", "Check for attribute in XML document" ); - equal( jQuery( "location", xml ).attr("checked"), "different", "Check that hooks are not attached in XML document" ); -}); + 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" ); +} ); -test( "attr(String, Function)", function() { - expect( 2 ); +QUnit.test( "attr(String, Function)", function( assert ) { + assert.expect( 2 ); - equal( - jQuery("#text1").attr( "value", function() { + assert.equal( + jQuery( "#text1" ).attr( "value", function() { return this.id; - }).attr("value"), + } ).attr( "value" ), "text1", "Set value from id" ); - equal( - jQuery("#text1").attr( "title", function(i) { + assert.equal( + jQuery( "#text1" ).attr( "title", function( i ) { return i; - }).attr("title"), + } ).attr( "title" ), "0", "Set value with an index" ); -}); +} ); -test( "attr(Hash)", function() { - expect( 3 ); +QUnit.test( "attr(Hash)", function( assert ) { + assert.expect( 3 ); var pass = true; - jQuery("div").attr({ + + jQuery( "#qunit-fixture div" ).attr( { "foo": "baz", "zoo": "ping" - }).each(function() { - if ( this.getAttribute("foo") !== "baz" && this.getAttribute("zoo") !== "ping" ) { + } ).each( function() { + if ( this.getAttribute( "foo" ) !== "baz" && this.getAttribute( "zoo" ) !== "ping" ) { pass = false; } - }); + } ); - ok( pass, "Set Multiple Attributes" ); + assert.ok( pass, "Set Multiple Attributes" ); - equal( - jQuery("#text1").attr({ + assert.equal( + jQuery( "#text1" ).attr( { "value": function() { - return this["id"]; - }}).attr("value"), + return this[ "id" ]; + } } ).attr( "value" ), "text1", "Set attribute to computed value #1" ); - equal( - jQuery("#text1").attr({ - "title": function(i) { + assert.equal( + jQuery( "#text1" ).attr( { + "title": function( i ) { return i; } - }).attr("title"), + } ).attr( "title" ), "0", "Set attribute to computed value #2" ); -}); +} ); -test( "attr(String, Object)", function() { - expect( 71 ); +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"), + div = jQuery( "#qunit-fixture div" ).attr( "foo", "bar" ), i = 0, fail = false; for ( ; i < div.length; i++ ) { - if ( div[ i ].getAttribute("foo") !== "bar" ) { + if ( div[ i ].getAttribute( "foo" ) !== "bar" ) { fail = i; break; } } - equal( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" ); + assert.equal( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" ); - ok( - jQuery("#foo").attr({ + assert.ok( + jQuery( "#foo" ).attr( { "width": null - }), + } ), "Try to set an attribute to nothing" ); - jQuery("#name").attr( "name", "something" ); - equal( jQuery("#name").attr("name"), "something", "Set name attribute" ); - jQuery("#name").attr( "name", null ); - equal( jQuery("#name").attr("name"), undefined, "Remove name attribute" ); + 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" - }); - equal( $input.attr("name"), "something", "Check element creation gets/sets the name attribute." ); - equal( $input.attr("id"), "specified", "Check element creation gets/sets the id attribute." ); + } ); + 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 ); - equal( $input.prop("checked"), true, "Setting checked updates property (verified by .prop)" ); - equal( $input[0].checked, true, "Setting checked updates property (verified by native property)" ); - $input = jQuery("
"); - td = table.find("td").eq(0); + table = jQuery( "#table" ).append( "" ); + td = table.find( "td" ).eq( 0 ); td.attr( "rowspan", "2" ); - equal( td[ 0 ]["rowSpan"], 2, "Check rowspan is correctly set" ); + assert.equal( td[ 0 ][ "rowSpan" ], 2, "Check rowspan is correctly set" ); td.attr( "colspan", "2" ); - equal( td[ 0 ]["colSpan"], 2, "Check colspan is correctly set" ); - table.attr("cellspacing", "2"); - equal( table[ 0 ]["cellSpacing"], "2", "Check cellspacing is correctly set" ); + assert.equal( td[ 0 ][ "colSpan" ], 2, "Check colspan is correctly set" ); + table.attr( "cellspacing", "2" ); + assert.equal( table[ 0 ][ "cellSpacing" ], "2", "Check cellspacing is correctly set" ); - equal( jQuery("#area1").attr("value"), undefined, "Value attribute is distinct from value property." ); + assert.equal( jQuery( "#area1" ).attr( "value" ), undefined, "Value attribute is distinct from value property." ); // for #1070 - jQuery("#name").attr( "someAttr", "0" ); - equal( jQuery("#name").attr("someAttr"), "0", "Set attribute to a string of '0'" ); - jQuery("#name").attr( "someAttr", 0 ); - equal( jQuery("#name").attr("someAttr"), "0", "Set attribute to the number 0" ); - jQuery("#name").attr( "someAttr", 1 ); - equal( jQuery("#name").attr("someAttr"), "1", "Set attribute to the number 1" ); + jQuery( "#name" ).attr( "someAttr", "0" ); + assert.equal( jQuery( "#name" ).attr( "someAttr" ), "0", "Set attribute to a string of '0'" ); + jQuery( "#name" ).attr( "someAttr", 0 ); + assert.equal( jQuery( "#name" ).attr( "someAttr" ), "0", "Set attribute to the number 0" ); + jQuery( "#name" ).attr( "someAttr", 1 ); + assert.equal( jQuery( "#name" ).attr( "someAttr" ), "1", "Set attribute to the number 1" ); // using contents will get comments regular, text, and comment nodes - j = jQuery("#nonnodes").contents(); + j = jQuery( "#nonnodes" ).contents(); j.attr( "name", "attrvalue" ); - equal( j.attr("name"), "attrvalue", "Check node,textnode,comment for attr" ); - j.removeAttr("name"); + assert.equal( j.attr( "name" ), "attrvalue", "Check node,textnode,comment for attr" ); + j.removeAttr( "name" ); // Type - type = jQuery("#check2").attr("type"); + type = jQuery( "#check2" ).attr( "type" ); try { - jQuery("#check2").attr( "type", "hidden" ); - ok( true, "No exception thrown on input type change" ); - } catch( e ) { - ok( true, "Exception thrown on input type change: " + e ); + jQuery( "#check2" ).attr( "type", "hidden" ); + assert.ok( true, "No exception thrown on input type change" ); + } catch ( e ) { + assert.ok( true, "Exception thrown on input type change: " + e ); } - check = document.createElement("input"); + check = document.createElement( "input" ); thrown = true; try { jQuery( check ).attr( "type", "checkbox" ); - } catch( e ) { + } catch ( e ) { thrown = false; } - ok( thrown, "Exception thrown when trying to change type property" ); - equal( "checkbox", jQuery( check ).attr("type"), "Verify that you can change the type of an input element that isn't in the DOM" ); + assert.ok( thrown, "Exception thrown when trying to change type property" ); + assert.equal( "checkbox", jQuery( check ).attr( "type" ), "Verify that you can change the type of an input element that isn't in the DOM" ); - check = jQuery(""); + check = jQuery( "" ); thrown = true; try { check.attr( "type", "checkbox" ); - } catch( e ) { + } catch ( e ) { thrown = false; } - ok( thrown, "Exception thrown when trying to change type property" ); - equal( "checkbox", check.attr("type"), "Verify that you can change the type of an input element that isn't in the DOM" ); + assert.ok( thrown, "Exception thrown when trying to change type property" ); + assert.equal( "checkbox", check.attr( "type" ), "Verify that you can change the type of an input element that isn't in the DOM" ); - button = jQuery("#button"); + button = jQuery( "#button" ); try { button.attr( "type", "submit" ); - ok( true, "No exception thrown on button type change" ); - } catch( e ) { - ok( true, "Exception thrown on button type change: " + e ); + assert.ok( true, "No exception thrown on button type change" ); + } catch ( e ) { + assert.ok( true, "Exception thrown on button type change: " + e ); } $radio = jQuery( "", { "value": "sup", - "type": "radio" - }).appendTo("#testForm"); - equal( $radio.val(), "sup", "Value is not reset when type is set after value on a radio" ); + // Use uppercase here to ensure the type + // attrHook is still used + "TYPE": "radio" + } ).appendTo( "#testForm" ); + assert.equal( $radio.val(), "sup", "Value is not reset when type is set after value on a radio" ); // Setting attributes on svg elements (bug #3116) $svg = jQuery( "" + + "" + "" - ).appendTo("body"); - equal( $svg.attr( "cx", 100 ).attr("cx"), "100", "Set attribute on svg element" ); + ).appendTo( "body" ); + assert.equal( $svg.attr( "cx", 100 ).attr( "cx" ), "100", "Set attribute on svg element" ); $svg.remove(); // undefined values are chainable - jQuery("#name").attr( "maxlength", "5" ).removeAttr("nonexisting"); - equal( typeof jQuery("#name").attr( "maxlength", undefined ), "object", ".attr('attribute', undefined) is chainable (#5571)" ); - equal( jQuery("#name").attr( "maxlength", undefined ).attr("maxlength"), "5", ".attr('attribute', undefined) does not change value (#5571)" ); - equal( jQuery("#name").attr( "nonexisting", undefined ).attr("nonexisting"), undefined, ".attr('attribute', undefined) does not create attribute (#5571)" ); -}); + jQuery( "#name" ).attr( "maxlength", "5" ).removeAttr( "nonexisting" ); + assert.equal( typeof jQuery( "#name" ).attr( "maxlength", undefined ), "object", ".attr('attribute', undefined) is chainable (#5571)" ); + assert.equal( jQuery( "#name" ).attr( "maxlength", undefined ).attr( "maxlength" ), "5", ".attr('attribute', undefined) does not change value (#5571)" ); + assert.equal( jQuery( "#name" ).attr( "nonexisting", undefined ).attr( "nonexisting" ), undefined, ".attr('attribute', undefined) does not create attribute (#5571)" ); +} ); + +QUnit.test( "attr(non-ASCII)", function( assert ) { + assert.expect( 2 ); + + var $div = jQuery( "
" ).appendTo( "#qunit-fixture" ); + + assert.equal( $div.attr( "Ω" ), "omega", ".attr() exclusively lowercases characters in the range A-Z (gh-2730)" ); + assert.equal( $div.attr( "AØC" ), "alpha", ".attr() exclusively lowercases characters in the range A-Z (gh-2730)" ); +} ); -test( "attr - extending the boolean attrHandle", function() { - expect( 1 ); +QUnit.test( "attr - extending the boolean attrHandle", function( assert ) { + assert.expect( 1 ); var called = false, - _handle = jQuery.expr.attrHandle.checked || $.noop; + origAttrHandleHadChecked = "checked" in jQuery.expr.attrHandle, + origAttrHandleChecked = jQuery.expr.attrHandle.checked, + _handle = origAttrHandleChecked || $.noop; jQuery.expr.attrHandle.checked = function() { called = true; _handle.apply( this, arguments ); }; - jQuery( "input" ).attr( "checked" ); + jQuery( "#qunit-fixture input" ).attr( "checked" ); called = false; - jQuery( "input" ).attr( "checked" ); - ok( called, "The boolean attrHandle does not drop custom attrHandles" ); -}); + jQuery( "#qunit-fixture input" ).attr( "checked" ); + assert.ok( called, "The boolean attrHandle does not drop custom attrHandles" ); -test( "attr(String, Object) - Loaded via XML document", function() { - expect( 2 ); + if ( origAttrHandleHadChecked ) { + jQuery.expr.attrHandle.checked = origAttrHandleChecked; + } else { + delete jQuery.expr.attrHandle.checked; + } + +} ); + +QUnit.test( "attr(String, Object) - Loaded via XML document", function( assert ) { + assert.expect( 2 ); var xml = createDashboardXML(), titles = []; - jQuery( "tab", xml ).each(function() { - titles.push( jQuery( this ).attr("title") ); - }); - equal( titles[ 0 ], "Location", "attr() in XML context: Check first title" ); - equal( titles[ 1 ], "Users", "attr() in XML context: Check second title" ); -}); + jQuery( "tab", xml ).each( function() { + titles.push( jQuery( this ).attr( "title" ) ); + } ); + assert.equal( titles[ 0 ], "Location", "attr() in XML context: Check first title" ); + assert.equal( titles[ 1 ], "Users", "attr() in XML context: Check second title" ); +} ); -test( "attr(String, Object) - Loaded via XML fragment", function() { - expect( 2 ); +QUnit.test( "attr(String, Object) - Loaded via XML fragment", function( assert ) { + assert.expect( 2 ); var frag = createXMLFragment(), $frag = jQuery( frag ); $frag.attr( "test", "some value" ); - equal( $frag.attr("test"), "some value", "set attribute" ); + assert.equal( $frag.attr( "test" ), "some value", "set attribute" ); $frag.attr( "test", null ); - equal( $frag.attr("test"), undefined, "remove attribute" ); -}); + assert.equal( $frag.attr( "test" ), undefined, "remove attribute" ); +} ); -test( "attr('tabindex')", function() { - expect( 8 ); +QUnit.test( "attr('tabindex')", function( assert ) { + assert.expect( 8 ); // elements not natively tabbable - equal( jQuery("#listWithTabIndex").attr("tabindex"), "5", "not natively tabbable, with tabindex set to 0" ); - equal( jQuery("#divWithNoTabIndex").attr("tabindex"), undefined, "not natively tabbable, no tabindex set" ); + assert.equal( jQuery( "#listWithTabIndex" ).attr( "tabindex" ), "5", "not natively tabbable, with tabindex set to 0" ); + assert.equal( jQuery( "#divWithNoTabIndex" ).attr( "tabindex" ), undefined, "not natively tabbable, no tabindex set" ); // anchor with href - equal( jQuery("#linkWithNoTabIndex").attr("tabindex"), undefined, "anchor with href, no tabindex set" ); - equal( jQuery("#linkWithTabIndex").attr("tabindex"), "2", "anchor with href, tabindex set to 2" ); - equal( jQuery("#linkWithNegativeTabIndex").attr("tabindex"), "-1", "anchor with href, tabindex set to -1" ); + assert.equal( jQuery( "#linkWithNoTabIndex" ).attr( "tabindex" ), undefined, "anchor with href, no tabindex set" ); + assert.equal( jQuery( "#linkWithTabIndex" ).attr( "tabindex" ), "2", "anchor with href, tabindex set to 2" ); + assert.equal( jQuery( "#linkWithNegativeTabIndex" ).attr( "tabindex" ), "-1", "anchor with href, tabindex set to -1" ); // anchor without href - equal( jQuery("#linkWithNoHrefWithNoTabIndex").attr("tabindex"), undefined, "anchor without href, no tabindex set" ); - equal( jQuery("#linkWithNoHrefWithTabIndex").attr("tabindex"), "1", "anchor without href, tabindex set to 2" ); - equal( jQuery("#linkWithNoHrefWithNegativeTabIndex").attr("tabindex"), "-1", "anchor without href, no tabindex set" ); -}); + assert.equal( jQuery( "#linkWithNoHrefWithNoTabIndex" ).attr( "tabindex" ), undefined, "anchor without href, no tabindex set" ); + assert.equal( jQuery( "#linkWithNoHrefWithTabIndex" ).attr( "tabindex" ), "1", "anchor without href, tabindex set to 2" ); + assert.equal( jQuery( "#linkWithNoHrefWithNegativeTabIndex" ).attr( "tabindex" ), "-1", "anchor without href, no tabindex set" ); +} ); -test( "attr('tabindex', value)", function() { - expect( 9 ); +QUnit.test( "attr('tabindex', value)", function( assert ) { + assert.expect( 9 ); - var element = jQuery("#divWithNoTabIndex"); - equal( element.attr("tabindex"), undefined, "start with no tabindex" ); + var element = jQuery( "#divWithNoTabIndex" ); + assert.equal( element.attr( "tabindex" ), undefined, "start with no tabindex" ); // set a positive string element.attr( "tabindex", "1" ); - equal( element.attr("tabindex"), "1", "set tabindex to 1 (string)" ); + assert.equal( element.attr( "tabindex" ), "1", "set tabindex to 1 (string)" ); // set a zero string element.attr( "tabindex", "0" ); - equal( element.attr("tabindex"), "0", "set tabindex to 0 (string)" ); + assert.equal( element.attr( "tabindex" ), "0", "set tabindex to 0 (string)" ); // set a negative string element.attr( "tabindex", "-1" ); - equal( element.attr("tabindex"), "-1", "set tabindex to -1 (string)" ); + assert.equal( element.attr( "tabindex" ), "-1", "set tabindex to -1 (string)" ); // set a positive number element.attr( "tabindex", 1 ); - equal( element.attr("tabindex"), "1", "set tabindex to 1 (number)" ); + assert.equal( element.attr( "tabindex" ), "1", "set tabindex to 1 (number)" ); // set a zero number element.attr( "tabindex", 0 ); - equal(element.attr("tabindex"), "0", "set tabindex to 0 (number)"); + assert.equal( element.attr( "tabindex" ), "0", "set tabindex to 0 (number)" ); // set a negative number element.attr( "tabindex", -1 ); - equal( element.attr("tabindex"), "-1", "set tabindex to -1 (number)" ); + assert.equal( element.attr( "tabindex" ), "-1", "set tabindex to -1 (number)" ); - element = jQuery("#linkWithTabIndex"); - equal( element.attr("tabindex"), "2", "start with tabindex 2" ); + element = jQuery( "#linkWithTabIndex" ); + assert.equal( element.attr( "tabindex" ), "2", "start with tabindex 2" ); element.attr( "tabindex", -1 ); - equal( element.attr("tabindex"), "-1", "set negative tabindex" ); -}); + assert.equal( element.attr( "tabindex" ), "-1", "set negative tabindex" ); +} ); -test( "removeAttr(String)", function() { - expect( 12 ); +QUnit.test( "removeAttr(String)", function( assert ) { + assert.expect( 12 ); var $first; - equal( jQuery("#mark").removeAttr("class").attr("class"), undefined, "remove class" ); - equal( jQuery("#form").removeAttr("id").attr("id"), undefined, "Remove id" ); - equal( jQuery("#foo").attr( "style", "position:absolute;" ).removeAttr("style").attr("style"), undefined, "Check removing style attribute" ); - equal( jQuery("#form").attr( "style", "position:absolute;" ).removeAttr("style").attr("style"), undefined, "Check removing style attribute on a form" ); - equal( jQuery("
").appendTo("#foo").removeAttr("style").prop("style").cssText, "", "Check removing style attribute (#9699 Webkit)" ); - equal( jQuery("#fx-test-group").attr( "height", "3px" ).removeAttr("height").get( 0 ).style.height, "1px", "Removing height attribute has no effect on height set with style attribute" ); - - jQuery("#check1").removeAttr("checked").prop( "checked", true ).removeAttr("checked"); - equal( document.getElementById("check1").checked, false, "removeAttr sets boolean properties to false" ); - jQuery("#text1").prop( "readOnly", true ).removeAttr("readonly"); - equal( document.getElementById("text1").readOnly, false, "removeAttr sets boolean properties to false" ); + assert.equal( jQuery( "#mark" ).removeAttr( "class" ).attr( "class" ), undefined, "remove class" ); + assert.equal( jQuery( "#form" ).removeAttr( "id" ).attr( "id" ), undefined, "Remove id" ); + assert.equal( jQuery( "#foo" ).attr( "style", "position:absolute;" ).removeAttr( "style" ).attr( "style" ), undefined, "Check removing style attribute" ); + assert.equal( jQuery( "#form" ).attr( "style", "position:absolute;" ).removeAttr( "style" ).attr( "style" ), undefined, "Check removing style attribute on a form" ); + assert.equal( jQuery( "
" ).appendTo( "#foo" ).removeAttr( "style" ).prop( "style" ).cssText, "", "Check removing style attribute (#9699 Webkit)" ); + assert.equal( jQuery( "#fx-test-group" ).attr( "height", "3px" ).removeAttr( "height" ).get( 0 ).style.height, "1px", "Removing height attribute has no effect on height set with style attribute" ); + + jQuery( "#check1" ).removeAttr( "checked" ).prop( "checked", true ).removeAttr( "checked" ); + assert.equal( document.getElementById( "check1" ).checked, true, "removeAttr should not set checked to false, since the checked attribute does NOT mirror the checked property" ); + jQuery( "#text1" ).prop( "readOnly", true ).removeAttr( "readonly" ); + assert.equal( document.getElementById( "text1" ).readOnly, false, "removeAttr sets boolean properties to false" ); - jQuery("#option2c").removeAttr("selected"); - equal( jQuery("#option2d").attr("selected"), "selected", "Removing `selected` from an option that is not selected does not remove selected from the currently selected option (#10870)" ); + jQuery( "#option2c" ).removeAttr( "selected" ); + assert.equal( jQuery( "#option2d" ).attr( "selected" ), "selected", "Removing `selected` from an option that is not selected does not remove selected from the currently selected option (#10870)" ); try { - $first = jQuery("#first").attr( "contenteditable", "true" ).removeAttr("contenteditable"); - equal( $first.attr("contenteditable"), undefined, "Remove the contenteditable attribute" ); - } catch( e ) { - ok( false, "Removing contenteditable threw an error (#10429)" ); + $first = jQuery( "#first" ).attr( "contenteditable", "true" ).removeAttr( "contenteditable" ); + assert.equal( $first.attr( "contenteditable" ), undefined, "Remove the contenteditable attribute" ); + } catch ( e ) { + assert.ok( false, "Removing contenteditable threw an error (#10429)" ); } - $first = jQuery("
"); - equal( $first.attr("Case"), "mixed", "case of attribute doesn't matter" ); - $first.removeAttr("Case"); - // IE 6/7 return empty string here, not undefined - ok( !$first.attr("Case"), "mixed-case attribute was removed" ); -}); + $first = jQuery( "
" ); + assert.equal( $first.attr( "Case" ), "mixed", "case of attribute doesn't matter" ); + $first.removeAttr( "Case" ); + assert.equal( $first.attr( "Case" ), undefined, "mixed-case attribute was removed" ); +} ); -test( "removeAttr(String) in XML", function() { - expect( 7 ); +QUnit.test( "removeAttr(String) in XML", function( assert ) { + assert.expect( 7 ); var xml = createDashboardXML(), iwt = jQuery( "infowindowtab", xml ); - equal( iwt.attr("normal"), "ab", "Check initial value" ); - iwt.removeAttr("Normal"); - equal( iwt.attr("normal"), "ab", "Should still be there" ); - iwt.removeAttr("normal"); - equal( iwt.attr("normal"), undefined, "Removed" ); - - equal( iwt.attr("mixedCase"), "yes", "Check initial value" ); - equal( iwt.attr("mixedcase"), undefined, "toLowerCase not work good" ); - iwt.removeAttr("mixedcase"); - equal( iwt.attr("mixedCase"), "yes", "Should still be there" ); - iwt.removeAttr("mixedCase"); - equal( iwt.attr("mixedCase"), undefined, "Removed" ); -}); + assert.equal( iwt.attr( "normal" ), "ab", "Check initial value" ); + iwt.removeAttr( "Normal" ); + assert.equal( iwt.attr( "normal" ), "ab", "Should still be there" ); + iwt.removeAttr( "normal" ); + assert.equal( iwt.attr( "normal" ), undefined, "Removed" ); + + assert.equal( iwt.attr( "mixedCase" ), "yes", "Check initial value" ); + assert.equal( iwt.attr( "mixedcase" ), undefined, "toLowerCase not work good" ); + iwt.removeAttr( "mixedcase" ); + assert.equal( iwt.attr( "mixedCase" ), "yes", "Should still be there" ); + iwt.removeAttr( "mixedCase" ); + assert.equal( iwt.attr( "mixedCase" ), undefined, "Removed" ); +} ); -test( "removeAttr(Multi String, variable space width)", function() { - expect( 8 ); +QUnit.test( "removeAttr(Multi String, variable space width)", function( assert ) { + assert.expect( 8 ); - var div = jQuery("
"), + var div = jQuery( "
" ), tests = { id: "a", alt: "b", @@ -629,804 +647,956 @@ }; jQuery.each( tests, function( key, val ) { - equal( div.attr( key ), val, "Attribute `" + key + "` exists, and has a value of `" + val + "`" ); - }); + assert.equal( div.attr( key ), val, "Attribute `" + key + "` exists, and has a value of `" + val + "`" ); + } ); div.removeAttr( "id alt title rel " ); jQuery.each( tests, function( key ) { - equal( div.attr( key ), undefined, "Attribute `" + key + "` was removed" ); - }); -}); - -test( "prop(String, Object)", function() { - expect( 17 ); - - equal( jQuery("#text1").prop("value"), "Test", "Check for value attribute" ); - equal( jQuery("#text1").prop( "value", "Test2" ).prop("defaultValue"), "Test", "Check for defaultValue attribute" ); - equal( jQuery("#select2").prop("selectedIndex"), 3, "Check for selectedIndex attribute" ); - equal( jQuery("#foo").prop("nodeName").toUpperCase(), "DIV", "Check for nodeName attribute" ); - equal( jQuery("#foo").prop("tagName").toUpperCase(), "DIV", "Check for tagName attribute" ); - equal( jQuery("").val(), + assert.strictEqual( + jQuery( "" ).val(), null, "Select-one with only option disabled (#12584)" ); if ( jQuery.fn.serialize ) { - checks = jQuery("").appendTo("#form"); + checks = jQuery( "" ).appendTo( "#form" ); - deepEqual( checks.serialize(), "", "Get unchecked values." ); + assert.deepEqual( checks.serialize(), "", "Get unchecked values." ); - equal( checks.eq( 3 ).val(), "on", "Make sure a value of 'on' is provided if none is specified." ); + assert.equal( checks.eq( 3 ).val(), "on", "Make sure a value of 'on' is provided if none is specified." ); - checks.val([ "2" ]); - deepEqual( checks.serialize(), "test=2", "Get a single checked value." ); + checks.val( [ "2" ] ); + assert.deepEqual( checks.serialize(), "test=2", "Get a single checked value." ); - checks.val([ "1", "" ]); - deepEqual( checks.serialize(), "test=1&test=", "Get multiple checked values." ); + checks.val( [ "1", "" ] ); + assert.deepEqual( checks.serialize(), "test=1&test=", "Get multiple checked values." ); - checks.val([ "", "2" ]); - deepEqual( checks.serialize(), "test=2&test=", "Get multiple checked values." ); + checks.val( [ "", "2" ] ); + assert.deepEqual( checks.serialize(), "test=2&test=", "Get multiple checked values." ); - checks.val([ "1", "on" ]); - deepEqual( checks.serialize(), "test=1&test=on", "Get multiple checked values." ); + checks.val( [ "1", "on" ] ); + assert.deepEqual( checks.serialize(), "test=1&test=on", "Get multiple checked values." ); checks.remove(); } - $button = jQuery("").insertAfter("#button"); - equal( $button.val(), "foobar", "Value retrieval on a button does not return innerHTML" ); - equal( $button.val("baz").html(), "text", "Setting the value does not change innerHTML" ); + $button = jQuery( "" ).insertAfter( "#button" ); + assert.equal( $button.val(), "foobar", "Value retrieval on a button does not return innerHTML" ); + assert.equal( $button.val( "baz" ).html(), "text", "Setting the value does not change innerHTML" ); - equal( jQuery(""); + $select1.append( "" ); $select1.val( valueObj( 4 ) ); - equal( $select1.val(), "4", "Should be possible to set the val() to a newly created option" ); + 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 = jQuery( "#nonnodes" ).contents(); j.val( valueObj( "asdf" ) ); - equal( j.val(), "asdf", "Check node,textnode,comment with val()" ); - j.removeAttr("value"); + assert.equal( j.val(), "asdf", "Check node,textnode,comment with val()" ); + j.removeAttr( "value" ); $select.val( valueObj( [ "1", "2" ] ) ); - deepEqual( $select.val(), [ "1", "2" ], "Should set array of values" ); + assert.deepEqual( $select.val(), [ "1", "2" ], "Should set array of values" ); }; -test( "val(String/Number)", function() { - testVal( bareObj ); -}); - -test( "val(Function)", function() { - testVal( functionReturningObj ); -}); - -test( "val(Array of Numbers) (Bug #7123)", function() { - expect( 4 ); - jQuery("#form").append(""); - var elements = jQuery("input[name=arrayTest]").val([ 1, 2 ]); - ok( elements[ 0 ].checked, "First element was checked" ); - ok( elements[ 1 ].checked, "Second element was checked" ); - ok( !elements[ 2 ].checked, "Third element was unchecked" ); - ok( !elements[ 3 ].checked, "Fourth element remained unchecked" ); +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( "#form 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(); -}); +} ); -test( "val(Function) with incoming value", function() { - expect( 10 ); +QUnit.test( "val(Function) with incoming value", function( assert ) { + assert.expect( 10 ); - var oldVal = jQuery("#text1").val(); + var oldVal = jQuery( "#text1" ).val(); - jQuery("#text1").val(function( i, val ) { - equal( val, oldVal, "Make sure the incoming value is correct." ); + jQuery( "#text1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); return "test"; - }); + } ); - equal( document.getElementById("text1").value, "test", "Check for modified (via val(String)) value of input element" ); + assert.equal( document.getElementById( "text1" ).value, "test", "Check for modified (via val(String)) value of input element" ); - oldVal = jQuery("#text1").val(); + oldVal = jQuery( "#text1" ).val(); - jQuery("#text1").val(function( i, val ) { - equal( val, oldVal, "Make sure the incoming value is correct." ); + jQuery( "#text1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); return 67; - }); + } ); - equal( document.getElementById("text1").value, "67", "Check for modified (via val(Number)) value of input element" ); + assert.equal( document.getElementById( "text1" ).value, "67", "Check for modified (via val(Number)) value of input element" ); - oldVal = jQuery("#select1").val(); + oldVal = jQuery( "#select1" ).val(); - jQuery("#select1").val(function( i, val ) { - equal( val, oldVal, "Make sure the incoming value is correct." ); + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); return "3"; - }); + } ); - equal( jQuery("#select1").val(), "3", "Check for modified (via val(String)) value of select element" ); + assert.equal( jQuery( "#select1" ).val(), "3", "Check for modified (via val(String)) value of select element" ); - oldVal = jQuery("#select1").val(); + oldVal = jQuery( "#select1" ).val(); - jQuery("#select1").val(function( i, val ) { - equal( val, oldVal, "Make sure the incoming value is correct." ); + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); return 2; - }); + } ); - equal( jQuery("#select1").val(), "2", "Check for modified (via val(Number)) value of select element" ); + assert.equal( jQuery( "#select1" ).val(), "2", "Check for modified (via val(Number)) value of select element" ); - jQuery("#select1").append(""); + jQuery( "#select1" ).append( "" ); - oldVal = jQuery("#select1").val(); + oldVal = jQuery( "#select1" ).val(); - jQuery("#select1").val(function( i, val ) { - equal( val, oldVal, "Make sure the incoming value is correct." ); + jQuery( "#select1" ).val( function( i, val ) { + assert.equal( val, oldVal, "Make sure the incoming value is correct." ); return 4; - }); + } ); - equal( jQuery("#select1").val(), "4", "Should be possible to set the val() to a newly created option" ); -}); + 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) -test( "val(select) after form.reset() (Bug #2551)", function() { - expect( 3 ); +QUnit.test( "val(select) after form.reset() (Bug #2551)", function( assert ) { + assert.expect( 3 ); - jQuery("").appendTo("#qunit-fixture"); + jQuery( "" ).appendTo( "#qunit-fixture" ); - jQuery("#kkk").val("gf"); + jQuery( "#kkk" ).val( "gf" ); - document["kk"].reset(); + document[ "kk" ].reset(); - equal( jQuery("#kkk")[ 0 ].value, "cf", "Check value of select after form reset." ); - equal( jQuery("#kkk").val(), "cf", "Check value of select after form 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 - deepEqual( jQuery("#select3").val(), ["1", "2"], "Call val() on a multiple='multiple' select" ); + assert.deepEqual( jQuery( "#select3" ).val(), [ "1", "2" ], "Call val() on a multiple='multiple' select" ); - jQuery("#kk").remove(); -}); + jQuery( "#kk" ).remove(); +} ); -var testAddClass = function( valueObj ) { - expect( 9 ); +QUnit.test( "select.val(space characters) (gh-2978)", function( assert ) { + assert.expect( 37 ); - var pass, j, i, - div = jQuery("#qunit-fixture div"); + var $select = jQuery( "" ).val( "2" ).val(), "2" ); +} ); -test( "Insignificant white space returned for $(option).val() (#14858)", function() { - expect ( 3 ); +QUnit.test( "Insignificant white space returned for $(option).val() (#14858, gh-2978)", function( assert ) { + assert.expect( 16 ); var val = jQuery( "" ).val(); - equal( val.length, 0, "Empty option should have no value" ); + assert.equal( val.length, 0, "Empty option should have no value" ); + + jQuery.each( [ " ", "\n", "\t", "\f", "\r" ], function( i, character ) { + var 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" ); + + val = jQuery( "" ).val(); + assert.equal( val, "te st", "Whitespace is collapsed in values" ); + } ); +} ); - val = jQuery( "" ).val(); - equal( val.length, 0, "insignificant white-space returned for value" ); +QUnit.test( "SVG class manipulation (gh-2199)", function( assert ) { + assert.expect( 12 ); - val = jQuery( "" ).val(); - equal( val.length, 4, "insignificant white-space returned for value" ); -}); + 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" ); + } ); +} ); + +QUnit.test( "non-lowercase boolean attribute getters should not crash", function( assert ) { + assert.expect( 3 ); + + var elem = jQuery( "" ); + + jQuery.each( { + checked: "Checked", + required: "requiRed", + autofocus: "AUTOFOCUS" + }, function( lowercased, original ) { + try { + assert.strictEqual( elem.attr( original ), lowercased, + "The '" + this + "' attribute getter should return the lowercased name" ); + } catch ( e ) { + assert.ok( false, "The '" + this + "' attribute getter threw" ); + } + } ); +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/basic.js jquery-3.2.1/test/unit/basic.js --- jquery-1.11.3+dfsg/test/unit/basic.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/unit/basic.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,293 @@ +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( 1 ); + + var div = jQuery( "
" ).appendTo( "#qunit-fixture" ); + + assert.strictEqual( div.css( "width", "50px" ).css( "width" ), "50px", ".css getter/setter" ); +} ); +} + +if ( jQuery.fn.show && jQuery.fn.hide ) { +QUnit.test( "show/hide", function( assert ) { + assert.expect( 2 ); + + var div = jQuery( "
" ).appendTo( "#qunit-fixture" ); + + 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( 27 ); + + 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" ); +} ); + +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( + elem1.html( "" ).html(), + "", + ".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( + elem1.html(), + "
", + ".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( + elem.html(), + "", + ".wrap" + ); + + elem.find( "span" ).wrapInner( "" ); + + assert.strictEqual( + elem.html(), + "", + ".wrapInner" + ); + + elem.find( "a" ).wrapAll( "" ); + + assert.strictEqual( + elem.html(), + "", + ".wrapAll" + ); + +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/callbacks.js jquery-3.2.1/test/unit/callbacks.js --- jquery-1.11.3+dfsg/test/unit/callbacks.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/callbacks.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,8 +1,8 @@ -module( "callbacks", { +QUnit.module( "callbacks", { teardown: moduleTeardown -}); +} ); -(function() { +( function() { var output, addToOutput = function( string ) { @@ -10,9 +10,9 @@ output += string; }; }, - outputA = addToOutput("A"), - outputB = addToOutput("B"), - outputC = addToOutput("C"), + 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", @@ -54,22 +54,18 @@ if ( this.length ) { objectFlags[ this ] = true; } - }); + } ); jQuery.each( filters, function( filterLabel ) { - jQuery.each({ + jQuery.each( { "string": strFlags, "object": objectFlags }, function( flagsTypes, flags ) { - test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function() { + QUnit.test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function( assert ) { - expect( 21 ); - - // Give qunit a little breathing room - stop(); - setTimeout( start, 0 ); + assert.expect( 29 ); var cblist, results = resultString.split( /\s+/ ); @@ -77,26 +73,32 @@ // Basic binding and firing output = "X"; cblist = jQuery.Callbacks( flags ); - cblist.add(function( str ) { + 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; - }); - cblist.fire("A"); - strictEqual( output, "XA", "Basic binding and firing" ); - strictEqual( cblist.fired(), true, ".fired() detects firing" ); + } ); + 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 ) { + cblist.add( function( str ) { output += str; - }); - strictEqual( output, "X", "Adding a callback after disabling" ); - cblist.fire("A"); - strictEqual( output, "X", "Firing after disabling" ); + } ); + 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" ); - // #13517 - Emptying while firing + // Emptying while firing (#13517) cblist = jQuery.Callbacks( flags ); cblist.add( cblist.empty ); cblist.add( function() { - ok( false, "not emptied" ); + assert.ok( false, "not emptied" ); } ); cblist.fire(); @@ -104,27 +106,27 @@ cblist = jQuery.Callbacks( flags ); cblist.add( cblist.disable ); cblist.add( function() { - ok( false, "not disabled" ); + assert.ok( false, "not disabled" ); } ); cblist.fire(); // Basic binding and firing (context, arguments) output = "X"; cblist = jQuery.Callbacks( flags ); - cblist.add(function() { - equal( this, window, "Basic binding and firing (context)" ); + cblist.add( function() { + assert.equal( this, window, "Basic binding and firing (context)" ); output += Array.prototype.join.call( arguments, "" ); - }); + } ); cblist.fireWith( window, [ "A", "B" ] ); - strictEqual( output, "XAB", "Basic binding and firing (arguments)" ); + assert.strictEqual( output, "XAB", "Basic binding and firing (arguments)" ); // fireWith with no arguments output = ""; cblist = jQuery.Callbacks( flags ); - cblist.add(function() { - equal( this, window, "fireWith with no arguments (context is window)" ); - strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" ); - }); + 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 @@ -133,7 +135,7 @@ cblist.add( outputA, outputB, outputC ); cblist.remove( outputB, outputC ); cblist.fire(); - strictEqual( output, "XA", "Basic binding, removing and firing" ); + assert.strictEqual( output, "XA", "Basic binding, removing and firing" ); // Empty output = "X"; @@ -143,67 +145,78 @@ cblist.add( outputC ); cblist.empty(); cblist.fire(); - strictEqual( output, "X", "Empty" ); + assert.strictEqual( output, "X", "Empty" ); // Locking output = "X"; cblist = jQuery.Callbacks( flags ); - cblist.add(function( str ) { + cblist.add( function( str ) { output += str; - }); + } ); cblist.lock(); - cblist.add(function( str ) { + cblist.add( function( str ) { + output += str; + } ); + cblist.fire( "A" ); + cblist.add( function( str ) { output += str; - }); - cblist.fire("A"); - cblist.add(function( str ) { + } ); + assert.strictEqual( output, "X", "Lock early" ); + assert.strictEqual( cblist.locked(), true, "Locking reflected in accessor" ); + + // Locking while firing (gh-1990) + output = "X"; + cblist = jQuery.Callbacks( flags ); + cblist.add( cblist.lock ); + cblist.add( function( str ) { output += str; - }); - strictEqual( output, "X", "Lock early" ); + } ); + cblist.fire( "A" ); + assert.strictEqual( output, "XA", "Locking doesn't abort execution (gh-1990)" ); // Ordering output = "X"; cblist = jQuery.Callbacks( flags ); - cblist.add(function() { + cblist.add( function() { cblist.add( outputC ); outputA(); }, outputB ); cblist.fire(); - strictEqual( output, results.shift(), "Proper ordering" ); + assert.strictEqual( output, results.shift(), "Proper ordering" ); // Add and fire again output = "X"; - cblist.add(function() { + cblist.add( function() { cblist.add( outputC ); outputA(); }, outputB ); - strictEqual( output, results.shift(), "Add after fire" ); + assert.strictEqual( output, results.shift(), "Add after fire" ); output = "X"; cblist.fire(); - strictEqual( output, results.shift(), "Fire again" ); + assert.strictEqual( output, results.shift(), "Fire again" ); // Multiple fire output = "X"; cblist = jQuery.Callbacks( flags ); - cblist.add(function( str ) { + cblist.add( function( str ) { output += str; - }); - cblist.fire("A"); - strictEqual( output, "XA", "Multiple fire (first fire)" ); + } ); + cblist.fire( "A" ); + assert.strictEqual( output, "XA", "Multiple fire (first fire)" ); output = "X"; - cblist.add(function( str ) { + cblist.add( function( str ) { output += str; - }); - strictEqual( output, results.shift(), "Multiple fire (first new callback)" ); + } ); + assert.strictEqual( output, results.shift(), "Multiple fire (first new callback)" ); output = "X"; - cblist.fire("B"); - strictEqual( output, results.shift(), "Multiple fire (second fire)" ); + cblist.fire( "B" ); + assert.strictEqual( output, results.shift(), "Multiple fire (second fire)" ); output = "X"; - cblist.add(function( str ) { + cblist.add( function( str ) { output += str; - }); - strictEqual( output, results.shift(), "Multiple fire (second new callback)" ); + } ); + assert.strictEqual( output, results.shift(), "Multiple fire (second new callback)" ); // Return false output = "X"; @@ -211,12 +224,12 @@ cblist.add( outputA, function() { return false; }, outputB ); cblist.add( outputA ); cblist.fire(); - strictEqual( output, results.shift(), "Callback returning false" ); + 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 ); - strictEqual( output, results.shift(), "Adding a callback after one returned false" ); + assert.strictEqual( output, results.shift(), "Adding a callback after one returned false" ); // Callbacks are not iterated output = ""; @@ -230,17 +243,17 @@ cblist.add( handler ); cblist.add( handler ); cblist.fire(); - strictEqual( output, results.shift(), "No callback iteration" ); - }); - }); - }); -}); + assert.strictEqual( output, results.shift(), "No callback iteration" ); + } ); + } ); + } ); +} ); -})(); +} )(); -test( "jQuery.Callbacks( options ) - options are copied", function() { +QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert ) { - expect( 1 ); + assert.expect( 1 ); var options = { "unique": true @@ -248,46 +261,46 @@ cb = jQuery.Callbacks( options ), count = 0, fn = function() { - ok( !( count++ ), "called once" ); + assert.ok( !( count++ ), "called once" ); }; - options["unique"] = false; + options[ "unique" ] = false; cb.add( fn, fn ); cb.fire(); -}); +} ); -test( "jQuery.Callbacks.fireWith - arguments are copied", function() { +QUnit.test( "jQuery.Callbacks.fireWith - arguments are copied", function( assert ) { - expect( 1 ); + assert.expect( 1 ); - var cb = jQuery.Callbacks("memory"), - args = ["hello"]; + var cb = jQuery.Callbacks( "memory" ), + args = [ "hello" ]; cb.fireWith( null, args ); args[ 0 ] = "world"; - cb.add(function( hello ) { - strictEqual( hello, "hello", "arguments are copied internally" ); - }); -}); + cb.add( function( hello ) { + assert.strictEqual( hello, "hello", "arguments are copied internally" ); + } ); +} ); -test( "jQuery.Callbacks.remove - should remove all instances", function() { +QUnit.test( "jQuery.Callbacks.remove - should remove all instances", function( assert ) { - expect( 1 ); + assert.expect( 1 ); var cb = jQuery.Callbacks(); function fn() { - ok( false, "function wasn't removed" ); + assert.ok( false, "function wasn't removed" ); } cb.add( fn, fn, function() { - ok( true, "end of test" ); - }).remove( fn ).fire(); -}); + assert.ok( true, "end of test" ); + } ).remove( fn ).fire(); +} ); -test( "jQuery.Callbacks.has", function() { +QUnit.test( "jQuery.Callbacks.has", function( assert ) { - expect( 13 ); + assert.expect( 13 ); var cb = jQuery.Callbacks(); function getA() { @@ -299,44 +312,78 @@ function getC() { return "C"; } - cb.add(getA, getB, getC); - strictEqual( cb.has(), true, "No arguments to .has() returns whether callback function(s) are attached or not" ); - strictEqual( cb.has(getA), true, "Check if a specific callback function is in the Callbacks list" ); - - cb.remove(getB); - strictEqual( cb.has(getB), false, "Remove a specific callback function and make sure its no longer there" ); - strictEqual( cb.has(getA), true, "Remove a specific callback function and make sure other callback function is still there" ); + 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(); - strictEqual( cb.has(), false, "Empty list and make sure there are no callback function(s)" ); - strictEqual( cb.has(getA), false, "Check for a specific function in an empty() list" ); + 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(){ - strictEqual( cb.has(), true, "Check if list has callback function(s) from within a callback function" ); - strictEqual( cb.has(getA), true, "Check if list has a specific callback from within a callback function" ); - }).fire(); + 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(); - strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" ); + assert.strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" ); cb.disable(); - strictEqual( cb.has(), false, "disabled() list has no callback functions (returns false)" ); - strictEqual( cb.has(getA), false, "Check for a specific function in a disabled() list" ); + 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); - strictEqual( cb.has(), true, "Check if unique list has callback function(s) attached" ); + 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(); - strictEqual( cb.has(), false, "locked() list is empty and returns false" ); + 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 ); -test( "jQuery.Callbacks() - adding a string doesn't cause a stack overflow", function() { + jQuery.Callbacks().add( "hello world" ); - expect( 1 ); + assert.ok( true, "no stack overflow" ); +} ); - jQuery.Callbacks().add( "hello world" ); +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" ); +} ); + +QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", function( assert ) { + + assert.expect( 3 ); - ok( true, "no stack overflow" ); -}); + var cb = jQuery.Callbacks( "memory" ), + fired = 0, + count1 = function() { fired += 1; }, + count2 = function() { fired += 10; }; + + cb.add( count1 ); + cb.fire(); + assert.equal( fired, 1, "Pre-lock() fire" ); + + cb.lock(); + cb.add( count2 ); + assert.equal( fired, 11, "Post-lock() add" ); + + cb.fire(); + assert.equal( fired, 11, "Post-lock() fire ignored" ); +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/core.js jquery-3.2.1/test/unit/core.js --- jquery-1.11.3+dfsg/test/unit/core.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/core.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,32 +1,33 @@ -module("core", { teardown: moduleTeardown }); - -test("Unit Testing Environment", function () { - expect(2); - ok( hasPHP, "Running in an environment with PHP support. The AJAX tests only run if the environment supports PHP!" ); - 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!)" ); -}); - -test("Basic requirements", function() { - expect(7); - ok( Array.prototype.push, "Array.push()" ); - ok( Function.prototype.apply, "Function.apply()" ); - ok( document.getElementById, "getElementById" ); - ok( document.getElementsByTagName, "getElementsByTagName" ); - ok( RegExp, "RegExp" ); - ok( jQuery, "jQuery" ); - ok( $, "$" ); -}); +QUnit.module( "core", { + setup: function() { + this.sandbox = sinon.sandbox.create(); + }, + teardown: function() { + this.sandbox.restore(); + return moduleTeardown.apply( this, arguments ); + } +} ); + +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( $, "$" ); +} ); -test("jQuery()", function() { +QUnit.test( "jQuery()", function( assert ) { var elem, i, - obj = jQuery("div"), - code = jQuery(""), - img = jQuery(""), - div = jQuery("

"), + obj = jQuery( "div" ), + code = jQuery( "" ), + img = jQuery( "" ), + div = jQuery( "

" ), exec = false, - lng = "", - expected = 22, + expected = 23, attrObj = { "text": "test", "class": "test2", @@ -37,38 +38,43 @@ // few here but beware of modular builds where these methods may be excluded. if ( jQuery.fn.click ) { expected++; - attrObj["click"] = function() { ok( exec, "Click executed." ); }; + attrObj[ "click" ] = function() { assert.ok( exec, "Click executed." ); }; } if ( jQuery.fn.width ) { expected++; - attrObj["width"] = 10; + attrObj[ "width" ] = 10; } if ( jQuery.fn.offset ) { expected++; - attrObj["offset"] = { "top": 1, "left": 1 }; + attrObj[ "offset" ] = { "top": 1, "left": 1 }; } if ( jQuery.fn.css ) { expected += 2; - attrObj["css"] = { "paddingLeft": 1, "paddingRight": 1 }; + attrObj[ "css" ] = { "paddingLeft": 1, "paddingRight": 1 }; } if ( jQuery.fn.attr ) { expected++; attrObj.attr = { "desired": "very" }; } - expect( expected ); + assert.expect( expected ); // Basic constructor's behavior - equal( jQuery().length, 0, "jQuery() === jQuery([])" ); - equal( jQuery(undefined).length, 0, "jQuery(undefined) === jQuery([])" ); - equal( jQuery(null).length, 0, "jQuery(null) === jQuery([])" ); - equal( jQuery("").length, 0, "jQuery('') === jQuery([])" ); - equal( jQuery("#").length, 0, "jQuery('#') === jQuery([])" ); + 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.deepEqual( jQuery( obj ).get(), obj.get(), "jQuery(jQueryObj) == jQueryObj" ); - equal( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" ); + // Invalid #id goes to Sizzle which will throw an error (gh-1682) + try { + jQuery( "#" ); + } catch ( e ) { + assert.ok( true, "Threw an error on #id with no id" ); + } // can actually yield more than one, when iframes are included, the window is an array as well - equal( jQuery(window).length, 1, "Correct number of elements generated for jQuery(window)" ); + 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 @@ -76,7 +82,7 @@ // make sure this is handled var crlfContainer = jQuery('

\r\n

'); var x = crlfContainer.contents().get(0).nodeValue; - equal( x, what???, "Check for \\r and \\n in jQuery()" ); + assert.equal( x, what???, "Check for \\r and \\n in jQuery()" ); */ /* // Disabled until we add this functionality in @@ -86,383 +92,407 @@ } catch(e){ pass = false; } - ok( pass, "jQuery('<tag>') needs optional document parameter to ease cross-frame DOM wrangling, see #968" );*/ + assert.ok( pass, "jQuery('<tag>') needs optional document parameter to ease cross-frame DOM wrangling, see #968" );*/ - equal( code.length, 1, "Correct number of elements generated for code" ); - equal( code.parent().length, 0, "Make sure that the generated HTML has no parent." ); + 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." ); - equal( img.length, 1, "Correct number of elements generated for img" ); - equal( img.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." ); - equal( div.length, 4, "Correct number of elements generated for div hr code b" ); - equal( div.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." ); - equal( jQuery([1,2,3]).get(1), 2, "Test passing an array to the factory" ); + assert.equal( jQuery( [ 1, 2, 3 ] ).get( 1 ), 2, "Test passing an array to the factory" ); - equal( jQuery(document.body).get(0), jQuery("body").get(0), "Test passing an html node 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]; - equal( elem.nodeName.toLowerCase(), "em", "leading space" ); + elem = jQuery( " hello" )[ 0 ]; + assert.equal( elem.nodeName.toLowerCase(), "em", "leading space" ); - elem = jQuery("\n\nworld")[0]; - equal( elem.nodeName.toLowerCase(), "em", "leading newlines" ); + elem = jQuery( "\n\nworld" )[ 0 ]; + assert.equal( elem.nodeName.toLowerCase(), "em", "leading newlines" ); - elem = jQuery("
", attrObj ); + elem = jQuery( "
", attrObj ); if ( jQuery.fn.width ) { - equal( elem[0].style.width, "10px", "jQuery() quick setter width"); + assert.equal( elem[ 0 ].style.width, "10px", "jQuery() quick setter width" ); } if ( jQuery.fn.offset ) { - equal( elem[0].style.top, "1px", "jQuery() quick setter offset"); + assert.equal( elem[ 0 ].style.top, "1px", "jQuery() quick setter offset" ); } if ( jQuery.fn.css ) { - equal( elem[0].style.paddingLeft, "1px", "jQuery quick setter css"); - equal( elem[0].style.paddingRight, "1px", "jQuery quick setter 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 ) { - equal( elem[0].getAttribute("desired"), "very", "jQuery quick setter attr"); + assert.equal( elem[ 0 ].getAttribute( "desired" ), "very", "jQuery quick setter attr" ); } - equal( elem[0].childNodes.length, 1, "jQuery quick setter text"); - equal( elem[0].firstChild.nodeValue, "test", "jQuery quick setter text"); - equal( elem[0].className, "test2", "jQuery() quick setter class"); - equal( elem[0].id, "test3", "jQuery() quick setter id"); + 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"); + elem.trigger( "click" ); // manually clean up detached elements elem.remove(); for ( i = 0; i < 3; ++i ) { - elem = jQuery(""); - } - equal( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); - - // manually clean up detached elements - elem.remove(); - - for ( i = 0; i < 128; i++ ) { - lng += "12345678"; + elem = jQuery( "" ); } -}); - -test("jQuery(selector, context)", function() { - expect(3); - deepEqual( jQuery("div p", "#qunit-fixture").get(), q("sndp", "en", "sap"), "Basic selector with string as context" ); - deepEqual( jQuery("div p", q("qunit-fixture")[0]).get(), q("sndp", "en", "sap"), "Basic selector with element as context" ); - deepEqual( jQuery("div p", jQuery("#qunit-fixture")).get(), q("sndp", "en", "sap"), "Basic selector with jQuery object as context" ); -}); - -test( "selector state", function() { - expect( 18 ); - - var test; + assert.equal( elem[ 0 ].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" ); - test = jQuery( undefined ); - equal( test.selector, "", "Empty jQuery Selector" ); - equal( test.context, undefined, "Empty jQuery Context" ); + elem = jQuery( "", {} ); + assert.strictEqual( elem[ 0 ].ownerDocument, document, + "Empty attributes object is not interpreted as a document (trac-8950)" ); +} ); - test = jQuery( document ); - equal( test.selector, "", "Document Selector" ); - equal( test.context, document, "Document Context" ); +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" ); +} ); - test = jQuery( document.body ); - equal( test.selector, "", "Body Selector" ); - equal( test.context, document.body, "Body Context" ); +QUnit.test( "globalEval", function( assert ) { + assert.expect( 3 ); + Globals.register( "globalEvalTest" ); - test = jQuery("#qunit-fixture"); - equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" ); - equal( test.context, document, "#qunit-fixture Context" ); + jQuery.globalEval( "globalEvalTest = 1;" ); + assert.equal( window.globalEvalTest, 1, "Test variable assignments are global" ); - test = jQuery("#notfoundnono"); - equal( test.selector, "#notfoundnono", "#notfoundnono Selector" ); - equal( test.context, document, "#notfoundnono Context" ); + jQuery.globalEval( "var globalEvalTest = 2;" ); + assert.equal( window.globalEvalTest, 2, "Test variable declarations are global" ); - test = jQuery( "#qunit-fixture", document ); - equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" ); - equal( test.context, document, "#qunit-fixture Context" ); + jQuery.globalEval( "this.globalEvalTest = 3;" ); + assert.equal( window.globalEvalTest, 3, "Test context (this) is the window object" ); +} ); - test = jQuery( "#qunit-fixture", document.body ); - equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" ); - equal( test.context, document.body, "#qunit-fixture Context" ); +QUnit.test( "globalEval with 'use strict'", function( assert ) { + assert.expect( 1 ); + Globals.register( "strictEvalTest" ); - // Test cloning - test = jQuery( test ); - equal( test.selector, "#qunit-fixture", "#qunit-fixture Selector" ); - equal( test.context, document.body, "#qunit-fixture Context" ); + jQuery.globalEval( "'use strict'; var strictEvalTest = 1;" ); + assert.equal( window.strictEvalTest, 1, "Test variable declarations are global (strict mode)" ); +} ); - test = jQuery( document.body ).find("#qunit-fixture"); - equal( test.selector, "#qunit-fixture", "#qunit-fixture find Selector" ); - equal( test.context, document.body, "#qunit-fixture find Context" ); -}); +QUnit.test( "globalEval execution after script injection (#7862)", function( assert ) { + assert.expect( 1 ); -test( "globalEval", function() { - expect( 3 ); - Globals.register("globalEvalTest"); + var now, + script = document.createElement( "script" ); - jQuery.globalEval("globalEvalTest = 1;"); - equal( window.globalEvalTest, 1, "Test variable assignments are global" ); + script.src = "data/longLoadScript.php?sleep=2"; - jQuery.globalEval("var globalEvalTest = 2;"); - equal( window.globalEvalTest, 2, "Test variable declarations are global" ); + now = jQuery.now(); + document.body.appendChild( script ); - jQuery.globalEval("this.globalEvalTest = 3;"); - equal( window.globalEvalTest, 3, "Test context (this) is the window object" ); -}); + jQuery.globalEval( "var strictEvalTest = " + jQuery.now() + ";" ); + assert.ok( window.strictEvalTest - now < 500, "Code executed synchronously" ); +} ); -test("noConflict", function() { - expect(7); +QUnit.test( "noConflict", function( assert ) { + assert.expect( 7 ); var $$ = jQuery; - strictEqual( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" ); - strictEqual( window["jQuery"], $$, "Make sure jQuery wasn't touched." ); - strictEqual( window["$"], original$, "Make sure $ was reverted." ); + 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 = $ = $$; - strictEqual( jQuery.noConflict(true), $$, "noConflict returned the jQuery object" ); - strictEqual( window["jQuery"], originaljQuery, "Make sure jQuery was reverted." ); - strictEqual( window["$"], original$, "Make sure $ was reverted." ); - ok( $$().pushStack([]), "Make sure that jQuery still works." ); - - window["jQuery"] = jQuery = $$; -}); - -test("trim", function() { - expect(13); - - var nbsp = String.fromCharCode(160); - - equal( jQuery.trim("hello "), "hello", "trailing space" ); - equal( jQuery.trim(" hello"), "hello", "leading space" ); - equal( jQuery.trim(" hello "), "hello", "space on both sides" ); - equal( jQuery.trim(" " + nbsp + "hello " + nbsp + " "), "hello", " " ); - - equal( jQuery.trim(), "", "Nothing in." ); - equal( jQuery.trim( undefined ), "", "Undefined" ); - equal( jQuery.trim( null ), "", "Null" ); - equal( jQuery.trim( 5 ), "5", "Number" ); - equal( jQuery.trim( false ), "false", "Boolean" ); - - equal( jQuery.trim(" "), "", "space should be trimmed" ); - equal( jQuery.trim("ipad\xA0"), "ipad", "nbsp should be trimmed" ); - equal( jQuery.trim("\uFEFF"), "", "zwsp should be trimmed" ); - equal( jQuery.trim("\uFEFF \xA0! | \uFEFF"), "! |", "leading/trailing should be trimmed" ); -}); - -test("type", function() { - expect( 28 ); - - equal( jQuery.type(null), "null", "null" ); - equal( jQuery.type(undefined), "undefined", "undefined" ); - equal( jQuery.type(true), "boolean", "Boolean" ); - equal( jQuery.type(false), "boolean", "Boolean" ); - equal( jQuery.type(Boolean(true)), "boolean", "Boolean" ); - equal( jQuery.type(0), "number", "Number" ); - equal( jQuery.type(1), "number", "Number" ); - equal( jQuery.type(Number(1)), "number", "Number" ); - equal( jQuery.type(""), "string", "String" ); - equal( jQuery.type("a"), "string", "String" ); - equal( jQuery.type(String("a")), "string", "String" ); - equal( jQuery.type({}), "object", "Object" ); - equal( jQuery.type(/foo/), "regexp", "RegExp" ); - equal( jQuery.type(new RegExp("asdf")), "regexp", "RegExp" ); - equal( jQuery.type([1]), "array", "Array" ); - equal( jQuery.type(new Date()), "date", "Date" ); - equal( jQuery.type(new Function("return;")), "function", "Function" ); - equal( jQuery.type(function(){}), "function", "Function" ); - equal( jQuery.type(new Error()), "error", "Error" ); - equal( jQuery.type(window), "object", "Window" ); - equal( jQuery.type(document), "object", "Document" ); - equal( jQuery.type(document.body), "object", "Element" ); - equal( jQuery.type(document.createTextNode("foo")), "object", "TextNode" ); - equal( jQuery.type(document.getElementsByTagName("*")), "object", "NodeList" ); + 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; - equal( jQuery.type(new MyBoolean(true)), "boolean", "Boolean" ); - equal( jQuery.type(new MyNumber(1)), "number", "Number" ); - equal( jQuery.type(new MyString("a")), "string", "String" ); - equal( jQuery.type(new MyObject()), "object", "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" ); +} ); -asyncTest("isPlainObject", function() { - expect(16); +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" ); +} ); - var pass, iframe, doc, +QUnit.asyncTest( "isPlainObject", function( assert ) { + + assert.expect( 23 ); + + var pass, iframe, doc, parentObj, childObj, deep, fn = function() {}; // The use case that we want to match - ok( jQuery.isPlainObject({}), "{}" ); + assert.ok( jQuery.isPlainObject( {} ), "{}" ); + assert.ok( jQuery.isPlainObject( new window.Object() ), "new Object" ); + assert.ok( jQuery.isPlainObject( { constructor: fn } ), + "plain object with constructor property" ); + assert.ok( jQuery.isPlainObject( { constructor: "foo" } ), + "plain object with primitive constructor property" ); + + parentObj = {}; + childObj = Object.create( parentObj ); + assert.ok( !jQuery.isPlainObject( childObj ), "Object.create({})" ); + parentObj.foo = "bar"; + assert.ok( !jQuery.isPlainObject( childObj ), "Object.create({...})" ); + childObj.bar = "foo"; + assert.ok( !jQuery.isPlainObject( childObj ), "extend(Object.create({...}), ...)" ); // Not objects shouldn't be matched - ok( !jQuery.isPlainObject(""), "string" ); - ok( !jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number" ); - ok( !jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean" ); - ok( !jQuery.isPlainObject(null), "null" ); - ok( !jQuery.isPlainObject(undefined), "undefined" ); + 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 - ok( !jQuery.isPlainObject([]), "array" ); + assert.ok( !jQuery.isPlainObject( [] ), "array" ); // Instantiated objects shouldn't be matched - ok( !jQuery.isPlainObject(new Date()), "new Date" ); + assert.ok( !jQuery.isPlainObject( new Date() ), "new Date" ); // Functions shouldn't be matched - ok( !jQuery.isPlainObject(fn), "fn" ); + assert.ok( !jQuery.isPlainObject( fn ), "fn" ); // Again, instantiated objects shouldn't be matched - ok( !jQuery.isPlainObject(new fn()), "new fn (no methods)" ); + 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(){}; + fn.prototype[ "someMethod" ] = function() {}; // Again, instantiated objects shouldn't be matched - ok( !jQuery.isPlainObject(new fn()), "new fn" ); - - // Make it even harder to detect in IE < 9 - fn = function() { - this.a = "a"; - }; - fn.prototype = { - b: "b" - }; + assert.ok( !jQuery.isPlainObject( new fn() ), "new fn" ); - ok( !jQuery.isPlainObject(new fn()), "fn (inherited and own properties)"); + // Instantiated objects with primitive constructors shouldn't be matched + fn.prototype.constructor = "foo"; + assert.ok( !jQuery.isPlainObject( new fn() ), "new fn with primitive constructor" ); + + // Deep object + deep = { "foo": { "baz": true }, "foo2": document }; + assert.ok( jQuery.isPlainObject( deep ), "Object with objects is still plain" ); // DOM Element - ok( !jQuery.isPlainObject( document.createElement("div") ), "DOM Element" ); + assert.ok( !jQuery.isPlainObject( document.createElement( "div" ) ), "DOM Element" ); // Window - ok( !jQuery.isPlainObject( window ), "window" ); + assert.ok( !jQuery.isPlainObject( window ), "window" ); pass = false; try { jQuery.isPlainObject( window.location ); pass = true; } catch ( e ) {} - ok( pass, "Does not throw exceptions on host objects" ); + assert.ok( pass, "Does not throw exceptions on host objects" ); // Objects from other windows should be matched - Globals.register("iframeDone"); + Globals.register( "iframeDone" ); window.iframeDone = function( otherObject, detail ) { window.iframeDone = undefined; iframe.parentNode.removeChild( iframe ); - ok( jQuery.isPlainObject(new otherObject()), "new otherObject" + ( detail ? " - " + detail : "" ) ); - start(); + assert.ok( jQuery.isPlainObject( new otherObject() ), "new otherObject" + ( detail ? " - " + detail : "" ) ); + QUnit.start(); }; try { - iframe = jQuery("#qunit-fixture")[0].appendChild( document.createElement("iframe") ); + iframe = jQuery( "#qunit-fixture" )[ 0 ].appendChild( document.createElement( "iframe" ) ); doc = iframe.contentDocument || iframe.contentWindow.document; doc.open(); - doc.write(""); + doc.write( "" ); doc.close(); - } catch(e) { + } 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( "isPlainObject(localStorage)", function( assert ) { + assert.expect( 1 ); -test("isFunction", function() { - expect(19); + assert.equal( jQuery.isPlainObject( localStorage ), false ); +} ); + +QUnit[ "assign" in Object ? "test" : "skip" ]( "isPlainObject(Object.assign(...))", + function( assert ) { + assert.expect( 1 ); + + var parentObj = { foo: "bar" }; + var childObj = Object.assign( Object.create( parentObj ), { bar: "foo" } ); + + assert.ok( !jQuery.isPlainObject( childObj ), "isPlainObject(Object.assign(...))" ); + } +); + + +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 - ok( !jQuery.isFunction(), "No Value" ); - ok( !jQuery.isFunction( null ), "null Value" ); - ok( !jQuery.isFunction( undefined ), "undefined Value" ); - ok( !jQuery.isFunction( "" ), "Empty String Value" ); - ok( !jQuery.isFunction( 0 ), "0 Value" ); + 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 - // Safari uses "(Internal Function)" - ok( jQuery.isFunction(String), "String Function("+String+")" ); - ok( jQuery.isFunction(Array), "Array Function("+Array+")" ); - ok( jQuery.isFunction(Object), "Object Function("+Object+")" ); - ok( jQuery.isFunction(Function), "Function Function("+Function+")" ); + 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"; - ok( !jQuery.isFunction(mystr), "Function String" ); + assert.ok( !jQuery.isFunction( mystr ), "Function String" ); // When stringified, this could be misinterpreted myarr = [ "function" ]; - ok( !jQuery.isFunction(myarr), "Function Array" ); + assert.ok( !jQuery.isFunction( myarr ), "Function Array" ); // When stringified, this could be misinterpreted myfunction = { "function": "test" }; - ok( !jQuery.isFunction(myfunction), "Function Object" ); + assert.ok( !jQuery.isFunction( myfunction ), "Function Object" ); // Make sure normal functions still work - fn = function(){}; - ok( jQuery.isFunction(fn), "Normal Function" ); + fn = function() {}; + assert.ok( jQuery.isFunction( fn ), "Normal Function" ); - obj = document.createElement("object"); + obj = document.createElement( "object" ); // Firefox says this is a function - ok( !jQuery.isFunction(obj), "Object Element" ); + assert.ok( !jQuery.isFunction( obj ), "Object Element" ); - // IE says this is an object // 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 - ok( !jQuery.isFunction(nodes), "childNodes Property" ); + assert.ok( !jQuery.isFunction( nodes ), "childNodes Property" ); first = document.body.firstChild; // Normal elements are reported ok everywhere - ok( !jQuery.isFunction(first), "A normal DOM Element" ); + assert.ok( !jQuery.isFunction( first ), "A normal DOM Element" ); - input = document.createElement("input"); + input = document.createElement( "input" ); input.type = "text"; document.body.appendChild( input ); - // IE says this is an object // 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 = document.createElement( "a" ); a.href = "some-function"; document.body.appendChild( a ); // This serializes with the word 'function' in it - ok( !jQuery.isFunction(a), "Anchor Element" ); + 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); + function callme( callback ) { + function fn( response ) { + callback( response ); } - ok( jQuery.isFunction(fn), "Recursive Function Call" ); + assert.ok( jQuery.isFunction( fn ), "Recursive Function Call" ); - fn({ some: "data" }); + fn( { some: "data" } ); } - callme(function(){ - callme(function(){}); - }); -}); + callme( function() { + callme( function() {} ); + } ); +} ); -test( "isNumeric", function() { - expect( 38 ); +QUnit.test( "isNumeric", function( assert ) { + assert.expect( 43 ); var t = jQuery.isNumeric, ToString = function( value ) { @@ -471,369 +501,423 @@ }; }; - ok( t( "-10" ), "Negative integer string" ); - ok( t( "0" ), "Zero string" ); - ok( t( "5" ), "Positive integer string" ); - ok( t( -16 ), "Negative integer number" ); - ok( t( 0 ), "Zero integer number" ); - ok( t( 32 ), "Positive integer number" ); - ok( t( "040" ), "Octal integer literal string" ); - ok( t( "0xFF" ), "Hexadecimal integer literal string" ); - ok( t( 0xFFF ), "Hexadecimal integer literal" ); - ok( t( "-1.6" ), "Negative floating point string" ); - ok( t( "4.536" ), "Positive floating point string" ); - ok( t( -2.6 ), "Negative floating point number" ); - ok( t( 3.1415 ), "Positive floating point number" ); - ok( t( 1.5999999999999999 ), "Very precise floating point number" ); - ok( t( 8e5 ), "Exponential notation" ); - ok( t( "123e-2" ), "Exponential notation string" ); - ok( t( new ToString( "42" ) ), "Custom .toString returning number" ); - - equal( t( "" ), false, "Empty string" ); - equal( t( " " ), false, "Whitespace characters string" ); - equal( t( "\t\t" ), false, "Tab characters string" ); - equal( t( "abcdefghijklm1234567890" ), false, "Alphanumeric character string" ); - equal( t( "xabcdefx" ), false, "Non-numeric character string" ); - equal( t( true ), false, "Boolean true literal" ); - equal( t( false ), false, "Boolean false literal" ); - equal( t( "bcfed5.2" ), false, "Number with preceding non-numeric characters" ); - equal( t( "7.2acdgs" ), false, "Number with trailling non-numeric characters" ); - equal( t( undefined ), false, "Undefined value" ); - equal( t( null ), false, "Null value" ); - equal( t( NaN ), false, "NaN value" ); - equal( t( Infinity ), false, "Infinity primitive" ); - equal( t( Number.POSITIVE_INFINITY ), false, "Positive Infinity" ); - equal( t( Number.NEGATIVE_INFINITY ), false, "Negative Infinity" ); - equal( t( new ToString( "Devo" ) ), false, "Custom .toString returning non-number" ); - equal( t( {} ), false, "Empty object" ); - equal( t( [] ), false, "Empty array" ); - equal( t( [ 42 ] ), false, "Array with one number" ); - equal( t( function(){} ), false, "Instance of a function" ); - equal( t( new Date() ), false, "Instance of a Date" ); -}); - -test("isXMLDoc - HTML", function() { - expect(4); - - ok( !jQuery.isXMLDoc( document ), "HTML document" ); - ok( !jQuery.isXMLDoc( document.documentElement ), "HTML documentElement" ); - ok( !jQuery.isXMLDoc( document.body ), "HTML Body Element" ); + 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( "-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( "040" ), "Legacy octal integer literal string" ); + assert.ok( t( "0xFF" ), "Hexadecimal integer literal string (0x...)" ); + assert.ok( t( "0Xba" ), "Hexadecimal integer literal string (0X...)" ); + assert.ok( t( 0xFFF ), "Hexadecimal integer literal" ); + + if ( +"0b1" === 1 ) { + assert.ok( t( "0b111110" ), "Binary integer literal string (0b...)" ); + assert.ok( t( "0B111110" ), "Binary integer literal string (0B...)" ); + } else { + assert.ok( true, "Browser does not support binary integer literal (0b...)" ); + assert.ok( true, "Browser does not support binary integer literal (0B...)" ); + } + + if ( +"0o1" === 1 ) { + assert.ok( t( "0o76" ), "Octal integer literal string (0o...)" ); + assert.ok( t( "0O76" ), "Octal integer literal string (0O...)" ); + } else { + assert.ok( true, "Browser does not support octal integer literal (0o...)" ); + assert.ok( true, "Browser does not support octal integer literal (0O...)" ); + } + + assert.equal( t( new ToString( "42" ) ), false, "Only limited to strings and numbers" ); + 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 trailing 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"); + iframe = document.createElement( "iframe" ); document.body.appendChild( iframe ); try { - body = jQuery(iframe).contents()[0]; + body = jQuery( iframe ).contents()[ 0 ]; try { - ok( !jQuery.isXMLDoc( body ), "Iframe body element" ); - } catch(e) { - ok( false, "Iframe body element exception" ); + assert.ok( !jQuery.isXMLDoc( body ), "Iframe body element" ); + } catch ( e ) { + assert.ok( false, "Iframe body element exception" ); } - } catch(e) { - ok( true, "Iframe body element - iframe not working correctly" ); + } catch ( e ) { + assert.ok( true, "Iframe body element - iframe not working correctly" ); } document.body.removeChild( iframe ); -}); +} ); -test("XSS via location.hash", function() { - expect(1); +QUnit.test( "XSS via location.hash", function( assert ) { + assert.expect( 1 ); - stop(); - jQuery["_check9521"] = function(x){ - ok( x, "script called from #id-like selector with inline handler" ); - jQuery("#check9521").remove(); - delete jQuery["_check9521"]; - start(); + 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); + jQuery( "#" ).appendTo( "#qunit-fixture" ); + } catch ( err ) { + jQuery[ "_check9521" ]( true ); } -}); +} ); -test("isXMLDoc - XML", function() { - expect(3); +QUnit.test( "isXMLDoc - XML", function( assert ) { + assert.expect( 3 ); var xml = createDashboardXML(); - ok( jQuery.isXMLDoc( xml ), "XML document" ); - ok( jQuery.isXMLDoc( xml.documentElement ), "XML documentElement" ); - ok( jQuery.isXMLDoc( jQuery("tab", xml)[0] ), "XML Tab Element" ); -}); - -test("isWindow", function() { - expect( 14 ); - - ok( jQuery.isWindow(window), "window" ); - ok( jQuery.isWindow(document.getElementsByTagName("iframe")[0].contentWindow), "iframe.contentWindow" ); - ok( !jQuery.isWindow(), "empty" ); - ok( !jQuery.isWindow(null), "null" ); - ok( !jQuery.isWindow(undefined), "undefined" ); - ok( !jQuery.isWindow(document), "document" ); - ok( !jQuery.isWindow(document.documentElement), "documentElement" ); - ok( !jQuery.isWindow(""), "string" ); - ok( !jQuery.isWindow(1), "number" ); - ok( !jQuery.isWindow(true), "boolean" ); - ok( !jQuery.isWindow({}), "object" ); - ok( !jQuery.isWindow({ setInterval: function(){} }), "fake window" ); - ok( !jQuery.isWindow(/window/), "regexp" ); - ok( !jQuery.isWindow(function(){}), "function" ); -}); + 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" ); +} ); -test("jQuery('html')", function() { - expect( 18 ); +QUnit.test( "jQuery('html')", function( assert ) { + assert.expect( 18 ); var s, div, j; - jQuery["foo"] = false; - s = jQuery("")[0]; - ok( s, "Creating a script" ); - ok( !jQuery["foo"], "Make sure the script wasn't executed prematurely" ); - jQuery("body").append(""); - ok( jQuery["foo"], "Executing a scripts contents in the right context" ); + 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 script's contents in the right context" ); // Test multi-line HTML - div = jQuery("
\r\nsome text\n

some p

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

This is a test.

<#/if>" ) || true, "Garbage input should not cause error" ); +} ); + +QUnit.test( "jQuery.parseHTML() - gh-2965", function( assert ) { + assert.expect( 1 ); + + var html = "", + href = jQuery.parseHTML( html )[ 0 ].href; + + assert.ok( /\/test\.html$/.test( href ), "href is not lost after parsing anchor" ); +} ); + +if ( jQuery.support.createHTMLDocument ) { + 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.parseXML", function( assert ) { + assert.expect( 8 ); -test("jQuery.parseXML", 8, function(){ var xml, tmp; try { xml = jQuery.parseXML( "

A well-formed xml string

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

present in document" ); + assert.ok( !!tmp, "

present in document" ); tmp = tmp.getElementsByTagName( "b" )[ 0 ]; - ok( !!tmp, " present in document" ); - strictEqual( tmp.childNodes[ 0 ].nodeValue, "well-formed", " text is as expected" ); - } catch (e) { - strictEqual( e, undefined, "unexpected error" ); + 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

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

Not a <well-formed xml string

", "invalid xml detected" ); + 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( "" ); - strictEqual( xml, null, "empty string => null document" ); + assert.strictEqual( xml, null, "empty string => null document" ); xml = jQuery.parseXML(); - strictEqual( xml, null, "undefined string => null document" ); + assert.strictEqual( xml, null, "undefined string => null document" ); xml = jQuery.parseXML( null ); - strictEqual( xml, null, "null string => null document" ); + assert.strictEqual( xml, null, "null string => null document" ); xml = jQuery.parseXML( true ); - strictEqual( xml, null, "non-string => null document" ); - } catch( e ) { - ok( false, "empty input throws exception" ); + assert.strictEqual( xml, null, "non-string => null document" ); + } catch ( e ) { + assert.ok( false, "empty input throws exception" ); } -}); +} ); -test("jQuery.camelCase()", function() { +QUnit.test( "jQuery.camelCase()", function( assert ) { var tests = { "foo-bar": "fooBar", "foo-bar-baz": "fooBarBaz", "girl-u-want": "girlUWant", - "the-4th-dimension": "the4thDimension", + "the-4th-dimension": "the-4thDimension", "-o-tannenbaum": "OTannenbaum", "-moz-illa": "MozIlla", "-ms-take": "msTake" }; - expect(7); + assert.expect( 7 ); jQuery.each( tests, function( key, val ) { - equal( jQuery.camelCase( key ), val, "Converts: " + key + " => " + val ); - }); -}); - -testIframeWithCallback( "Conditional compilation compatibility (#13274)", "core/cc_on.html", function( cc_on, errors, $ ) { - expect( 3 ); - ok( true, "JScript conditional compilation " + ( cc_on ? "supported" : "not supported" ) ); - deepEqual( errors, [], "No errors" ); - ok( $(), "jQuery executes" ); -}); + assert.equal( jQuery.camelCase( key ), val, "Converts: " + key + " => " + val ); + } ); +} ); + +testIframe( + "Conditional compilation compatibility (#13274)", + "core/cc_on.html", + function( assert, jQuery, window, document, cc_on, errors ) { + assert.expect( 3 ); + assert.ok( true, "JScript conditional compilation " + ( cc_on ? "supported" : "not supported" ) ); + assert.deepEqual( errors, [], "No errors" ); + assert.ok( jQuery(), "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 ) { - expect( 1 ); - equal( true, ready, "document ready correctly fired when jQuery is loaded after DOMContentLoaded" ); - }); + testIframe( + "document ready when jQuery loaded asynchronously (#13655)", + "core/dynamic_ready.html", + function( assert, jQuery, window, document, ready ) { + 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 ) { - expect( 1 ); - deepEqual( errors, [], "jQuery loaded" ); +testIframe( + "Tolerating alias-masked DOM properties (#14074)", + "core/aliased.html", + function( assert, jQuery, window, document, errors ) { + assert.expect( 1 ); + assert.deepEqual( errors, [], "jQuery loaded" ); } ); -testIframeWithCallback( "Don't call window.onready (#14802)", "core/onready.html", - function( error ) { - expect( 1 ); - equal( error, false, "no call to user-defined onready" ); +testIframe( + "Don't call window.onready (#14802)", + "core/onready.html", + function( assert, jQuery, window, document, error ) { + assert.expect( 1 ); + assert.equal( error, false, "no call to user-defined onready" ); } ); + +QUnit.test( "Iterability of jQuery objects (gh-1693)", function( assert ) { + 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" ); + } +} ); + +QUnit[ jQuery.Deferred ? "test" : "skip" ]( "jQuery.readyException (original)", function( assert ) { + assert.expect( 1 ); + + var message; + + this.sandbox.stub( window, "setTimeout", function( fn ) { + try { + fn(); + } catch ( error ) { + message = error.message; + } + } ); + + jQuery( function() { + throw new Error( "Error in jQuery ready" ); + } ); + assert.strictEqual( + message, + "Error in jQuery ready", + "The error should have been thrown in a timeout" + ); +} ); + +QUnit[ jQuery.Deferred ? "test" : "skip" ]( "jQuery.readyException (custom)", function( assert ) { + assert.expect( 1 ); + + var done = assert.async(); + + this.sandbox.stub( jQuery, "readyException", function( error ) { + assert.strictEqual( + error.message, + "Error in jQuery ready", + "The custom jQuery.readyException should have been called" + ); + done(); + } ); + + jQuery( function() { + throw new Error( "Error in jQuery ready" ); + } ); +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/css.js jquery-3.2.1/test/unit/css.js --- jquery-1.11.3+dfsg/test/unit/css.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/css.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,263 +1,338 @@ if ( jQuery.css ) { -module("css", { teardown: moduleTeardown }); +QUnit.module( "css", { teardown: moduleTeardown } ); -test("css(String|Hash)", function() { - expect( 43 ); +QUnit.test( "css(String|Hash)", function( assert ) { + assert.expect( 42 ); - equal( jQuery("#qunit-fixture").css("display"), "block", "Check for css property \"display\"" ); + 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%" }); - notEqual( $child.css("width"), "20px", "Retrieving a width percentage on the child of a hidden div returns percentage" ); - notEqual( $child.css("height"), "20px", "Retrieving a height percentage on the child of a hidden div returns percentage" ); + $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 - equal( div.css("width"), "0px", "Width on disconnected node." ); - equal( div.css("height"), "0px", "Height on disconnected node." ); + 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 }); + div.css( { "width": 4, "height": 4 } ); - equal( div.css("width"), "4px", "Width on disconnected node." ); - equal( div.css("height"), "4px", "Height on disconnected node." ); + assert.equal( div.css( "width" ), "4px", "Width on disconnected node." ); + assert.equal( div.css( "height" ), "4px", "Height on disconnected node." ); - div2 = jQuery( "
"); + element = jQuery( "" ); clone = element.clone(); - equal( clone[ 0 ].defaultValue, "foo", "Textarea defaultValue cloned correctly" ); -}); + assert.equal( clone[ 0 ].defaultValue, "foo", "Textarea defaultValue cloned correctly" ); +} ); -test( "clone(multiple selected options) (Bug #8129)", function() { +QUnit.test( "clone(multiple selected options) (Bug #8129)", function( assert ) { - expect( 1 ); + assert.expect( 1 ); - var element = jQuery(""); + var element = jQuery( "" ); - equal( element.clone().find("option:selected").length, element.find("option:selected").length, "Multiple selected options cloned correctly" ); + 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" + ); +} ); -test( "clone() on XML nodes", function() { +QUnit.test( "clone() on XML nodes", function( assert ) { - expect( 2 ); + 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"); - equal( origTab.text(), "origval", "Check original XML node was correctly set" ); - equal( cloneTab.text(), "cloneval", "Check cloned XML node was correctly set" ); -}); + 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" ); +} ); -test( "clone() on local XML nodes with html5 nodename", function() { +QUnit.test( "clone() on local XML nodes with html5 nodename", function( assert ) { - expect( 2 ); + assert.expect( 2 ); var $xmlDoc = jQuery( jQuery.parseXML( "" ) ), $meter = $xmlDoc.find( "meter" ).clone(); - equal( $meter[ 0 ].nodeName, "meter", "Check if nodeName was not changed due to cloning" ); - equal( $meter[ 0 ].nodeType, 1, "Check if nodeType is not changed due to cloning" ); -}); + 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" ); +} ); -test( "html(undefined)", function() { +QUnit.test( "html(undefined)", function( assert ) { - expect( 1 ); + assert.expect( 1 ); - equal( jQuery("#foo").html("test").html(undefined).html().toLowerCase(), "test", ".html(undefined) is chainable (#5571)" ); -}); + assert.equal( jQuery( "#foo" ).html( "test" ).html( undefined ).html().toLowerCase(), "test", ".html(undefined) is chainable (#5571)" ); +} ); -test( "html() on empty set", function() { +QUnit.test( "html() on empty set", function( assert ) { - expect( 1 ); + assert.expect( 1 ); - strictEqual( jQuery().html(), undefined, ".html() returns undefined for empty sets (#11962)" ); -}); + 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(" "); + } ).join( " " ); } -function testHtml( valueObj ) { - expect( 39 ); +function testHtml( valueObj, assert ) { + assert.expect( 40 ); var actual, expected, tmp, - div = jQuery("
"), - fixture = jQuery("#qunit-fixture"); + div = jQuery( "
" ), + fixture = jQuery( "#qunit-fixture" ); - div.html( valueObj("
") ); - equal( div.children().length, 2, "Found children" ); - equal( div.children().children().length, 1, "Found grandchild" ); + 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"); + tmp = jQuery( "" ).html( valueObj( "area" ) ).each( function() { + expected.push( "AREA" ); actual.push( childNodeNames( this ) ); - }); - equal( expected.length, 1, "Expecting one parent" ); - deepEqual( actual, expected, "Found the inserted area element" ); - - equal( div.html(valueObj(5)).html(), "5", "Setting a number as html" ); - equal( div.html(valueObj(0)).html(), "0", "Setting a zero as html" ); - equal( div.html(valueObj(Infinity)).html(), "Infinity", "Setting Infinity as html" ); - equal( div.html(valueObj(NaN)).html(), "", "Setting NaN as html" ); - equal( div.html(valueObj(1e2)).html(), "100", "Setting exponential number notation as html" ); + } ); + assert.equal( expected.length, 1, "Expecting one parent" ); + assert.deepEqual( actual, expected, "Found the inserted area element" ); - div.html( valueObj(" &") ); - equal( + 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>"; - equal( div.html(valueObj(tmp) ).html().replace( />/g, ">" ), tmp, "Escaped html" ); + assert.equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html" ); tmp = "x" + tmp; - equal( div.html(valueObj( tmp )).html().replace( />/g, ">" ), tmp, "Escaped html, leading x" ); + assert.equal( div.html( valueObj( tmp ) ).html().replace( />/g, ">" ), tmp, "Escaped html, leading x" ); tmp = " " + tmp.slice( 1 ); - equal( div.html(valueObj( tmp )).html().replace( />/g, ">" ), tmp, "Escaped html, leading space" ); + 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() { + 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 ); - }); - deepEqual( actual, expected, "Set containing element, text node, comment" ); - ok( tmp[ 1 ], "element" ); - ok( tmp[ 3 ], "text node" ); - ok( tmp[ 8 ], "comment" ); + } ); + 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"); + fixture.children( "div" ).html( valueObj( "test" ) ).each( function() { + expected.push( "B" ); actual.push( childNodeNames( this ) ); - }); - equal( expected.length, 7, "Expecting many parents" ); - deepEqual( actual, expected, "Correct childNodes after setting HTML" ); + } ); + 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"); + fixture.html( valueObj( "" ) ).each( function() { + expected.push( "STYLE" ); actual.push( childNodeNames( this ) ); - }); - equal( expected.length, 1, "Expecting one parent" ); - deepEqual( actual, expected, "Found the inserted style element" ); - - fixture.html( valueObj("" ) ); + jQuery( "#qunit-fixture select" ).html( valueObj( "" ) ); + assert.equal( jQuery( "#qunit-fixture select" ).val(), "O2", "Selected option correct" ); tmp = fixture.html( - valueObj([ + valueObj( [ "", "", "", @@ -1706,224 +1764,216 @@ "", "", "
" - ].join("")) - ).find("script"); - equal( tmp.length, 8, "All script tags remain." ); - equal( tmp[ 0 ].type, "something/else", "Non-evaluated type." ); - equal( tmp[ 1 ].type, "text/javascript", "Evaluated type." ); - - fixture.html( valueObj("") ); - fixture.html( valueObj("") ); - fixture.html( valueObj("") ); - fixture.html( valueObj("foo
") ); + ].join( "" ) ) + ).find( "script" ); + assert.equal( tmp.length, 8, "All script tags remain." ); + assert.equal( tmp[ 0 ].type, "something/else", "Non-evaluated type." ); + assert.equal( tmp[ 1 ].type, "text/javascript", "Evaluated type." ); + + fixture.html( valueObj( "" ) ); + fixture.html( valueObj( "" ) ); + fixture.html( valueObj( "" ) ); + fixture.html( valueObj( "foo
" ) ); jQuery.scriptorder = 0; - fixture.html( valueObj([ + fixture.html( valueObj( [ "", "", "" - ].join("")) ); -} - -test( "html(String|Number)", function() { - testHtml( manipulationBareObj ); -}); - -test( "html(Function)", function() { - testHtml( manipulationFunctionReturningObj ); -}); - -test( "html( $.text() )", function() { - - expect( 1 ); + ].join( "" ) ) ); - var fixture = jQuery("#qunit-fixture"); - fixture.html( fixture.text() ); - ok( /^[^<]*[^<\s][^<]*$/.test( fixture.html() ), "Replace html with text" ); -}); - -test( "html( fn ) returns $.text()", function() { + fixture.html( valueObj( fixture.text() ) ); + assert.ok( /^[^<]*[^<\s][^<]*$/.test( fixture.html() ), "Replace html with text" ); +} - expect( 1 ); +QUnit.test( "html(String|Number)", function( assert ) { + testHtml( manipulationBareObj, assert ); +} ); - var fixture = jQuery("#qunit-fixture"); - fixture.html( manipulationFunctionReturningObj( fixture.text() ) ); - ok( /^[^<]*[^<\s][^<]*$/.test( fixture.html() ), "Replace html with text" ); -}); +QUnit.test( "html(Function)", function( assert ) { + testHtml( manipulationFunctionReturningObj, assert ); +} ); -test( "html(Function) with incoming value -- direct selection", function() { +QUnit.test( "html(Function) with incoming value -- direct selection", function( assert ) { - expect( 4 ); + assert.expect( 4 ); var els, actualhtml, pass; - els = jQuery("#foo > p"); - actualhtml = els.map(function() { + els = jQuery( "#foo > p" ); + actualhtml = els.map( function() { return jQuery( this ).html(); - }); + } ); - els.html(function( i, val ) { - equal( val, actualhtml[ i ], "Make sure the incoming value is correct." ); + els.html( function( i, val ) { + assert.equal( val, actualhtml[ i ], "Make sure the incoming value is correct." ); return "test"; - }); + } ); pass = true; - els.each(function() { + els.each( function() { if ( this.childNodes.length !== 1 ) { pass = false; } - }); - ok( pass, "Set HTML" ); -}); + } ); + assert.ok( pass, "Set HTML" ); +} ); -test( "html(Function) with incoming value -- jQuery.contents()", function() { +QUnit.test( "html(Function) with incoming value -- jQuery.contents()", function( assert ) { - expect( 14 ); + assert.expect( 14 ); - var actualhtml, j, $div, $div2, insert; + var actualhtml, j, $div, $div2, insert; - j = jQuery("#nonnodes").contents(); - actualhtml = j.map(function() { + j = jQuery( "#nonnodes" ).contents(); + actualhtml = j.map( function() { return jQuery( this ).html(); - }); + } ); - j.html(function( i, val ) { - equal( val, actualhtml[ i ], "Make sure the incoming value is correct." ); + j.html( function( i, val ) { + assert.equal( val, actualhtml[ i ], "Make sure the incoming value is correct." ); return "bold"; - }); + } ); // Handle the case where no comment is in the document if ( j.length === 2 ) { - equal( null, null, "Make sure the incoming value is correct." ); + assert.equal( null, null, "Make sure the incoming value is correct." ); } - equal( j.html().replace( / xmlns="[^"]+"/g, "" ).toLowerCase(), "bold", "Check node,textnode,comment with html()" ); + assert.equal( j.html().replace( / xmlns="[^"]+"/g, "" ).toLowerCase(), "bold", "Check node,textnode,comment with html()" ); - $div = jQuery("
"); + $div = jQuery( "
" ); - equal( $div.html(function( i, val ) { - equal( val, "", "Make sure the incoming value is correct." ); + assert.equal( $div.html( function( i, val ) { + assert.equal( val, "", "Make sure the incoming value is correct." ); return 5; - }).html(), "5", "Setting a number as html" ); + } ).html(), "5", "Setting a number as html" ); - equal( $div.html(function( i, val ) { - equal( val, "5", "Make sure the incoming value is correct." ); + assert.equal( $div.html( function( i, val ) { + assert.equal( val, "5", "Make sure the incoming value is correct." ); return 0; - }).html(), "0", "Setting a zero as html" ); + } ).html(), "0", "Setting a zero as html" ); - $div2 = jQuery("
"); + $div2 = jQuery( "
" ); insert = "<div>hello1</div>"; - equal( $div2.html(function( i, val ) { - equal( val, "", "Make sure the incoming value is correct." ); + assert.equal( $div2.html( function( i, val ) { + assert.equal( val, "", "Make sure the incoming value is correct." ); return insert; - }).html().replace(/>/g, ">"), insert, "Verify escaped insertion." ); + } ).html().replace( />/g, ">" ), insert, "Verify escaped insertion." ); - equal( $div2.html(function( i, val ) { - equal( val.replace(/>/g, ">"), insert, "Make sure the incoming value is correct." ); + assert.equal( $div2.html( function( i, val ) { + assert.equal( val.replace( />/g, ">" ), insert, "Make sure the incoming value is correct." ); return "x" + insert; - }).html().replace( />/g, ">" ), "x" + insert, "Verify escaped insertion." ); + } ).html().replace( />/g, ">" ), "x" + insert, "Verify escaped insertion." ); - equal( $div2.html(function( i, val ) { - equal( val.replace( />/g, ">" ), "x" + insert, "Make sure the incoming value is correct." ); + assert.equal( $div2.html( function( i, val ) { + assert.equal( val.replace( />/g, ">" ), "x" + insert, "Make sure the incoming value is correct." ); return " " + insert; - }).html().replace( />/g, ">" ), " " + insert, "Verify escaped insertion." ); -}); + } ).html().replace( />/g, ">" ), " " + insert, "Verify escaped insertion." ); +} ); -test( "clone()/html() don't expose jQuery/Sizzle expandos (#12858)", function() { +QUnit.test( "clone()/html() don't expose jQuery/Sizzle expandos (#12858)", function( assert ) { - expect( 2 ); + assert.expect( 2 ); - var $content = jQuery("
text
").appendTo("#qunit-fixture"), + var $content = jQuery( "
text
" ).appendTo( "#qunit-fixture" ), expected = /^text<\/i><\/b>$/i; // Attach jQuery and Sizzle data (the latter with a non-qSA nth-child) try { - $content.find(":nth-child(1):lt(4)").data( "test", true ); + $content.find( ":nth-child(1):lt(4)" ).data( "test", true ); // But don't break on a non-Sizzle build - } catch( e ) { - $content.find("*").data( "test", true ); + } catch ( e ) { + $content.find( "*" ).data( "test", true ); } - ok( expected.test( $content.clone( false )[ 0 ].innerHTML ), "clone()" ); - ok( expected.test( $content.html() ), "html()" ); -}); - -test( "remove() no filters", function() { + assert.ok( expected.test( $content.clone( false )[ 0 ].innerHTML ), "clone()" ); + assert.ok( expected.test( $content.html() ), "html()" ); +} ); - expect( 3 ); +QUnit.test( "remove() no filters", function( assert ) { - var first = jQuery("#ap").children().first(); + assert.expect( 2 ); - first.data("foo", "bar"); + var first = jQuery( "#ap" ).children().first(); - jQuery("#ap").children().remove(); - ok( jQuery("#ap").text().length > 10, "Check text is not removed" ); - equal( jQuery("#ap").children().length, 0, "Check remove" ); + first.data( "foo", "bar" ); - equal( first.data("foo"), null, "first data" ); + jQuery( "#ap" ).children().remove(); + assert.ok( jQuery( "#ap" ).text().length > 10, "Check text is not removed" ); + assert.equal( jQuery( "#ap" ).children().length, 0, "Check remove" ); +} ); -}); +QUnit.test( "remove() with filters", function( assert ) { -test( "remove() with filters", function() { + assert.expect( 8 ); - expect( 8 ); + var markup, div; + jQuery( "#ap" ).children().remove( "a" ); + assert.ok( jQuery( "#ap" ).text().length > 10, "Check text is not removed" ); + assert.equal( jQuery( "#ap" ).children().length, 1, "Check filtered remove" ); - var markup, div; - jQuery("#ap").children().remove("a"); - ok( jQuery("#ap").text().length > 10, "Check text is not removed" ); - equal( jQuery("#ap").children().length, 1, "Check filtered remove" ); - - jQuery("#ap").children().remove("a, code"); - equal( jQuery("#ap").children().length, 0, "Check multi-filtered remove" ); + jQuery( "#ap" ).children().remove( "a, code" ); + assert.equal( jQuery( "#ap" ).children().length, 0, "Check multi-filtered remove" ); // Positional and relative selectors markup = "
1234
"; div = jQuery( markup ); - div.children().remove("span:nth-child(2n)"); - equal( div.text(), "13", "relative selector in remove" ); - div = jQuery( markup ); - div.children().remove("span:first"); - equal( div.text(), "234", "positional selector in remove" ); - div = jQuery( markup ); - div.children().remove("span:last"); - equal( div.text(), "123", "positional selector in remove" ); + div.children().remove( "span:nth-child(2n)" ); + assert.equal( div.text(), "13", "relative selector in remove" ); + + if ( jQuery.find.compile ) { + div = jQuery( markup ); + div.children().remove( "span:first" ); + assert.equal( div.text(), "234", "positional selector in remove" ); + div = jQuery( markup ); + div.children().remove( "span:last" ); + assert.equal( div.text(), "123", "positional selector in remove" ); + } else { + assert.ok( "skip", "Positional selectors not supported in selector-native" ); + assert.ok( "skip", "Positional selectors not supported in selector-native" ); + } // using contents will get comments regular, text, and comment nodes // Handle the case where no comment is in the document - ok( jQuery("#nonnodes").contents().length >= 2, "Check node,textnode,comment remove works" ); - jQuery("#nonnodes").contents().remove(); - equal( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" ); -}); + assert.ok( jQuery( "#nonnodes" ).contents().length >= 2, "Check node,textnode,comment remove works" ); + jQuery( "#nonnodes" ).contents().remove(); + assert.equal( jQuery( "#nonnodes" ).contents().length, 0, "Check node,textnode,comment remove works" ); +} ); + +QUnit.test( "remove() event cleaning ", function( assert ) { + assert.expect( 1 ); -test( "remove() event cleaning ", 1, function() { var count, first, cleanUp; count = 0; - first = jQuery("#ap").children().first(); + first = jQuery( "#ap" ).children().first(); cleanUp = first.on( "click", function() { count++; - }).remove().appendTo("#qunit-fixture").trigger("click"); + } ).remove().appendTo( "#qunit-fixture" ).trigger( "click" ); - strictEqual( 0, count, "Event handler has been removed" ); + assert.strictEqual( 0, count, "Event handler has been removed" ); // Clean up detached data cleanUp.remove(); -}); +} ); + +QUnit.test( "remove() in document order #13779", function( assert ) { + assert.expect( 1 ); -test( "remove() in document order #13779", 1, function() { var last, cleanData = jQuery.cleanData; jQuery.cleanData = function( nodes ) { - last = jQuery.text( nodes[0] ); + last = jQuery.text( nodes[ 0 ] ); cleanData.call( this, nodes ); }; - jQuery("#qunit-fixture").append( + jQuery( "#qunit-fixture" ).append( jQuery.parseHTML( "
1
" + "
2
" + @@ -1931,98 +1981,100 @@ ) ); - jQuery(".removal-fixture").remove(); + jQuery( ".removal-fixture" ).remove(); - equal( last, 3, "The removal fixtures were removed in document order" ); + assert.equal( last, 3, "The removal fixtures were removed in document order" ); jQuery.cleanData = cleanData; -}); +} ); -test("detach() no filters", function () { +QUnit.test( "detach() no filters", function( assert ) { - expect(3); + assert.expect( 3 ); - var first = jQuery("#ap").children().first(); + var first = jQuery( "#ap" ).children().first(); - first.data("foo", "bar"); + first.data( "foo", "bar" ); - jQuery("#ap").children().detach(); - ok(jQuery("#ap").text().length > 10, "Check text is not removed"); - equal(jQuery("#ap").children().length, 0, "Check remove"); + jQuery( "#ap" ).children().detach(); + assert.ok( jQuery( "#ap" ).text().length > 10, "Check text is not removed" ); + assert.equal( jQuery( "#ap" ).children().length, 0, "Check remove" ); - equal(first.data("foo"), "bar"); - first.remove(); + assert.equal( first.data( "foo" ), "bar" ); + first.remove(); -}); +} ); -test("detach() with filters", function () { +QUnit.test( "detach() with filters", function( assert ) { - expect(8); + assert.expect( 8 ); - var markup, div; - jQuery("#ap").children().detach("a"); - ok(jQuery("#ap").text().length > 10, "Check text is not removed"); - equal(jQuery("#ap").children().length, 1, "Check filtered remove"); + var markup, div; + jQuery( "#ap" ).children().detach( "a" ); + assert.ok( jQuery( "#ap" ).text().length > 10, "Check text is not removed" ); + assert.equal( jQuery( "#ap" ).children().length, 1, "Check filtered remove" ); + + jQuery( "#ap" ).children().detach( "a, code" ); + assert.equal( jQuery( "#ap" ).children().length, 0, "Check multi-filtered remove" ); + + // Positional and relative selectors + markup = "
1234
"; + div = jQuery( markup ); + div.children().detach( "span:nth-child(2n)" ); + assert.equal( div.text(), "13", "relative selector in detach" ); - jQuery("#ap").children().detach("a, code"); - equal(jQuery("#ap").children().length, 0, "Check multi-filtered remove"); + if ( jQuery.find.compile ) { + div = jQuery( markup ); + div.children().detach( "span:first" ); + assert.equal( div.text(), "234", "positional selector in detach" ); + div = jQuery( markup ); + div.children().detach( "span:last" ); + assert.equal( div.text(), "123", "positional selector in detach" ); + } else { + assert.ok( "skip", "positional selectors not supported in selector-native" ); + assert.ok( "skip", "positional selectors not supported in selector-native" ); + } - // Positional and relative selectors - markup = "
1234
"; - div = jQuery(markup); - div.children().detach("span:nth-child(2n)"); - equal(div.text(), "13", "relative selector in detach"); - div = jQuery(markup); - div.children().detach("span:first"); - equal(div.text(), "234", "positional selector in detach"); - div = jQuery(markup); - div.children().detach("span:last"); - equal(div.text(), "123", "positional selector in detach"); + // using contents will get comments regular, text, and comment nodes + // Handle the case where no comment is in the document + assert.ok( jQuery( "#nonnodes" ).contents().length >= 2, "Check node,textnode,comment remove works" ); + jQuery( "#nonnodes" ).contents().detach(); + assert.equal( jQuery( "#nonnodes" ).contents().length, 0, "Check node,textnode,comment remove works" ); +} ); - // using contents will get comments regular, text, and comment nodes - // Handle the case where no comment is in the document - ok(jQuery("#nonnodes").contents().length >= 2, "Check node,textnode,comment remove works"); - jQuery("#nonnodes").contents().detach(); - equal(jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works"); -}); +QUnit.test( "detach() event cleaning ", function( assert ) { + assert.expect( 1 ); -test( "detach() event cleaning ", 1, function() { var count, first, cleanUp; count = 0; - first = jQuery("#ap").children().first(); + first = jQuery( "#ap" ).children().first(); cleanUp = first.on( "click", function() { count++; - }).detach().appendTo("#qunit-fixture").trigger("click"); + } ).detach().appendTo( "#qunit-fixture" ).trigger( "click" ); - strictEqual( 1, count, "Event handler has not been removed" ); + assert.strictEqual( 1, count, "Event handler has not been removed" ); // Clean up detached data cleanUp.remove(); -}); +} ); -test("empty()", function() { +QUnit.test( "empty()", function( assert ) { - expect( 6 ); + assert.expect( 3 ); - equal( jQuery("#ap").children().empty().text().length, 0, "Check text is removed" ); - equal( jQuery("#ap").children().length, 4, "Check elements are not removed" ); + assert.equal( jQuery( "#ap" ).children().empty().text().length, 0, "Check text is removed" ); + assert.equal( jQuery( "#ap" ).children().length, 4, "Check elements are not removed" ); // using contents will get comments regular, text, and comment nodes - var j = jQuery("#nonnodes").contents(); + var j = jQuery( "#nonnodes" ).contents(); j.empty(); - equal( j.html(), "", "Check node,textnode,comment empty works" ); - - // Ensure oldIE empties selects (#12336) - notEqual( jQuery("#select1").find("option").length, 0, "Have some initial options" ); - jQuery("#select1").empty(); - equal( jQuery("#select1").find("option").length, 0, "No more option elements found" ); - equal( jQuery("#select1")[0].options.length, 0, "options.length cleared as well" ); -}); + assert.equal( j.html(), "", "Check node,textnode,comment empty works" ); +} ); -test( "jQuery.cleanData", function() { +QUnit.test( "jQuery.cleanData", function( assert ) { - expect( 14 ); + assert.expect( 14 ); var type, pos, div, child; @@ -2033,10 +2085,10 @@ // Should both do nothing pos = "Outer"; - div.trigger("click"); + div.trigger( "click" ); pos = "Inner"; - div.children().trigger("click"); + div.children().trigger( "click" ); type = "empty"; div = getDiv(); @@ -2047,11 +2099,11 @@ // Should trigger 1 pos = "Outer"; - div.trigger("click"); + div.trigger( "click" ); // Should do nothing pos = "Inner"; - child.trigger("click"); + child.trigger( "click" ); // Should trigger 2 div.remove(); @@ -2062,45 +2114,84 @@ child = div.children(); // Should trigger 2 remove event - div.html("
"); + div.html( "
" ); // Should trigger 1 pos = "Outer"; - div.trigger("click"); + div.trigger( "click" ); // Should do nothing pos = "Inner"; - child.trigger("click"); + child.trigger( "click" ); // Should trigger 2 div.remove(); function getDiv() { - var div = jQuery("
").on( "click", function() { - ok( true, type + " " + pos + " Click event fired." ); - }).on( "focus", function() { - ok( true, type + " " + pos + " Focus event fired." ); - }).find("div").on( "click", function() { - ok( false, type + " " + pos + " Click event fired." ); - }).on( "focus", function() { - ok( false, type + " " + pos + " Focus event fired." ); - }).end().appendTo("body"); + var div = jQuery( "
" ).on( "click", function() { + assert.ok( true, type + " " + pos + " Click event fired." ); + } ).on( "focus", function() { + assert.ok( true, type + " " + pos + " Focus event fired." ); + } ).find( "div" ).on( "click", function() { + assert.ok( false, type + " " + pos + " Click event fired." ); + } ).on( "focus", function() { + assert.ok( false, type + " " + pos + " Focus event fired." ); + } ).end().appendTo( "body" ); div[ 0 ].detachEvent = div[ 0 ].removeEventListener = function( t ) { - ok( true, type + " Outer " + t + " event unbound" ); + assert.ok( true, type + " Outer " + t + " event unbound" ); }; div[ 0 ].firstChild.detachEvent = div[ 0 ].firstChild.removeEventListener = function( t ) { - ok( true, type + " Inner " + t + " event unbound" ); + assert.ok( true, type + " Inner " + t + " event unbound" ); }; return div; } -}); +} ); + +QUnit.test( "jQuery.cleanData eliminates all private data (gh-2127)", function( assert ) { + assert.expect( 3 ); + + var div = jQuery( "
" ).appendTo( "#qunit-fixture" ); + + jQuery._data( div[ 0 ], "gh-2127", "testing" ); + + assert.ok( !jQuery.isEmptyObject( jQuery._data( div[ 0 ] ) ), "Ensure some private data exists" ); + + div.remove(); -test( "jQuery.buildFragment - no plain-text caching (Bug #6779)", function() { + assert.ok( !jQuery.hasData( div[ 0 ] ), "Removed element hasData should return false" ); - expect( 1 ); + assert.ok( jQuery.isEmptyObject( jQuery._data( div[ 0 ] ) ), + "Private data is empty after node is removed" ); + + div.remove(); +} ); + +QUnit.test( "jQuery.cleanData eliminates all public data", function( assert ) { + assert.expect( 3 ); + + var key, + div = jQuery( "
" ); + div.data( "some", "data" ); + assert.ok( !jQuery.isEmptyObject( jQuery.data( div[ 0 ] ) ), "Ensure some public data exists" ); + + div.remove(); + + assert.ok( !jQuery.hasData( div[ 0 ] ), "Removed element hasData should return false" ); + + // Make sure the expando is gone + for ( key in div[ 0 ] ) { + if ( /^jQuery/.test( key ) ) { + assert.strictEqual( div[ 0 ][ key ], undefined, "Expando was not removed when there was no more data" ); + } + } +} ); + +QUnit.test( "domManip plain-text caching (trac-6779)", function( assert ) { + + assert.expect( 1 ); // DOM manipulation fails if added text matches an Object method var i, @@ -2111,64 +2202,76 @@ try { $f.append( bad[ i ] ); } - catch( e ) {} + catch ( e ) {} } - equal( $f.text(), bad.join(""), "Cached strings that match Object properties" ); + assert.equal( $f.text(), bad.join( "" ), "Cached strings that match Object properties" ); $f.remove(); -}); - -test( "jQuery.html - execute scripts escaped with html comment or CDATA (#9221)", function() { - - expect( 3 ); +} ); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); - jQuery([ - "" - ].join("\n")).appendTo("#qunit-fixture"); -}); +QUnit.test( "domManip executes scripts containing html comments or CDATA (trac-9221)", function( assert ) { -test( "jQuery.buildFragment - plain objects are not a document #8950", function() { + assert.expect( 3 ); - expect( 1 ); + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); + + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); + + jQuery( [ + "" + ].join( "\n" ) ).appendTo( "#qunit-fixture" ); +} ); + +testIframe( + "domManip tolerates window-valued document[0] in IE9/10 (trac-12266)", + "manipulation/iframe-denied.html", + function( assert, jQuery, window, document, test ) { + assert.expect( 1 ); + assert.ok( test.status, test.description ); + } +); - try { - jQuery( "", {} ); - ok( true, "Does not allow attribute object to be treated like a doc object" ); - } catch ( e ) {} -}); +testIframe( + "domManip executes scripts in iframes in the iframes' context", + "manipulation/scripts-context.html", + function( assert, framejQuery, frameWindow, frameDocument ) { + assert.expect( 2 ); + jQuery( frameDocument.body ).append( ""); - ok( false, "Exception ignored" ); - }, "Exception bubbled from inline script" ); + QUnit.start(); + }, 1000 ); - if ( jQuery.ajax ) { - throws(function() { - jQuery("#qunit-fixture").html(""); - ok( false, "Exception ignored" ); - }, "Exception thrown in remote script" ); - } else { - ok( true, "No jQuery.ajax" ); - } -}); + window.onerror = function() { + assert.ok( true, "Exception thrown" ); -test( "checked state is cloned with clone()", function() { + if ( jQuery.ajax ) { + window.onerror = function() { + assert.ok( true, "Exception thrown in remote script" ); + }; - expect( 2 ); + jQuery( "#qunit-fixture" ).html( "" ); + assert.ok( true, "Exception ignored" ); + } else { + assert.ok( true, "No jQuery.ajax" ); + assert.ok( true, "No jQuery.ajax" ); + } + }; + + jQuery( "#qunit-fixture" ).html( "" ); +} ); + +QUnit.test( "checked state is cloned with clone()", function( assert ) { - var elem = jQuery.parseHTML("")[ 0 ]; + assert.expect( 2 ); + + var elem = jQuery.parseHTML( "" )[ 0 ]; elem.checked = false; - equal( jQuery(elem).clone().attr("id","clone")[ 0 ].checked, false, "Checked false state correctly cloned" ); + assert.equal( jQuery( elem ).clone().attr( "id", "clone" )[ 0 ].checked, false, "Checked false state correctly cloned" ); - elem = jQuery.parseHTML("")[ 0 ]; + elem = jQuery.parseHTML( "" )[ 0 ]; elem.checked = true; - equal( jQuery(elem).clone().attr("id","clone")[ 0 ].checked, true, "Checked true state correctly cloned" ); -}); + assert.equal( jQuery( elem ).clone().attr( "id", "clone" )[ 0 ].checked, true, "Checked true state correctly cloned" ); +} ); -test( "manipulate mixed jQuery and text (#12384, #12346)", function() { +QUnit.test( "manipulate mixed jQuery and text (#12384, #12346)", function( assert ) { - expect( 2 ); + assert.expect( 2 ); - var div = jQuery("
a
").append( " ", jQuery("b"), " ", jQuery("c") ), + var div = jQuery( "
a
" ).append( " ", jQuery( "b" ), " ", jQuery( "c" ) ), nbsp = String.fromCharCode( 160 ); - equal( div.text(), "a" + nbsp + "b" + nbsp+ "c", "Appending mixed jQuery with text nodes" ); + assert.equal( div.text(), "a" + nbsp + "b" + nbsp + "c", "Appending mixed jQuery with text nodes" ); - div = jQuery("
") - .find("div") + div = jQuery( "
" ) + .find( "div" ) .after( "

a

", "

b

" ) .parent(); - equal( div.find("*").length, 3, "added 2 paragraphs after inner div" ); -}); - -testIframeWithCallback( "buildFragment works even if document[0] is iframe's window object in IE9/10 (#12266)", "manipulation/iframe-denied.html", function( test ) { - expect( 1 ); - - ok( test.status, test.description ); -}); + assert.equal( div.find( "*" ).length, 3, "added 2 paragraphs after inner div" ); +} ); -test( "script evaluation (#11795)", function() { +QUnit.test( "script evaluation (#11795)", function( assert ) { - expect( 13 ); + assert.expect( 13 ); var scriptsIn, scriptsOut, - fixture = jQuery("#qunit-fixture").empty(), - objGlobal = (function() { + fixture = jQuery( "#qunit-fixture" ).empty(), + objGlobal = ( function() { return this; - })(), + } )(), isOk = objGlobal.ok, notOk = function() { var args = arguments; @@ -2334,7 +2434,7 @@ }; objGlobal.ok = notOk; - scriptsIn = jQuery([ + scriptsIn = jQuery( [ "", "", "", @@ -2345,35 +2445,35 @@ "", "", "
" - ].join("")); - scriptsIn.appendTo( jQuery("
") ); + ].join( "" ) ); + scriptsIn.appendTo( jQuery( "
" ) ); objGlobal.ok = isOk; - scriptsOut = fixture.append( scriptsIn ).find("script"); - equal( scriptsOut[ 0 ].type, "something/else", "Non-evaluated type." ); - equal( scriptsOut[ 1 ].type, "text/javascript", "Evaluated type." ); - deepEqual( scriptsOut.get(), fixture.find("script").get(), "All script tags remain." ); + 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") ); - deepEqual( fixture.find("div script").get(), scriptsOut.get(), "Scripts cloned without reevaluation" ); + 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() ); - deepEqual( fixture.children("script").get(), scriptsOut.get(), "Scripts detached without reevaluation" ); + 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 " ); + + setTimeout( function() { + if ( window.testSrcFoo === "foo" ) { + assert.strictEqual( window.testFoo, window.testSrcFoo, "data-URI script executed" ); + + } else { + assert.ok( true, "data-URI script is not supported by this environment" ); + } + + done(); + }, 100 ); +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/offset.js jquery-3.2.1/test/unit/offset.js --- jquery-1.11.3+dfsg/test/unit/offset.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/offset.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,73 +1,103 @@ -(function() { +( function() { if ( !jQuery.fn.offset ) { return; } var supportsScroll, supportsFixedPosition, - forceScroll = jQuery("
").css({ width: 2000, height: 2000 }), + forceScroll = jQuery( "
" ).css( { width: 2000, height: 2000 } ), checkSupport = function() { + // Only run once checkSupport = false; - var checkFixed = jQuery("
").css({ position: "fixed", top: "20px" }).appendTo("#qunit-fixture"); + var checkFixed = jQuery( "
" ).css( { position: "fixed", top: "20px" } ).appendTo( "#qunit-fixture" ); // Must append to body because #qunit-fixture is hidden and elements inside it don't have a scrollTop - forceScroll.appendTo("body"); + forceScroll.appendTo( "body" ); window.scrollTo( 200, 200 ); supportsScroll = document.documentElement.scrollTop || document.body.scrollTop; forceScroll.detach(); - // Safari subtracts parent border width here (which is 5px) - supportsFixedPosition = checkFixed[0].offsetTop === 20 || checkFixed[0].offsetTop === 15; + supportsFixedPosition = checkFixed[ 0 ].offsetTop === 20; checkFixed.remove(); }; -module("offset", { setup: function(){ +QUnit.module( "offset", { setup: function() { if ( typeof checkSupport === "function" ) { checkSupport(); } // Force a scroll value on the main window to ensure incorrect results // if offset is using the scroll offset of the parent window - forceScroll.appendTo("body"); + forceScroll.appendTo( "body" ); window.scrollTo( 1, 1 ); forceScroll.detach(); -}, teardown: moduleTeardown }); +}, teardown: moduleTeardown } ); + +QUnit.test( "empty set", function( assert ) { + assert.expect( 2 ); + assert.strictEqual( jQuery().offset(), undefined, "offset() returns undefined for empty set (#11962)" ); + assert.strictEqual( jQuery().position(), undefined, "position() returns undefined for empty set (#11962)" ); +} ); + +QUnit.test( "disconnected element", function( assert ) { + assert.expect( 3 ); + + var result = jQuery( document.createElement( "div" ) ).offset(); + + // These tests are solely for master/compat consistency + // Retrieving offset on disconnected/hidden elements is not officially + // valid input, but will return zeros for back-compat + assert.equal( result.top, 0, "Retrieving offset on disconnected elements returns zeros (gh-2310)" ); + assert.equal( result.left, 0, "Retrieving offset on disconnected elements returns zeros (gh-2310)" ); + assert.equal( Object.keys( result ).length, 2, "Retrieving offset on disconnected elements returns offset object (gh-3167)" ); +} ); + +QUnit.test( "hidden (display: none) element", function( assert ) { + assert.expect( 3 ); + + var node = jQuery( "
" ).appendTo( "#qunit-fixture" ), + result = node.offset(); + + node.remove(); + + // These tests are solely for master/compat consistency + // Retrieving offset on disconnected/hidden elements is not officially + // valid input, but will return zeros for back-compat + assert.equal( result.top, 0, "Retrieving offset on hidden elements returns zeros (gh-2310)" ); + assert.equal( result.left, 0, "Retrieving offset on hidden elements returns zeros (gh-2310)" ); + assert.equal( Object.keys( result ).length, 2, "Retrieving offset on hidden elements returns offset object (gh-3167)" ); +} ); + +QUnit.test( "0 sized element", function( assert ) { + assert.expect( 3 ); + + var node = jQuery( "
" ).appendTo( "#qunit-fixture" ), + result = node.offset(); + + node.remove(); -/* - Closure-compiler will roll static methods off of the jQuery object and so they will - not be passed with the jQuery object across the windows. To differentiate this, the - testIframe callbacks use the "$" symbol to refer to the jQuery object passed from - the iframe window and the "jQuery" symbol is used to access any static methods. -*/ - -test("empty set", function() { - expect(2); - strictEqual( jQuery().offset(), undefined, "offset() returns undefined for empty set (#11962)" ); - strictEqual( jQuery().position(), undefined, "position() returns undefined for empty set (#11962)" ); -}); - -test("object without getBoundingClientRect", function() { - expect(2); - - // Simulates a browser without gBCR on elements, we just want to return 0,0 - var result = jQuery({ ownerDocument: document }).offset(); - equal( result.top, 0, "Check top" ); - equal( result.left, 0, "Check left" ); -}); - -test("disconnected node", function() { - expect(2); - - var result = jQuery( document.createElement("div") ).offset(); - - equal( result.top, 0, "Check top" ); - equal( result.left, 0, "Check left" ); -}); + assert.notEqual( result.top, 0, "Retrieving offset on 0 sized elements (gh-3167)" ); + assert.notEqual( result.left, 0, "Retrieving offset on 0 sized elements (gh-3167)" ); + assert.equal( Object.keys( result ).length, 2, "Retrieving offset on 0 sized elements returns offset object (gh-3167)" ); +} ); -testIframe("offset/absolute", "absolute", function($, iframe) { - expect(4); +QUnit.test( "hidden (visibility: hidden) element", function( assert ) { + assert.expect( 3 ); + + var node = jQuery( "
" ).appendTo( "#qunit-fixture" ), + result = node.offset(); + + node.remove(); + + assert.notEqual( result.top, 0, "Retrieving offset on visibility:hidden elements (gh-3167)" ); + assert.notEqual( result.left, 0, "Retrieving offset on visibility:hidden elements (gh-3167)" ); + assert.equal( Object.keys( result ).length, 2, "Retrieving offset on visibility:hidden elements returns offset object (gh-3167)" ); +} ); + +testIframe( "absolute", "offset/absolute.html", function( assert, $, iframe ) { + assert.expect( 4 ); var doc = iframe.document, tests; @@ -77,23 +107,22 @@ { "id": "#absolute-1", "top": 1, "left": 1 } ]; jQuery.each( tests, function() { - equal( jQuery( this["id"], doc ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" ); - equal( jQuery( this["id"], doc ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" ); - }); - + assert.equal( jQuery( this.id, doc ).offset().top, this.top, "jQuery('" + this.id + "').offset().top" ); + assert.equal( jQuery( this.id, doc ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" ); + } ); // get position tests = [ { "id": "#absolute-1", "top": 0, "left": 0 } ]; jQuery.each( tests, function() { - equal( jQuery( this["id"], doc ).position().top, this["top"], "jQuery('" + this["id"] + "').position().top" ); - equal( jQuery( this["id"], doc ).position().left, this["left"], "jQuery('" + this["id"] + "').position().left" ); - }); -}); + assert.equal( jQuery( this.id, doc ).position().top, this.top, "jQuery('" + this.id + "').position().top" ); + assert.equal( jQuery( this.id, doc ).position().left, this.left, "jQuery('" + this.id + "').position().left" ); + } ); +} ); -testIframe("offset/absolute", "absolute", function( $ ) { - expect(178); +testIframe( "absolute", "offset/absolute.html", function( assert, $ ) { + assert.expect( 178 ); var tests, offset; @@ -105,10 +134,9 @@ { "id": "#absolute-2", "top": 20, "left": 20 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" ); - }); - + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset().top" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" ); + } ); // get position tests = [ @@ -118,15 +146,14 @@ { "id": "#absolute-2", "top": 19, "left": 19 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).position().top, this["top"], "jQuery('" + this["id"] + "').position().top" ); - equal( $( this["id"] ).position().left, this["left"], "jQuery('" + this["id"] + "').position().left" ); - }); + assert.equal( $( this.id ).position().top, this.top, "jQuery('" + this.id + "').position().top" ); + assert.equal( $( this.id ).position().left, this.left, "jQuery('" + this.id + "').position().left" ); + } ); // test #5781 - offset = $( "#positionTest" ).offset({ "top": 10, "left": 10 }).offset(); - equal( offset.top, 10, "Setting offset on element with position absolute but 'auto' values." ); - equal( offset.left, 10, "Setting offset on element with position absolute but 'auto' values." ); - + offset = $( "#positionTest" ).offset( { "top": 10, "left": 10 } ).offset(); + assert.equal( offset.top, 10, "Setting offset on element with position absolute but 'auto' values." ); + assert.equal( offset.left, 10, "Setting offset on element with position absolute but 'auto' values." ); // set offset tests = [ @@ -148,68 +175,63 @@ { "id": "#absolute-1", "top": 1, "left": 1 } ]; jQuery.each( tests, function() { - $( this["id"] ).offset({ "top": this["top"], "left": this["left"] }); - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" ); - - var top = this["top"], left = this["left"]; - - $( this["id"] ).offset(function(i, val){ - equal( val.top, top, "Verify incoming top position." ); - equal( val.left, left, "Verify incoming top position." ); + $( this.id ).offset( { "top": this.top, "left": this.left } ); + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); + + var top = this.top, left = this.left; + + $( this.id ).offset( function( i, val ) { + assert.equal( val.top, top, "Verify incoming top position." ); + assert.equal( val.left, left, "Verify incoming top position." ); return { "top": top + 1, "left": left + 1 }; - }); - equal( $( this["id"] ).offset().top, this["top"] + 1, "jQuery('" + this["id"] + "').offset({ top: " + (this["top"] + 1) + " })" ); - equal( $( this["id"] ).offset().left, this["left"] + 1, "jQuery('" + this["id"] + "').offset({ left: " + (this["left"] + 1) + " })" ); - - $( this["id"] ) - .offset({ "left": this["left"] + 2 }) - .offset({ "top": this["top"] + 2 }); - equal( $( this["id"] ).offset().top, this["top"] + 2, "Setting one property at a time." ); - equal( $( this["id"] ).offset().left, this["left"] + 2, "Setting one property at a time." ); + } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + " })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + " })" ); + + $( this.id ) + .offset( { "left": this.left + 2 } ) + .offset( { "top": this.top + 2 } ); + assert.equal( $( this.id ).offset().top, this.top + 2, "Setting one property at a time." ); + assert.equal( $( this.id ).offset().left, this.left + 2, "Setting one property at a time." ); - $( this["id"] ).offset({ "top": this["top"], "left": this["left"], "using": function( props ) { - $( this ).css({ + $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { + $( this ).css( { "top": props.top + 1, "left": props.left + 1 - }); - }}); - equal( $( this["id"] ).offset().top, this["top"] + 1, "jQuery('" + this["id"] + "').offset({ top: " + (this["top"] + 1) + ", using: fn })" ); - equal( $( this["id"] ).offset().left, this["left"] + 1, "jQuery('" + this["id"] + "').offset({ left: " + (this["left"] + 1) + ", using: fn })" ); - }); -}); - -testIframe("offset/relative", "relative", function( $ ) { - expect(60); - - var ie, tests; + } ); + } } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); + } ); +} ); - // IE is collapsing the top margin of 1px; detect and adjust accordingly - ie = $("#relative-1").offset().top === 6; +testIframe( "relative", "offset/relative.html", function( assert, $ ) { + assert.expect( 64 ); // get offset - tests = [ - { "id": "#relative-1", "top": ie ? 6 : 7, "left": 7 }, - { "id": "#relative-1-1", "top": ie ? 13 : 15, "left": 15 }, - { "id": "#relative-2", "top": ie ? 141 : 142, "left": 27 } + var tests = [ + { "id": "#relative-1", "top": 7, "left": 7 }, + { "id": "#relative-1-1", "top": 15, "left": 15 }, + { "id": "#relative-2", "top": 142, "left": 27 }, + { "id": "#relative-2-1", "top": 149, "left": 52 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" ); - }); - + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset().top" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" ); + } ); // get position tests = [ - { "id": "#relative-1", "top": ie ? 5 : 6, "left": 6 }, - { "id": "#relative-1-1", "top": ie ? 4 : 5, "left": 5 }, - { "id": "#relative-2", "top": ie ? 140 : 141, "left": 26 } + { "id": "#relative-1", "top": 6, "left": 6 }, + { "id": "#relative-1-1", "top": 5, "left": 5 }, + { "id": "#relative-2", "top": 141, "left": 26 }, + { "id": "#relative-2-1", "top": 5, "left": 5 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).position().top, this["top"], "jQuery('" + this["id"] + "').position().top" ); - equal( $( this["id"] ).position().left, this["left"], "jQuery('" + this["id"] + "').position().left" ); - }); - + assert.equal( $( this.id ).position().top, this.top, "jQuery('" + this.id + "').position().top" ); + assert.equal( $( this.id ).position().left, this.left, "jQuery('" + this.id + "').position().left" ); + } ); // set offset tests = [ @@ -227,54 +249,47 @@ { "id": "#relative-1", "top": 7, "left": 7 } ]; jQuery.each( tests, function() { - $( this["id"] ).offset({ "top": this["top"], "left": this["left"] }); - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" ); + $( this.id ).offset( { "top": this.top, "left": this.left } ); + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); - $( this["id"] ).offset({ "top": this["top"], "left": this["left"], "using": function( props ) { - $( this ).css({ + $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { + $( this ).css( { "top": props.top + 1, "left": props.left + 1 - }); - }}); - equal( $( this["id"] ).offset().top, this["top"] + 1, "jQuery('" + this["id"] + "').offset({ top: " + (this["top"] + 1) + ", using: fn })" ); - equal( $( this["id"] ).offset().left, this["left"] + 1, "jQuery('" + this["id"] + "').offset({ left: " + (this["left"] + 1) + ", using: fn })" ); - }); -}); + } ); + } } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); + } ); +} ); -testIframe("offset/static", "static", function( $ ) { - expect( 80 ); - - var ie, tests; - - // IE is collapsing the top margin of 1px; detect and adjust accordingly - ie = $("#static-1").offset().top === 6; +testIframe( "static", "offset/static.html", function( assert, $ ) { + assert.expect( 80 ); // get offset - tests = [ - { "id": "#static-1", "top": ie ? 6 : 7, "left": 7 }, - { "id": "#static-1-1", "top": ie ? 13 : 15, "left": 15 }, - { "id": "#static-1-1-1", "top": ie ? 20 : 23, "left": 23 }, - { "id": "#static-2", "top": ie ? 121 : 122, left: 7 } + var tests = [ + { "id": "#static-1", "top": 7, "left": 7 }, + { "id": "#static-1-1", "top": 15, "left": 15 }, + { "id": "#static-1-1-1", "top": 23, "left": 23 }, + { "id": "#static-2", "top": 122, left: 7 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset().top" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset().left" ); - }); - + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset().top" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset().left" ); + } ); // get position tests = [ - { "id": "#static-1", "top": ie ? 5 : 6, "left": 6 }, - { "id": "#static-1-1", "top": ie ? 12 : 14, "left": 14 }, - { "id": "#static-1-1-1", "top": ie ? 19 : 22, "left": 22 }, - { "id": "#static-2", "top": ie ? 120 : 121, "left": 6 } + { "id": "#static-1", "top": 6, "left": 6 }, + { "id": "#static-1-1", "top": 14, "left": 14 }, + { "id": "#static-1-1-1", "top": 22, "left": 22 }, + { "id": "#static-2", "top": 121, "left": 6 } ]; jQuery.each( tests, function() { - equal( $( this["id"] ).position().top, this["top"], "jQuery('" + this["top"] + "').position().top" ); - equal( $( this["id"] ).position().left, this["left"], "jQuery('" + this["left"] +"').position().left" ); - }); - + assert.equal( $( this.id ).position().top, this.top, "jQuery('" + this.top + "').position().top" ); + assert.equal( $( this.id ).position().left, this.left, "jQuery('" + this.left + "').position().left" ); + } ); // set offset tests = [ @@ -296,66 +311,64 @@ { "id": "#static-1", "top": 7, "left": 7 } ]; jQuery.each( tests, function() { - $( this["id"] ).offset({ "top": this["top"], "left": this["left"] }); - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" ); + $( this.id ).offset( { "top": this.top, "left": this.left } ); + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); - $( this["id"] ).offset({ "top": this["top"], "left": this["left"], "using": function( props ) { - $( this ).css({ + $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { + $( this ).css( { "top": props.top + 1, "left": props.left + 1 - }); - }}); - equal( $( this["id"] ).offset().top, this["top"] + 1, "jQuery('" + this["id"] + "').offset({ top: " + (this["top"] + 1) + ", using: fn })" ); - equal( $( this["id"] ).offset().left, this["left"] + 1, "jQuery('" + this["id"] + "').offset({ left: " + (this["left"] + 1) + ", using: fn })" ); - }); -}); - -testIframe("offset/fixed", "fixed", function( $ ) { - expect(34); + } ); + } } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); + } ); +} ); - var ie, tests, $noTopLeft; +testIframe( "fixed", "offset/fixed.html", function( assert, $, window ) { + assert.expect( 34 ); - // IE is collapsing the top margin of 1px; detect and adjust accordingly - ie = $("#fixed-1").position().top === 2; + var tests, $noTopLeft; tests = [ { "id": "#fixed-1", "offsetTop": 1001, "offsetLeft": 1001, - "positionTop": ie ? 2 : 0, - "positionLeft": ie ? 2 : 0 + "positionTop": 0, + "positionLeft": 0 }, { "id": "#fixed-2", "offsetTop": 1021, "offsetLeft": 1021, - "positionTop": ie ? 22 : 20, - "positionLeft": ie ? 22 : 20 + "positionTop": 20, + "positionLeft": 20 } ]; jQuery.each( tests, function() { if ( !window.supportsScroll ) { - ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); } else if ( window.supportsFixedPosition ) { - equal( $( this["id"] ).offset().top, this["offsetTop"], "jQuery('" + this["id"] + "').offset().top" ); - equal( $( this["id"] ).position().top, this["positionTop"], "jQuery('" + this["id"] + "').position().top" ); - equal( $( this["id"] ).offset().left, this["offsetLeft"], "jQuery('" + this["id"] + "').offset().left" ); - equal( $( this["id"] ).position().left, this["positionLeft"], "jQuery('" + this["id"] + "').position().left" ); + assert.equal( $( this.id ).offset().top, this.offsetTop, "jQuery('" + this.id + "').offset().top" ); + assert.equal( $( this.id ).position().top, this.positionTop, "jQuery('" + this.id + "').position().top" ); + assert.equal( $( this.id ).offset().left, this.offsetLeft, "jQuery('" + this.id + "').offset().left" ); + assert.equal( $( this.id ).position().left, this.positionLeft, "jQuery('" + this.id + "').position().left" ); } else { + // need to have same number of assertions - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); } - }); + } ); tests = [ { "id": "#fixed-1", "top": 100, "left": 100 }, @@ -368,192 +381,221 @@ jQuery.each( tests, function() { if ( window.supportsFixedPosition ) { - $( this["id"] ).offset({ "top": this["top"], "left": this["left"] }); - equal( $( this["id"] ).offset().top, this["top"], "jQuery('" + this["id"] + "').offset({ top: " + this["top"] + " })" ); - equal( $( this["id"] ).offset().left, this["left"], "jQuery('" + this["id"] + "').offset({ left: " + this["left"] + " })" ); + $( this.id ).offset( { "top": this.top, "left": this.left } ); + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); - $( this["id"] ).offset({ "top": this["top"], "left": this["left"], "using": function( props ) { - $( this ).css({ + $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { + $( this ).css( { "top": props.top + 1, "left": props.left + 1 - }); - }}); - equal( $( this["id"] ).offset().top, this["top"] + 1, "jQuery('" + this["id"] + "').offset({ top: " + (this["top"] + 1) + ", using: fn })" ); - equal( $( this["id"] ).offset().left, this["left"] + 1, "jQuery('" + this["id"] + "').offset({ left: " + (this["left"] + 1) + ", using: fn })" ); + } ); + } } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); } else { + // need to have same number of assertions - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); } - }); + } ); // Bug 8316 - $noTopLeft = $("#fixed-no-top-left"); + $noTopLeft = $( "#fixed-no-top-left" ); if ( window.supportsFixedPosition ) { - equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); - equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); + assert.equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); + assert.equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); } else { + // need to have same number of assertions - ok( true, "Fixed position is not supported" ); - ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); + assert.ok( true, "Fixed position is not supported" ); } -}); +} ); -testIframe("offset/table", "table", function( $ ) { - expect(4); +testIframe( "table", "offset/table.html", function( assert, $ ) { + assert.expect( 4 ); - equal( $("#table-1").offset().top, 6, "jQuery('#table-1').offset().top" ); - equal( $("#table-1").offset().left, 6, "jQuery('#table-1').offset().left" ); + assert.equal( $( "#table-1" ).offset().top, 6, "jQuery('#table-1').offset().top" ); + assert.equal( $( "#table-1" ).offset().left, 6, "jQuery('#table-1').offset().left" ); - equal( $("#th-1").offset().top, 10, "jQuery('#th-1').offset().top" ); - equal( $("#th-1").offset().left, 10, "jQuery('#th-1').offset().left" ); -}); + assert.equal( $( "#th-1" ).offset().top, 10, "jQuery('#th-1').offset().top" ); + assert.equal( $( "#th-1" ).offset().left, 10, "jQuery('#th-1').offset().left" ); +} ); -testIframe("offset/scroll", "scroll", function( $, win ) { - expect(24); +testIframe( "scroll", "offset/scroll.html", function( assert, $, win ) { + assert.expect( 26 ); - // If we're going to bastardize the tests, let's just DO it - var ie = /msie [678]/i.test( navigator.userAgent ); + assert.equal( $( "#scroll-1" ).offset().top, 7, "jQuery('#scroll-1').offset().top" ); + assert.equal( $( "#scroll-1" ).offset().left, 7, "jQuery('#scroll-1').offset().left" ); - if ( ie ) { - ok( true, "TestSwarm's iframe has hosed this test in oldIE, we surrender" ); - } else { - equal( $("#scroll-1").offset().top, 7, "jQuery('#scroll-1').offset().top" ); - } - equal( $("#scroll-1").offset().left, 7, "jQuery('#scroll-1').offset().left" ); + assert.equal( $( "#scroll-1-1" ).offset().top, 11, "jQuery('#scroll-1-1').offset().top" ); + assert.equal( $( "#scroll-1-1" ).offset().left, 11, "jQuery('#scroll-1-1').offset().left" ); - if ( ie ) { - ok( true, "TestSwarm's iframe has hosed this test in oldIE, we surrender" ); - } else { - equal( $("#scroll-1-1").offset().top, 11, "jQuery('#scroll-1-1').offset().top" ); - } - equal( $("#scroll-1-1").offset().left, 11, "jQuery('#scroll-1-1').offset().left" ); + // These tests are solely for master/compat consistency + // Retrieving offset on disconnected/hidden elements is not officially + // valid input, but will return zeros for back-compat + assert.equal( $( "#hidden" ).offset().top, 0, "Hidden elements do not subtract scroll" ); + assert.equal( $( "#hidden" ).offset().left, 0, "Hidden elements do not subtract scroll" ); // scroll offset tests .scrollTop/Left - equal( $("#scroll-1").scrollTop(), 5, "jQuery('#scroll-1').scrollTop()" ); - equal( $("#scroll-1").scrollLeft(), 5, "jQuery('#scroll-1').scrollLeft()" ); + assert.equal( $( "#scroll-1" ).scrollTop(), 5, "jQuery('#scroll-1').scrollTop()" ); + assert.equal( $( "#scroll-1" ).scrollLeft(), 5, "jQuery('#scroll-1').scrollLeft()" ); - equal( $("#scroll-1-1").scrollTop(), 0, "jQuery('#scroll-1-1').scrollTop()" ); - equal( $("#scroll-1-1").scrollLeft(), 0, "jQuery('#scroll-1-1').scrollLeft()" ); + assert.equal( $( "#scroll-1-1" ).scrollTop(), 0, "jQuery('#scroll-1-1').scrollTop()" ); + assert.equal( $( "#scroll-1-1" ).scrollLeft(), 0, "jQuery('#scroll-1-1').scrollLeft()" ); // scroll method chaining - equal( $("#scroll-1").scrollTop(undefined).scrollTop(), 5, ".scrollTop(undefined) is chainable (#5571)" ); - equal( $("#scroll-1").scrollLeft(undefined).scrollLeft(), 5, ".scrollLeft(undefined) is chainable (#5571)" ); + assert.equal( $( "#scroll-1" ).scrollTop( undefined ).scrollTop(), 5, ".scrollTop(undefined) is chainable (#5571)" ); + assert.equal( $( "#scroll-1" ).scrollLeft( undefined ).scrollLeft(), 5, ".scrollLeft(undefined) is chainable (#5571)" ); win.name = "test"; if ( !window.supportsScroll ) { - ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); - ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); + assert.ok( true, "Browser doesn't support scroll position." ); } else { - equal( $(win).scrollTop(), 1000, "jQuery(window).scrollTop()" ); - equal( $(win).scrollLeft(), 1000, "jQuery(window).scrollLeft()" ); + assert.equal( $( win ).scrollTop(), 1000, "jQuery(window).scrollTop()" ); + assert.equal( $( win ).scrollLeft(), 1000, "jQuery(window).scrollLeft()" ); - equal( $(win.document).scrollTop(), 1000, "jQuery(document).scrollTop()" ); - equal( $(win.document).scrollLeft(), 1000, "jQuery(document).scrollLeft()" ); + assert.equal( $( win.document ).scrollTop(), 1000, "jQuery(document).scrollTop()" ); + assert.equal( $( win.document ).scrollLeft(), 1000, "jQuery(document).scrollLeft()" ); } // test jQuery using parent window/document // jQuery reference here is in the iframe - window.scrollTo(0,0); - equal( $(window).scrollTop(), 0, "jQuery(window).scrollTop() other window" ); - equal( $(window).scrollLeft(), 0, "jQuery(window).scrollLeft() other window" ); - equal( $(document).scrollTop(), 0, "jQuery(window).scrollTop() other document" ); - equal( $(document).scrollLeft(), 0, "jQuery(window).scrollLeft() other document" ); + window.scrollTo( 0, 0 ); + assert.equal( $( window ).scrollTop(), 0, "jQuery(window).scrollTop() other window" ); + assert.equal( $( window ).scrollLeft(), 0, "jQuery(window).scrollLeft() other window" ); + assert.equal( $( document ).scrollTop(), 0, "jQuery(window).scrollTop() other document" ); + assert.equal( $( document ).scrollLeft(), 0, "jQuery(window).scrollLeft() other document" ); // Tests scrollTop/Left with empty jquery objects - notEqual( $().scrollTop(100), null, "jQuery().scrollTop(100) testing setter on empty jquery object" ); - notEqual( $().scrollLeft(100), null, "jQuery().scrollLeft(100) testing setter on empty jquery object" ); - notEqual( $().scrollTop(null), null, "jQuery().scrollTop(null) testing setter on empty jquery object" ); - notEqual( $().scrollLeft(null), null, "jQuery().scrollLeft(null) testing setter on empty jquery object" ); - strictEqual( $().scrollTop(), null, "jQuery().scrollTop(100) testing setter on empty jquery object" ); - strictEqual( $().scrollLeft(), null, "jQuery().scrollLeft(100) testing setter on empty jquery object" ); -}); - -testIframe("offset/body", "body", function( $ ) { - expect(4); - - equal( $("body").offset().top, 1, "jQuery('#body').offset().top" ); - equal( $("body").offset().left, 1, "jQuery('#body').offset().left" ); - equal( $("#firstElement").position().left, 5, "$('#firstElement').position().left" ); - equal( $("#firstElement").position().top, 5, "$('#firstElement').position().top" ); -}); + assert.notEqual( $().scrollTop( 100 ), null, "jQuery().scrollTop(100) testing setter on empty jquery object" ); + assert.notEqual( $().scrollLeft( 100 ), null, "jQuery().scrollLeft(100) testing setter on empty jquery object" ); + assert.notEqual( $().scrollTop( null ), null, "jQuery().scrollTop(null) testing setter on empty jquery object" ); + assert.notEqual( $().scrollLeft( null ), null, "jQuery().scrollLeft(null) testing setter on empty jquery object" ); + assert.strictEqual( $().scrollTop(), undefined, "jQuery().scrollTop() testing getter on empty jquery object" ); + assert.strictEqual( $().scrollLeft(), undefined, "jQuery().scrollLeft() testing getter on empty jquery object" ); +} ); + +testIframe( "body", "offset/body.html", function( assert, $ ) { + assert.expect( 4 ); + + assert.equal( $( "body" ).offset().top, 1, "jQuery('#body').offset().top" ); + assert.equal( $( "body" ).offset().left, 1, "jQuery('#body').offset().left" ); + assert.equal( $( "#firstElement" ).position().left, 5, "$('#firstElement').position().left" ); + assert.equal( $( "#firstElement" ).position().top, 5, "$('#firstElement').position().top" ); +} ); + +QUnit.test( "chaining", function( assert ) { + assert.expect( 3 ); -test("chaining", function() { - expect(3); var coords = { "top": 1, "left": 1 }; - equal( jQuery("#absolute-1").offset(coords).selector, "#absolute-1", "offset(coords) returns jQuery object" ); - equal( jQuery("#non-existent").offset(coords).selector, "#non-existent", "offset(coords) with empty jQuery set returns jQuery object" ); - equal( jQuery("#absolute-1").offset(undefined).selector, "#absolute-1", "offset(undefined) returns jQuery object (#5571)" ); -}); + assert.equal( jQuery( "#absolute-1" ).offset( coords ).jquery, jQuery.fn.jquery, "offset(coords) returns jQuery object" ); + assert.equal( jQuery( "#non-existent" ).offset( coords ).jquery, jQuery.fn.jquery, "offset(coords) with empty jQuery set returns jQuery object" ); + assert.equal( jQuery( "#absolute-1" ).offset( undefined ).jquery, jQuery.fn.jquery, "offset(undefined) returns jQuery object (#5571)" ); +} ); -test("offsetParent", function(){ - expect(13); +QUnit.test( "offsetParent", function( assert ) { + assert.expect( 13 ); var body, header, div, area; - body = jQuery("body").offsetParent(); - equal( body.length, 1, "Only one offsetParent found." ); - equal( body[0], document.documentElement, "The html element is the offsetParent of the body." ); - - header = jQuery("#qunit").offsetParent(); - equal( header.length, 1, "Only one offsetParent found." ); - equal( header[0], document.documentElement, "The html element is the offsetParent of #qunit." ); - - div = jQuery("#nothiddendivchild").offsetParent(); - equal( div.length, 1, "Only one offsetParent found." ); - equal( div[0], document.getElementById("qunit-fixture"), "The #qunit-fixture is the offsetParent of #nothiddendivchild." ); - - jQuery("#nothiddendiv").css("position", "relative"); - - div = jQuery("#nothiddendivchild").offsetParent(); - equal( div.length, 1, "Only one offsetParent found." ); - equal( div[0], jQuery("#nothiddendiv")[0], "The div is the offsetParent." ); - - div = jQuery("body, #nothiddendivchild").offsetParent(); - equal( div.length, 2, "Two offsetParent found." ); - equal( div[0], document.documentElement, "The html element is the offsetParent of the body." ); - equal( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." ); + body = jQuery( "body" ).offsetParent(); + assert.equal( body.length, 1, "Only one offsetParent found." ); + assert.equal( body[ 0 ], document.documentElement, "The html element is the offsetParent of the body." ); + + header = jQuery( "#qunit" ).offsetParent(); + assert.equal( header.length, 1, "Only one offsetParent found." ); + assert.equal( header[ 0 ], document.documentElement, "The html element is the offsetParent of #qunit." ); + + div = jQuery( "#nothiddendivchild" ).offsetParent(); + assert.equal( div.length, 1, "Only one offsetParent found." ); + assert.equal( div[ 0 ], document.getElementById( "qunit-fixture" ), "The #qunit-fixture is the offsetParent of #nothiddendivchild." ); + + jQuery( "#nothiddendiv" ).css( "position", "relative" ); + + div = jQuery( "#nothiddendivchild" ).offsetParent(); + assert.equal( div.length, 1, "Only one offsetParent found." ); + assert.equal( div[ 0 ], jQuery( "#nothiddendiv" )[ 0 ], "The div is the offsetParent." ); + + div = jQuery( "body, #nothiddendivchild" ).offsetParent(); + assert.equal( div.length, 2, "Two offsetParent found." ); + assert.equal( div[ 0 ], document.documentElement, "The html element is the offsetParent of the body." ); + assert.equal( div[ 1 ], jQuery( "#nothiddendiv" )[ 0 ], "The div is the offsetParent." ); - area = jQuery("#imgmap area").offsetParent(); - equal( area[0], document.documentElement, "The html element is the offsetParent of the body." ); + area = jQuery( "#imgmap area" ).offsetParent(); + assert.equal( area[ 0 ], document.documentElement, "The html element is the offsetParent of the body." ); - div = jQuery("
").css({ "position": "absolute" }).appendTo("body"); - equal( div.offsetParent()[0], document.documentElement, "Absolutely positioned div returns html as offset parent, see #12139" ); + div = jQuery( "
" ).css( { "position": "absolute" } ).appendTo( "body" ); + assert.equal( div.offsetParent()[ 0 ], document.documentElement, "Absolutely positioned div returns html as offset parent, see #12139" ); div.remove(); -}); +} ); -test("fractions (see #7730 and #7885)", function() { - expect(2); +QUnit.test( "fractions (see #7730 and #7885)", function( assert ) { + assert.expect( 2 ); - jQuery("body").append("
"); + jQuery( "body" ).append( "
" ); var result, expected = { "top": 1000, "left": 1000 }, - div = jQuery("#fractions"); + div = jQuery( "#fractions" ); - div.css({ + div.css( { "position": "absolute", "left": "1000.7432222px", "top": "1000.532325px", "width": 100, "height": 100 - }); + } ); - div.offset(expected); + div.offset( expected ); result = div.offset(); - equal( result.top, expected.top, "Check top" ); - equal( result.left, expected.left, "Check left" ); + // Support: Chrome <=45 - 46 + // In recent Chrome these values differ a little. + assert.ok( Math.abs( result.top - expected.top ) < 0.25, "Check top within 0.25 of expected" ); + assert.equal( result.left, expected.left, "Check left" ); div.remove(); -}); +} ); + +QUnit.test( "iframe scrollTop/Left (see gh-1945)", function( assert ) { + assert.expect( 2 ); + + var ifDoc = jQuery( "#iframe" )[ 0 ].contentDocument; + + // Mobile Safari resize the iframe by its content meaning it's not possible to scroll + // the iframe but only its parent element. + // It seems (not confirmed) in android 4.0 it's not possible to scroll iframes from the code. + if ( + /iphone os/i.test( navigator.userAgent ) || + /android 4\.0/i.test( navigator.userAgent ) + ) { + assert.equal( true, true, "Can't scroll iframes in this environment" ); + assert.equal( true, true, "Can't scroll iframes in this environment" ); + + } else { + + // Tests scrollTop/Left with iframes + jQuery( "#iframe" ).css( "width", "50px" ).css( "height", "50px" ); + ifDoc.write( "
" ); + + jQuery( ifDoc ).scrollTop( 200 ); + jQuery( ifDoc ).scrollLeft( 500 ); + + assert.equal( jQuery( ifDoc ).scrollTop(), 200, "$($('#iframe')[0].contentDocument).scrollTop()" ); + assert.equal( jQuery( ifDoc ).scrollLeft(), 500, "$($('#iframe')[0].contentDocument).scrollLeft()" ); + } +} ); -})(); +} )(); diff -Nru jquery-1.11.3+dfsg/test/unit/queue.js jquery-3.2.1/test/unit/queue.js --- jquery-1.11.3+dfsg/test/unit/queue.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/queue.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,274 +1,287 @@ -module( "queue", { teardown: moduleTeardown }); +QUnit.module( "queue", { teardown: moduleTeardown } ); -test( "queue() with other types", 14, function() { - stop(); +QUnit.test( "queue() with other types", function( assert ) { + assert.expect( 14 ); - var $div = jQuery({}), + QUnit.stop(); + + var $div = jQuery( {} ), counter = 0; - $div.promise( "foo" ).done(function() { - equal( counter, 0, "Deferred for collection with no queue is automatically resolved" ); - }); + $div.promise( "foo" ).done( function() { + assert.equal( counter, 0, "Deferred for collection with no queue is automatically resolved" ); + } ); $div - .queue("foo",function(){ - equal( ++counter, 1, "Dequeuing" ); - jQuery.dequeue(this,"foo"); - }) - .queue("foo",function(){ - equal( ++counter, 2, "Dequeuing" ); - jQuery(this).dequeue("foo"); - }) - .queue("foo",function(){ - equal( ++counter, 3, "Dequeuing" ); - }) - .queue("foo",function(){ - equal( ++counter, 4, "Dequeuing" ); - }); + .queue( "foo", function() { + assert.equal( ++counter, 1, "Dequeuing" ); + jQuery.dequeue( this, "foo" ); + } ) + .queue( "foo", function() { + assert.equal( ++counter, 2, "Dequeuing" ); + jQuery( this ).dequeue( "foo" ); + } ) + .queue( "foo", function() { + assert.equal( ++counter, 3, "Dequeuing" ); + } ) + .queue( "foo", function() { + assert.equal( ++counter, 4, "Dequeuing" ); + } ); - $div.promise("foo").done(function() { - equal( counter, 4, "Testing previous call to dequeue in deferred" ); - start(); - }); + $div.promise( "foo" ).done( function() { + assert.equal( counter, 4, "Testing previous call to dequeue in deferred" ); + QUnit.start(); + } ); - equal( $div.queue("foo").length, 4, "Testing queue length" ); + assert.equal( $div.queue( "foo" ).length, 4, "Testing queue length" ); - equal( $div.queue("foo", undefined).queue("foo").length, 4, ".queue('name',undefined) does nothing but is chainable (#5571)"); + assert.equal( $div.queue( "foo", undefined ).queue( "foo" ).length, 4, ".queue('name',undefined) does nothing but is chainable (#5571)" ); - $div.dequeue("foo"); + $div.dequeue( "foo" ); - equal( counter, 3, "Testing previous call to dequeue" ); - equal( $div.queue("foo").length, 1, "Testing queue length" ); + assert.equal( counter, 3, "Testing previous call to dequeue" ); + assert.equal( $div.queue( "foo" ).length, 1, "Testing queue length" ); - $div.dequeue("foo"); + $div.dequeue( "foo" ); - equal( counter, 4, "Testing previous call to dequeue" ); - equal( $div.queue("foo").length, 0, "Testing queue length" ); + assert.equal( counter, 4, "Testing previous call to dequeue" ); + assert.equal( $div.queue( "foo" ).length, 0, "Testing queue length" ); - $div.dequeue("foo"); + $div.dequeue( "foo" ); - equal( counter, 4, "Testing previous call to dequeue" ); - equal( $div.queue("foo").length, 0, "Testing queue length" ); + assert.equal( counter, 4, "Testing previous call to dequeue" ); + assert.equal( $div.queue( "foo" ).length, 0, "Testing queue length" ); -}); +} ); -test("queue(name) passes in the next item in the queue as a parameter", function() { - expect(2); +QUnit.test( "queue(name) passes in the next item in the queue as a parameter", function( assert ) { + assert.expect( 2 ); - var div = jQuery({}), + var div = jQuery( {} ), counter = 0; - div.queue("foo", function(next) { - equal(++counter, 1, "Dequeueing"); + div.queue( "foo", function( next ) { + assert.equal( ++counter, 1, "Dequeueing" ); next(); - }).queue("foo", function(next) { - equal(++counter, 2, "Next was called"); + } ).queue( "foo", function( next ) { + assert.equal( ++counter, 2, "Next was called" ); next(); - }).queue("bar", function() { - equal(++counter, 3, "Other queues are not triggered by next()"); - }); - - div.dequeue("foo"); -}); - -test("queue() passes in the next item in the queue as a parameter to fx queues", function() { - expect(3); - stop(); + } ).queue( "bar", function() { + assert.equal( ++counter, 3, "Other queues are not triggered by next()" ); + } ); + + div.dequeue( "foo" ); +} ); + +QUnit.test( "queue() passes in the next item in the queue as a parameter to fx queues", function( assert ) { + assert.expect( 3 ); + QUnit.stop(); - var div = jQuery({}), + var div = jQuery( {} ), counter = 0; - div.queue(function( next ) { - equal(++counter, 1, "Dequeueing"); - setTimeout(function() { next(); }, 500); - }).queue(function(next) { - equal(++counter, 2, "Next was called"); + div.queue( function( next ) { + assert.equal( ++counter, 1, "Dequeueing" ); + setTimeout( function() { next(); }, 500 ); + } ).queue( function( next ) { + assert.equal( ++counter, 2, "Next was called" ); next(); - }).queue("bar", function() { - equal(++counter, 3, "Other queues are not triggered by next()"); - }); - - jQuery.when( div.promise("fx"), div ).done(function() { - equal(counter, 2, "Deferreds resolved"); - start(); - }); -}); - -test("callbacks keep their place in the queue", function() { - expect(5); - stop(); - var div = jQuery("
"), + } ).queue( "bar", function() { + assert.equal( ++counter, 3, "Other queues are not triggered by next()" ); + } ); + + jQuery.when( div.promise( "fx" ), div ).done( function() { + assert.equal( counter, 2, "Deferreds resolved" ); + QUnit.start(); + } ); +} ); + +QUnit.test( "callbacks keep their place in the queue", function( assert ) { + assert.expect( 5 ); + QUnit.stop(); + var div = jQuery( "
" ), counter = 0; - div.queue(function( next ) { - equal( ++counter, 1, "Queue/callback order: first called" ); + div.queue( function( next ) { + assert.equal( ++counter, 1, "Queue/callback order: first called" ); setTimeout( next, 200 ); - }).delay( 100 ).queue(function( next ) { - equal( ++counter, 2, "Queue/callback order: second called" ); - jQuery( this ).delay( 100 ).queue(function( next ) { - equal( ++counter, 4, "Queue/callback order: fourth called" ); + } ).delay( 100 ).queue( function( next ) { + assert.equal( ++counter, 2, "Queue/callback order: second called" ); + jQuery( this ).delay( 100 ).queue( function( next ) { + assert.equal( ++counter, 4, "Queue/callback order: fourth called" ); next(); - }); + } ); next(); - }).queue(function( next ) { - equal( ++counter, 3, "Queue/callback order: third called" ); + } ).queue( function( next ) { + assert.equal( ++counter, 3, "Queue/callback order: third called" ); next(); - }); + } ); + + div.promise( "fx" ).done( function() { + assert.equal( counter, 4, "Deferreds resolved" ); + QUnit.start(); + } ); +} ); + +QUnit.test( "jQuery.queue should return array while manipulating the queue", function( assert ) { + assert.expect( 1 ); + + var div = document.createElement( "div" ); - div.promise("fx").done(function() { - equal(counter, 4, "Deferreds resolved"); - start(); - }); -}); + assert.ok( Array.isArray( jQuery.queue( div, "fx", jQuery.noop ) ), "jQuery.queue should return an array while manipulating the queue" ); +} ); -test("delay()", function() { - expect(2); - stop(); +QUnit.test( "delay()", function( assert ) { + assert.expect( 2 ); + QUnit.stop(); - var foo = jQuery({}), run = 0; + var foo = jQuery( {} ), run = 0; - foo.delay(100).queue(function(){ + foo.delay( 100 ).queue( function() { run = 1; - ok( true, "The function was dequeued." ); - start(); - }); + assert.ok( true, "The function was dequeued." ); + QUnit.start(); + } ); - equal( run, 0, "The delay delayed the next function from running." ); -}); + assert.equal( run, 0, "The delay delayed the next function from running." ); +} ); -test("clearQueue(name) clears the queue", function() { - expect(2); +QUnit.test( "clearQueue(name) clears the queue", function( assert ) { + assert.expect( 2 ); - stop(); + QUnit.stop(); - var div = jQuery({}), + var div = jQuery( {} ), counter = 0; - div.queue("foo", function( next ) { + div.queue( "foo", function( next ) { counter++; - jQuery(this).clearQueue("foo"); + jQuery( this ).clearQueue( "foo" ); next(); - }).queue("foo", function() { + } ).queue( "foo", function() { counter++; - }); + } ); - div.promise("foo").done(function() { - ok( true, "dequeue resolves the deferred" ); - start(); - }); + div.promise( "foo" ).done( function() { + assert.ok( true, "dequeue resolves the deferred" ); + QUnit.start(); + } ); - div.dequeue("foo"); + div.dequeue( "foo" ); - equal(counter, 1, "the queue was cleared"); -}); + assert.equal( counter, 1, "the queue was cleared" ); +} ); -test("clearQueue() clears the fx queue", function() { - expect(1); +QUnit.test( "clearQueue() clears the fx queue", function( assert ) { + assert.expect( 1 ); - var div = jQuery({}), + var div = jQuery( {} ), counter = 0; - div.queue(function( next ) { + div.queue( function( next ) { counter++; var self = this; - setTimeout(function() { jQuery(self).clearQueue(); next(); }, 50); - }).queue(function() { + setTimeout( function() { jQuery( self ).clearQueue(); next(); }, 50 ); + } ).queue( function() { counter++; - }); + } ); - equal(counter, 1, "the queue was cleared"); + assert.equal( counter, 1, "the queue was cleared" ); div.removeData(); -}); +} ); -asyncTest( "fn.promise() - called when fx queue is empty", 3, function() { +QUnit.asyncTest( "fn.promise() - called when fx queue is empty", 3, function( assert ) { var foo = jQuery( "#foo" ).clone().addBack(), promised = false; foo.queue( function( next ) { + // called twice! - ok( !promised, "Promised hasn't been called" ); + assert.ok( !promised, "Promised hasn't been called" ); setTimeout( next, 10 ); - }); + } ); foo.promise().done( function() { - ok( promised = true, "Promised" ); - start(); - }); -}); + assert.ok( promised = true, "Promised" ); + QUnit.start(); + } ); +} ); -asyncTest( "fn.promise( \"queue\" ) - called whenever last queue function is dequeued", 5, function() { +QUnit.asyncTest( "fn.promise( \"queue\" ) - called whenever last queue function is dequeued", 5, function( assert ) { var foo = jQuery( "#foo" ), test; foo.promise( "queue" ).done( function() { - strictEqual( test, undefined, "called immediately when queue was already empty" ); - }); + assert.strictEqual( test, undefined, "called immediately when queue was already empty" ); + } ); test = 1; foo.queue( "queue", function( next ) { - strictEqual( test++, 1, "step one" ); + assert.strictEqual( test++, 1, "step one" ); setTimeout( next, 0 ); - }).queue( "queue", function( next ) { - strictEqual( test++, 2, "step two" ); + } ).queue( "queue", function( next ) { + assert.strictEqual( test++, 2, "step two" ); setTimeout( function() { next(); - strictEqual( test++, 4, "step four" ); - start(); + assert.strictEqual( test++, 4, "step four" ); + QUnit.start(); }, 10 ); - }).promise( "queue" ).done( function() { - strictEqual( test++, 3, "step three" ); - }); + } ).promise( "queue" ).done( function() { + assert.strictEqual( test++, 3, "step three" ); + } ); foo.dequeue( "queue" ); -}); +} ); + +if ( jQuery.fn.animate ) { -asyncTest( "fn.promise( \"queue\" ) - waits for animation to complete before resolving", 2, function() { +QUnit.asyncTest( "fn.promise( \"queue\" ) - waits for animation to complete before resolving", 2, function( assert ) { var foo = jQuery( "#foo" ), test = 1; - foo.animate({ + foo.animate( { top: 100 }, { duration: 1, queue: "queue", complete: function() { - strictEqual( test++, 1, "step one" ); + assert.strictEqual( test++, 1, "step one" ); } - }).dequeue( "queue" ); + } ).dequeue( "queue" ); foo.promise( "queue" ).done( function() { - strictEqual( test++, 2, "step two" ); - start(); - }); + assert.strictEqual( test++, 2, "step two" ); + QUnit.start(); + } ); -}); +} ); +} -test( ".promise(obj)", function() { - expect(2); +QUnit.test( ".promise(obj)", function( assert ) { + assert.expect( 2 ); var obj = {}, promise = jQuery( "#foo" ).promise( "promise", obj ); - ok( jQuery.isFunction( promise.promise ), ".promise(type, obj) returns a promise" ); - strictEqual( promise, obj, ".promise(type, obj) returns obj" ); -}); - + assert.ok( jQuery.isFunction( promise.promise ), ".promise(type, obj) returns a promise" ); + assert.strictEqual( promise, obj, ".promise(type, obj) returns obj" ); +} ); if ( jQuery.fn.stop ) { - test("delay() can be stopped", function() { - expect( 3 ); - stop(); + QUnit.test( "delay() can be stopped", function( assert ) { + assert.expect( 3 ); + QUnit.stop(); var done = {}; - jQuery({}) + jQuery( {} ) .queue( "alternate", function( next ) { done.alt1 = true; - ok( true, "This first function was dequeued" ); + assert.ok( true, "This first function was dequeued" ); next(); - }) + } ) .delay( 1000, "alternate" ) .queue( "alternate", function() { done.alt2 = true; - ok( true, "The function was dequeued immediately, the delay was stopped" ); - }) + assert.ok( true, "The function was dequeued immediately, the delay was stopped" ); + } ) .dequeue( "alternate" ) // stop( "alternate", false ) will NOT clear the queue, so it should automatically dequeue the next @@ -276,39 +289,39 @@ // this test .delay( 1 ) - .queue(function() { + .queue( function() { done.default1 = true; - ok( false, "This queue should never run" ); - }) + assert.ok( false, "This queue should never run" ); + } ) // stop( clearQueue ) should clear the queue .stop( true, false ); - deepEqual( done, { alt1: true, alt2: true }, "Queue ran the proper functions" ); + assert.deepEqual( done, { alt1: true, alt2: true }, "Queue ran the proper functions" ); - setTimeout(function() { - start(); + setTimeout( function() { + QUnit.start(); }, 1500 ); - }); + } ); - asyncTest( "queue stop hooks", 2, function() { + QUnit.asyncTest( "queue stop hooks", 2, function( assert ) { var foo = jQuery( "#foo" ); foo.queue( function( next, hooks ) { hooks.stop = function( gotoEnd ) { - equal( !!gotoEnd, false, "Stopped without gotoEnd" ); + assert.equal( !!gotoEnd, false, "Stopped without gotoEnd" ); }; - }); + } ); foo.stop(); foo.queue( function( next, hooks ) { hooks.stop = function( gotoEnd ) { - equal( gotoEnd, true, "Stopped with gotoEnd" ); - start(); + assert.equal( gotoEnd, true, "Stopped with gotoEnd" ); + QUnit.start(); }; - }); + } ); foo.stop( false, true ); - }); + } ); } // if ( jQuery.fn.stop ) diff -Nru jquery-1.11.3+dfsg/test/unit/ready.js jquery-3.2.1/test/unit/ready.js --- jquery-1.11.3+dfsg/test/unit/ready.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/ready.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,73 +1,163 @@ -module("event"); +QUnit.module( "ready" ); -(function(){ +( function() { var notYetReady, noEarlyExecution, + whenified = jQuery.when( jQuery.ready ), + promisified = Promise.resolve( jQuery.ready ), + start = new Date(), order = [], args = {}; notYetReady = !jQuery.isReady; - test("jQuery.isReady", function() { - expect(2); + QUnit.test( "jQuery.isReady", function( assert ) { + assert.expect( 2 ); - equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready"); - equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready"); - }); + assert.equal( notYetReady, true, "jQuery.isReady should not be true before DOM ready" ); + assert.equal( jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready" ); + } ); // Create an event handler. function makeHandler( testId ) { + // When returned function is executed, push testId onto `order` array // to ensure execution order. Also, store event handler arg to ensure // the correct arg is being passed into the event handler. return function( arg ) { - order.push(testId); - args[testId] = arg; + order.push( testId ); + args[ testId ] = arg; + }; + } + + function throwError( num ) { + + // Not a global QUnit failure + var onerror = window.onerror; + window.onerror = function() { + window.onerror = onerror; }; + + throw new Error( "Ready error " + num ); } // Bind to the ready event in every possible way. - jQuery(makeHandler("a")); - jQuery(document).ready(makeHandler("b")); - jQuery(document).on("ready.readytest", makeHandler("c")); - - // Do it twice, just to be sure. - jQuery(makeHandler("d")); - jQuery(document).ready(makeHandler("e")); - jQuery(document).on("ready.readytest", makeHandler("f")); + jQuery( makeHandler( "a" ) ); + jQuery( document ).ready( makeHandler( "b" ) ); + jQuery.ready.then( makeHandler( "c" ) ); + + // Throw in some errors + jQuery( function() { + throwError( 1 ); + } ); + jQuery( function() { + throwError( 2 ); + } ); + + // Bind again to ensure that the errors didn't lock everything up + jQuery( makeHandler( "d" ) ); + jQuery( document ).ready( makeHandler( "e" ) ); + jQuery.ready.then( makeHandler( "f" ) ); noEarlyExecution = order.length === 0; // This assumes that QUnit tests are run on DOM ready! - test("jQuery ready", function() { - expect(10); + QUnit.test( "jQuery ready", function( assert ) { + assert.expect( 10 ); - ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready"); + assert.ok( noEarlyExecution, + "Handlers bound to DOM ready should not execute before DOM ready" ); // Ensure execution order. - deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in on-order, but those bound with jQuery(document).on( 'ready', fn ) will always execute last"); + assert.deepEqual( order, [ "a", "b", "c", "d", "e", "f" ], + "Bound DOM ready handlers should execute in bind order" ); // Ensure handler argument is correct. - equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery"); - equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery"); - ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).on( 'ready', fn ) should be an event object"); + assert.equal( args.a, jQuery, + "Argument passed to fn in jQuery( fn ) should be jQuery" ); + assert.equal( args.b, jQuery, + "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" ); order = []; - // Now that the ready event has fired, again bind to the ready event - // in every possible way. These event handlers should execute immediately. - jQuery(makeHandler("g")); - equal(order.pop(), "g", "Event handler should execute immediately"); - equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery"); - - jQuery(document).ready(makeHandler("h")); - equal(order.pop(), "h", "Event handler should execute immediately"); - equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery"); - - jQuery(document).on("ready.readytest", makeHandler("never")); - equal(order.length, 0, "Event handler should never execute since DOM ready has already passed"); - - // Cleanup. - jQuery(document).off("ready.readytest"); - }); + // Now that the ready event has fired, again bind to the ready event. + // These ready handlers should execute asynchronously. + var done = assert.async(); + jQuery( makeHandler( "g" ) ); + jQuery( document ).ready( makeHandler( "h" ) ); + jQuery.ready.then( makeHandler( "i" ) ); + window.setTimeout( function() { + assert.equal( order.shift(), "g", + "Event handler should execute immediately, but async" ); + assert.equal( args.g, jQuery, + "Argument passed to fn in jQuery( fn ) should be jQuery" ); + + assert.equal( order.shift(), "h", + "Event handler should execute immediately, but async" ); + assert.equal( args.h, jQuery, + "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" ); + + assert.equal( order.shift(), "i", + "Event handler should execute immediately, but async" ); + assert.equal( args.h, jQuery, + "Argument passed to fn in jQuery.ready.then( fn ) should be jQuery" ); + + done(); + } ); + } ); + + QUnit.test( "jQuery.when(jQuery.ready)", function( assert ) { + assert.expect( 2 ); + var done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ); + + whenified.then( function() { + assert.ok( jQuery.isReady, "jQuery.when Deferred resolved" ); + done.pop()(); + } ); + + jQuery.when( jQuery.ready ).then( function() { + assert.ok( jQuery.isReady, "jQuery.when Deferred resolved" ); + done.pop()(); + } ); + } ); + + QUnit.test( "Promise.resolve(jQuery.ready)", function( assert ) { + assert.expect( 2 ); + var done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ); + + promisified.then( function() { + assert.ok( jQuery.isReady, "Native promised resolved" ); + done.pop()(); + } ); + + Promise.resolve( jQuery.ready ).then( function() { + assert.ok( jQuery.isReady, "Native promised resolved" ); + done.pop()(); + } ); + } ); + + QUnit.test( "Error in ready callback does not halt all future executions (gh-1823)", function( assert ) { + assert.expect( 1 ); + var done = assert.async(); + + jQuery( function() { + throwError( 3 ); + } ); + + jQuery( function() { + assert.ok( true, "Subsequent handler called" ); + done(); + } ); + } ); + + testIframe( + "holdReady test needs to be a standalone test since it deals with DOM ready", + "readywait.html", + function( assert, jQuery, window, document, releaseCalled ) { + assert.expect( 2 ); + var now = new Date(); + assert.ok( now - start >= 300, "Needs to have waited at least half a second" ); + assert.ok( releaseCalled, "The release function was called, which resulted in ready" ); + } + ); -})(); +} )(); diff -Nru jquery-1.11.3+dfsg/test/unit/selector.js jquery-3.2.1/test/unit/selector.js --- jquery-1.11.3+dfsg/test/unit/selector.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/selector.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,205 +1,216 @@ -module("selector", { teardown: moduleTeardown }); +QUnit.module( "selector", { teardown: moduleTeardown } ); /** * This test page is for selector tests that require jQuery in order to do the selection */ -test("element - jQuery only", function() { - expect( 7 ); +QUnit.test( "element", function( assert ) { + assert.expect( 7 ); - var fixture = document.getElementById("qunit-fixture"); + var fixture = document.getElementById( "qunit-fixture" ); - deepEqual( jQuery("p", fixture).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a Node context." ); - deepEqual( jQuery("p", "#qunit-fixture").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a selector context." ); - deepEqual( jQuery("p", jQuery("#qunit-fixture")).get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a jQuery object context." ); - deepEqual( jQuery("#qunit-fixture").find("p").get(), q("firstp","ap","sndp","en","sap","first"), "Finding elements with a context via .find()." ); + assert.deepEqual( jQuery( "p", fixture ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." ); + assert.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." ); + assert.deepEqual( jQuery( "p", jQuery( "#qunit-fixture" ) ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a jQuery object context." ); + assert.deepEqual( jQuery( "#qunit-fixture" ).find( "p" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a context via .find()." ); - ok( jQuery("#length").length, " cannot be found under IE, see #945" ); - ok( jQuery("#lengthtest input").length, " cannot be found under IE, see #945" ); + assert.ok( jQuery( "#length" ).length, " cannot be found under IE, see #945" ); + assert.ok( jQuery( "#lengthtest input" ).length, " cannot be found under IE, see #945" ); // #7533 - equal( jQuery("

foo

").find("p").length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" ); -}); + assert.equal( jQuery( "

foo

" ).find( "p" ).length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" ); +} ); -test("id", function() { - expect( 26 ); +QUnit.test( "id", function( assert ) { + assert.expect( 26 ); var a; - t( "ID Selector", "#body", ["body"] ); - t( "ID Selector w/ Element", "body#body", ["body"] ); - t( "ID Selector w/ Element", "ul#first", [] ); - t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] ); - t( "ID selector with non-existant descendant", "#firstp #foobar", [] ); - t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] ); - t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] ); - t( "Descendant ID selector using UTF8", "div #台北", ["台北"] ); - t( "Child ID selector using UTF8", "form > #台北", ["台北"] ); - - t( "Escaped ID", "#foo\\:bar", ["foo:bar"] ); - t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] ); - t( "Descendant escaped ID", "div #foo\\:bar", ["foo:bar"] ); - t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] ); - t( "Child escaped ID", "form > #foo\\:bar", ["foo:bar"] ); - t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] ); - - t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267 - t( "ID Selector, not an ancestor ID", "#form #first", [] ); - t( "ID Selector, not a child ID", "#form > #option1a", [] ); - - t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] ); - t( "All Children of ID with no children", "#firstUL > *", [] ); - - a = jQuery("").appendTo("#qunit-fixture"); - t( "ID Selector contains backslash", "#backslash\\\\foo", ["backslash\\foo"] ); - - t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", ["lengthtest"] ); - - t( "ID selector with non-existant ancestor", "#asdfasdf #foobar", [] ); // bug #986 - - t( "Underscore ID", "#types_all", ["types_all"] ); - t( "Dash ID", "#qunit-fixture", ["qunit-fixture"] ); - - t( "ID with weird characters in it", "#name\\+value", ["name+value"] ); -}); - -test("class - jQuery only", function() { - expect( 4 ); - - deepEqual( jQuery(".blog", document.getElementsByTagName("p")).get(), q("mark", "simon"), "Finding elements with a context." ); - deepEqual( jQuery(".blog", "p").get(), q("mark", "simon"), "Finding elements with a context." ); - deepEqual( jQuery(".blog", jQuery("p")).get(), q("mark", "simon"), "Finding elements with a context." ); - deepEqual( jQuery("p").find(".blog").get(), q("mark", "simon"), "Finding elements with a context." ); -}); + assert.t( "ID Selector", "#body", [ "body" ] ); + assert.t( "ID Selector w/ Element", "body#body", [ "body" ] ); + assert.t( "ID Selector w/ Element", "ul#first", [] ); + assert.t( "ID selector with existing ID descendant", "#firstp #simon1", [ "simon1" ] ); + assert.t( "ID selector with non-existent descendant", "#firstp #foobar", [] ); + assert.t( "ID selector using UTF8", "#台北Táiběi", [ "台北Táiběi" ] ); + assert.t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", [ "台北Táiběi", "台北" ] ); + assert.t( "Descendant ID selector using UTF8", "div #台北", [ "台北" ] ); + assert.t( "Child ID selector using UTF8", "form > #台北", [ "台北" ] ); + + assert.t( "Escaped ID", "#foo\\:bar", [ "foo:bar" ] ); + assert.t( "Escaped ID", "#test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); + assert.t( "Descendant escaped ID", "div #foo\\:bar", [ "foo:bar" ] ); + assert.t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); + assert.t( "Child escaped ID", "form > #foo\\:bar", [ "foo:bar" ] ); + assert.t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", [ "test.foo[5]bar" ] ); + + assert.t( "ID Selector, child ID present", "#form > #radio1", [ "radio1" ] ); // bug #267 + assert.t( "ID Selector, not an ancestor ID", "#form #first", [] ); + assert.t( "ID Selector, not a child ID", "#form > #option1a", [] ); + + assert.t( "All Children of ID", "#foo > *", [ "sndp", "en", "sap" ] ); + assert.t( "All Children of ID with no children", "#firstUL > *", [] ); + + a = jQuery( "" ).appendTo( "#qunit-fixture" ); + assert.t( "ID Selector contains backslash", "#backslash\\\\foo", [ "backslash\\foo" ] ); + + assert.t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", [ "lengthtest" ] ); + + assert.t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug #986 + + assert.t( "Underscore ID", "#types_all", [ "types_all" ] ); + assert.t( "Dash ID", "#qunit-fixture", [ "qunit-fixture" ] ); + + assert.t( "ID with weird characters in it", "#name\\+value", [ "name+value" ] ); +} ); + +QUnit.test( "class", function( assert ) { + assert.expect( 4 ); + + assert.deepEqual( jQuery( ".blog", document.getElementsByTagName( "p" ) ).get(), q( "mark", "simon" ), "Finding elements with a context." ); + assert.deepEqual( jQuery( ".blog", "p" ).get(), q( "mark", "simon" ), "Finding elements with a context." ); + assert.deepEqual( jQuery( ".blog", jQuery( "p" ) ).get(), q( "mark", "simon" ), "Finding elements with a context." ); + assert.deepEqual( jQuery( "p" ).find( ".blog" ).get(), q( "mark", "simon" ), "Finding elements with a context." ); +} ); -test("name", function() { - expect( 5 ); +QUnit.test( "name", function( assert ) { + assert.expect( 5 ); var form; - t( "Name selector", "input[name=action]", ["text1"] ); - t( "Name selector with single quotes", "input[name='action']", ["text1"] ); - t( "Name selector with double quotes", "input[name=\"action\"]", ["text1"] ); + assert.t( "Name selector", "input[name=action]", [ "text1" ] ); + assert.t( "Name selector with single quotes", "input[name='action']", [ "text1" ] ); + assert.t( "Name selector with double quotes", "input[name=\"action\"]", [ "text1" ] ); - t( "Name selector for grouped input", "input[name='types[]']", ["types_all", "types_anime", "types_movie"] ); + assert.t( "Name selector for grouped input", "input[name='types[]']", [ "types_all", "types_anime", "types_movie" ] ); - form = jQuery("
").appendTo("body"); - equal( jQuery("input", form[0]).length, 1, "Make sure that rooted queries on forms (with possible expandos) work." ); + form = jQuery( "
" ).appendTo( "body" ); + assert.equal( jQuery( "input", form[ 0 ] ).length, 1, "Make sure that rooted queries on forms (with possible expandos) work." ); form.remove(); -}); +} ); -test( "selectors with comma", function() { - expect( 4 ); +QUnit.test( "selectors with comma", function( assert ) { + assert.expect( 4 ); var fixture = jQuery( "

" ); - equal( fixture.find( "h2, div p" ).filter( "p" ).length, 2, "has to find two

" ); - equal( fixture.find( "h2, div p" ).filter( "h2" ).length, 1, "has to find one

" ); - equal( fixture.find( "h2 , div p" ).filter( "p" ).length, 2, "has to find two

" ); - equal( fixture.find( "h2 , div p" ).filter( "h2" ).length, 1, "has to find one

" ); -}); - -test( "child and adjacent", function() { - expect( 27 ); - - var nothiddendiv; - - t( "Child", "p > a", ["simon1","google","groups","mark","yahoo","simon"] ); - t( "Child", "p> a", ["simon1","google","groups","mark","yahoo","simon"] ); - t( "Child", "p >a", ["simon1","google","groups","mark","yahoo","simon"] ); - t( "Child", "p>a", ["simon1","google","groups","mark","yahoo","simon"] ); - t( "Child w/ Class", "p > a.blog", ["mark","simon"] ); - t( "All Children", "code > *", ["anchor1","anchor2"] ); - t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] ); - t( "Adjacent", "p + p", ["ap","en","sap"] ); - t( "Adjacent", "p#firstp + p", ["ap"] ); - t( "Adjacent", "p[lang=en] + p", ["sap"] ); - t( "Adjacent", "a.GROUPS + code + a", ["mark"] ); - t( "Element Preceded By", "#groups ~ a", ["mark"] ); - t( "Element Preceded By", "#length ~ input", ["idTest"] ); - t( "Element Preceded By", "#siblingfirst ~ em", ["siblingnext", "siblingthird"] ); - t( "Element Preceded By (multiple)", "#siblingTest em ~ em ~ em ~ span", ["siblingspan"] ); - t( "Element Preceded By, Containing", "#liveHandlerOrder ~ div em:contains('1')", ["siblingfirst"] ); - - t( "Multiple combinators selects all levels", "#siblingTest em *", ["siblingchild", "siblinggrandchild", "siblinggreatgrandchild"] ); - t( "Multiple combinators selects all levels", "#siblingTest > em *", ["siblingchild", "siblinggrandchild", "siblinggreatgrandchild"] ); - t( "Multiple sibling combinators doesn't miss general siblings", "#siblingTest > em:first-child + em ~ span", ["siblingspan"] ); - t( "Combinators are not skipped when mixing general and specific", "#siblingTest > em:contains('x') + em ~ span", [] ); - - equal( jQuery("#listWithTabIndex").length, 1, "Parent div for next test is found via ID (#8310)" ); - equal( jQuery("#listWithTabIndex li:eq(2) ~ li").length, 1, "Find by general sibling combinator (#8310)" ); - equal( jQuery("#__sizzle__").length, 0, "Make sure the temporary id assigned by sizzle is cleared out (#8310)" ); - equal( jQuery("#listWithTabIndex").length, 1, "Parent div for previous test is still found via ID (#8310)" ); - - t( "Verify deep class selector", "div.blah > p > a", [] ); - - t( "No element deep selector", "div.foo > span > a", [] ); - - nothiddendiv = document.getElementById("nothiddendiv"); + assert.equal( fixture.find( "h2, div p" ).filter( "p" ).length, 2, "has to find two

" ); + assert.equal( fixture.find( "h2, div p" ).filter( "h2" ).length, 1, "has to find one

" ); + assert.equal( fixture.find( "h2 , div p" ).filter( "p" ).length, 2, "has to find two

" ); + assert.equal( fixture.find( "h2 , div p" ).filter( "h2" ).length, 1, "has to find one

" ); +} ); + +QUnit.test( "child and adjacent", function( assert ) { + assert.expect( 27 ); + + assert.t( "Child", "p > a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); + assert.t( "Child", "p> a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); + assert.t( "Child", "p >a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); + assert.t( "Child", "p>a", [ "simon1", "google", "groups", "mark", "yahoo", "simon" ] ); + assert.t( "Child w/ Class", "p > a.blog", [ "mark", "simon" ] ); + assert.t( "All Children", "code > *", [ "anchor1", "anchor2" ] ); + assert.selectInFixture( "All Grandchildren", "p > * > *", [ "anchor1", "anchor2" ] ); + assert.t( "Adjacent", "p + p", [ "ap", "en", "sap" ] ); + assert.t( "Adjacent", "p#firstp + p", [ "ap" ] ); + assert.t( "Adjacent", "p[lang=en] + p", [ "sap" ] ); + assert.t( "Adjacent", "a.GROUPS + code + a", [ "mark" ] ); + assert.t( "Element Preceded By", "#groups ~ a", [ "mark" ] ); + assert.t( "Element Preceded By", "#length ~ input", [ "idTest" ] ); + assert.t( "Element Preceded By", "#siblingfirst ~ em", [ "siblingnext", "siblingthird" ] ); + assert.t( "Element Preceded By (multiple)", "#siblingTest em ~ em ~ em ~ span", [ "siblingspan" ] ); + + if ( jQuery.find.compile ) { + assert.t( "Element Preceded By, Containing", "#liveHandlerOrder ~ div em:contains('1')", [ "siblingfirst" ] ); + assert.t( "Combinators are not skipped when mixing general and specific", "#siblingTest > em:contains('x') + em ~ span", [] ); + assert.equal( jQuery( "#listWithTabIndex li:eq(2) ~ li" ).length, 1, "Find by general sibling combinator (#8310)" ); + } else { + assert.ok( "skip", ":contains not supported in selector-native" ); + assert.ok( "skip", ":contains not supported in selector-native" ); + assert.ok( "skip", ":eq not supported in selector-native" ); + } - t( "Non-existant ancestors", ".fototab > .thumbnails > a", [] ); -}); + assert.t( "Multiple combinators selects all levels", "#siblingTest em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] ); + assert.t( "Multiple combinators selects all levels", "#siblingTest > em *", [ "siblingchild", "siblinggrandchild", "siblinggreatgrandchild" ] ); + assert.t( "Multiple sibling combinators doesn't miss general siblings", "#siblingTest > em:first-child + em ~ span", [ "siblingspan" ] ); + + assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for next test is found via ID (#8310)" ); + assert.equal( jQuery( "#__sizzle__" ).length, 0, "Make sure the temporary id assigned by sizzle is cleared out (#8310)" ); + assert.equal( jQuery( "#listWithTabIndex" ).length, 1, "Parent div for previous test is still found via ID (#8310)" ); + + assert.t( "Verify deep class selector", "div.blah > p > a", [] ); + assert.t( "No element deep selector", "div.foo > span > a", [] ); + assert.t( "Non-existent ancestors", ".fototab > .thumbnails > a", [] ); +} ); -test("attributes", function() { - expect( 54 ); +QUnit.test( "attributes", function( assert ) { + assert.expect( 54 ); var attrbad, div, withScript; - t( "Find elements with a tabindex attribute", "[tabindex]", ["listWithTabIndex", "foodWithNegativeTabIndex", "linkWithTabIndex", "linkWithNegativeTabIndex", "linkWithNoHrefWithTabIndex", "linkWithNoHrefWithNegativeTabIndex"] ); + assert.t( "Find elements with a tabindex attribute", "[tabindex]", [ "listWithTabIndex", "foodWithNegativeTabIndex", "linkWithTabIndex", "linkWithNegativeTabIndex", "linkWithNoHrefWithTabIndex", "linkWithNoHrefWithNegativeTabIndex" ] ); + + assert.t( "Attribute Exists", "#qunit-fixture a[title]", [ "google" ] ); + assert.t( "Attribute Exists (case-insensitive)", "#qunit-fixture a[TITLE]", [ "google" ] ); + assert.t( "Attribute Exists", "#qunit-fixture *[title]", [ "google" ] ); + assert.t( "Attribute Exists", "#qunit-fixture [title]", [ "google" ] ); + assert.t( "Attribute Exists", "#qunit-fixture a[ title ]", [ "google" ] ); + + assert.t( "Boolean attribute exists", "#select2 option[selected]", [ "option2d" ] ); + assert.t( "Boolean attribute equals", "#select2 option[selected='selected']", [ "option2d" ] ); + + assert.t( "Attribute Equals", "#qunit-fixture a[rel='bookmark']", [ "simon1" ] ); + assert.t( "Attribute Equals", "#qunit-fixture a[rel='bookmark']", [ "simon1" ] ); + assert.t( "Attribute Equals", "#qunit-fixture a[rel=bookmark]", [ "simon1" ] ); + assert.t( "Attribute Equals", "#qunit-fixture a[href='http://www.google.com/']", [ "google" ] ); + assert.t( "Attribute Equals", "#qunit-fixture a[ rel = 'bookmark' ]", [ "simon1" ] ); + assert.t( "Attribute Equals Number", "#qunit-fixture option[value='1']", [ "option1b", "option2b", "option3b", "option4b", "option5c" ] ); + assert.t( "Attribute Equals Number", "#qunit-fixture li[tabIndex='-1']", [ "foodWithNegativeTabIndex" ] ); + + document.getElementById( "anchor2" ).href = "#2"; + assert.t( "href Attribute", "p a[href^='#']", [ "anchor2" ] ); + assert.t( "href Attribute", "p a[href*='#']", [ "simon1", "anchor2" ] ); + + assert.t( "for Attribute", "form label[for]", [ "label-for" ] ); + assert.t( "for Attribute in form", "#form [for=action]", [ "label-for" ] ); + + assert.t( "Attribute containing []", "input[name^='foo[']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name^='foo[bar]']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name*='[bar]']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name$='bar]']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name$='[bar]']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name$='foo[bar]']", [ "hidden2" ] ); + assert.t( "Attribute containing []", "input[name*='foo[bar]']", [ "hidden2" ] ); + + assert.t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type='hidden']", [ "radio1", "radio2", "hidden1" ] ); + assert.t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=\"hidden\"]", [ "radio1", "radio2", "hidden1" ] ); + assert.t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=hidden]", [ "radio1", "radio2", "hidden1" ] ); + + assert.t( "Attribute selector using UTF8", "span[lang=中文]", [ "台北" ] ); + + assert.t( "Attribute Begins With", "a[href ^= 'http://www']", [ "google", "yahoo" ] ); + assert.t( "Attribute Ends With", "a[href $= 'org/']", [ "mark" ] ); + assert.t( "Attribute Contains", "a[href *= 'google']", [ "google", "groups" ] ); + + if ( jQuery.find.compile ) { + assert.t( "Empty values", "#select1 option[value!='']", [ "option1b", "option1c", "option1d" ] ); + assert.t( "Attribute Is Not Equal", "#ap a[hreflang!='en']", [ "google", "groups", "anchor1" ] ); + assert.t( "Select options via :selected", "#select1 option:selected", [ "option1a" ] ); + assert.t( "Select options via :selected", "#select2 option:selected", [ "option2d" ] ); + assert.t( "Select options via :selected", "#select3 option:selected", [ "option3b", "option3c" ] ); + assert.t( "Select options via :selected", "select[name='select2'] option:selected", [ "option2d" ] ); + } else { + assert.ok( "skip", "!= not supported in selector-native" ); + assert.ok( "skip", "!= not supported in selector-native" ); + assert.ok( "skip", ":selected not supported in selector-native" ); + assert.ok( "skip", ":selected not supported in selector-native" ); + assert.ok( "skip", ":selected not supported in selector-native" ); + assert.ok( "skip", ":selected not supported in selector-native" ); + } + + assert.t( "Empty values", "#select1 option[value='']", [ "option1a" ] ); - t( "Attribute Exists", "#qunit-fixture a[title]", ["google"] ); - t( "Attribute Exists (case-insensitive)", "#qunit-fixture a[TITLE]", ["google"] ); - t( "Attribute Exists", "#qunit-fixture *[title]", ["google"] ); - t( "Attribute Exists", "#qunit-fixture [title]", ["google"] ); - t( "Attribute Exists", "#qunit-fixture a[ title ]", ["google"] ); - - t( "Boolean attribute exists", "#select2 option[selected]", ["option2d"]); - t( "Boolean attribute equals", "#select2 option[selected='selected']", ["option2d"]); - - t( "Attribute Equals", "#qunit-fixture a[rel='bookmark']", ["simon1"] ); - t( "Attribute Equals", "#qunit-fixture a[rel='bookmark']", ["simon1"] ); - t( "Attribute Equals", "#qunit-fixture a[rel=bookmark]", ["simon1"] ); - t( "Attribute Equals", "#qunit-fixture a[href='http://www.google.com/']", ["google"] ); - t( "Attribute Equals", "#qunit-fixture a[ rel = 'bookmark' ]", ["simon1"] ); - t( "Attribute Equals Number", "#qunit-fixture option[value=1]", ["option1b","option2b","option3b","option4b","option5c"] ); - t( "Attribute Equals Number", "#qunit-fixture li[tabIndex=-1]", ["foodWithNegativeTabIndex"] ); - - document.getElementById("anchor2").href = "#2"; - t( "href Attribute", "p a[href^=#]", ["anchor2"] ); - t( "href Attribute", "p a[href*=#]", ["simon1", "anchor2"] ); - - t( "for Attribute", "form label[for]", ["label-for"] ); - t( "for Attribute in form", "#form [for=action]", ["label-for"] ); - - t( "Attribute containing []", "input[name^='foo[']", ["hidden2"] ); - t( "Attribute containing []", "input[name^='foo[bar]']", ["hidden2"] ); - t( "Attribute containing []", "input[name*='[bar]']", ["hidden2"] ); - t( "Attribute containing []", "input[name$='bar]']", ["hidden2"] ); - t( "Attribute containing []", "input[name$='[bar]']", ["hidden2"] ); - t( "Attribute containing []", "input[name$='foo[bar]']", ["hidden2"] ); - t( "Attribute containing []", "input[name*='foo[bar]']", ["hidden2"] ); - - t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type='hidden']", ["radio1", "radio2", "hidden1"] ); - t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=\"hidden\"]", ["radio1", "radio2", "hidden1"] ); - t( "Multiple Attribute Equals", "#form input[type='radio'], #form input[type=hidden]", ["radio1", "radio2", "hidden1"] ); - - t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] ); - - t( "Attribute Begins With", "a[href ^= 'http://www']", ["google","yahoo"] ); - t( "Attribute Ends With", "a[href $= 'org/']", ["mark"] ); - t( "Attribute Contains", "a[href *= 'google']", ["google","groups"] ); - t( "Attribute Is Not Equal", "#ap a[hreflang!='en']", ["google","groups","anchor1"] ); - - t( "Empty values", "#select1 option[value='']", ["option1a"] ); - t( "Empty values", "#select1 option[value!='']", ["option1b","option1c","option1d"] ); - - t( "Select options via :selected", "#select1 option:selected", ["option1a"] ); - t( "Select options via :selected", "#select2 option:selected", ["option2d"] ); - t( "Select options via :selected", "#select3 option:selected", ["option3b", "option3c"] ); - t( "Select options via :selected", "select[name='select2'] option:selected", ["option2d"] ); - t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] ); + assert.t( "Grouped Form Elements", "input[name='foo[bar]']", [ "hidden2" ] ); // Make sure attribute value quoting works correctly. See jQuery #6093; #6428; #13894 // Use seeded results to bypass querySelectorAll optimizations @@ -213,180 +224,192 @@ "" + "" + "" - ).appendTo("#qunit-fixture").get(); + ).appendTo( "#qunit-fixture" ).get(); - t( "Underscores don't need escaping", "input[id=types_all]", ["types_all"] ); + assert.t( "Underscores don't need escaping", "input[id=types_all]", [ "types_all" ] ); - t( "input[type=text]", "#form input[type=text]", ["text1", "text2", "hidden2", "name"] ); - t( "input[type=search]", "#form input[type=search]", ["search"] ); + assert.t( "input[type=text]", "#form input[type=text]", [ "text1", "text2", "hidden2", "name" ] ); + assert.t( "input[type=search]", "#form input[type=search]", [ "search" ] ); withScript = supportjQuery( "
" + + " " + + "" + ); + + var content = jQuery( "#template" ).contents(); -test("sort direction", function() { - expect( 12 ); + assert.strictEqual( window.testScript, true, "script in template isn't executed" ); + assert.strictEqual( window.testImgOnload, true, "onload of image in template isn't executed" ); + } +); - var elems = jQuery("#ap, #select1 > *, #moretests > form"), +QUnit.test( "sort direction", function( assert ) { + assert.expect( 12 ); + + var elems = jQuery( "#ap, #select1 > *, #moretests > form" ), methodDirections = { parent: false, parents: true, @@ -696,102 +816,101 @@ jQuery.each( methodDirections, function( method, reversed ) { var actual = elems[ method ]().get(), - forward = jQuery.unique( [].concat( actual ) ); - deepEqual( actual, reversed ? forward.reverse() : forward, "Correct sort direction for " + method ); - }); -}); + forward = jQuery.uniqueSort( [].concat( actual ) ); + assert.deepEqual( actual, reversed ? forward.reverse() : forward, "Correct sort direction for " + method ); + } ); +} ); -test("add(String selector)", function() { - expect( 2 ); +QUnit.test( "add(String selector)", function( assert ) { + assert.expect( 2 ); var divs; - deepEqual( - jQuery("#sndp").add("#en").add("#sap").toArray(), - q("sndp", "en", "sap"), + assert.deepEqual( + jQuery( "#sndp" ).add( "#en" ).add( "#sap" ).toArray(), + q( "sndp", "en", "sap" ), "Check elements from document" ); - divs = jQuery("
").add("#sndp"); - ok( divs[0].parentNode, "Sort with the disconnected node last (started with disconnected first)." ); -}); - -test("add(String selector, String context)", function() { - expect( 1 ); - - deepEqual( - jQuery([]).add("div", "#nothiddendiv").toArray(), - q("nothiddendivchild"), + divs = jQuery( "
" ).add( "#sndp" ); + assert.ok( divs[ 0 ].parentNode, "Sort with the disconnected node last (started with disconnected first)." ); +} ); + +QUnit.test( "add(String selector, String context)", function( assert ) { + assert.expect( 1 ); + + assert.deepEqual( + jQuery( [] ).add( "div", "#nothiddendiv" ).toArray(), + q( "nothiddendivchild" ), "Check elements from document" ); -}); +} ); -test("add(String html)", function() { - expect( 3 ); +QUnit.test( "add(String html)", function( assert ) { + assert.expect( 3 ); var x, - divs = jQuery("#sndp").add("
"); - - ok( !divs[1].parentNode, "Sort with the disconnected node last." ); + divs = jQuery( "#sndp" ).add( "
" ); + assert.ok( !divs[ 1 ].parentNode, "Sort with the disconnected node last." ); - x = jQuery([]).add("

xxx

").add("

xxx

"); - equal( x[0].id, "x1", "Check detached element1" ); - equal( x[1].id, "x2", "Check detached element2" ); -}); + x = jQuery( [] ).add( "

xxx

" ).add( "

xxx

" ); + assert.equal( x[ 0 ].id, "x1", "Check detached element1" ); + assert.equal( x[ 1 ].id, "x2", "Check detached element2" ); +} ); -test("add(jQuery)", function() { - expect( 4 ); +QUnit.test( "add(jQuery)", function( assert ) { + assert.expect( 4 ); var x, - tmp = jQuery("
"); + tmp = jQuery( "
" ); - x = jQuery([]) + x = jQuery( [] ) .add( - jQuery("

xxx

").appendTo(tmp) + jQuery( "

xxx

" ).appendTo( tmp ) ) .add( - jQuery("

xxx

").appendTo(tmp) + jQuery( "

xxx

" ).appendTo( tmp ) ); - equal( x[0].id, "x1", "Check element1 in detached parent" ); - equal( x[1].id, "x2", "Check element2 in detached parent" ); + assert.equal( x[ 0 ].id, "x1", "Check element1 in detached parent" ); + assert.equal( x[ 1 ].id, "x2", "Check element2 in detached parent" ); - x = jQuery([]) + x = jQuery( [] ) .add( - jQuery("

xxx

") + jQuery( "

xxx

" ) ) .add( - jQuery("

xxx

") + jQuery( "

xxx

" ) ); - equal( x[0].id, "x1", "Check detached element1" ); - equal( x[1].id, "x2", "Check detached element2" ); -}); + assert.equal( x[ 0 ].id, "x1", "Check detached element1" ); + assert.equal( x[ 1 ].id, "x2", "Check detached element2" ); +} ); -test("add(Element)", function() { - expect( 2 ); +QUnit.test( "add(Element)", function( assert ) { + assert.expect( 2 ); var x, - tmp = jQuery("
"); + tmp = jQuery( "
" ); - x = jQuery([]).add(jQuery("

xxx

").appendTo(tmp)[0]).add(jQuery("

xxx

").appendTo(tmp)[0]); - equal( x[0].id, "x1", "Check on-the-fly element1" ); - equal( x[1].id, "x2", "Check on-the-fly element2" ); -}); - -test("add(Array elements)", function() { - expect( 1 ); - - deepEqual( - jQuery("#sndp").add( jQuery("#en")[0] ).add( jQuery("#sap") ).toArray(), - q("sndp", "en", "sap"), + x = jQuery( [] ).add( jQuery( "

xxx

" ).appendTo( tmp )[ 0 ] ).add( jQuery( "

xxx

" ).appendTo( tmp )[ 0 ] ); + assert.equal( x[ 0 ].id, "x1", "Check on-the-fly element1" ); + assert.equal( x[ 1 ].id, "x2", "Check on-the-fly element2" ); +} ); + +QUnit.test( "add(Array elements)", function( assert ) { + assert.expect( 1 ); + + assert.deepEqual( + jQuery( "#sndp" ).add( jQuery( "#en" )[ 0 ] ).add( jQuery( "#sap" ) ).toArray(), + q( "sndp", "en", "sap" ), "Check elements from document" ); -}); +} ); -test("add(Window)", function() { - expect( 1 ); +QUnit.test( "add(Window)", function( assert ) { + assert.expect( 1 ); var frame1 = document.createElement( "iframe" ), frame2 = document.createElement( "iframe" ); @@ -802,25 +921,25 @@ // Window is tricky because it is a lot like an array, even Array#slice will // turn it into a multi-item array. - equal( jQuery([]).add( window ).length, 1, "Add a window" ); + assert.equal( jQuery( [] ).add( window ).length, 1, "Add a window" ); document.body.removeChild( frame1 ); document.body.removeChild( frame2 ); -}); +} ); -test("add(NodeList|undefined|HTMLFormElement|HTMLSelectElement)", function() { - expect( 4 ); +QUnit.test( "add(NodeList|undefined|HTMLFormElement|HTMLSelectElement)", function( assert ) { + assert.expect( 4 ); var ps, notDefined; - ps = document.getElementsByTagName("p"); + ps = document.getElementsByTagName( "p" ); - equal( jQuery([]).add(ps).length, ps.length, "Add a NodeList" ); + assert.equal( jQuery( [] ).add( ps ).length, ps.length, "Add a NodeList" ); - equal( jQuery([]).add(notDefined).length, 0, "Adding undefined adds nothing" ); + assert.equal( jQuery( [] ).add( notDefined ).length, 0, "Adding undefined adds nothing" ); - equal( jQuery([]).add( document.getElementById("form") ).length, 1, "Add a form" ); - equal( jQuery([]).add( document.getElementById("select1") ).length, 1, "Add a select" ); + assert.equal( jQuery( [] ).add( document.getElementById( "form" ) ).length, 1, "Add a form" ); + assert.equal( jQuery( [] ).add( document.getElementById( "select1" ) ).length, 1, "Add a select" ); // We no longer support .add(form.elements), unfortunately. // There is no way, in browsers, to reliably determine the difference @@ -831,53 +950,53 @@ // For the time being, we're discontinuing support for jQuery(form.elements) since it's ambiguous in IE // use jQuery([]).add(form.elements) instead. //equal( jQuery([]).add(jQuery("#form")[0].elements).length, jQuery(jQuery("#form")[0].elements).length, "Array in constructor must equals array in add()" ); -}); +} ); -test("add(String, Context)", function() { - expect(6); +QUnit.test( "add(String, Context)", function( assert ) { + assert.expect( 6 ); - deepEqual( jQuery( "#firstp" ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add selector to selector " ); - deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add gEBId to selector" ); - deepEqual( jQuery( document.getElementById("firstp") ).add( document.getElementById("ap") ).get(), q( "firstp", "ap" ), "Add gEBId to gEBId" ); - - var ctx = document.getElementById("firstp"); - deepEqual( jQuery( "#firstp" ).add( "#ap", ctx ).get(), q( "firstp" ), "Add selector to selector " ); - deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", ctx ).get(), q( "firstp" ), "Add gEBId to selector, not in context" ); - deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", document.getElementsByTagName("body")[0] ).get(), q( "firstp", "ap" ), "Add gEBId to selector, in context" ); -}); + assert.deepEqual( jQuery( "#firstp" ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add selector to selector " ); + assert.deepEqual( jQuery( document.getElementById( "firstp" ) ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add gEBId to selector" ); + assert.deepEqual( jQuery( document.getElementById( "firstp" ) ).add( document.getElementById( "ap" ) ).get(), q( "firstp", "ap" ), "Add gEBId to gEBId" ); + + var ctx = document.getElementById( "firstp" ); + assert.deepEqual( jQuery( "#firstp" ).add( "#ap", ctx ).get(), q( "firstp" ), "Add selector to selector " ); + assert.deepEqual( jQuery( document.getElementById( "firstp" ) ).add( "#ap", ctx ).get(), q( "firstp" ), "Add gEBId to selector, not in context" ); + assert.deepEqual( jQuery( document.getElementById( "firstp" ) ).add( "#ap", document.getElementsByTagName( "body" )[ 0 ] ).get(), q( "firstp", "ap" ), "Add gEBId to selector, in context" ); +} ); -test("eq('-1') #10616", function() { - expect(3); +QUnit.test( "eq('-1') #10616", function( assert ) { + assert.expect( 3 ); var $divs = jQuery( "div" ); - equal( $divs.eq( -1 ).length, 1, "The number -1 returns a selection that has length 1" ); - equal( $divs.eq( "-1" ).length, 1, "The string '-1' returns a selection that has length 1" ); - deepEqual( $divs.eq( "-1" ), $divs.eq( -1 ), "String and number -1 match" ); -}); + assert.equal( $divs.eq( -1 ).length, 1, "The number -1 returns a selection that has length 1" ); + assert.equal( $divs.eq( "-1" ).length, 1, "The string '-1' returns a selection that has length 1" ); + assert.deepEqual( $divs.eq( "-1" ), $divs.eq( -1 ), "String and number -1 match" ); +} ); -test("index(no arg) #10977", function() { - expect(2); +QUnit.test( "index(no arg) #10977", function( assert ) { + assert.expect( 2 ); var $list, fragment, div; - $list = jQuery("
  • THIS ONE
  • a
  • b
  • c
"); - jQuery("#qunit-fixture").append( $list ); - strictEqual ( jQuery( "#indextest li.zero" ).first().index() , 0, "No Argument Index Check" ); + $list = jQuery( "
  • THIS ONE
  • a
  • b
  • c
" ); + jQuery( "#qunit-fixture" ).append( $list ); + assert.strictEqual( jQuery( "#indextest li.zero" ).first().index(), 0, "No Argument Index Check" ); $list.remove(); fragment = document.createDocumentFragment(); - div = fragment.appendChild( document.createElement("div") ); + div = fragment.appendChild( document.createElement( "div" ) ); - equal( jQuery( div ).index(), 0, "If jQuery#index called on element whose parent is fragment, it still should work correctly" ); -}); + assert.equal( jQuery( div ).index(), 0, "If jQuery#index called on element whose parent is fragment, it still should work correctly" ); +} ); -test("traversing non-elements with attribute filters (#12523)", function() { - expect(5); +QUnit.test( "traversing non-elements with attribute filters (#12523)", function( assert ) { + assert.expect( 5 ); - var nonnodes = jQuery("#nonnodes").contents(); - - equal( nonnodes.filter("[id]").length, 1, ".filter" ); - equal( nonnodes.find("[id]").length, 0, ".find" ); - strictEqual( nonnodes.is("[id]"), true, ".is" ); - deepEqual( nonnodes.closest("[id='nonnodes']").get(), q("nonnodes"), ".closest" ); - deepEqual( nonnodes.parents("[id='nonnodes']").get(), q("nonnodes"), ".parents" ); -}); + var nonnodes = jQuery( "#nonnodes" ).contents(); + + assert.equal( nonnodes.filter( "[id]" ).length, 1, ".filter" ); + assert.equal( nonnodes.find( "[id]" ).length, 0, ".find" ); + assert.strictEqual( nonnodes.is( "[id]" ), true, ".is" ); + assert.deepEqual( nonnodes.closest( "[id='nonnodes']" ).get(), q( "nonnodes" ), ".closest" ); + assert.deepEqual( nonnodes.parents( "[id='nonnodes']" ).get(), q( "nonnodes" ), ".parents" ); +} ); diff -Nru jquery-1.11.3+dfsg/test/unit/tween.js jquery-3.2.1/test/unit/tween.js --- jquery-1.11.3+dfsg/test/unit/tween.js 1970-01-01 00:00:00.000000000 +0000 +++ jquery-3.2.1/test/unit/tween.js 2017-03-20 19:00:06.000000000 +0000 @@ -0,0 +1,319 @@ +( function() { + +// Can't test what ain't there +if ( !jQuery.fx ) { + return; +} + +var oldRaf = window.requestAnimationFrame; + +QUnit.module( "tween", { + setup: function() { + window.requestAnimationFrame = null; + this.sandbox = sinon.sandbox.create(); + this.clock = this.sandbox.useFakeTimers( 505877050 ); + this._oldInterval = jQuery.fx.interval; + jQuery.fx.step = {}; + jQuery.fx.interval = 10; + jQuery.now = Date.now; + }, + teardown: function() { + this.sandbox.restore(); + jQuery.now = Date.now; + jQuery.fx.stop(); + jQuery.fx.interval = this._oldInterval; + window.requestAnimationFrame = oldRaf; + return moduleTeardown.apply( this, arguments ); + } +} ); + +QUnit.test( "jQuery.Tween - Default propHooks on plain objects", function( assert ) { + assert.expect( 8 ); + var propHooks, defaultHook, testObject, fakeTween, stepSpy; + + propHooks = jQuery.Tween.propHooks; + assert.equal( typeof propHooks, "object", "jQuery.Tween.propHooks exists" ); + + defaultHook = propHooks._default; + assert.ok( defaultHook, "_default propHook exists" ); + + testObject = { test: 0 }; + fakeTween = { elem: testObject, prop: "test", now: 10, unit: "px" }; + + assert.equal( defaultHook.get( fakeTween ), 0, "Can get property of object" ); + + fakeTween.prop = "testMissing"; + assert.equal( defaultHook.get( fakeTween ), undefined, "Can get missing property on object" ); + + defaultHook.set( fakeTween ); + assert.equal( testObject.testMissing, 10, "Sets missing value properly on plain object" ); + + fakeTween.prop = "opacity"; + defaultHook.set( fakeTween ); + assert.equal( testObject.opacity, 10, "Correctly set opacity on plain object" ); + + fakeTween.prop = "test"; + stepSpy = jQuery.fx.step.test = this.sandbox.spy(); + + defaultHook.set( fakeTween ); + assert.ok( stepSpy.calledWith( fakeTween ), "Step function called with Tween" ); + assert.equal( testObject.test, 0, "Because step didn't set, value is unchanged" ); +} ); + +QUnit.test( "jQuery.Tween - Default propHooks on elements", function( assert ) { + assert.expect( 19 ); + var propHooks, defaultHook, testElement, fakeTween, cssStub, styleStub, stepSpy; + + propHooks = jQuery.Tween.propHooks; + assert.equal( typeof propHooks, "object", "jQuery.Tween.propHooks exists" ); + + defaultHook = propHooks._default; + assert.ok( defaultHook, "_default propHook exists" ); + + testElement = jQuery( "
" )[ 0 ]; + fakeTween = { elem: testElement, prop: "height", now: 10, unit: "px" }; + + cssStub = this.sandbox.stub( jQuery, "css" ).returns( 10 ); + + assert.equal( defaultHook.get( fakeTween ), 10, "Gets expected style value" ); + assert.ok( cssStub.calledWith( testElement, "height", "" ), "Calls jQuery.css correctly" ); + + fakeTween.prop = "testOpti"; + testElement.testOpti = 15; + cssStub.reset(); + + assert.equal( defaultHook.get( fakeTween ), 15, "Gets expected value not defined on style" ); + assert.equal( cssStub.callCount, 0, "Did not call jQuery.css" ); + + fakeTween.prop = "testMissing"; + assert.equal( defaultHook.get( fakeTween ), 10, "Can get missing property on element" ); + assert.ok( cssStub.calledWith( testElement, "testMissing", "" ), "...using jQuery.css" ); + + cssStub.returns( "" ); + assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for empty string" ); + + cssStub.returns( "auto" ); + assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for 'auto'" ); + + cssStub.returns( null ); + assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for null" ); + + cssStub.returns( undefined ); + assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for undefined" ); + + cssStub.reset(); + + // Setters + styleStub = this.sandbox.stub( jQuery, "style" ); + fakeTween.prop = "height"; + + defaultHook.set( fakeTween ); + assert.ok( styleStub.calledWith( testElement, "height", "10px" ), + "Calls jQuery.style with elem, prop, now+unit" ); + + styleStub.reset(); + fakeTween.prop = "testMissing"; + + defaultHook.set( fakeTween ); + assert.equal( styleStub.callCount, 0, "Did not call jQuery.style for non css property" ); + assert.equal( testElement.testMissing, 10, "Instead, set value on element directly" ); + + jQuery.cssHooks.testMissing = jQuery.noop; + fakeTween.now = 11; + + defaultHook.set( fakeTween ); + delete jQuery.cssHooks.testMissing; + + assert.ok( styleStub.calledWith( testElement, "testMissing", "11px" ), + "Presence of cssHooks causes jQuery.style with elem, prop, now+unit" ); + assert.equal( testElement.testMissing, 10, "And value was unchanged" ); + + stepSpy = jQuery.fx.step.test = this.sandbox.spy(); + styleStub.reset(); + + fakeTween.prop = "test"; + defaultHook.set( fakeTween ); + assert.ok( stepSpy.calledWith( fakeTween ), "Step function called with Tween" ); + assert.equal( styleStub.callCount, 0, "Did not call jQuery.style" ); +} ); + +QUnit.test( "jQuery.Tween - Plain Object", function( assert ) { + assert.expect( 13 ); + var testObject = { test: 100 }, + testOptions = { duration: 100 }, + tween, easingSpy; + + tween = jQuery.Tween( testObject, testOptions, "test", 0, "linear" ); + assert.equal( tween.elem, testObject, "Sets .element" ); + assert.equal( tween.options, testOptions, "sets .options" ); + assert.equal( tween.prop, "test", "sets .prop" ); + assert.equal( tween.end, 0, "sets .end" ); + + assert.equal( tween.easing, "linear", "sets .easing when provided" ); + + assert.equal( tween.start, 100, "Reads .start value during construction" ); + assert.equal( tween.now, 100, "Reads .now value during construction" ); + + easingSpy = this.sandbox.spy( jQuery.easing, "linear" ); + + assert.equal( tween.run( 0.1 ), tween, ".run() returns this" ); + + assert.equal( tween.now, 90, "Calculated tween" ); + + assert.ok( easingSpy.calledWith( 0.1, 0.1 * testOptions.duration, 0, 1, testOptions.duration ), + "...using jQuery.easing.linear with back-compat arguments" ); + assert.equal( testObject.test, 90, "Set value" ); + + tween.run( 1 ); + assert.equal( testObject.test, 0, "Checking another value" ); + + tween.run( 0 ); + assert.equal( testObject.test, 100, "Can even go back in time" ); +} ); + +QUnit.test( "jQuery.Tween - Element", function( assert ) { + assert.expect( 15 ); + var testElement = jQuery( "
" ).css( "height", 100 )[ 0 ], + testOptions = { duration: 100 }, + tween, easingSpy, eased; + + tween = jQuery.Tween( testElement, testOptions, "height", 0 ); + assert.equal( tween.elem, testElement, "Sets .element" ); + assert.equal( tween.options, testOptions, "sets .options" ); + assert.equal( tween.prop, "height", "sets .prop" ); + assert.equal( tween.end, 0, "sets .end" ); + + assert.equal( + tween.easing, + jQuery.easing._default, + "sets .easing to default when not provided" + ); + assert.equal( tween.unit, "px", "sets .unit to px when not provided" ); + + assert.equal( tween.start, 100, "Reads .start value during construction" ); + assert.equal( tween.now, 100, "Reads .now value during construction" ); + + easingSpy = this.sandbox.spy( jQuery.easing, "swing" ); + + assert.equal( tween.run( 0.1 ), tween, ".run() returns this" ); + assert.equal( tween.pos, jQuery.easing.swing( 0.1 ), "set .pos" ); + eased = 100 - ( jQuery.easing.swing( 0.1 ) * 100 ); + assert.equal( tween.now, eased, "Calculated tween" ); + + assert.ok( + easingSpy.calledWith( 0.1, 0.1 * testOptions.duration, 0, 1, testOptions.duration ), + "...using jQuery.easing.linear with back-compat arguments" + ); + assert.equal( + parseFloat( testElement.style.height ).toFixed( 2 ), + eased.toFixed( 2 ), "Set value" + ); + + tween.run( 1 ); + assert.equal( testElement.style.height, "0px", "Checking another value" ); + + tween.run( 0 ); + assert.equal( testElement.style.height, "100px", "Can even go back in time" ); +} ); + +QUnit.test( "jQuery.Tween - No duration", function( assert ) { + assert.expect( 3 ); + + var testObject = { test: 100 }, + testOptions = { duration: 0 }, + tween, easingSpy; + + tween = jQuery.Tween( testObject, testOptions, "test", 0 ); + easingSpy = this.sandbox.spy( jQuery.easing, "swing" ); + tween.run( 0.5 ); + + assert.equal( tween.pos, 0.5, "set .pos correctly" ); + assert.equal( testObject.test, 50, "set value on object correctly" ); + assert.equal( easingSpy.callCount, 0, "didn't ease the value" ); +} ); + +QUnit.test( "jQuery.Tween - step function option", function( assert ) { + assert.expect( 4 ); + + var testObject = { test: 100 }, + testOptions = { duration: 100, step: this.sandbox.spy() }, + tween, propHookSpy; + + propHookSpy = this.sandbox.spy( jQuery.Tween.propHooks._default, "set" ); + + tween = jQuery.Tween( testObject, testOptions, "test", 0, "linear" ); + assert.equal( testOptions.step.callCount, 0, "didn't call step on create" ); + + tween.run( 0.5 ); + assert.ok( + testOptions.step.calledOn( testObject ), + "Called step function in context of animated object" + ); + assert.ok( + testOptions.step.calledWith( 50, tween ), + "Called step function with correct parameters" + ); + assert.ok( + testOptions.step.calledBefore( propHookSpy ), + "Called step function before calling propHook.set" + ); + +} ); + +QUnit.test( "jQuery.Tween - custom propHooks", function( assert ) { + assert.expect( 3 ); + + var testObject = {}, + testOptions = { duration: 100, step: this.sandbox.spy() }, + propHook = { + get: sinon.stub().returns( 100 ), + set: sinon.stub() + }, + tween; + + jQuery.Tween.propHooks.testHooked = propHook; + + tween = jQuery.Tween( testObject, testOptions, "testHooked", 0, "linear" ); + assert.ok( propHook.get.calledWith( tween ), "called propHook.get on create" ); + assert.equal( tween.now, 100, "Used return value from propHook.get" ); + + tween.run( 0.5 ); + assert.ok( + propHook.set.calledWith( tween ), + "Called propHook.set function with correct parameters" + ); + + delete jQuery.Tween.propHooks.testHooked; +} ); + +QUnit.test( "jQuery.Tween - custom propHooks - advanced values", function( assert ) { + assert.expect( 5 ); + + var testObject = {}, + testOptions = { duration: 100, step: this.sandbox.spy() }, + propHook = { + get: sinon.stub().returns( [ 0, 0 ] ), + set: sinon.spy() + }, + tween; + + jQuery.Tween.propHooks.testHooked = propHook; + + tween = jQuery.Tween( testObject, testOptions, "testHooked", [ 1, 1 ], "linear" ); + assert.ok( propHook.get.calledWith( tween ), "called propHook.get on create" ); + assert.deepEqual( tween.start, [ 0, 0 ], "Used return value from get" ); + + tween.run( 0.5 ); + + // Some day this NaN assumption might change - perhaps add a "calc" helper to the hooks? + assert.ok( isNaN( tween.now ), "Used return value from propHook.get" ); + assert.equal( tween.pos, 0.5, "But the eased percent is still available" ); + assert.ok( + propHook.set.calledWith( tween ), + "Called propHook.set function with correct parameters" + ); + + delete jQuery.Tween.propHooks.testHooked; +} ); + +} )(); diff -Nru jquery-1.11.3+dfsg/test/unit/wrap.js jquery-3.2.1/test/unit/wrap.js --- jquery-1.11.3+dfsg/test/unit/wrap.js 2015-04-28 16:20:21.000000000 +0000 +++ jquery-3.2.1/test/unit/wrap.js 2017-03-20 19:00:06.000000000 +0000 @@ -1,15 +1,15 @@ -(function() { +( function() { if ( !jQuery.fn.wrap ) { // no wrap module return; } -module( "wrap", { +QUnit.module( "wrap", { teardown: moduleTeardown -}); +} ); // See test/unit/manipulation.js for explanation about these 2 functions -function manipulationBareObj( value ) { +function manipulationBareObj( value ) { return value; } @@ -19,37 +19,54 @@ }; } -function testWrap( val ) { +function testWrap( val, assert ) { - expect( 19 ); + assert.expect( 19 ); var defaultText, result, j, i, cacheLength; defaultText = "Try them out:"; - result = jQuery("#first").wrap( val("
") ).text(); + result = jQuery( "#first" ).wrap( val( "
" ) ).text(); - equal( defaultText, result, "Check for wrapping of on-the-fly html" ); - ok( jQuery("#first").parent().parent().is(".red"), "Check if wrapper has class 'red'" ); + assert.equal( + defaultText, result, "Check for wrapping of on-the-fly html" + ); + assert.ok( + jQuery( "#first" ).parent().parent().is( ".red" ), "Check if wrapper has class 'red'" + ); + + result = jQuery( "#first" ).wrap( val( document.getElementById( "empty" ) ) ).parent(); + assert.ok( + result.is( "ol" ), "Check for element wrapping" + ); + assert.equal( + result.text(), defaultText, "Check for element wrapping" + ); - result = jQuery("#first").wrap( val(document.getElementById("empty")) ).parent(); - ok( result.is("ol"), "Check for element wrapping" ); - equal( result.text(), defaultText, "Check for element wrapping" ); - - jQuery("#check1").on( "click", function() { + jQuery( "#check1" ).on( "click", function() { var checkbox = this; - ok( checkbox.checked, "Checkbox's state is erased after wrap() action, see #769" ); - jQuery( checkbox ).wrap( val("") ); - ok( checkbox.checked, "Checkbox's state is erased after wrap() action, see #769" ); - }).prop( "checked", false )[ 0 ].click(); + assert.ok( + checkbox.checked, "Checkbox's state is erased after wrap() action, see #769" + ); + jQuery( checkbox ).wrap( val( "" ) ); + assert.ok( + checkbox.checked, "Checkbox's state is erased after wrap() action, see #769" + ); + } ).prop( "checked", false )[ 0 ].click(); // using contents will get comments regular, text, and comment nodes - j = jQuery("#nonnodes").contents(); - j.wrap( val("") ); + j = jQuery( "#nonnodes" ).contents(); + j.wrap( val( "" ) ); - // Blackberry 4.6 doesn't maintain comments in the DOM - equal( jQuery("#nonnodes > i").length, jQuery("#nonnodes")[ 0 ].childNodes.length, "Check node,textnode,comment wraps ok" ); - equal( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" ); + assert.equal( + jQuery( "#nonnodes > i" ).length, 3, + "Check node,textnode,comment wraps ok" + ); + assert.equal( + jQuery( "#nonnodes > i" ).text(), j.text(), + "Check node,textnode,comment wraps doesn't hurt text" + ); // Try wrapping a disconnected node cacheLength = 0; @@ -57,245 +74,463 @@ cacheLength++; } - j = jQuery("

cell
cellcell
cellcell
cell
cellcell
cellcell
")[ 1 ].parentNode.nodeType, 11, "parentNode should be documentFragment" ); -}); - -test("jQuery.parseJSON", function() { - expect( 20 ); - - strictEqual( jQuery.parseJSON( null ), null, "primitive null" ); - strictEqual( jQuery.parseJSON("0.88"), 0.88, "Number" ); - strictEqual( - jQuery.parseJSON("\" \\\" \\\\ \\/ \\b \\f \\n \\r \\t \\u007E \\u263a \""), - " \" \\ / \b \f \n \r \t ~ \u263A ", - "String escapes" - ); - deepEqual( jQuery.parseJSON("{}"), {}, "Empty object" ); - deepEqual( jQuery.parseJSON("{\"test\":1}"), { "test": 1 }, "Plain object" ); - deepEqual( jQuery.parseJSON("[0]"), [ 0 ], "Simple array" ); - - 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" - ); - 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" - ); - - deepEqual( jQuery.parseJSON("\n{\"test\":1}\t"), { "test": 1 }, - "Leading and trailing whitespace are ignored" ); - - throws(function() { - jQuery.parseJSON(); - }, null, "Undefined raises an error" ); - throws(function() { - jQuery.parseJSON( "" ); - }, null, "Empty string raises an error" ); - throws(function() { - jQuery.parseJSON("''"); - }, null, "Single-quoted string raises an error" ); - /* - - // Broken on IE8 - throws(function() { - jQuery.parseJSON("\" \\a \""); - }, null, "Invalid string escape raises an error" ); - - // Broken on IE8, Safari 5.1 Windows - throws(function() { - jQuery.parseJSON("\"\t\""); - }, null, "Unescaped control character raises an error" ); - - // Broken on IE8 - throws(function() { - jQuery.parseJSON(".123"); - }, null, "Number with no integer component raises an error" ); - - */ - 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" ); - throws(function() { - jQuery.parseJSON("{a:1}"); - }, null, "Unquoted property raises an error" ); - throws(function() { - jQuery.parseJSON("{'a':1}"); - }, null, "Single-quoted property raises an error" ); - throws(function() { - jQuery.parseJSON("[,]"); - }, null, "Array element elision raises an error" ); - throws(function() { - jQuery.parseJSON("{},[]"); - }, null, "Comma expression raises an error" ); - throws(function() { - jQuery.parseJSON("[]\n,{}"); - }, null, "Newline-containing comma expression raises an error" ); - throws(function() { - jQuery.parseJSON("\"\"\n\"\""); - }, null, "Automatic semicolon insertion raises an error" ); + assert.equal( html[ 0 ].parentNode.nodeType, 11, "parentNode should be documentFragment" ); + assert.equal( html[ 0 ].innerHTML, "test div", "Content should be preserved" ); - strictEqual( jQuery.parseJSON([ 0 ]), 0, "Input cast to string" ); -}); + 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>