Merge branch 'master' into proxy-native-bind

* master: (194 commits)
  Revert "Make sure that focusin/focusout bubbles in non-IE browsers." This was causing problems with the focusin event, see: #7340.
  Replaces "text in-between" technique with a full-fledged one-level transitive search for converters (unit tests added). Also cleans up auto dataType determination and adds converter checks in order to guess the best dataType possible.
  Moves determineResponse logic into main ajax callback. Puts responseXXX fields definitions into ajaxSettings.
  Removes misleading comment.
  Bring jQuery('#id') and jQuery('body') logic back into core (while leaving it in Sizzle at the same time). Was causing too much of a performance hit to leave it all to Sizzle.
  Renames Deferred's fire and fireReject methods as resolveWith and rejectWith respectively.
  Fix typo in regex tweak from previous commit.
  Renames determineDataType as determineResponse. Makes it more generic as a first step into integrating the logic into the main ajax done callback. Also fixes some comments in ajax/xhr.js.
  Move jQuery(...) selector speed-up logic into Sizzle(...) qSA handling. Additionally add in a new catch for Sizzle('.class') (avoid using qSA and use getElementsByClassName instead, where applicable).
  Revises the way arguments are handled in ajax.
  Makes sure statusCode callbacks are ordered in the same way success and error callbacks are. Unit tests added.
  Cleans up and simplifies code shared by ajaxPrefilter and ajaxTransport. Removes chainability of ajaxSetup, ajaxPrefilter and ajaxTransport. Also makes sure context is handled properly by ajaxSetup (unit test added).
  Rework unit tests to check actual result elements.
  Moves active counter test after all other ajax tests where it should be.
  Revised the Nokia support fallback. It turns out that Nokia supports the documentElement property but does not define document.compatMode. Adding this third fallback allows Nokia to run jQuery error-free and return proper values for window width and height.
  Moves things around to make jsLint happier.
  Fixes crossDomain test so that it assumes port to be 80 for http and 443 for https when it is not provided.
  Moves determineDataType into ajaxSettings so that it is accessible to transports without the need for a second argument and so that we can now pass the original options to the transport instead. Also ensures the original options are actually propagated to prefilters (they were not).
  Re-adds hastily removed variable and simplifies statusCode based callbacks handling.
  Use undefined instead of 0 to deference transport for clarity.
  ...

Conflicts:
	src/event.js
This commit is contained in:
Gianni Chiappetta 2011-01-21 09:58:55 -05:00
commit a03f040dbf
56 changed files with 6696 additions and 3009 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) 2010 John Resig, http://jquery.com/ Copyright (c) 2011 John Resig, http://jquery.com/
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View file

@ -7,11 +7,8 @@ BUILD_DIR = build
PREFIX = . PREFIX = .
DIST_DIR = ${PREFIX}/dist DIST_DIR = ${PREFIX}/dist
RHINO ?= java -jar ${BUILD_DIR}/js.jar JS_ENGINE ?= `which node nodejs`
COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
CLOSURE_COMPILER = ${BUILD_DIR}/google-compiler-20100917.jar
MINJAR ?= java -jar ${CLOSURE_COMPILER}
BASE_FILES = ${SRC_DIR}/core.js\ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/support.js\ ${SRC_DIR}/support.js\
@ -24,10 +21,9 @@ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/manipulation.js\ ${SRC_DIR}/manipulation.js\
${SRC_DIR}/css.js\ ${SRC_DIR}/css.js\
${SRC_DIR}/ajax.js\ ${SRC_DIR}/ajax.js\
${SRC_DIR}/xhr.js\ ${SRC_DIR}/ajax/jsonp.js\
${SRC_DIR}/transports/jsonp.js\ ${SRC_DIR}/ajax/script.js\
${SRC_DIR}/transports/script.js\ ${SRC_DIR}/ajax/xhr.js\
${SRC_DIR}/transports/xhr.js\
${SRC_DIR}/effects.js\ ${SRC_DIR}/effects.js\
${SRC_DIR}/offset.js\ ${SRC_DIR}/offset.js\
${SRC_DIR}/dimensions.js ${SRC_DIR}/dimensions.js
@ -79,13 +75,13 @@ init:
jquery: ${JQ} jquery: ${JQ}
jq: ${JQ} jq: ${JQ}
${JQ}: ${MODULES} ${DIST_DIR} ${JQ}: ${MODULES} | ${DIST_DIR}
@@echo "Building" ${JQ} @@echo "Building" ${JQ}
@@cat ${MODULES} | \ @@cat ${MODULES} | \
sed 's/.function..jQuery...{//' | \ sed 's/.function..jQuery...{//' | \
sed 's/}...jQuery..;//' | \ sed 's/}...jQuery..;//' | \
sed 's/Date:./&'"${DATE}"'/' | \ sed 's/@DATE/'"${DATE}"'/' | \
${VER} > ${JQ}; ${VER} > ${JQ};
${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
@ -94,17 +90,16 @@ ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
lint: ${JQ} lint: ${JQ}
@@echo "Checking jQuery against JSLint..." @@echo "Checking jQuery against JSLint..."
@@${RHINO} build/jslint-check.js @@${JS_ENGINE} build/jslint-check.js
min: ${JQ_MIN} min: ${JQ_MIN}
${JQ_MIN}: ${JQ} ${JQ_MIN}: ${JQ}
@@echo "Building" ${JQ_MIN} @@echo "Building" ${JQ_MIN}
@@${COMPILER} ${JQ} > ${JQ_MIN}.tmp
@@head -15 ${JQ} > ${JQ_MIN} @@echo ";" >> ${JQ_MIN}.tmp
@@${MINJAR} --js ${JQ} --warning_level QUIET --js_output_file ${JQ_MIN}.tmp @@sed 's/\*\/(/*\/ʩ(/' ${JQ_MIN}.tmp | tr "ʩ" "\n" > ${JQ_MIN}
@@cat ${JQ_MIN}.tmp >> ${JQ_MIN} @@rm -rf ${JQ_MIN}.tmp
@@rm -f ${JQ_MIN}.tmp
clean: clean:
@@echo "Removing Distribution directory:" ${DIST_DIR} @@echo "Removing Distribution directory:" ${DIST_DIR}

View file

@ -1,85 +1,64 @@
[jQuery](http://jquery.com/) - New Wave Javascript [jQuery](http://jquery.com/) - New Wave Javascript
================================ ==================================================
What you need to build your own jQuery What you need to build your own jQuery
--------------------------------------- --------------------------------------
* Make sure that you have Java installed (if you want to build a minified version of jQuery).
If not, [go to this page](http://java.sun.com/javase/downloads/index.jsp) and download "Java Runtime Environment (JRE) 5.0"
Build Options In order to build jQuery, you need to have GNU make 3.8 or later, Node.js 0.2 or later, and git 1.7 or later.
-------------- (Earlier versions might work OK, but are not tested.)
You now have **three** options for building jQuery: Windows users have two options:
* **`make`**: If you have access to common UNIX commands (like `make`, `mkdir`, `rm`, `cat`, and `echo`) then simply type `make` to build all the components. 1. Install [msysgit](https://code.google.com/p/msysgit/) (Full installer for official Git),
[GNU make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm), and a
[binary version of Node.js](http://node-js.prcn.co.cc/). Make sure all three packages are installed to the same
location (by default, this is C:\Program Files\Git).
2. Install [Cygwin](http://cygwin.com/) (make sure you install the git, make, and which packages), then either follow
the [Node.js build instructions](https://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29) or install
the [binary version of Node.js](http://node-js.prcn.co.cc/).
* **`rake`**: If you have Ruby Rake installed (on either Windows or UNIX/Linux), you can simply type `rake` to build all the components. Mac OS users should install Xcode (comes on your Mac OS install DVD, or downloadable from
[Apple's Xcode site](http://developer.apple.com/technologies/xcode.html)) and
[http://mxcl.github.com/homebrew/](Homebrew). 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 make, git, and node, or build from source
if you swing that way. Easy-peasy.
* **`ant`**: If you have Ant installed (or are on Windows and don't have access to make). You can download Ant from here: [http://ant.apache.org/bindownload.cgi].
How to build your own jQuery How to build your own jQuery
----------------------------- ----------------------------
*Note: If you are using either `rake` or `ant`, substitute your chosen method in place of `make` in the examples below. They work identically for all intents and purposes. Quick reference is also available for `rake` by typing `rake -T` in the `jquery` directory.* First, clone a copy of the main jQuery git repo by running `git clone git://github.com/jquery/jquery.git`.
In the main directory of the distribution (the one that this file is in), type Then, to get a complete, minified, jslinted version of jQuery, simply `cd` to the `jquery` directory and type
the following to make all versions of jQuery: `make`. If you don't have Node installed and/or want to make a basic, uncompressed, unlinted version of jQuery, use
`make jquery` instead of `make`.
make The built version of jQuery will be put in the `dist/` subdirectory.
*Here are the individual items that are buildable from the Makefile:* To remove all built files, run `make clean`.
make init
Pull in all the external dependencies (QUnit, Sizzle) for the project.
make jquery
The standard, uncompressed, jQuery code.
Makes: `./dist/jquery.js`
make min
A compressed version of jQuery (made the Closure Compiler).
Makes: `./dist/jquery.min.js`
make lint
Tests a build of jQuery against JSLint, looking for potential errors or bits of confusing code.
make selector
Builds the selector library for jQuery from Sizzle.
Makes: `./src/selector.js`
Finally, you can remove all the built files using the command:
make clean
Building to a different directory Building to a different directory
---------------------------------- ---------------------------------
If you want to build jQuery to a directory that is different from the default location, you can... If you want to build jQuery to a directory that is different from the default location, you can specify the PREFIX
directory: `make PREFIX=/home/jquery/test/ [command]`
**Make only:** Specify the PREFIX directory, for example: With this example, the output files would end up in `/home/jquery/test/dist/`.
make PREFIX=/home/john/test/ [command]
With this example, the output files would be contained in `/home/john/test/dist/` Troubleshooting
---------------
**Rake only:** Define the DIST_DIR directory, for example: Sometimes, the various git repositories get into an inconsistent state where builds don't complete properly
(usually this results in the jquery.js or jquery.min.js being 0 bytes). If this happens, run `make clean`, then
run `make` again.
rake DIST_DIR=/home/john/test/ [command]
With this example, the output files would be contained in `/home/john/test/`
*In both examples, `[command]` is optional.*
**Ant only:** You cannot currently build to another directory when using Ant.
Questions? Questions?
---------- ----------
If you have any questions, please feel free to ask them on the Developing jQuery Core If you have any questions, please feel free to ask on the
forum, which can be found here: [Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.
[http://forum.jquery.com/developing-jquery-core](http://forum.jquery.com/developing-jquery-core)

138
Rakefile
View file

@ -1,138 +0,0 @@
prefix = File.dirname( __FILE__ )
# Directory variables
src_dir = File.join( prefix, 'src' )
build_dir = File.join( prefix, 'build' )
test_dir = File.join( prefix, 'test' )
# A different destination directory can be set by
# setting DIST_DIR before calling rake
dist_dir = ENV['DIST_DIR'] || File.join( prefix, 'dist' )
base_files = %w{intro core support data queue attributes event selector traversing manipulation css ajax xhr transports/jsonp transports/script transports/xhr effects offset dimensions outro}.map { |js| File.join( src_dir, "#{js}.js" ) }
# Sizzle, QUnit and jQuery files/dirs
sizzle_dir = File.join( src_dir, "sizzle" )
sizzle = File.join( sizzle_dir, "sizzle.js" )
selector = File.join( src_dir, "selector.js" )
qunit_dir = File.join( test_dir, "qunit" )
qunit = File.join( qunit_dir, "qunit", "qunit.js" )
jq = File.join( dist_dir, "jquery.js" )
jq_min = File.join( dist_dir, "jquery.min.js" )
# General Variables
date = `git log -1`[/^Date:\s+(.+)$/, 1]
version = File.read( File.join( prefix, 'version.txt' ) ).strip
# Build tools
rhino = "java -jar #{build_dir}/js.jar"
minfier = "java -jar #{build_dir}/google-compiler-20100917.jar"
# Turn off output other than needed from `sh` and file commands
verbose(false)
# Tasks
task :default => "all"
desc "Builds jQuery; Tests with JSLint; Minifies jQuery"
task :all => [:jquery, :lint, :min] do
puts "jQuery build complete."
end
desc "Builds jQuery: jquery.js (Default task)"
task :jquery => [:selector, jq]
desc "Builds a minified version of jQuery: jquery.min.js"
task :min => jq_min
task :init => [sizzle, qunit] do
sizzle_git = File.join(sizzle_dir, '.git')
qunit_git = File.join(qunit_dir, '.git')
puts "Updating SizzleJS with latest..."
sh "git --git-dir=#{sizzle_git} pull -q origin master"
puts "Updating QUnit with latest..."
sh "git --git-dir=#{qunit_git} pull -q origin master"
end
desc "Removes dist folder, selector.js, and Sizzle/QUnit"
task :clean do
puts "Removing Distribution directory: #{dist_dir}..."
rm_rf dist_dir
puts "Removing built copy of Sizzle..."
rm_rf selector
puts "Removing cloned directories..."
rm_rf qunit_dir
rm_rf sizzle_dir
end
desc "Rebuilds selector.js from SizzleJS"
task :selector => [:init, selector]
desc "Tests built jquery.js against JSLint"
task :lint => jq do
puts "Checking jQuery against JSLint..."
sh "#{rhino} " + File.join(build_dir, 'jslint-check.js')
end
# File and Directory Dependencies
directory dist_dir
file jq => [dist_dir, base_files].flatten do
puts "Building jquery.js..."
File.open(jq, 'w') do |f|
f.write cat(base_files).gsub(/(Date:.)/, "\\1#{date}" ).gsub(/@VERSION/, version)
end
end
file jq_min => jq do
puts "Building jquery.min.js..."
sh "#{minfier} --js #{jq} --warning_level QUIET --js_output_file #{jq_min}"
min = File.read( jq_min )
# Equivilent of "head"
File.open(jq_min, 'w') do |f|
f.write File.readlines(jq)[0..14].join()
f.write min
end
end
file selector => [sizzle, :init] do
puts "Building selector code from Sizzle..."
File.open(selector, 'w') do |f|
f.write File.read(sizzle).gsub(
/^.+EXPOSE$\n/,
'\0' + File.read( File.join( src_dir, 'sizzle-jquery.js' ))
).gsub(
/^window.Sizzle.+$\n/, ''
)
end
end
file sizzle do
puts "Retrieving SizzleJS from Github..."
sh "git clone git://github.com/jeresig/sizzle.git #{sizzle_dir}"
end
file qunit do
puts "Retrieving QUnit from Github..."
sh "git clone git://github.com/jquery/qunit.git #{qunit_dir}"
end
def cat( files )
files.map do |file|
File.read(file)
end.join('')
end

133
build.xml
View file

@ -1,133 +0,0 @@
<project name="jQuery" default="all" basedir=".">
<loadfile property="version" srcfile="version.txt" />
<property name="PREFIX" value="." />
<property description="Folder for jquery and min target" name="dist" value="${PREFIX}/dist" />
<property name="JQ" value="${dist}/jquery.js" />
<property name="JQ_MIN" value="${dist}/jquery.min.js" />
<loadfile property="sizzle-exports" srcfile="src/sizzle-jquery.js" />
<available property="qunit" file="test/qunit" />
<available property="sizzle" file="src/sizzle" />
<target name="all" depends="jquery,lint,min" />
<target name="qunit-clone" unless="qunit">
<exec executable="git" outputproperty="git-qunit" >
<arg line="clone git://github.com/jquery/qunit.git test/qunit" />
</exec>
<echo message="git clone qunit: ${git-qunit}" />
</target>
<target name="qunit-pull" if="qunit">
<exec executable="git" outputproperty="git-qunit" dir="test/qunit" >
<arg line="pull origin master" />
</exec>
<echo message="git pull sizzle: ${git-qunit}" />
</target>
<target name="sizzle-clone" unless="sizzle">
<exec executable="git" outputproperty="git-sizzle" >
<arg line="clone git://github.com/jeresig/sizzle.git src/sizzle" />
</exec>
<echo message="git clone sizzle: ${git-sizzle}" />
</target>
<target name="sizzle-pull" if="sizzle">
<exec executable="git" outputproperty="git-sizzle" dir="src/sizzle" >
<arg line="pull origin master" />
</exec>
<echo message="git pull sizzle: ${git-sizzle}" />
</target>
<target name="init" depends="qunit-clone,qunit-pull,sizzle-clone,sizzle-pull" />
<target name="selector" depends="init" description="Builds the selector library for jQuery from Sizzle.">
<copy file="src/sizzle/sizzle.js" tofile="src/selector.js" overwrite="true" />
<replaceregexp match="// EXPOSE(.*)&#10;" replace="// EXPOSE\1&#10;${sizzle-exports}" file="src/selector.js" />
<replaceregexp match="window.Sizzle(.*)&#10;" replace="" file="src/selector.js" />
</target>
<target name="jquery" depends="init,selector" description="Main jquery build, concatenates source files and replaces @VERSION">
<echo message="Building ${JQ}" />
<mkdir dir="${dist}" />
<concat destfile="${JQ}">
<fileset file="src/intro.js" />
<fileset file="src/core.js" />
<fileset file="src/support.js" />
<fileset file="src/data.js" />
<fileset file="src/queue.js" />
<fileset file="src/attributes.js" />
<fileset file="src/event.js" />
<fileset file="src/selector.js" />
<fileset file="src/traversing.js" />
<fileset file="src/manipulation.js" />
<fileset file="src/css.js" />
<fileset file="src/ajax.js" />
<fileset file="src/xhr.js" />
<fileset file="src/transports/jsonp.js" />
<fileset file="src/transports/script.js" />
<fileset file="src/transports/xhr.js" />
<fileset file="src/effects.js" />
<fileset file="src/offset.js" />
<fileset file="src/dimensions.js" />
<fileset file="src/outro.js" />
</concat>
<replaceregexp match="@VERSION" replace="${version}" flags="g" byline="true" file="${JQ}" />
<exec executable="git" outputproperty="date">
<arg line="log -1 --pretty=format:%ad" />
</exec>
<replaceregexp match="(\(\s*function\s*\(\s*jQuery\s*\)\s*\{)|(\}\s*\)\s*\(\s*jQuery\s*\)\s*;)" flags="g" replace="" file="${JQ}" />
<replaceregexp match="Date: " replace="Date: ${date}" file="${JQ}" />
<echo message="${JQ} built." />
</target>
<target name="lint" depends="jquery" description="Check jQuery against JSLint">
<exec executable="java">
<arg line="-jar build/js.jar build/jslint-check.js" />
</exec>
</target>
<target name="min" depends="jquery" description="Remove all comments and whitespace, no compression, great in combination with GZip">
<echo message="Building ${JQ_MIN}" />
<apply executable="java" parallel="false" verbose="true" dest="${dist}">
<fileset dir="${dist}">
<include name="jquery.js" />
</fileset>
<arg line="-jar" />
<arg path="build/google-compiler-20100917.jar" />
<arg value="--warning_level" />
<arg value="QUIET" />
<arg value="--js_output_file" />
<targetfile />
<arg value="--js" />
<mapper type="glob" from="jquery.js" to="tmpmin" />
</apply>
<concat destfile="${JQ_MIN}">
<filelist files="${JQ}, ${dist}/tmpmin" />
<filterchain>
<headfilter lines="15" />
</filterchain>
</concat>
<concat destfile="${JQ_MIN}" append="yes">
<filelist files="${dist}/tmpmin" />
</concat>
<delete file="${dist}/tmpmin" />
<echo message="${JQ_MIN} built." />
</target>
<target name="clean">
<delete dir="${dist}" />
<delete file="src/selector.js" />
<delete dir="test/qunit" />
<delete dir="src/sizzle" />
</target>
<target name="openAjaxMetadata">
<property name="target" value="openAjaxMetadata-jquery-${version}.xml" />
<delete file="${dist}/jquery-*.xml" />
<get src="http://www.exfer.net/jquery/createjQueryXMLDocs.py?version=1.3" dest="${target}" />
<xslt includes="${target}" excludes="build.xml" destdir="./dist" style="build/style.xsl" extension=".xml" />
<delete file="${target}" />
</target>
</project>

Binary file not shown.

Binary file not shown.

View file

@ -1,6 +1,6 @@
load("build/jslint.js"); var JSLINT = require("./lib/jslint").JSLINT,
print = require("sys").print,
var src = readFile("dist/jquery.js"); src = require("fs").readFileSync("dist/jquery.js", "utf8");
JSLINT(src, { evil: true, forin: true, maxerr: 100 }); JSLINT(src, { evil: true, forin: true, maxerr: 100 });
@ -29,8 +29,8 @@ for ( var i = 0; i < e.length; i++ ) {
} }
if ( found > 0 ) { if ( found > 0 ) {
print( "\n" + found + " Error(s) found." ); print( "\n" + found + " Error(s) found.\n" );
} else { } else {
print( "JSLint check passed." ); print( "JSLint check passed.\n" );
} }

View file

@ -5495,6 +5495,10 @@ loop: for (;;) {
itself.edition = '2010-02-20'; itself.edition = '2010-02-20';
if (typeof exports !== "undefined") {
exports.JSLINT = itself;
}
return itself; return itself;
}()); }());

1239
build/lib/parse-js.js Normal file

File diff suppressed because it is too large Load diff

1562
build/lib/process.js Normal file

File diff suppressed because it is too large Load diff

22
build/lib/squeeze-more.js Normal file
View file

@ -0,0 +1,22 @@
var jsp = require("./parse-js"),
pro = require("./process"),
slice = jsp.slice,
member = jsp.member,
PRECEDENCE = jsp.PRECEDENCE,
OPERATORS = jsp.OPERATORS;
function ast_squeeze_more(ast) {
var w = pro.ast_walker(), walk = w.walk;
return w.with_walkers({
"call": function(expr, args) {
if (expr[0] == "dot" && expr[2] == "toString" && args.length == 0) {
// foo.toString() ==> foo+""
return [ "binary", "+", expr[1], [ "string", "" ]];
}
}
}, function() {
return walk(ast);
});
};
exports.ast_squeeze_more = ast_squeeze_more;

199
build/uglify.js Normal file
View file

@ -0,0 +1,199 @@
#! /usr/bin/env node
// -*- js2 -*-
global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util");
var fs = require("fs"),
jsp = require("./lib/parse-js"),
pro = require("./lib/process");
pro.set_logger(function(msg){
sys.debug(msg);
});
var options = {
ast: false,
mangle: true,
mangle_toplevel: false,
squeeze: true,
make_seqs: true,
dead_code: true,
beautify: false,
verbose: false,
show_copyright: true,
out_same_file: false,
extra: false,
unsafe: false, // XXX: extra & unsafe? but maybe we don't want both, so....
beautify_options: {
indent_level: 4,
indent_start: 0,
quote_keys: false,
space_colon: false
},
output: true // stdout
};
var args = jsp.slice(process.argv, 2);
var filename;
out: while (args.length > 0) {
var v = args.shift();
switch (v) {
case "-b":
case "--beautify":
options.beautify = true;
break;
case "-i":
case "--indent":
options.beautify_options.indent_level = args.shift();
break;
case "-q":
case "--quote-keys":
options.beautify_options.quote_keys = true;
break;
case "-mt":
case "--mangle-toplevel":
options.mangle_toplevel = true;
break;
case "--no-mangle":
case "-nm":
options.mangle = false;
break;
case "--no-squeeze":
case "-ns":
options.squeeze = false;
break;
case "--no-seqs":
options.make_seqs = false;
break;
case "--no-dead-code":
options.dead_code = false;
break;
case "--no-copyright":
case "-nc":
options.show_copyright = false;
break;
case "-o":
case "--output":
options.output = args.shift();
break;
case "--overwrite":
options.out_same_file = true;
break;
case "-v":
case "--verbose":
options.verbose = true;
break;
case "--ast":
options.ast = true;
break;
case "--extra":
options.extra = true;
break;
case "--unsafe":
options.unsafe = true;
break;
default:
filename = v;
break out;
}
}
if (filename) {
fs.readFile(filename, "utf8", function(err, text){
if (err) {
throw err;
}
output(squeeze_it(text));
});
} else {
var stdin = process.openStdin();
stdin.setEncoding("utf8");
var text = "";
stdin.on("data", function(chunk){
text += chunk;
});
stdin.on("end", function() {
output(squeeze_it(text));
});
}
function output(text) {
var out;
if (options.out_same_file && filename)
options.output = filename;
if (options.output === true) {
out = process.stdout;
} else {
out = fs.createWriteStream(options.output, {
flags: "w",
encoding: "utf8",
mode: 0644
});
}
out.write(text);
out.end();
};
// --------- main ends here.
function show_copyright(comments) {
var ret = "";
for (var i = 0; i < comments.length; ++i) {
var c = comments[i];
if (c.type == "comment1") {
ret += "//" + c.value + "\n";
} else {
ret += "/*" + c.value + "*/";
}
}
return ret;
};
function squeeze_it(code) {
var result = "";
if (options.show_copyright) {
var initial_comments = [];
// keep first comment
var tok = jsp.tokenizer(code, false), c;
c = tok();
var prev = null;
while (/^comment/.test(c.type) && (!prev || prev == c.type)) {
initial_comments.push(c);
prev = c.type;
c = tok();
}
result += show_copyright(initial_comments);
}
try {
var ast = time_it("parse", function(){ return jsp.parse(code); });
if (options.mangle)
ast = time_it("mangle", function(){ return pro.ast_mangle(ast, options.mangle_toplevel); });
if (options.squeeze)
ast = time_it("squeeze", function(){
ast = pro.ast_squeeze(ast, {
make_seqs : options.make_seqs,
dead_code : options.dead_code,
extra : options.extra
});
if (options.unsafe)
ast = pro.ast_squeeze_more(ast);
return ast;
});
if (options.ast)
return sys.inspect(ast, null, null);
result += time_it("generate", function(){ return pro.gen_code(ast, options.beautify && options.beautify_options) });
return result;
} catch(ex) {
sys.debug(ex.stack);
sys.debug(sys.inspect(ex));
sys.debug(JSON.stringify(ex));
}
};
function time_it(name, cont) {
if (!options.verbose)
return cont();
var t1 = new Date().getTime();
try { return cont(); }
finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); }
};

View file

@ -1,11 +1,20 @@
(function( jQuery ) { (function( jQuery ) {
var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, var r20 = /%20/g,
rselectTextarea = /^(?:select|textarea)/i,
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rbracket = /\[\]$/, rbracket = /\[\]$/,
rhash = /#.*$/,
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rnoContent = /^(?:GET|HEAD)$/,
rquery = /\?/, rquery = /\?/,
r20 = /%20/g, rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /^(?:select|textarea)/i,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#:]+)(?::(\d+))?/,
rCRLF = /\r?\n/g,
// Slice function
sliceFunc = Array.prototype.slice,
// Keep a copy of the old load method // Keep a copy of the old load method
_load = jQuery.fn.load; _load = jQuery.fn.load;
@ -52,26 +61,34 @@ jQuery.fn.extend({
type: type, type: type,
dataType: "html", dataType: "html",
data: params, data: params,
complete: function( res, status ) { // Complete callback (responseText is used internally)
complete: function( jXHR, status, responseText ) {
// Store the response as specified by the jXHR object
responseText = jXHR.responseText;
// If successful, inject the HTML into all the matched elements // If successful, inject the HTML into all the matched elements
if ( status === "success" || status === "notmodified" ) { if ( jXHR.isResolved() ) {
// #4825: Get the actual response in case
// a dataFilter is present in ajaxSettings
jXHR.done(function( r ) {
responseText = r;
});
// See if a selector was specified // See if a selector was specified
self.html( selector ? self.html( selector ?
// Create a dummy div to hold the results // Create a dummy div to hold the results
jQuery("<div>") jQuery("<div>")
// inject the contents of the document in, removing the scripts // inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE // to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(rscript, "")) .append(responseText.replace(rscript, ""))
// Locate the specified elements // Locate the specified elements
.find(selector) : .find(selector) :
// If not, just inject the full result // If not, just inject the full result
res.responseText ); responseText );
} }
if ( callback ) { if ( callback ) {
self.each( callback, [res.responseText, status, res] ); self.each( callback, [responseText, status, jXHR] );
} }
} }
}); });
@ -99,9 +116,9 @@ jQuery.fn.extend({
null : null :
jQuery.isArray(val) ? jQuery.isArray(val) ?
jQuery.map( val, function(val, i){ jQuery.map( val, function(val, i){
return {name: elem.name, value: val}; return { name: elem.name, value: val.replace(rCRLF, "\r\n") };
}) : }) :
{name: elem.name, value: val}; { name: elem.name, value: val.replace(rCRLF, "\r\n") };
}).get(); }).get();
} }
}); });
@ -113,9 +130,8 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp
}; };
}); });
jQuery.extend({ jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
get: function( url, data, callback, type ) {
// shift arguments if data argument was omited // shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) { if ( jQuery.isFunction( data ) ) {
type = type || callback; type = type || callback;
@ -124,13 +140,16 @@ jQuery.extend({
} }
return jQuery.ajax({ return jQuery.ajax({
type: "GET", type: method,
url: url, url: url,
data: data, data: data,
success: callback, success: callback,
dataType: type dataType: type
}); });
}, };
});
jQuery.extend({
getScript: function( url, callback ) { getScript: function( url, callback ) {
return jQuery.get(url, null, callback, "script"); return jQuery.get(url, null, callback, "script");
@ -140,25 +159,11 @@ jQuery.extend({
return jQuery.get(url, data, callback, "json"); return jQuery.get(url, data, callback, "json");
}, },
post: function( url, data, callback, type ) {
// shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = {};
}
return jQuery.ajax({
type: "POST",
url: url,
data: data,
success: callback,
dataType: type
});
},
ajaxSetup: function( settings ) { ajaxSetup: function( settings ) {
jQuery.extend( jQuery.ajaxSettings, settings ); jQuery.extend( true, jQuery.ajaxSettings, settings );
if ( settings.context ) {
jQuery.ajaxSettings.context = settings.context;
}
}, },
ajaxSettings: { ajaxSettings: {
@ -172,20 +177,13 @@ jQuery.extend({
timeout: 0, timeout: 0,
data: null, data: null,
dataType: null, dataType: null,
dataTypes: null,
username: null, username: null,
password: null, password: null,
cache: null, cache: null,
traditional: false, traditional: false,
headers: {},
crossDomain: null,
*/ */
xhr: function() {
return new window.XMLHttpRequest();
},
xhrResponseFields: {
xml: "XML",
text: "Text",
json: "JSON"
},
accepts: { accepts: {
xml: "application/xml, text/xml", xml: "application/xml, text/xml",
@ -195,96 +193,603 @@ jQuery.extend({
"*": "*/*" "*": "*/*"
}, },
autoDataType: { contents: {
xml: /xml/, xml: /xml/,
html: /html/, html: /html/,
json: /json/ json: /json/
}, },
responseFields: {
xml: "responseXML",
text: "responseText"
},
// Prefilters // Prefilters
// 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example) // 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example)
// 2) These are called: // 2) These are called:
// * BEFORE asking for a transport // * BEFORE asking for a transport
// * AFTER param serialization (s.data is a string if s.processData is true) // * AFTER param serialization (s.data is a string if s.processData is true)
// 3) They MUST be order agnostic // 3) key is the dataType
prefilters: [], // 4) the catchall symbol "*" can be used
// 5) execution will start with transport dataType and THEN continue down to "*" if needed
prefilters: {},
// Transports bindings // Transports bindings
// 1) key is the dataType // 1) key is the dataType
// 2) the catchall symbol "*" can be used // 2) the catchall symbol "*" can be used
// 3) selection will start with transport dataType and THEN go to "*" if needed // 3) selection will start with transport dataType and THEN go to "*" if needed
transports: { transports: {},
},
// Checkers
// 1) key is dataType
// 2) they are called to control successful response
// 3) error throws is used as error data
dataCheckers: {
// Check if data is a string
"text": function(data) {
if ( typeof data != "string" ) {
jQuery.error("typeerror");
}
},
// Check if xml has been properly parsed
"xml": function(data) {
var documentElement = data ? data.documentElement : data;
if ( ! documentElement || ! documentElement.nodeName ) {
jQuery.error("typeerror");
}
if ( documentElement.nodeName == "parsererror" ) {
jQuery.error("parsererror");
}
}
},
// List of data converters // List of data converters
// 1) key format is "source_type => destination_type" (spaces required) // 1) key format is "source_type destination_type" (a single space in-between)
// 2) the catchall symbol "*" can be used for source_type // 2) the catchall symbol "*" can be used for source_type
dataConverters: { converters: {
// Convert anything to text // Convert anything to text
"* => text": function(data) { "* text": window.String,
return "" + data;
},
// Text to html (no transformation) // Text to html (true = no transformation)
"text => html": function(data) { "text html": true,
return data;
},
// Evaluate text as a json expression // Evaluate text as a json expression
"text => json": jQuery.parseJSON, "text json": jQuery.parseJSON,
// Parse text as xml // Parse text as xml
"text => xml": function(data) { "text xml": jQuery.parseXML
var xml, parser;
if ( window.DOMParser ) { // Standard
parser = new DOMParser();
xml = parser.parseFromString(data,"text/xml");
} else { // IE
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async="false";
xml.loadXML(data);
}
return xml;
}
} }
}, },
ajaxPrefilter: function( a , b ) {
ajaxPrefilterOrTransport( "prefilters" , a , b );
},
ajaxTransport: function( a , b ) {
return ajaxPrefilterOrTransport( "transports" , a , b );
},
// Main method // Main method
ajax: function( url , s ) { ajax: function( url , options ) {
if ( arguments.length === 1 ) { // If options is not an object,
s = url; // we simulate pre-1.5 signature
url = s ? s.url : undefined; if ( typeof( options ) !== "object" ) {
options = url;
url = undefined;
} }
return jQuery.xhr().open( s ? s.type : undefined , url ).send( undefined , s ); // Force options to be an object
options = options || {};
var // Create the final options object
s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ),
// jQuery lists
jQuery_lastModified = jQuery.lastModified,
jQuery_etag = jQuery.etag,
// Callbacks contexts
// We force the original context if it exists
// or take it from jQuery.ajaxSettings otherwise
// (plain objects used as context get extended)
callbackContext =
( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s,
globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ),
// Deferreds
deferred = jQuery.Deferred(),
completeDeferred = jQuery._Deferred(),
// Status-dependent callbacks
statusCode = s.statusCode || {},
// Headers (they are sent all at once)
requestHeaders = {},
// Response headers
responseHeadersString,
responseHeaders,
// transport
transport,
// timeout handle
timeoutTimer,
// Cross-domain detection vars
loc = document.location,
protocol = loc.protocol || "http:",
parts,
// The jXHR state
state = 0,
// Loop variable
i,
// Fake xhr
jXHR = {
readyState: 0,
// Caches the header
setRequestHeader: function(name,value) {
if ( state === 0 ) {
requestHeaders[ name.toLowerCase() ] = value;
}
return this;
},
// Raw string
getAllResponseHeaders: function() {
return state === 2 ? responseHeadersString : null;
},
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
var match;
if ( state === 2 ) {
if ( !responseHeaders ) {
responseHeaders = {};
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
}
}
match = responseHeaders[ key.toLowerCase() ];
}
return match || null;
},
// Cancel the request
abort: function( statusText ) {
if ( transport ) {
transport.abort( statusText || "abort" );
}
done( 0 , statusText );
return this;
}
};
// Callback for when everything is done
// It is defined here because jslint complains if it is declared
// at the end of the function (which would be more logical and readable)
function done( status , statusText , responses , headers) {
// Called once
if ( state === 2 ) {
return;
}
// State is "done" now
state = 2;
// Dereference transport for early garbage collection
// (no matter how long the jXHR object will be used)
transport = undefined;
// Set readyState
jXHR.readyState = status ? 4 : 0;
// Cache response headers
responseHeadersString = headers || "";
// Clear timeout if it exists
if ( timeoutTimer ) {
clearTimeout(timeoutTimer);
}
var // Reference dataTypes, converters and responseFields
dataTypes = s.dataTypes,
converters = s.converters,
responseFields = s.responseFields,
responseField,
// Flag to mark as success
isSuccess,
// Stored success
success,
// Stored error
error,
// To keep track of statusCode based callbacks
oldStatusCode,
// Actual response
response;
// If we got responses:
// - find the right one
// - update dataTypes accordingly
// - set responseXXX accordingly too
if ( responses ) {
var contents = s.contents,
transportDataType = dataTypes[0],
ct,
type,
finalDataType,
firstDataType;
// Auto (xml, json, script or text determined given headers)
if ( transportDataType === "*" ) {
// Remove all auto types
while( dataTypes[0] === "*" ) {
dataTypes.shift();
}
transportDataTypes = dataTypes[0];
// Get content type
ct = jXHR.getResponseHeader( "content-type" );
// Check if it's a known type
for ( type in contents ) {
if ( contents[ type ] && contents[ type ].test( ct ) ) {
dataTypes.unshift( ( transportDataType = type ) );
break;
}
}
}
// Check to see if we have a response for the expected dataType
if ( transportDataType in responses ) {
finalDataType = transportDataType;
} else {
// Try convertible dataTypes
for ( type in responses ) {
if ( ! firstDataType ) {
firstDataType = type;
}
if ( ! transportDataType || converters[ type + " " + transportDataType ] ) {
finalDataType = type;
break;
}
}
// Or just use first one
finalDataType = finalDataType || firstDataType;
}
// If we found a dataType
// We get the corresponding response
// and add the dataType to the list if needed
if ( finalDataType ) {
response = responses[ finalDataType ];
if ( finalDataType !== transportDataType ) {
dataTypes.unshift( finalDataType );
}
}
// Fill responseXXX fields
for( type in responseFields ) {
if ( type in responses ) {
jXHR[ responseFields[ type ] ] = responses[ type ];
}
}
}
// If successful, handle type chaining
if ( status >= 200 && status < 300 || status === 304 ) {
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
var lastModified = jXHR.getResponseHeader("Last-Modified"),
etag = jXHR.getResponseHeader("Etag");
if (lastModified) {
jQuery_lastModified[ s.url ] = lastModified;
}
if (etag) {
jQuery_etag[ s.url ] = etag;
}
}
// If not modified
if ( status === 304 ) {
statusText = "notmodified";
isSuccess = 1;
// If we have data
} else {
statusText = "success";
// Chain data conversions and determine the final value
// (if an exception is thrown in the process, it'll be notified as an error)
try {
var i,
tmp,
// Current dataType
current,
// Previous dataType
prev,
// Conversion expression
conversion,
// Conversion function
conv,
// Conversion functions (when text is used in-between)
conv1,
conv2;
// For each dataType in the chain
for( i = 0 ; i < dataTypes.length ; i++ ) {
current = dataTypes[ i ];
// If a responseXXX field for this dataType exists
// and if it hasn't been set yet
responseField = responseFields[ current ];
if ( responseField && ! ( responseField in jXHR ) ) {
jXHR[ responseField ] = response;
}
// If this is not the first element
if ( i ) {
// Get the dataType to convert from
prev = dataTypes[ i - 1 ];
// If no auto and dataTypes are actually different
if ( prev !== "*" && current !== "*" && prev !== current ) {
// Get the converter
conversion = prev + " " + current;
conv = converters[ conversion ] || converters[ "* " + current ];
// If there is no direct converter, search transitively
if ( ! conv ) {
conv1 = conv2 = undefined;
for( conv1 in converters ) {
tmp = conv1.split( " " );
if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
conv2 = converters[ tmp[ 1 ] + " " + current ];
if ( conv2 ) {
conv1 = converters[ conv1 ];
if ( conv1 === true ) {
conv = conv2;
} else if ( conv2 === true ) {
conv = conv1;
}
break;
}
}
}
}
// If we found no converter, dispatch an error
if ( ! ( conv || conv1 && conv2 ) ) {
throw conversion;
}
// If found converter is not an equivalence
if ( conv !== true ) {
// Convert with 1 or 2 converters accordingly
response = conv ? conv( response ) : conv2( conv1( response ) );
}
}
// If it is the first element of the chain
// and we have a dataFilter
} else if ( s.dataFilter ) {
// Apply the dataFilter
response = s.dataFilter( response , current );
// Get dataTypes again in case the filter changed them
dataTypes = s.dataTypes;
}
}
// End of loop
// We have a real success
success = response;
isSuccess = 1;
// If an exception was thrown
} catch(e) {
// We have a parsererror
statusText = "parsererror";
error = "" + e;
}
}
// if not success, mark it as an error
} else {
error = statusText = statusText || "error";
}
// Set data for the fake xhr object
jXHR.status = status;
jXHR.statusText = statusText;
// Success/Error
if ( isSuccess ) {
deferred.resolveWith( callbackContext , [ success , statusText , jXHR ] );
} else {
deferred.rejectWith( callbackContext , [ jXHR , statusText , error ] );
}
// Status-dependent callbacks
oldStatusCode = statusCode;
statusCode = undefined;
jXHR.statusCode( oldStatusCode );
if ( s.global ) {
globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) ,
[ jXHR , s , isSuccess ? success : error ] );
}
// Complete
completeDeferred.resolveWith( callbackContext, [ jXHR , statusText ] );
if ( s.global ) {
globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] );
// Handle the global AJAX counter
if ( ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
}
}
}
// Attach deferreds
deferred.promise( jXHR );
jXHR.success = jXHR.done;
jXHR.error = jXHR.fail;
jXHR.complete = completeDeferred.done;
// Status-dependent callbacks
jXHR.statusCode = function( map ) {
if ( map ) {
var tmp;
if ( statusCode ) {
for( tmp in map ) {
statusCode[ tmp ] = [ statusCode[ tmp ] , map[ tmp ] ];
}
} else {
tmp = map[ jXHR.status ];
jXHR.done( tmp ).fail( tmp );
}
}
return this;
};
// Remove hash character (#7531: and string promotion)
// We also use the url parameter if available
s.url = ( "" + ( url || s.url ) ).replace( rhash , "" );
// Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );
// Determine if a cross-domain request is in order
if ( ! s.crossDomain ) {
parts = rurl.exec( s.url.toLowerCase() );
s.crossDomain = !!(
parts &&
( parts[ 1 ] && parts[ 1 ] != protocol ||
parts[ 2 ] != loc.hostname ||
( parts[ 3 ] || ( ( parts[ 1 ] || protocol ) === "http:" ? 80 : 443 ) ) !=
( loc.port || ( protocol === "http:" ? 80 : 443 ) ) )
);
}
// Convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" ) {
s.data = jQuery.param( s.data , s.traditional );
}
// Apply prefilters
jQuery.ajaxPrefilter( s , options );
// Uppercase the type
s.type = s.type.toUpperCase();
// Determine if request has content
s.hasContent = ! rnoContent.test( s.type );
// Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" );
}
// More options handling for requests with no content
if ( ! s.hasContent ) {
// If data is available, append data to url
if ( s.data ) {
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
}
// Add anti-cache in url if needed
if ( s.cache === false ) {
var ts = jQuery.now(),
// try replacing _= if it is there
ret = s.url.replace( rts , "$1_=" + ts );
// if nothing was replaced, add timestamp to the end
s.url = ret + ( (ret == s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "");
}
}
// Set the correct header, if data is being sent
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
requestHeaders[ "content-type" ] = s.contentType;
}
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
if ( jQuery_lastModified[ s.url ] ) {
requestHeaders[ "if-modified-since" ] = jQuery_lastModified[ s.url ];
}
if ( jQuery_etag[ s.url ] ) {
requestHeaders[ "if-none-match" ] = jQuery_etag[ s.url ];
}
}
// Set the Accepts header for the server, depending on the dataType
requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
s.accepts[ "*" ];
// Check for headers option
for ( i in s.headers ) {
requestHeaders[ i.toLowerCase() ] = s.headers[ i ];
}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend && ( s.beforeSend.call( callbackContext , jXHR , s ) === false || state === 2 ) ) {
// Abort if not done already
done( 0 , "abort" );
// Return false
jXHR = false;
} else {
// Install callbacks on deferreds
for ( i in { success:1, error:1, complete:1 } ) {
jXHR[ i ]( s[ i ] );
}
// Get transport
transport = jQuery.ajaxTransport( s , options );
// If no transport, we auto-abort
if ( ! transport ) {
done( 0 , "notransport" );
} else {
// Set state as sending
state = jXHR.readyState = 1;
// Send global event
if ( s.global ) {
globalEventContext.trigger( "ajaxSend" , [ jXHR , s ] );
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout(function(){
jXHR.abort( "timeout" );
}, s.timeout);
}
// Try to send
try {
transport.send(requestHeaders, done);
} catch (e) {
// Propagate exception as error if not done
if ( status === 1 ) {
done(0, "error", "" + e);
jXHR = false;
// Simply rethrow otherwise
} else {
jQuery.error(e);
}
}
}
}
return jXHR;
}, },
// Serialize an array of form elements or a set of // Serialize an array of form elements or a set of
@ -343,7 +848,9 @@ function buildParams( prefix, obj, traditional, add ) {
}); });
} else if ( !traditional && obj != null && typeof obj === "object" ) { } else if ( !traditional && obj != null && typeof obj === "object" ) {
if ( jQuery.isEmptyObject( obj ) ) { // If we see an array here, it is empty and should be treated as an empty
// object
if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) {
add( prefix, "" ); add( prefix, "" );
// Serialize object item. // Serialize object item.
@ -372,33 +879,97 @@ jQuery.extend({
}); });
/* // Base function for both ajaxPrefilter and ajaxTransport
* Create the request object; Microsoft failed to properly function ajaxPrefilterOrTransport( arg0 , arg1 , arg2 ) {
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available var type = jQuery.type( arg1 ),
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so structure = jQuery.ajaxSettings[ arg0 ],
* we need a fallback. i,
*/ length;
if ( window.ActiveXObject ) {
jQuery.ajaxSettings.xhr = function() { // We have an options map so we have to inspect the structure
if ( window.location.protocol !== "file:" ) { if ( type === "object" ) {
try {
return new window.XMLHttpRequest(); var options = arg1,
} catch( xhrError ) {} originalOptions = arg2,
// When dealing with prefilters, we execute only
// (no selection so we never stop when a function
// returns a non-falsy, non-string value)
executeOnly = ( arg0 === "prefilters" ),
inspect = function( dataType, tested ) {
if ( ! tested[ dataType ] ) {
tested[ dataType ] = true;
var list = structure[ dataType ],
selected;
for( i = 0, length = list ? list.length : 0 ; ( executeOnly || ! selected ) && i < length ; i++ ) {
selected = list[ i ]( options , originalOptions );
// If we got redirected to a different dataType,
// we add it and switch to the corresponding list
if ( typeof( selected ) === "string" && selected !== dataType ) {
options.dataTypes.unshift( selected );
selected = inspect( selected , tested );
// We always break in order not to continue
// to iterate in previous list
break;
}
}
// If we're only executing or nothing was selected
// we try the catchall dataType
if ( executeOnly || ! selected ) {
selected = inspect( "*" , tested );
}
// This will be ignored by ajaxPrefilter
// so it's safe to return no matter what
return selected;
} }
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( activeError ) {}
}; };
// Start inspection with current transport dataType
return inspect( options.dataTypes[ 0 ] , {} );
} else {
// We're requested to add to the structure
// Signature is ( dataTypeExpression , function )
// with dataTypeExpression being optional and
// defaulting to catchAll (*)
type = type === "function";
if ( type ) {
arg2 = arg1;
arg1 = undefined;
} }
arg1 = arg1 || "*";
var testXHR = jQuery.ajaxSettings.xhr(); // We control that the second argument is really a function
if ( type || jQuery.isFunction( arg2 ) ) {
// Does this browser support XHR requests? var dataTypes = arg1.split( /\s+/ ),
jQuery.support.ajax = !!testXHR; functor = arg2,
dataType,
list,
placeBefore;
// Does this browser support crossDomain XHR requests // For each dataType in the dataTypeExpression
jQuery.support.cors = testXHR && "withCredentials" in testXHR; for( i = 0 , length = dataTypes.length ; i < length ; i++ ) {
dataType = dataTypes[ i ];
// We control if we're asked to add before
// any existing element
placeBefore = /^\+/.test( dataType );
if ( placeBefore ) {
dataType = dataType.substr( 1 );
}
list = structure[ dataType ] = structure[ dataType ] || [];
// then we add to the structure accordingly
list[ placeBefore ? "unshift" : "push" ]( functor );
}
}
}
}
})( jQuery ); })( jQuery );

87
src/ajax/jsonp.js Normal file
View file

@ -0,0 +1,87 @@
(function( jQuery ) {
var jsc = jQuery.now(),
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i;
// Default jsonp settings
jQuery.ajaxSetup({
jsonp: "callback",
jsonpCallback: function() {
return "jsonp" + jsc++;
}
});
// Detect, normalize options and install callbacks for jsonp requests
// (dataIsString is used internally)
jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
dataIsString = ( typeof(s.data) === "string" );
if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonpCallback ||
originalSettings.jsonp != null ||
s.jsonp !== false && ( jsre.test( s.url ) ||
dataIsString && jsre.test( s.data ) ) ) {
var responseContainer,
jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
previous = window[ jsonpCallback ],
url = s.url,
data = s.data,
replace = "$1" + jsonpCallback + "$2";
if ( s.jsonp !== false ) {
url = url.replace( jsre, replace );
if ( s.url === url ) {
if ( dataIsString ) {
data = data.replace( jsre, replace );
}
if ( s.data === data ) {
// Add callback manually
url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
}
}
}
s.url = url;
s.data = data;
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
s.complete = [function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction ( previous ) ) {
window[ jsonpCallback ] ( responseContainer[0] );
}
} else {
// else, more memory leak avoidance
try{ delete window[ jsonpCallback ]; } catch(e){}
}
}, s.complete ];
// Use data converter to retrieve json after script execution
s.converters["script json"] = function() {
if ( ! responseContainer ) {
jQuery.error( jsonpCallback + " was not called" );
}
return responseContainer[ 0 ];
};
// force json dataType
s.dataTypes[ 0 ] = "json";
// Delegate to script
return "script";
}
});
})( jQuery );

View file

@ -1,33 +1,39 @@
(function( jQuery ) { (function( jQuery ) {
// Install text to script executor // Install script dataType
jQuery.extend( true, jQuery.ajaxSettings , { jQuery.ajaxSetup({
accepts: { accepts: {
script: "text/javascript, application/javascript" script: "text/javascript, application/javascript"
}, },
autoDataType: { contents: {
script: /javascript/ script: /javascript/
}, },
dataConverters: { converters: {
"text => script": jQuery.globalEval "text script": jQuery.globalEval
} }
}); });
// Bind script tag hack transport // Handle cache's special case and global
jQuery.xhr.bindTransport("script", function(s) { jQuery.ajaxPrefilter("script", function(s) {
// Handle cache special case
if ( s.cache === undefined ) { if ( s.cache === undefined ) {
s.cache = false; s.cache = false;
} }
// This transport only deals with cross domain get requests if ( s.crossDomain ) {
if ( s.crossDomain && s.async && ( s.type === "GET" || ! s.data ) ) { s.type = "GET";
s.global = false; s.global = false;
}
});
// Bind script tag hack transport
jQuery.ajaxTransport("script", function(s) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
var script, var script,
head = document.getElementsByTagName("head")[0] || document.documentElement; head = document.getElementsByTagName("head")[0] || document.documentElement;
@ -47,10 +53,9 @@ jQuery.xhr.bindTransport("script", function(s) {
script.src = s.url; script.src = s.url;
// Attach handlers for all browsers // Attach handlers for all browsers
script.onload = script.onreadystatechange = function(statusText) { script.onload = script.onreadystatechange = function( _ , isAbort ) {
if ( (!script.readyState || if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) {
script.readyState === "loaded" || script.readyState === "complete") ) {
// Handle memory leak in IE // Handle memory leak in IE
script.onload = script.onreadystatechange = null; script.onload = script.onreadystatechange = null;
@ -60,10 +65,13 @@ jQuery.xhr.bindTransport("script", function(s) {
head.removeChild( script ); head.removeChild( script );
} }
script = undefined; // Dereference the script
script = 0;
// Callback & dereference // Callback if not abort
callback(statusText ? 0 : 200, statusText || "success"); if ( ! isAbort ) {
callback( 200, "success" );
}
} }
}; };
// Use insertBefore instead of appendChild to circumvent an IE6 bug. // Use insertBefore instead of appendChild to circumvent an IE6 bug.
@ -71,9 +79,9 @@ jQuery.xhr.bindTransport("script", function(s) {
head.insertBefore( script, head.firstChild ); head.insertBefore( script, head.firstChild );
}, },
abort: function(statusText) { abort: function() {
if ( script ) { if ( script ) {
script.onload(statusText); script.onload(0,1);
} }
} }
}; };

225
src/ajax/xhr.js Normal file
View file

@ -0,0 +1,225 @@
(function( jQuery ) {
var // Next active xhr id
xhrId = jQuery.now(),
// active xhrs
xhrs = {},
// #5280: see below
xhrUnloadAbortInstalled,
// XHR used to determine supports properties
testXHR;
// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
if ( window.location.protocol !== "file:" ) {
try {
return new window.XMLHttpRequest();
} catch( xhrError ) {}
}
try {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} catch( activeError ) {}
} :
// For all other browsers, use the standard XMLHttpRequest object
function() {
return new window.XMLHttpRequest();
};
// Test if we can create an xhr object
try {
testXHR = jQuery.ajaxSettings.xhr();
} catch( xhrCreationException ) {}
//Does this browser support XHR requests?
jQuery.support.ajax = !!testXHR;
// Does this browser support crossDomain XHR requests
jQuery.support.cors = testXHR && "withCredentials" in testXHR;
// No need for the temporary xhr anymore
testXHR = undefined;
// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {
jQuery.ajaxTransport( function( s ) {
// Cross domain only allowed if supported through XMLHttpRequest
if ( ! s.crossDomain || jQuery.support.cors ) {
var callback;
return {
send: function(headers, complete) {
// #5280: we need to abort on unload or IE will keep connections alive
if ( ! xhrUnloadAbortInstalled ) {
xhrUnloadAbortInstalled = 1;
jQuery(window).bind( "unload" , function() {
// Abort all pending requests
jQuery.each(xhrs, function(_, xhr) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( 1 );
}
});
});
}
// Get a new xhr
var xhr = s.xhr(),
handle;
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
xhr.open(s.type, s.url, s.async, s.username, s.password);
} else {
xhr.open(s.type, s.url, s.async);
}
// Requested-With header
// Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
headers["x-requested-with"] = "XMLHttpRequest";
}
// Need an extra try/catch for cross domain requests in Firefox 3
try {
jQuery.each(headers, function(key,value) {
xhr.setRequestHeader(key,value);
});
} catch(_) {}
// Do send the request
try {
xhr.send( ( s.hasContent && s.data ) || null );
} catch(e) {
complete(0, "error", "" + e);
return;
}
// Listener
callback = function( _ , isAbort ) {
// Was never called and is aborted or complete
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Only called once
callback = 0;
// Do not keep as active anymore
if (handle) {
xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ];
}
// If it's an abort
if ( isAbort ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) {
xhr.abort();
}
} else {
// Get info
var status = xhr.status,
statusText,
responseHeaders = xhr.getAllResponseHeaders(),
responses = {},
xml = xhr.responseXML;
// Construct response list
if ( xml && xml.documentElement /* #4958 */ ) {
responses.xml = xml;
}
responses.text = xhr.responseText;
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
statusText = xhr.statusText;
} catch( e ) {
statusText = ""; // We normalize with Webkit giving an empty statusText
}
// Filter status for non standard behaviours
// (so many they seem to be the actual "standard")
status =
// Opera returns 0 when it should be 304
// Webkit returns 0 for failing cross-domain no matter the real status
status === 0 ?
(
! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests
(
responseHeaders ? // Opera: filter out real aborts #6060
304
:
0
)
:
302 // We assume 302 but could be anything cross-domain related
)
:
(
status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450)
204
:
status
);
// Call complete
complete(status,statusText,responses,responseHeaders);
}
}
};
// if we're in sync mode
// or it's in cache and has been retrieved directly (IE6 & IE7)
// we need to manually fire the callback
if ( ! s.async || xhr.readyState === 4 ) {
callback();
} else {
// Add to list of active xhrs
handle = xhrId++;
xhrs[ handle ] = xhr;
xhr.onreadystatechange = callback;
}
},
abort: function() {
if ( callback ) {
callback(0,1);
}
}
};
}
});
}
})( jQuery );

View file

@ -133,11 +133,11 @@ jQuery.fn.extend({
} else if ( type === "undefined" || type === "boolean" ) { } else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) { if ( this.className ) {
// store className if set // store className if set
jQuery.data( this, "__className__", this.className ); jQuery._data( this, "__className__", this.className );
} }
// toggle whole className // toggle whole className
this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
} }
}); });
}, },

View file

@ -3,7 +3,7 @@ var jQuery = (function() {
// Define a local copy of jQuery // Define a local copy of jQuery
var jQuery = function( selector, context ) { var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced' // The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context ); return new jQuery.fn.init( selector, context, rootjQuery );
}, },
// Map over jQuery in case of overwrite // Map over jQuery in case of overwrite
@ -19,12 +19,8 @@ var jQuery = function( selector, context ) {
// (both of which we optimize for) // (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/,
// Check if a string has a non-whitespace character in it // Check if a string has a non-whitespace character in it
rnotwhite = /\S/, rnotwhite = /\S/,
rwhite = /\s/,
// Used for trimming whitespace // Used for trimming whitespace
trimLeft = /^\s+/, trimLeft = /^\s+/,
@ -60,8 +56,11 @@ var jQuery = function( selector, context ) {
// Has the ready events already been bound? // Has the ready events already been bound?
readyBound = false, readyBound = false,
// The functions to execute on DOM ready // The deferred used on DOM ready
readyList = [], readyList,
// Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
// The ready event handler // The ready event handler
DOMContentLoaded, DOMContentLoaded,
@ -78,7 +77,8 @@ var jQuery = function( selector, context ) {
class2type = {}; class2type = {};
jQuery.fn = jQuery.prototype = { jQuery.fn = jQuery.prototype = {
init: function( selector, context ) { constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc; var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined) // Handle $(""), $(null), or $(undefined)
@ -112,6 +112,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(html) -> $(array) // HANDLE: $(html) -> $(array)
if ( match[1] ) { if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = (context ? context.ownerDocument || context : document); doc = (context ? context.ownerDocument || context : document);
// If a single string is passed in and it's a single tag // If a single string is passed in and it's a single tag
@ -129,7 +130,7 @@ jQuery.fn = jQuery.prototype = {
} else { } else {
ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; selector = (ret.cacheable ? jQuery(ret.fragment).clone()[0] : ret.fragment).childNodes;
} }
return jQuery.merge( this, selector ); return jQuery.merge( this, selector );
@ -157,13 +158,6 @@ jQuery.fn = jQuery.prototype = {
return this; return this;
} }
// HANDLE: $("TAG")
} else if ( !context && !rnonword.test( selector ) ) {
this.selector = selector;
this.context = document;
selector = document.getElementsByTagName( selector );
return jQuery.merge( this, selector );
// HANDLE: $(expr, $(...)) // HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) { } else if ( !context || context.jquery ) {
return (context || rootjQuery).find( selector ); return (context || rootjQuery).find( selector );
@ -171,7 +165,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(expr, context) // HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr) // (which is just equivalent to: $(context).find(expr)
} else { } else {
return jQuery( context ).find( selector ); return this.constructor( context ).find( selector );
} }
// HANDLE: $(function) // HANDLE: $(function)
@ -222,7 +216,7 @@ jQuery.fn = jQuery.prototype = {
// (returning the new matched element set) // (returning the new matched element set)
pushStack: function( elems, name, selector ) { pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set // Build a new jQuery matched element set
var ret = jQuery(); var ret = this.constructor();
if ( jQuery.isArray( elems ) ) { if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems ); push.apply( ret, elems );
@ -253,22 +247,12 @@ jQuery.fn = jQuery.prototype = {
return jQuery.each( this, callback, args ); return jQuery.each( this, callback, args );
}, },
ready: function( fn ) { ready: function() {
// Attach the listeners // Attach the listeners
jQuery.bindReady(); jQuery.bindReady();
// If the DOM is already ready // Change ready & apply
if ( jQuery.isReady ) { return ( jQuery.fn.ready = readyList.done ).apply( this , arguments );
// Execute the function immediately
fn.call( document, jQuery );
// Otherwise, remember the function for later
} else if ( readyList ) {
// Add the function to the wait list
readyList.push( fn );
}
return this;
}, },
eq: function( i ) { eq: function( i ) {
@ -297,7 +281,7 @@ jQuery.fn = jQuery.prototype = {
}, },
end: function() { end: function() {
return this.prevObject || jQuery(null); return this.prevObject || this.constructor(null);
}, },
// For internal use only. // For internal use only.
@ -415,25 +399,13 @@ jQuery.extend({
} }
// If there are functions bound, to execute // If there are functions bound, to execute
if ( readyList ) { readyList.resolveWith( document , [ jQuery ] );
// Execute all of them
var fn,
i = 0,
ready = readyList;
// Reset the list of functions
readyList = null;
while ( (fn = ready[ i++ ]) ) {
fn.call( document, jQuery );
}
// Trigger any bound ready events // Trigger any bound ready events
if ( jQuery.fn.trigger ) { if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).unbind( "ready" ); jQuery( document ).trigger( "ready" ).unbind( "ready" );
} }
} }
}
}, },
bindReady: function() { bindReady: function() {
@ -566,6 +538,28 @@ jQuery.extend({
} }
}, },
// Cross-browser xml parsing
// (xml & tmp used internally)
parseXML: function( data , xml , tmp ) {
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 );
}
tmp = xml.documentElement;
if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
jQuery.error( "Invalid XML: " + data );
}
return xml;
},
noop: function() {}, noop: function() {},
// Evalulates a script in a global context // Evalulates a script in a global context
@ -578,7 +572,7 @@ jQuery.extend({
script.type = "text/javascript"; script.type = "text/javascript";
if ( jQuery.support.scriptEval ) { if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) ); script.appendChild( document.createTextNode( data ) );
} else { } else {
script.text = data; script.text = data;
@ -816,6 +810,178 @@ jQuery.extend({
return (new Date()).getTime(); return (new Date()).getTime();
}, },
// Create a simple deferred (one callbacks list)
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {
// done( f1, f2, ...)
done: function () {
if ( ! cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length ; i < length ; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred , elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ] , _fired[ 1 ] );
}
}
return this;
},
// resolve with given context and args
resolveWith: function( context , args ) {
if ( ! cancelled && ! fired && ! firing ) {
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context , args );
}
}
finally {
fired = [ context , args ];
firing = 0;
}
}
return this;
},
// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments );
return this;
},
// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},
// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
// Full fledged deferred (two callbacks list)
// Typical success/error system
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred(),
promise;
// Add errorDeferred methods, then and promise
jQuery.extend( deferred , {
then: function( doneCallbacks , failCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks );
return this;
},
fail: failDeferred.done,
rejectWith: failDeferred.resolveWith,
reject: failDeferred.resolve,
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
// (i is used internally)
promise: function( obj , i ) {
if ( obj == null ) {
if ( promise ) {
return promise;
}
promise = obj = {};
}
i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
}
return obj;
}
} );
// Make sure only one callback list will be used
deferred.then( failDeferred.cancel , deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred , deferred );
}
return deferred;
},
// Deferred helper
when: function( object ) {
var args = arguments,
length = args.length,
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred(),
promise = deferred.promise(),
resolveArray;
if ( length > 1 ) {
resolveArray = new Array( length );
jQuery.each( args, function( index, element, args ) {
jQuery.when( element ).done( function( value ) {
args = arguments;
resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value;
if( ! --length ) {
deferred.resolveWith( promise, resolveArray );
}
}).fail( function() {
deferred.rejectWith( promise, arguments );
});
return !deferred.isRejected();
});
} else if ( deferred !== object ) {
deferred.resolve( object );
}
return promise;
},
// Use of jQuery.browser is frowned upon. // Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser // More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) { uaMatch: function( ua ) {
@ -830,9 +996,31 @@ jQuery.extend({
return { browser: match[1] || "", version: match[2] || "0" }; return { browser: match[1] || "", version: match[2] || "0" };
}, },
subclass: function(){
function jQuerySubclass( selector, context ) {
return new jQuerySubclass.fn.init( selector, context );
}
jQuerySubclass.superclass = this;
jQuerySubclass.fn = jQuerySubclass.prototype = this();
jQuerySubclass.fn.constructor = jQuerySubclass;
jQuerySubclass.subclass = this.subclass;
jQuerySubclass.fn.init = function init( selector, context ) {
if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){
context = jQuerySubclass(context);
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
};
jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
var rootjQuerySubclass = jQuerySubclass(document);
return jQuerySubclass;
},
browser: {} browser: {}
}); });
// Create readyList deferred
readyList = jQuery._Deferred();
// Populate the class2type map // Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase(); class2type[ "[object " + name + "]" ] = name.toLowerCase();
@ -855,9 +1043,8 @@ if ( indexOf ) {
}; };
} }
// Verify that \s matches non-breaking spaces // IE doesn't match non-breaking spaces with \s
// (IE fails on this test) if ( rnotwhite.test( "\xA0" ) ) {
if ( !rwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/; trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/; trimRight = /[\s\xA0]+$/;
} }

View file

@ -263,8 +263,9 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
if ( document.documentElement.currentStyle ) { if ( document.documentElement.currentStyle ) {
currentStyle = function( elem, name ) { currentStyle = function( elem, name ) {
var left, rsLeft, var left,
ret = elem.currentStyle && elem.currentStyle[ name ], ret = elem.currentStyle && elem.currentStyle[ name ],
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
style = elem.style; style = elem.style;
// From the awesome hack by Dean Edwards // From the awesome hack by Dean Edwards
@ -275,17 +276,20 @@ if ( document.documentElement.currentStyle ) {
if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
// Remember the original values // Remember the original values
left = style.left; left = style.left;
rsLeft = elem.runtimeStyle.left;
// Put in the new values to get a computed value out // Put in the new values to get a computed value out
if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left; elem.runtimeStyle.left = elem.currentStyle.left;
}
style.left = name === "fontSize" ? "1em" : (ret || 0); style.left = name === "fontSize" ? "1em" : (ret || 0);
ret = style.pixelLeft + "px"; ret = style.pixelLeft + "px";
// Revert the changed values // Revert the changed values
style.left = left; style.left = left;
if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft; elem.runtimeStyle.left = rsLeft;
} }
}
return ret === "" ? "auto" : ret; return ret === "" ? "auto" : ret;
}; };

View file

@ -1,7 +1,6 @@
(function( jQuery ) { (function( jQuery ) {
var windowData = {}, var rbrace = /^(?:\{.*\}|\[.*\])$/;
rbrace = /^(?:\{.*\}|\[.*\])$/;
jQuery.extend({ jQuery.extend({
cache: {}, cache: {},
@ -10,7 +9,8 @@ jQuery.extend({
uuid: 0, uuid: 0,
// Unique for each copy of jQuery on the page // Unique for each copy of jQuery on the page
expando: "jQuery" + jQuery.now(), // Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
// The following elements throw uncatchable exceptions if you // The following elements throw uncatchable exceptions if you
// attempt to add expando properties to them. // attempt to add expando properties to them.
@ -21,103 +21,171 @@ jQuery.extend({
"applet": true "applet": true
}, },
data: function( elem, name, data ) { hasData: function( elem ) {
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !jQuery.isEmptyObject(elem);
},
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
windowData :
elem;
var isNode = elem.nodeType, // We have to handle DOM nodes and JS objects differently because IE6-7
id = isNode ? elem[ jQuery.expando ] : null, // can't GC object references properly across the DOM-JS boundary
cache = jQuery.cache, thisCache; isNode = elem.nodeType,
if ( isNode && !id && typeof name === "string" && data === undefined ) { // 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[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
// 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 || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
return; return;
} }
// Get the data from the object directly if ( !id ) {
if ( !isNode ) { // Only DOM nodes need a new unique ID for each element since their data
cache = elem; // ends up in the global cache
// Compute a unique ID for the element
} else if ( !id ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
}
// Avoid generating a new cache unless none exists and we
// want to manipulate it.
if ( typeof name === "object" ) {
if ( isNode ) { if ( isNode ) {
cache[ id ] = jQuery.extend(cache[ id ], name); elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else { } else {
jQuery.extend( cache, name ); id = jQuery.expando;
}
} }
} else if ( isNode && !cache[ id ] ) { if ( !cache[ id ] ) {
cache[ id ] = {}; cache[ id ] = {};
} }
thisCache = isNode ? cache[ id ] : cache; // 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" ) {
if ( pvt ) {
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
} else {
cache[ id ] = jQuery.extend(cache[ id ], name);
}
}
thisCache = cache[ id ];
// Internal jQuery data is stored in a separate object inside the object's data
// cache in order to avoid key collisions between internal data and user-defined
// data
if ( pvt ) {
if ( !thisCache[ internalKey ] ) {
thisCache[ internalKey ] = {};
}
thisCache = thisCache[ internalKey ];
}
// Prevent overriding the named cache with undefined values
if ( data !== undefined ) { if ( data !== undefined ) {
thisCache[ name ] = data; thisCache[ name ] = data;
} }
return typeof name === "string" ? thisCache[ name ] : thisCache; // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
// not attempt to inspect the internal events object using jQuery.data, as this
// internal data object is undocumented and subject to change.
if ( name === "events" && !thisCache[name] ) {
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
}
return getByName ? thisCache[ name ] : thisCache;
}, },
removeData: function( elem, name ) { removeData: function( elem, name, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, isNode = elem.nodeType,
windowData :
elem;
var isNode = elem.nodeType, // See jQuery.data for more information
id = isNode ? elem[ jQuery.expando ] : elem, cache = isNode ? jQuery.cache : elem,
cache = jQuery.cache,
thisCache = isNode ? cache[ id ] : id; // See jQuery.data for more information
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 we want to remove a specific section of the element's data
if ( name ) { if ( name ) {
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
if ( thisCache ) { if ( thisCache ) {
// Remove the section of cache data
delete thisCache[ name ]; delete thisCache[ name ];
// If we've removed all the data, remove the element's cache // If there is no data left in the cache, we want to continue
if ( isNode && jQuery.isEmptyObject(thisCache) ) { // and let the cache object itself get destroyed
jQuery.removeData( elem ); if ( !jQuery.isEmptyObject(thisCache) ) {
return;
}
} }
} }
// Otherwise, we want to remove all of the element's data // See jQuery.data for more information
if ( pvt ) {
delete cache[ id ][ internalKey ];
// Don't destroy the parent cache unless the internal data object
// had been the only thing left in it
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
return;
}
}
var internalCache = cache[ id ][ internalKey ];
// Browsers that fail expando deletion also refuse to delete expandos on
// the window, but it will allow it on all other JS objects; other browsers
// don't care
if ( jQuery.support.deleteExpando || cache != window ) {
delete cache[ id ];
} else { } else {
if ( isNode && jQuery.support.deleteExpando ) { cache[ id ] = null;
delete elem[ jQuery.expando ]; }
// We destroyed the entire user cache at once because it's faster than
// iterating through each key, but we need to continue to persist internal
// data if it existed
if ( internalCache ) {
cache[ id ] = {};
cache[ id ][ internalKey ] = internalCache;
// Otherwise, we need to eliminate the expando on the node to avoid
// false lookups in the cache for entries that no longer exist
} else if ( isNode ) {
// IE does not allow us to delete expando properties from nodes,
// nor does it have a removeAttribute function on Document nodes;
// we must handle all of these cases
if ( jQuery.support.deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) { } else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando ); elem.removeAttribute( jQuery.expando );
// Completely remove the data cache
} else if ( isNode ) {
delete cache[ id ];
// Remove all fields from the object
} else { } else {
for ( var n in elem ) { elem[ jQuery.expando ] = null;
delete elem[ n ];
}
} }
} }
}, },
// For internal use only.
_data: function( elem, name, data ) {
return jQuery.data( elem, name, data, true );
},
// A method for determining if a DOM node can handle the data expando // A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) { acceptData: function( elem ) {
if ( elem.nodeName ) { if ( elem.nodeName ) {

View file

@ -35,8 +35,10 @@ jQuery.each([ "Height", "Width" ], function( i, name ) {
if ( jQuery.isWindow( elem ) ) { if ( jQuery.isWindow( elem ) ) {
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] || // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
elem.document.body[ "client" + name ]; var docElemProp = elem.document.documentElement[ "client" + name ];
return elem.document.compatMode === "CSS1Compat" && docElemProp ||
elem.document.body[ "client" + name ] || docElemProp;
// Get document width or height // Get document width or height
} else if ( elem.nodeType === 9 ) { } else if ( elem.nodeType === 9 ) {

12
src/effects.js vendored
View file

@ -27,7 +27,7 @@ jQuery.fn.extend({
// Reset the inline display of this element to learn if it is // Reset the inline display of this element to learn if it is
// being hidden by cascaded rules or not // being hidden by cascaded rules or not
if ( !jQuery.data(elem, "olddisplay") && display === "none" ) { if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
display = elem.style.display = ""; display = elem.style.display = "";
} }
@ -35,7 +35,7 @@ jQuery.fn.extend({
// in a stylesheet to whatever the default browser style is // in a stylesheet to whatever the default browser style is
// for such an element // for such an element
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName)); jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
} }
} }
@ -46,7 +46,7 @@ jQuery.fn.extend({
display = elem.style.display; display = elem.style.display;
if ( display === "" || display === "none" ) { if ( display === "" || display === "none" ) {
elem.style.display = jQuery.data(elem, "olddisplay") || ""; elem.style.display = jQuery._data(elem, "olddisplay") || "";
} }
} }
@ -62,8 +62,8 @@ jQuery.fn.extend({
for ( var i = 0, j = this.length; i < j; i++ ) { for ( var i = 0, j = this.length; i < j; i++ ) {
var display = jQuery.css( this[i], "display" ); var display = jQuery.css( this[i], "display" );
if ( display !== "none" ) { if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
jQuery.data( this[i], "olddisplay", display ); jQuery._data( this[i], "olddisplay", display );
} }
} }
@ -337,7 +337,7 @@ jQuery.fx.prototype = {
} }
var r = parseFloat( jQuery.css( this.elem, this.prop ) ); var r = parseFloat( jQuery.css( this.elem, this.prop ) );
return r && r > -10000 ? r : 0; return r || 0;
}, },
// Start an animation from one number to another // Start an animation from one number to another

View file

@ -8,7 +8,7 @@ var rnamespaces = /\.(.*)$/,
fcleanup = function( nm ) { fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&"); return nm.replace(rescape, "\\$&");
}, },
focusCounts = { focusin: 0, focusout: 0 }; eventKey = "events";
/* /*
* A number of helper functions used for managing events. * A number of helper functions used for managing events.
@ -50,7 +50,7 @@ jQuery.event = {
} }
// Init the element's event structure // Init the element's event structure
var elemData = jQuery.data( elem ); var elemData = jQuery._data( elem );
// If no elemData is found then we must be trying to bind to one of the // If no elemData is found then we must be trying to bind to one of the
// banned noData elements // banned noData elements
@ -58,10 +58,7 @@ jQuery.event = {
return; return;
} }
// Use a key less likely to result in collisions for plain JS objects. var events = elemData[ eventKey ],
// Fixes bug #7150.
var eventKey = elem.nodeType ? "events" : "__events__",
events = elemData[ eventKey ],
eventHandle = elemData.handle; eventHandle = elemData.handle;
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
@ -177,8 +174,7 @@ jQuery.event = {
} }
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
eventKey = elem.nodeType ? "events" : "__events__", elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
elemData = jQuery.data( elem ),
events = elemData && elemData[ eventKey ]; events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) { if ( !elemData || !events ) {
@ -290,10 +286,10 @@ jQuery.event = {
delete elemData.handle; delete elemData.handle;
if ( typeof elemData === "function" ) { if ( typeof elemData === "function" ) {
jQuery.removeData( elem, eventKey ); jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) { } else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem ); jQuery.removeData( elem, undefined, true );
} }
} }
}, },
@ -325,9 +321,16 @@ jQuery.event = {
// Only trigger if we've ever bound an event for it // Only trigger if we've ever bound an event for it
if ( jQuery.event.global[ type ] ) { if ( jQuery.event.global[ type ] ) {
// XXX This code smells terrible. event.js should not be directly
// inspecting the data cache
jQuery.each( jQuery.cache, function() { jQuery.each( jQuery.cache, function() {
if ( this.events && this.events[type] ) { // internalKey variable is just used to make it easier to find
jQuery.event.trigger( event, data, this.handle.elem ); // and potentially change this stuff later; currently it just
// points to jQuery.expando
var internalKey = jQuery.expando,
internalCache = this[ internalKey ];
if ( internalCache && internalCache.events && internalCache.events[type] ) {
jQuery.event.trigger( event, data, internalCache.handle.elem );
} }
}); });
} }
@ -353,8 +356,8 @@ jQuery.event = {
// Trigger the event, it is assumed that "handle" is a function // Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ? var handle = elem.nodeType ?
jQuery.data( elem, "handle" ) : jQuery._data( elem, "handle" ) :
(jQuery.data( elem, "__events__" ) || {}).handle; (jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) { if ( handle ) {
handle.apply( elem, data ); handle.apply( elem, data );
@ -432,7 +435,7 @@ jQuery.event = {
event.namespace = event.namespace || namespace_sort.join("."); event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery.data(this, this.nodeType ? "events" : "__events__"); events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
@ -600,6 +603,12 @@ jQuery.Event = function( src ) {
if ( src && src.type ) { if ( src && src.type ) {
this.originalEvent = src; this.originalEvent = src;
this.type = src.type; 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 // Event type
} else { } else {
this.type = src; this.type = src;
@ -781,12 +790,12 @@ if ( !jQuery.support.changeBubbles ) {
return; return;
} }
data = jQuery.data( elem, "_change_data" ); data = jQuery._data( elem, "_change_data" );
val = getVal(elem); val = getVal(elem);
// the current data will be also retrieved by beforeactivate // the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) { if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery.data( elem, "_change_data", val ); jQuery._data( elem, "_change_data", val );
} }
if ( data === undefined || val === data ) { if ( data === undefined || val === data ) {
@ -831,7 +840,7 @@ if ( !jQuery.support.changeBubbles ) {
// information // information
beforeactivate: function( e ) { beforeactivate: function( e ) {
var elem = e.target; var elem = e.target;
jQuery.data( elem, "_change_data", getVal(elem) ); jQuery._data( elem, "_change_data", getVal(elem) );
} }
}, },
@ -870,21 +879,17 @@ if ( document.addEventListener ) {
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
jQuery.event.special[ fix ] = { jQuery.event.special[ fix ] = {
setup: function() { setup: function() {
if ( focusCounts[fix]++ === 0 ) { this.addEventListener( orig, handler, true );
document.addEventListener( orig, handler, true );
}
}, },
teardown: function() { teardown: function() {
if ( --focusCounts[fix] === 0 ) { this.removeEventListener( orig, handler, true );
document.removeEventListener( orig, handler, true );
}
} }
}; };
function handler( e ) { function handler( e ) {
e = jQuery.event.fix( e ); e = jQuery.event.fix( e );
e.type = fix; e.type = fix;
return jQuery.event.trigger( e, null, e.target ); return jQuery.event.handle.call( this, e );
} }
}); });
} }
@ -1079,7 +1084,7 @@ function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [], elems = [],
selectors = [], selectors = [],
events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
@ -1187,21 +1192,4 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
} }
}); });
// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
jQuery(window).bind("unload", function() {
for ( var id in jQuery.cache ) {
if ( jQuery.cache[ id ].handle ) {
// Try/Catch is to handle iframes being unloaded, see #4280
try {
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
} catch(e) {}
}
}
});
}
})( jQuery ); })( jQuery );

View file

@ -11,7 +11,7 @@
* Copyright 2010, The Dojo Foundation * Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses. * Released under the MIT, BSD, and GPL Licenses.
* *
* Date: * Date: @DATE
*/ */
(function( window, undefined ) { (function( window, undefined ) {

View file

@ -346,7 +346,7 @@ jQuery.fn.extend({
table ? table ?
root(this[i], first) : root(this[i], first) :
this[i], this[i],
i > 0 || results.cacheable || this.length > 1 ? i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
jQuery(fragment).clone(true)[0] : jQuery(fragment).clone(true)[0] :
fragment fragment
); );
@ -370,24 +370,35 @@ function root( elem, cur ) {
} }
function cloneCopyEvent(orig, ret) { function cloneCopyEvent(orig, ret) {
var i = 0; ret.each(function (nodeIndex) {
if ( this.nodeType !== 1 || !jQuery.hasData(orig[nodeIndex]) ) {
ret.each(function() {
if ( this.nodeType !== 1 || this.nodeName !== (orig[i] && orig[i].nodeName) ) {
return; return;
} }
var oldData = jQuery.data( orig[i++] ), // XXX remove for 1.5 RC or merge back in if there is actually a reason for this check that has been
curData = jQuery.data( this, oldData ), // unexposed by unit tests
events = oldData && oldData.events; if ( this.nodeName !== (orig[nodeIndex] && orig[nodeIndex].nodeName) ) {
throw "Cloned data mismatch";
}
var internalKey = jQuery.expando,
oldData = jQuery.data( orig[nodeIndex] ),
curData = jQuery.data( this, oldData );
// Switch to use the internal data object, if it exists, for the next
// stage of data copying
if ( (oldData = oldData[ internalKey ]) ) {
var events = oldData.events;
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
if ( events ) { if ( events ) {
delete curData.handle; delete curData.handle;
curData.events = {}; curData.events = {};
for ( var type in events ) { for ( var type in events ) {
for ( var handler in events[ type ] ) { for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
}
} }
} }
} }
@ -415,18 +426,30 @@ function cloneFixAttributes(src, dest) {
// attribute) to identify the type of content to display // attribute) to identify the type of content to display
if ( nodeName === "object" ) { if ( nodeName === "object" ) {
dest.outerHTML = src.outerHTML; dest.outerHTML = src.outerHTML;
} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
// 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
if ( src.checked ) {
dest.defaultChecked = dest.checked = src.checked;
} }
// IE6-8 fails to persist the checked state of a cloned checkbox // IE6-7 get confused and end up setting the value of a cloned
// or radio button // checkbox/radio button to an empty string instead of "on"
else if ( nodeName === "input" && src.checked ) { if ( dest.value !== src.value ) {
dest.defaultChecked = dest.checked = src.checked; dest.value = src.value;
} }
// IE6-8 fails to return the selected option to the default selected // IE6-8 fails to return the selected option to the default selected
// state when cloning options // state when cloning options
else if ( nodeName === "option" ) { } else if ( nodeName === "option" ) {
dest.selected = src.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;
} }
// Event data gets referenced instead of copied if the expando // Event data gets referenced instead of copied if the expando
@ -438,12 +461,12 @@ jQuery.buildFragment = function( args, nodes, scripts ) {
var fragment, cacheable, cacheresults, var fragment, cacheable, cacheresults,
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
// Only cache "small" (1/2 KB) strings that are associated with the main document // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
// Cloning options loses the selected state, so don't cache them // Cloning options loses the selected state, so don't cache them
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
cacheable = true; cacheable = true;
cacheresults = jQuery.fragments[ args[0] ]; cacheresults = jQuery.fragments[ args[0] ];
@ -592,8 +615,7 @@ jQuery.extend({
}, },
cleanData: function( elems ) { cleanData: function( elems ) {
var data, id, cache = jQuery.cache, var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando; deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
@ -604,17 +626,23 @@ jQuery.extend({
id = elem[ jQuery.expando ]; id = elem[ jQuery.expando ];
if ( id ) { if ( id ) {
data = cache[ id ]; data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) { if ( data && data.events ) {
for ( var type in data.events ) { for ( var type in data.events ) {
if ( special[ type ] ) { if ( special[ type ] ) {
jQuery.event.remove( elem, type ); jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
} else { } else {
jQuery.removeEvent( elem, type, data.handle ); jQuery.removeEvent( elem, type, data.handle );
} }
} }
// Null the DOM reference to avoid IE6/7/8 leak (#7054)
if ( data.handle ) {
data.handle.elem = null;
}
} }
if ( deleteExpando ) { if ( deleteExpando ) {

View file

@ -30,7 +30,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
// Make sure we're not dealing with a disconnected DOM node // Make sure we're not dealing with a disconnected DOM node
if ( !box || !jQuery.contains( docElem, elem ) ) { if ( !box || !jQuery.contains( docElem, elem ) ) {
return box || { top: 0, left: 0 }; return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
} }
var body = doc.body, var body = doc.body,

View file

@ -7,7 +7,7 @@ jQuery.extend({
} }
type = (type || "fx") + "queue"; type = (type || "fx") + "queue";
var q = jQuery.data( elem, type ); var q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup // Speed up dequeue by getting out quickly if this is just a lookup
if ( !data ) { if ( !data ) {
@ -15,7 +15,7 @@ jQuery.extend({
} }
if ( !q || jQuery.isArray(data) ) { if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data) ); q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else { } else {
q.push( data ); q.push( data );
@ -46,6 +46,10 @@ jQuery.extend({
jQuery.dequeue(elem, type); jQuery.dequeue(elem, type);
}); });
} }
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
}
} }
}); });

View file

@ -4,10 +4,7 @@
jQuery.support = {}; jQuery.support = {};
var root = document.documentElement, var div = document.createElement("div");
script = document.createElement("script"),
div = document.createElement("div"),
id = "script" + jQuery.now();
div.style.display = "none"; div.style.display = "none";
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
@ -68,7 +65,7 @@
deleteExpando: true, deleteExpando: true,
optDisabled: false, optDisabled: false,
checkClone: false, checkClone: false,
scriptEval: false, _scriptEval: null,
noCloneEvent: true, noCloneEvent: true,
boxModel: null, boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
@ -81,6 +78,12 @@
select.disabled = true; select.disabled = true;
jQuery.support.optDisabled = !opt.disabled; jQuery.support.optDisabled = !opt.disabled;
jQuery.support.scriptEval = function() {
if ( jQuery.support._scriptEval === null ) {
var root = document.documentElement,
script = document.createElement("script"),
id = "script" + jQuery.now();
script.type = "text/javascript"; script.type = "text/javascript";
try { try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
@ -92,21 +95,29 @@
// tag with appendChild/createTextNode // tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead) // (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) { if ( window[ id ] ) {
jQuery.support.scriptEval = true; jQuery.support._scriptEval = true;
delete window[ id ]; delete window[ id ];
} else {
jQuery.support._scriptEval = false;
} }
root.removeChild( script );
// release memory in IE
root = script = id = null;
}
return jQuery.support._scriptEval;
};
// Test to see if it's possible to delete an expando from an element // Test to see if it's possible to delete an expando from an element
// Fails in Internet Explorer // Fails in Internet Explorer
try { try {
delete script.test; delete div.test;
} catch(e) { } catch(e) {
jQuery.support.deleteExpando = false; jQuery.support.deleteExpando = false;
} }
root.removeChild( script );
if ( div.attachEvent && div.fireEvent ) { if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() { div.attachEvent("onclick", function click() {
// Cloning a node shouldn't copy over any // Cloning a node shouldn't copy over any
@ -151,7 +162,7 @@
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
} }
div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>"; div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
var tds = div.getElementsByTagName("td"); var tds = div.getElementsByTagName("td");
// Check if table cells still have offsetWidth/Height when they are set // Check if table cells still have offsetWidth/Height when they are set
@ -181,6 +192,14 @@
var el = document.createElement("div"); var el = document.createElement("div");
eventName = "on" + eventName; eventName = "on" + eventName;
// We only care about the case where non-standard event systems
// are used, namely in IE. Short-circuiting here helps us to
// avoid an eval call (in setAttribute) which can cause CSP
// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
if ( !el.attachEvent ) {
return true;
}
var isSupported = (eventName in el); var isSupported = (eventName in el);
if ( !isSupported ) { if ( !isSupported ) {
el.setAttribute(eventName, "return;"); el.setAttribute(eventName, "return;");
@ -195,6 +214,6 @@
jQuery.support.changeBubbles = eventSupported("change"); jQuery.support.changeBubbles = eventSupported("change");
// release memory in IE // release memory in IE
root = script = div = all = a = null; div = all = a = null;
})(); })();
})( jQuery ); })( jQuery );

View file

@ -1,89 +0,0 @@
(function( jQuery ) {
var jsc = jQuery.now(),
jsre = /\=\?(&|$)/,
rquery_jsonp = /\?/;
// Default jsonp callback name
jQuery.ajaxSettings.jsonpCallback = function() {
return "jsonp" + jsc++;
};
// Normalize jsonp queries
// 1) put callback parameter in url or data
// 2) ensure transportDataType is json
// 3) ensure options jsonp is always provided so that jsonp requests are always
// json request with the jsonp option set
jQuery.xhr.prefilter( function(s) {
var transportDataType = s.dataTypes[0];
if ( s.jsonp ||
transportDataType === "jsonp" ||
transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
var jsonp = s.jsonp = s.jsonp || "callback",
jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
data = s.url == url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
if ( url == s.url && data == s.data ) {
url = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
}
s.url = url;
s.data = data;
s.dataTypes[0] = "json";
}
});
// Bind transport to json dataType
jQuery.xhr.bindTransport("json", function(s) {
if ( s.jsonp ) {
// Put callback in place
var responseContainer,
jsonpCallback = s.jsonpCallback,
previous = window[ jsonpCallback ];
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
s.complete = [function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction ( previous ) ) {
window[ jsonpCallback ] ( responseContainer[0] );
}
} else {
// else, more memory leak avoidance
try{ delete window[ jsonpCallback ]; } catch(e){}
}
}, s.complete ];
// Use data converter to retrieve json after script execution
s.dataConverters["script => json"] = function() {
if ( ! responseContainer ) {
jQuery.error("Callback '" + jsonpCallback + "' was not called");
}
return responseContainer[ 0 ];
};
// Delegate to script transport
return "script";
}
});
})( jQuery );

View file

@ -1,191 +0,0 @@
(function( jQuery ) {
var // Next fake timer id
xhrPollingId = jQuery.now(),
// Callbacks hashtable
xhrs = {},
// #5280: see end of file
xhrUnloadAbortMarker = [];
jQuery.xhr.bindTransport( function( s , determineDataType ) {
// Cross domain only allowed if supported through XMLHttpRequest
if ( ! s.crossDomain || jQuery.support.cors ) {
var callback;
return {
send: function(headers, complete) {
var xhr = s.xhr(),
handle;
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
if ( s.username ) {
xhr.open(s.type, s.url, s.async, s.username, s.password);
} else {
xhr.open(s.type, s.url, s.async);
}
// Requested-With header
// Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided in beforeSend
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
headers["x-requested-with"] = "XMLHttpRequest";
}
// Need an extra try/catch for cross domain requests in Firefox 3
try {
jQuery.each(headers, function(key,value) {
xhr.setRequestHeader(key,value);
});
} catch(_) {}
// Do send the request
try {
xhr.send( ( s.hasContent && s.data ) || null );
} catch(e) {
complete(0, "error", "" + e);
return;
}
// Listener
callback = function ( abortStatusText ) {
// Was never called and is aborted or complete
if ( callback && ( abortStatusText || xhr.readyState === 4 ) ) {
// Do not listen anymore
if (handle) {
xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ];
handle = undefined;
}
callback = 0;
// Get info
var status, statusText, response, responseHeaders;
if ( abortStatusText ) {
if ( xhr.readyState !== 4 ) {
xhr.abort();
}
// Stop here if unloadAbort
if ( abortStatusText === xhrUnloadAbortMarker ) {
return;
}
status = 0;
statusText = abortStatusText;
} else {
status = xhr.status;
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
statusText = xhr.statusText;
} catch( e ) {
statusText = ""; // We normalize with Webkit giving an empty statusText
}
responseHeaders = xhr.getAllResponseHeaders();
// Filter status for non standard behaviours
// (so many they seem to be the actual "standard")
status =
// Opera returns 0 when it should be 304
// Webkit returns 0 for failing cross-domain no matter the real status
status === 0 ?
(
! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests
(
responseHeaders ? // Opera: filter out real aborts #6060
304
:
0
)
:
302 // We assume 302 but could be anything cross-domain related
)
:
(
status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450)
204
:
status
);
// Guess response if needed & update datatype accordingly
if ( status >= 200 && status < 300 ) {
response =
determineDataType(
s,
xhr.getResponseHeader("content-type"),
xhr.responseText,
xhr.responseXML );
}
}
// Call complete
complete(status,statusText,response,responseHeaders);
}
};
// if we're in sync mode
// or it's in cache and has been retrieved directly (IE6 & IE7)
// we need to manually fire the callback
if ( ! s.async || xhr.readyState === 4 ) {
callback();
} else {
// Listener is externalized to handle abort on unload
handle = xhrPollingId++;
xhrs[ handle ] = xhr;
xhr.onreadystatechange = function() {
callback();
};
}
},
abort: function(statusText) {
if ( callback ) {
callback(statusText);
}
}
};
}
});
// #5280: we need to abort on unload or IE will keep connections alive
jQuery(window).bind( "unload" , function() {
// Abort all pending requests
jQuery.each(xhrs, function(_, xhr) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( xhrUnloadAbortMarker );
}
});
// Resest polling structure to be safe
xhrs = {};
});
})( jQuery );

View file

@ -6,7 +6,14 @@ var runtil = /Until$/,
rmultiselector = /,/, rmultiselector = /,/,
isSimple = /^.[^:#\[\.,]*$/, isSimple = /^.[^:#\[\.,]*$/,
slice = Array.prototype.slice, slice = Array.prototype.slice,
POS = jQuery.expr.match.POS; POS = jQuery.expr.match.POS,
// methods guaranteed to produce a unique set when starting from a unique set
guaranteedUnique = {
children: true,
contents: true,
next: true,
prev: true
};
jQuery.fn.extend({ jQuery.fn.extend({
find: function( selector ) { find: function( selector ) {
@ -134,7 +141,7 @@ jQuery.fn.extend({
add: function( selector, context ) { add: function( selector, context ) {
var set = typeof selector === "string" ? var set = typeof selector === "string" ?
jQuery( selector, context || this.context ) : jQuery( selector, context ) :
jQuery.makeArray( selector ), jQuery.makeArray( selector ),
all = jQuery.merge( this.get(), set ); all = jQuery.merge( this.get(), set );
@ -196,7 +203,12 @@ jQuery.each({
} }
}, function( name, fn ) { }, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) { jQuery.fn[ name ] = function( until, selector ) {
var ret = jQuery.map( this, fn, until ); var ret = jQuery.map( this, fn, until ),
// The variable 'args' was introduced in
// https://github.com/jquery/jquery/commit/52a0238
// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
// http://code.google.com/p/v8/issues/detail?id=1050
args = slice.call(arguments);
if ( !runtil.test( name ) ) { if ( !runtil.test( name ) ) {
selector = until; selector = until;
@ -206,13 +218,13 @@ jQuery.each({
ret = jQuery.filter( selector, ret ); ret = jQuery.filter( selector, ret );
} }
ret = this.length > 1 ? jQuery.unique( ret ) : ret; ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
ret = ret.reverse(); ret = ret.reverse();
} }
return this.pushStack( ret, name, slice.call(arguments).join(",") ); return this.pushStack( ret, name, args.join(",") );
}; };
}); });

View file

@ -1,909 +0,0 @@
(function( jQuery ) {
var rquery_xhr = /\?/,
rhash = /#.*$/,
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
rnoContent = /^(?:GET|HEAD)$/,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#]+)/,
sliceFunc = Array.prototype.slice,
isFunction = jQuery.isFunction;
// Creates a jQuery xhr object
jQuery.xhr = function( _native ) {
if ( _native ) {
return jQuery.ajaxSettings.xhr();
}
function reset(force) {
// We only need to reset if we went through the init phase
// (with the exception of object creation)
if ( force || internal ) {
// Reset callbacks lists
callbacksLists = {
success: createCBList(),
error: createCBList(),
complete: createCBList()
};
// Reset private variables
requestHeaders = {};
responseHeadersString = responseHeaders = internal = done = timeoutTimer = s = undefined;
// Reset state
xhr.readyState = 0;
sendFlag = 0;
// Remove responseX fields
for ( var name in xhr ) {
if ( /^response/.test(name) ) {
delete xhr[name];
}
}
}
}
function init() {
var // Options extraction
// Remove hash character (#7531: first for string promotion)
url = s.url = ( "" + s.url ).replace( rhash , "" ),
// Uppercase the type
type = s.type = s.type.toUpperCase(),
// Determine if request has content
hasContent = s.hasContent = ! rnoContent.test( type ),
// Extract dataTypes list
dataType = s.dataType,
dataTypes = s.dataTypes = dataType ? jQuery.trim(dataType).toLowerCase().split(/\s+/) : ["*"],
// Determine if a cross-domain request is in order
parts = rurl.exec( url.toLowerCase() ),
loc = location,
crossDomain = s.crossDomain = !!( parts && ( parts[1] && parts[1] != loc.protocol || parts[2] != loc.host ) ),
// Get other options locally
data = s.data,
originalContentType = s.contentType,
prefilters = s.prefilters,
accepts = s.accepts,
headers = s.headers,
// Other Variables
transportDataType,
i;
// Convert data if not already a string
if ( data && s.processData && typeof data != "string" ) {
data = s.data = jQuery.param( data , s.traditional );
}
// Apply option prefilters
for (i in prefilters) {
prefilters[i](s);
}
// Get internal
internal = selectTransport( s );
// Re-actualize url & data
url = s.url;
data = s.data;
// If internal was found
if ( internal ) {
// Get transportDataType
transportDataType = dataTypes[0];
// More options handling for requests with no content
if ( ! hasContent ) {
// If data is available, append data to url
if ( data ) {
url += (rquery_xhr.test(url) ? "&" : "?") + data;
}
// Add anti-cache in url if needed
if ( s.cache === false ) {
var ts = jQuery.now(),
// try replacing _= if it is there
ret = url.replace(rts, "$1_=" + ts );
// if nothing was replaced, add timestamp to the end
url = ret + ((ret == url) ? (rquery_xhr.test(url) ? "&" : "?") + "_=" + ts : "");
}
s.url = url;
}
// Set the correct header, if data is being sent
if ( ( data && hasContent ) || originalContentType ) {
requestHeaders["content-type"] = s.contentType;
}
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( s.ifModified ) {
if ( jQuery_lastModified[url] ) {
requestHeaders["if-modified-since"] = jQuery_lastModified[url];
}
if ( jQuery_etag[url] ) {
requestHeaders["if-none-match"] = jQuery_etag[url];
}
}
// Set the Accepts header for the server, depending on the dataType
requestHeaders.accept = transportDataType && accepts[ transportDataType ] ?
accepts[ transportDataType ] + ( transportDataType !== "*" ? ", */*; q=0.01" : "" ) :
accepts[ "*" ];
// Check for headers option
for ( i in headers ) {
requestHeaders[ i.toLowerCase() ] = headers[ i ];
}
}
callbackContext = s.context || s;
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
for ( i in callbacksLists ) {
callbacksLists[i].bind(s[i]);
}
// Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" );
}
done = whenDone;
}
function whenDone(status, statusText, response, headers) {
// Called once
done = undefined;
// Reset sendFlag
sendFlag = 0;
// Cache response headers
responseHeadersString = headers || "";
// Clear timeout if it exists
if ( timeoutTimer ) {
clearTimeout(timeoutTimer);
}
var // Reference url
url = s.url,
// and ifModified status
ifModified = s.ifModified,
// Is it a success?
isSuccess = 0,
// Stored success
success,
// Stored error
error = statusText;
// If not timeout, force a jQuery-compliant status text
if ( statusText != "timeout" ) {
statusText = ( status >= 200 && status < 300 ) ?
"success" :
( status === 304 ? "notmodified" : "error" );
}
// If successful, handle type chaining
if ( statusText === "success" || statusText === "notmodified" ) {
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
if ( ifModified ) {
var lastModified = xhr.getResponseHeader("Last-Modified"),
etag = xhr.getResponseHeader("Etag");
if (lastModified) {
jQuery_lastModified[url] = lastModified;
}
if (etag) {
jQuery_etag[url] = etag;
}
}
if ( ifModified && statusText === "notmodified" ) {
success = null;
isSuccess = 1;
} else {
// Chain data conversions and determine the final value
// (if an exception is thrown in the process, it'll be notified as an error)
try {
function checkData(data) {
if ( data !== undefined ) {
var testFunction = s.dataCheckers[srcDataType];
if ( isFunction( testFunction ) ) {
testFunction(data);
}
}
}
function convertData (data) {
var conversionFunction = dataConverters[srcDataType+" => "+destDataType] ||
dataConverters["* => "+destDataType],
noFunction = ! isFunction( conversionFunction );
if ( noFunction ) {
if ( srcDataType != "text" && destDataType != "text" ) {
// We try to put text inbetween
var first = dataConverters[srcDataType+" => text"] ||
dataConverters["* => text"],
second = dataConverters["text => "+destDataType] ||
dataConverters["* => "+destDataType],
areFunctions = isFunction( first ) && isFunction( second );
if ( areFunctions ) {
conversionFunction = function (data) {
return second( first ( data ) );
};
}
noFunction = ! areFunctions;
}
if ( noFunction ) {
jQuery.error( "no data converter between " + srcDataType + " and " + destDataType );
}
}
return conversionFunction(data);
}
var dataTypes = s.dataTypes,
i,
length,
data = response,
dataConverters = s.dataConverters,
srcDataType,
destDataType,
responseTypes = s.xhrResponseFields;
for ( i = 0, length = dataTypes.length ; i < length ; i++ ) {
destDataType = dataTypes[i];
if ( !srcDataType ) { // First time
// Copy type
srcDataType = destDataType;
// Check
checkData(data);
// Apply dataFilter
if ( isFunction( s.dataFilter ) ) {
data = s.dataFilter(data, s.dataType);
// Recheck data
checkData(data);
}
} else { // Subsequent times
// handle auto
// JULIAN: for reasons unknown to me === doesn't work here
if (destDataType == "*") {
destDataType = srcDataType;
} else if ( srcDataType != destDataType ) {
// Convert
data = convertData(data);
// Copy type & check
srcDataType = destDataType;
checkData(data);
}
}
// Copy response into the xhr if it hasn't been already
var responseDataType,
responseType = responseTypes[srcDataType];
if ( responseType ) {
responseDataType = srcDataType;
} else {
responseType = responseTypes[ responseDataType = "text" ];
}
if ( responseType !== 1 ) {
xhr[ "response" + responseType ] = data;
responseTypes[ responseType ] = 1;
}
}
// We have a real success
success = data;
isSuccess = 1;
} catch(e) {
statusText = "parsererror";
error = "" + e;
}
}
} else { // if not success, mark it as an error
error = error || statusText;
}
// Set data for the fake xhr object
xhr.status = status;
xhr.statusText = statusText;
// Keep local copies of vars in case callbacks re-use the xhr
var _s = s,
_callbacksLists = callbacksLists,
_callbackContext = callbackContext,
_globalEventContext = globalEventContext;
// Set state if the xhr hasn't been re-used
function _setState( value ) {
if ( xhr.readyState && s === _s ) {
setState( value );
}
}
// Really completed?
if ( status && s.async ) {
setState( 2 );
_setState( 3 );
}
// We're done
_setState( 4 );
// Success
_callbacksLists.success.fire( isSuccess , _callbackContext , success, statusText, xhr);
if ( isSuccess && _s.global ) {
_globalEventContext.trigger( "ajaxSuccess", [xhr, _s, success] );
}
// Error
_callbacksLists.error.fire( ! isSuccess , _callbackContext , xhr, statusText, error);
if ( !isSuccess && _s.global ) {
_globalEventContext.trigger( "ajaxError", [xhr, _s, error] );
}
// Complete
_callbacksLists.complete.fire( 1 , _callbackContext, xhr, statusText);
if ( _s.global ) {
_globalEventContext.trigger( "ajaxComplete", [xhr, _s] );
// Handle the global AJAX counter
if ( ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
}
}
}
// Ready state control
function checkState( expected , test ) {
if ( expected !== true && ( expected === false || test === false || xhr.readyState !== expected ) ) {
jQuery.error("INVALID_STATE_ERR");
}
}
// Ready state change
function setState( value ) {
xhr.readyState = value;
if ( isFunction( xhr.onreadystatechange ) ) {
xhr.onreadystatechange();
}
}
var // jQuery lists
jQuery_lastModified = jQuery.lastModified,
jQuery_etag = jQuery.etag,
// Options object
s,
// Callback stuff
callbackContext,
globalEventContext,
callbacksLists,
// Headers (they are sent all at once)
requestHeaders,
// Response headers
responseHeadersString,
responseHeaders,
// Done callback
done,
// transport
internal,
// timeout handle
timeoutTimer,
// The send flag
sendFlag,
// Fake xhr
xhr = {
// state
readyState: 0,
// Callback
onreadystatechange: null,
// Open
open: function(type, url, async, username, password) {
xhr.abort();
reset();
s = {
type: type,
url: url,
async: async,
username: username,
password: password
};
setState(1);
return xhr;
},
// Send
send: function(data, moreOptions) {
checkState(1 , !sendFlag);
s.data = data;
s = jQuery.extend( true,
{},
jQuery.ajaxSettings,
s,
moreOptions || ( moreOptions === false ? { global: false } : {} ) );
if ( moreOptions ) {
// We force the original context
// (plain objects used as context get extended)
s.context = moreOptions.context;
}
init();
// If not internal, abort
if ( ! internal ) {
done( 0 , "transport not found" );
return false;
}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend ) {
var _s = s;
if ( s.beforeSend.call(callbackContext, xhr, s) === false || ! xhr.readyState || _s !== s ) {
// Abort if not done
if ( xhr.readyState && _s === s ) {
xhr.abort();
}
// Handle the global AJAX counter
if ( _s.global && ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
}
return false;
}
}
sendFlag = 1;
// Send global event
if ( s.global ) {
globalEventContext.trigger("ajaxSend", [xhr, s]);
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout(function(){
xhr.abort("timeout");
}, s.timeout);
}
if ( s.async ) {
setState(1);
}
try {
internal.send(requestHeaders, done);
return xhr;
} catch (e) {
if ( done ) {
done(0, "error", "" + e);
} else {
jQuery.error(e);
}
}
return false;
},
// Caches the header
setRequestHeader: function(name,value) {
checkState(1, !sendFlag);
requestHeaders[ name.toLowerCase() ] = value;
return xhr;
},
// Raw string
getAllResponseHeaders: function() {
return xhr.readyState <= 1 ? "" : responseHeadersString;
},
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
if ( xhr.readyState <= 1 ) {
return null;
}
if ( responseHeaders === undefined ) {
responseHeaders = {};
if ( typeof responseHeadersString === "string" ) {
var match;
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
}
}
}
return responseHeaders[ key.toLowerCase() ];
},
// Cancel the request
abort: function(statusText) {
if (internal) {
internal.abort( statusText || "abort" );
}
xhr.readyState = 0;
}
};
// Init data (so that we can bind callbacks early
reset(1);
// Install callbacks related methods
jQuery.each(callbacksLists, function(name) {
var list;
xhr[name] = function() {
list = callbacksLists[name];
if ( list ) {
list.bind.apply(list, arguments );
}
return this;
};
});
// Return the xhr emulation
return xhr;
};
// Create a callback list
function createCBList() {
var functors = [],
autoFire = 0,
fireArgs,
list = {
fire: function( flag , context ) {
// Save info for later bindings
fireArgs = arguments;
// Remove autoFire to keep bindings in order
autoFire = 0;
var args = sliceFunc.call( fireArgs , 2 );
// Execute callbacks
while ( flag && functors.length ) {
flag = functors.shift().apply( context , args ) !== false;
}
// Clean if asked to stop
if ( ! flag ) {
clean();
}
// Set autoFire
autoFire = 1;
},
bind: function() {
var args = arguments,
i = 0,
length = args.length,
func;
for ( ; i < length ; i++ ) {
func = args[ i ];
if ( jQuery.isArray(func) ) {
list.bind.apply( list , func );
} else if ( isFunction(func) ) {
// Add if not already in
if ( ! pos( func ) ) {
functors.push( func );
}
}
}
if ( autoFire ) {
list.fire.apply( list , fireArgs );
}
},
unbind: function() {
var i = 0,
args = arguments,
length = args.length,
func,
position;
if ( length ) {
for( ; i < length ; i++ ) {
func = args[i];
if ( jQuery.isArray(func) ) {
list.unbind.apply(list,func);
} else if ( isFunction(func) ) {
position = pos(func);
if ( position ) {
functors.splice(position-1,1);
}
}
}
} else {
functors = [];
}
}
};
// Get the index of the functor in the list (1-based)
function pos( func ) {
for (var i = 0, length = functors.length; i < length && functors[i] !== func; i++) {
}
return i < length ? ( i + 1 ) : 0;
}
// Clean the object
function clean() {
// Empty callbacks list
functors = [];
// Inhibit methods
for (var i in list) {
list[i] = jQuery.noop;
}
}
return list;
}
jQuery.extend(jQuery.xhr, {
// Add new prefilter
prefilter: function (functor) {
if ( isFunction(functor) ) {
jQuery.ajaxSettings.prefilters.push( functor );
}
return this;
},
// Bind a transport to one or more dataTypes
bindTransport: function () {
var args = arguments,
i,
start = 0,
length = args.length,
dataTypes = [ "*" ],
functors = [],
functor,
first,
append,
list,
transports = jQuery.ajaxSettings.transports;
if ( length ) {
if ( ! isFunction( args[ 0 ] ) ) {
dataTypes = args[ 0 ].toLowerCase().split(/\s+/);
start = 1;
}
if ( dataTypes.length && start < length ) {
for ( i = start; i < length; i++ ) {
functor = args[i];
if ( isFunction(functor) ) {
functors.push( functor );
}
}
if ( functors.length ) {
jQuery.each ( dataTypes, function( _ , dataType ) {
first = /^\+/.test( dataType );
if (first) {
dataType = dataType.substr(1);
}
if ( dataType !== "" ) {
append = Array.prototype[ first ? "unshift" : "push" ];
list = transports[ dataType ];
jQuery.each ( functors, function( _ , functor ) {
if ( ! list ) {
list = transports[ dataType ] = [ functor ];
} else {
append.call( list , functor );
}
} );
}
} );
}
}
}
return this;
}
});
// Select a transport given options
function selectTransport( s ) {
var dataTypes = s.dataTypes,
transportDataType,
transportsList,
transport,
i,
length,
checked = {},
flag;
function initSearch( dataType ) {
flag = transportDataType !== dataType && ! checked[ dataType ];
if ( flag ) {
checked[ dataType ] = 1;
transportDataType = dataType;
transportsList = s.transports[ dataType ];
i = -1;
length = transportsList ? transportsList.length : 0 ;
}
return flag;
}
initSearch( dataTypes[ 0 ] );
for ( i = 0 ; ! transport && i <= length ; i++ ) {
if ( i === length ) {
initSearch( "*" );
} else {
transport = transportsList[ i ]( s , determineDataType );
// If we got redirected to another dataType
// Search there (if not in progress or already tried)
if ( typeof( transport ) === "string" &&
initSearch( transport ) ) {
dataTypes.unshift( transport );
transport = 0;
}
}
}
return transport;
}
// Utility function that handles dataType when response is received
// (for those transports that can give text or xml responses)
function determineDataType( s , ct , text , xml ) {
var autoDataType = s.autoDataType,
type,
regexp,
dataTypes = s.dataTypes,
transportDataType = dataTypes[0],
response;
// Auto (xml, json, script or text determined given headers)
if ( transportDataType === "*" ) {
for ( type in autoDataType ) {
if ( ( regexp = autoDataType[ type ] ) && regexp.test( ct ) ) {
transportDataType = dataTypes[0] = type;
break;
}
}
}
// xml and parsed as such
if ( transportDataType === "xml" &&
xml &&
xml.documentElement /* #4958 */ ) {
response = xml;
// Text response was provided
} else {
response = text;
// If it's not really text, defer to dataConverters
if ( transportDataType !== "text" ) {
dataTypes.unshift( "text" );
}
}
return response;
}
})( jQuery );

30
test/csp.php Normal file
View file

@ -0,0 +1,30 @@
<?php header("X-Content-Security-Policy-Report-Only: allow *"); ?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CSP Test Page</title>
<script src="../src/core.js"></script>
<script src="../src/support.js"></script>
<script src="../src/data.js"></script>
<script src="../src/queue.js"></script>
<script src="../src/attributes.js"></script>
<script src="../src/event.js"></script>
<script src="../src/sizzle/sizzle.js"></script>
<script src="../src/sizzle-jquery.js"></script>
<script src="../src/traversing.js"></script>
<script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script>
<script src="../src/ajax.js"></script>
<script src="../src/ajax/jsonp.js"></script>
<script src="../src/ajax/script.js"></script>
<script src="../src/ajax/xhr.js"></script>
<script src="../src/effects.js"></script>
<script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script>
</head>
<body>
<p>CSP Test Page</p>
</body>
</html>

View file

@ -0,0 +1,5 @@
<?php
header("HTTP/1.0 400 Bad Request");
echo "plain text message";

View file

@ -6,15 +6,11 @@ $headers = array();
foreach( $_SERVER as $key => $value ) { foreach( $_SERVER as $key => $value ) {
if ( substr( $key , 0 , 5 ) == "HTTP_" ) { $key = str_replace( "_" , "-" , substr( $key , 0 , 5 ) == "HTTP_" ? substr( $key , 5 ) : $key );
$key = str_replace( "_" , "-" , substr( $key , 5) );
$headers[ $key ] = $value; $headers[ $key ] = $value;
} }
}
foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) { foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) {
echo "$key: " . $headers[ strtoupper( $key ) ] . "\n"; echo "$key: " . @$headers[ strtoupper( $key ) ] . "\n";
} }

View file

@ -1,6 +1,10 @@
<?php <?php
error_reporting(0); error_reporting(0);
$callback = $_REQUEST['callback']; $callback = $_REQUEST['callback'];
if ( ! $callback ) {
$callback = explode("?",end(explode("/",$_SERVER['REQUEST_URI'])));
$callback = $callback[0];
}
$json = $_REQUEST['json']; $json = $_REQUEST['json'];
if($json) { if($json) {
echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])'; echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])';

View file

@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) { function url(value) {
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000); return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
} }
(function () {
// Store the old counts so that we only assert on tests that have actually leaked,
// instead of asserting every time a test has leaked sometime in the past
var oldCacheLength = 0,
oldFragmentsLength = 0,
oldTimersLength = 0,
oldActive = 0;
/**
* Ensures that tests have cleaned up properly after themselves. Should be passed as the
* teardown function on all modules' lifecycle object.
*/
this.moduleTeardown = function () {
var i, fragmentsLength = 0, cacheLength = 0;
// Allow QUnit.reset to clean up any attached elements before checking for leaks
QUnit.reset();
for ( i in jQuery.cache ) {
++cacheLength;
}
jQuery.fragments = {};
for ( i in jQuery.fragments ) {
++fragmentsLength;
}
// Because QUnit doesn't have a mechanism for retrieving the number of expected assertions for a test,
// if we unconditionally assert any of these, the test will fail with too many assertions :|
if ( cacheLength !== oldCacheLength ) {
equals( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
oldCacheLength = cacheLength;
}
if ( fragmentsLength !== oldFragmentsLength ) {
equals( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
oldFragmentsLength = fragmentsLength;
}
if ( jQuery.timers.length !== oldTimersLength ) {
equals( jQuery.timers.length, oldTimersLength, "No timers are still running" );
oldTimersLength = jQuery.timers.length;
}
if ( jQuery.active !== oldActive ) {
equals( jQuery.active, 0, "No AJAX requests are still active" );
oldActive = jQuery.active;
}
}
}());

View file

@ -20,10 +20,9 @@
<script src="../src/manipulation.js"></script> <script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script> <script src="../src/css.js"></script>
<script src="../src/ajax.js"></script> <script src="../src/ajax.js"></script>
<script src="../src/xhr.js"></script> <script src="../src/ajax/jsonp.js"></script>
<script src="../src/transports/jsonp.js"></script> <script src="../src/ajax/script.js"></script>
<script src="../src/transports/script.js"></script> <script src="../src/ajax/xhr.js"></script>
<script src="../src/transports/xhr.js"></script>
<script src="../src/effects.js"></script> <script src="../src/effects.js"></script>
<script src="../src/offset.js"></script> <script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script> <script src="../src/dimensions.js"></script>

View file

@ -1,4 +1,4 @@
module("ajax"); module("ajax", { teardown: moduleTeardown });
// Safari 3 randomly crashes when running these tests, // Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax // but only in the full suite - you can run just the Ajax
@ -70,44 +70,6 @@ test("jQuery.ajax() - success callbacks - (url, options) syntax", function() {
}, 13); }, 13);
}); });
test("jQuery.ajax() - success/error callbacks (remote)", function() {
var supports = jQuery.support.cors;
expect( supports ? 9 : 6 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
setTimeout(function(){
jQuery('#foo').ajaxStart(function(){
ok( true, "ajaxStart" );
}).ajaxStop(function(){
ok( true, "ajaxStop" );
start();
}).ajaxSend(function(){
ok( supports , "ajaxSend" );
}).ajaxComplete(function(){
ok( true, "ajaxComplete" );
}).ajaxError(function(){
ok( ! supports, "ajaxError" );
}).ajaxSuccess(function(){
ok( supports, "ajaxSuccess" );
});
jQuery.ajax({
// JULIAN TODO: Get an url especially for jQuery
url: "http://rockstarapps.com/test.php",
dataType: "text",
beforeSend: function(){ ok(supports, "beforeSend"); },
success: function( val ){ ok(supports, "success"); ok(supports && val.length, "data received"); },
error: function(_ , a , b ){ ok(!supports, "error"); },
complete: function(){ ok(true, "complete"); }
});
}, 13);
});
test("jQuery.ajax() - success callbacks (late binding)", function() { test("jQuery.ajax() - success callbacks (late binding)", function() {
expect( 8 ); expect( 8 );
@ -173,7 +135,7 @@ test("jQuery.ajax() - success callbacks (oncomplete binding)", function() {
.error(function(){ ok(false, "error"); }) .error(function(){ ok(false, "error"); })
.complete(function(){ start(); }); .complete(function(){ start(); });
} }
}) });
}, 13); }, 13);
}); });
@ -211,7 +173,7 @@ test("jQuery.ajax() - success callbacks (very late binding)", function() {
.complete(function(){ start(); }); .complete(function(){ start(); });
},100); },100);
} }
}) });
}, 13); }, 13);
}); });
@ -278,6 +240,46 @@ test("jQuery.ajax() - error callbacks", function() {
}); });
}); });
test("jQuery.ajax() - responseText on error", function() {
expect( 1 );
stop();
jQuery.ajax({
url: url("data/errorWithText.php"),
error: function(xhr) {
strictEqual( xhr.responseText , "plain text message" , "Test jXHR.responseText is filled for HTTP errors" );
},
complete: function() {
start();
}
});
});
test(".ajax() - retry with jQuery.ajax( this )", function() {
expect( 1 );
stop();
var firstTime = 1;
jQuery.ajax({
url: url("data/errorWithText.php"),
error: function() {
if ( firstTime ) {
firstTime = 0;
jQuery.ajax( this );
} else {
ok( true , "Test retrying with jQuery.ajax(this) works" );
start();
}
}
});
});
test(".ajax() - headers" , function() { test(".ajax() - headers" , function() {
expect( 2 ); expect( 2 );
@ -314,6 +316,64 @@ test(".ajax() - headers" , function() {
}); });
test(".ajax() - Accept header" , function() {
expect( 1 );
stop();
jQuery.ajax(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" );
start();
},
error: function(){ ok(false, "error"); }
});
});
test(".ajax() - contentType" , function() {
expect( 2 );
stop();
var count = 2;
function restart() {
if ( ! --count ) {
start();
}
}
jQuery.ajax(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" );
},
complete: function() {
restart();
}
});
jQuery.ajax(url("data/headers.php?keys=content-type" ), {
contentType: false,
success: function( data ) {
strictEqual( data , "content-type: \n" , "Test content-type is not sent when options.contentType===false" );
},
complete: function() {
restart();
}
});
});
test(".ajax() - hash", function() { test(".ajax() - hash", function() {
expect(3); expect(3);
@ -343,6 +403,53 @@ test(".ajax() - hash", function() {
}); });
}); });
test("jQuery ajax - cross-domain detection", function() {
expect( 4 );
var loc = document.location,
otherPort = loc.port === 666 ? 667 : 666,
otherProtocol = loc.protocol === "http:" ? "https:" : "http:";
jQuery.ajax({
dataType: "jsonp",
url: otherProtocol + "//" + loc.host,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different protocols are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + '//somewebsitethatdoesnotexist-656329477541.com:' + ( loc.port || 80 ),
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different hostnames are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + "//" + loc.hostname + ":" + otherPort,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different ports are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + "//" + loc.host,
crossDomain: true,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test forced crossDomain is detected as cross-domain" );
return false;
}
});
});
test(".ajax() - 304", function() { test(".ajax() - 304", function() {
expect( 1 ); expect( 1 );
stop(); stop();
@ -409,136 +516,6 @@ test("jQuery.ajax() - abort", function() {
equals( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); equals( xhr.readyState, 0, "XHR readyState indicates successful abortion" );
}); });
test("jQuery.ajax() - readyState (success)", function() {
expect( 1 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var control = "";
setTimeout(function(){
jQuery.ajax({
url: url("data/name.html"),
beforeSend: function( xhr ) {
xhr.onreadystatechange = function() {
control += xhr.readyState;
}
},
complete: function(){
setTimeout( function() {
equals( control , "1234" , "onreadystatechange was properly called" );
}, 13 );
start();
}
});
}, 13);
});
test("jQuery.ajax() - readyState (abort)", function() {
expect( 2 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var control = "";
setTimeout(function(){
jQuery.ajaxSetup({ timeout: 500 });
jQuery.ajax({
url: url("data/name.php?wait=5"),
beforeSend: function( xhr ) {
xhr.onreadystatechange = function() {
control += xhr.readyState;
}
},
complete: function( xhr ){
setTimeout( function() {
equals( control , "14" , "onreadystatechange was properly called" );
equals( xhr.readyState, 0 , "readyState is 0" );
}, 13 );
start();
}
});
}, 13);
});
test("jQuery.xhr() - reuse", function() {
expect( 15 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var number = 0;
setTimeout(function(){
jQuery('#foo').ajaxStart(function(){
ok( true, "ajaxStart" );
}).ajaxStop(function(){
ok( true, "ajaxStop" );
start();
}).ajaxSend(function(){
number++;
ok( true, "ajaxSend (" + number +")" );
}).ajaxComplete(function(){
ok( true, "ajaxComplete (" + number +")" );
}).ajaxError(function(){
ok( false, "ajaxError (" + number +")" );
}).ajaxSuccess(function(){
ok( true, "ajaxSuccess (" + number +")" );
});
jQuery.ajax({
url: url("data/name.html"),
beforeSend: function(){ ok(true, "beforeSend (1)"); },
success: function( _1 , _2 , xhr ){
ok(true, "success (1)");
xhr.complete(function() {
ok(true, "complete (1bis)");
});
xhr.open( "GET", url("data/name.html") );
xhr.success( function(){ ok(true, "beforeSend (2)"); } )
xhr.send( null, {
success: function(){ ok(true, "success (2)"); },
error: function(){ ok(false, "error (2)"); },
complete: function(){ ok(true, "complete (2)"); }
} );
},
error: function(){ ok(false, "error (1)"); },
complete: function(){ ok(true, "complete (1)"); }
});
}, 13);
});
test("jQuery.xhr() - early binding", function() {
expect( 2 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
jQuery.xhr()
.success( function(){ ok(true, "success"); } )
.error( function(){ ok(false, "error"); } )
.complete( function(){ ok(true, "complete"); start(); } )
.open( "GET", url("data/name.html") )
.send();
});
test("jQuery.xhr() - get native implementation", function() {
var xhr = jQuery.xhr(true);
ok( xhr.readyState !== undefined , "implements XMLHttpRequest" );
ok( ! jQuery.isFunction( xhr.success ) , "is not jQuery's abstraction" );
});
test("Ajax events with context", function() { test("Ajax events with context", function() {
expect(14); expect(14);
@ -606,7 +583,7 @@ test("jQuery.ajax context modification", function() {
stop(); stop();
var obj = {} var obj = {};
jQuery.ajax({ jQuery.ajax({
url: url("data/name.html"), url: url("data/name.html"),
@ -622,6 +599,47 @@ test("jQuery.ajax context modification", function() {
equals( obj.test, "foo", "Make sure the original object is maintained." ); equals( obj.test, "foo", "Make sure the original object is maintained." );
}); });
test("jQuery.ajax context modification through ajaxSetup", function() {
expect(4);
stop();
var obj = {};
jQuery.ajaxSetup({
context: obj
});
strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." );
jQuery.ajax({
url: url("data/name.html"),
complete: function() {
strictEqual( this, obj, "Make sure the original object is maintained." );
jQuery.ajax({
url: url("data/name.html"),
context: {},
complete: function() {
ok( this !== obj, "Make sure overidding context is possible." );
jQuery.ajaxSetup({
context: false
});
jQuery.ajax({
url: url("data/name.html"),
beforeSend: function(){
this.test = "foo2";
},
complete: function() {
ok( this !== obj, "Make sure unsetting context is possible." );
start();
}
});
}
});
}
});
});
test("jQuery.ajax() - disabled globals", function() { test("jQuery.ajax() - disabled globals", function() {
expect( 3 ); expect( 3 );
stop(); stop();
@ -653,34 +671,6 @@ test("jQuery.ajax() - disabled globals", function() {
}); });
}); });
test("jQuery.xhr() - disabled globals through xhr.send(data , false)", function() {
expect( 2 );
stop();
jQuery('#foo').ajaxStart(function(){
ok( false, "ajaxStart" );
}).ajaxStop(function(){
ok( false, "ajaxStop" );
}).ajaxSend(function(){
ok( false, "ajaxSend" );
}).ajaxComplete(function(){
ok( false, "ajaxComplete" );
}).ajaxError(function(){
ok( false, "ajaxError" );
}).ajaxSuccess(function(){
ok( false, "ajaxSuccess" );
});
jQuery.xhr()
.success(function(){ ok(true, "success"); })
.error(function(){ ok(false, "error"); })
.complete(function(){
ok(true, "complete");
setTimeout(function(){ start(); }, 13);
})
.open("GET", url("data/name.html")).send(undefined, false);
});
test("jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() { test("jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() {
expect(3); expect(3);
stop(); stop();
@ -707,6 +697,10 @@ test("jQuery.ajax - xml: non-namespace elements inside namespaced elements (over
equals( jQuery("jsconf", resp).length, 1, 'jsconf in responseXML' ); equals( jQuery("jsconf", resp).length, 1, 'jsconf in responseXML' );
equals( jQuery("thing", resp).length, 2, 'things in responseXML' ); equals( jQuery("thing", resp).length, 2, 'things in responseXML' );
start(); start();
},
error: function(_1,_2,error) {
ok( false, error );
start();
} }
}); });
}); });
@ -842,20 +836,20 @@ test("serialize()", function() {
'Check input serialization as query string'); 'Check input serialization as query string');
equals( jQuery('#testForm').serialize(), equals( jQuery('#testForm').serialize(),
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=', 'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
'Check form serialization as query string'); 'Check form serialization as query string');
equals( jQuery('#testForm :input').serialize(), equals( jQuery('#testForm :input').serialize(),
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=', 'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
'Check input serialization as query string'); 'Check input serialization as query string');
equals( jQuery('#form, #testForm').serialize(), equals( jQuery('#form, #testForm').serialize(),
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=", "action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
'Multiple form serialization as query string'); 'Multiple form serialization as query string');
/* Temporarily disabled. Opera 10 has problems with form serialization. /* Temporarily disabled. Opera 10 has problems with form serialization.
equals( jQuery('#form, #testForm :input').serialize(), equals( jQuery('#form, #testForm :input').serialize(),
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=", "action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
'Mixed form/input serialization as query string'); 'Mixed form/input serialization as query string');
*/ */
jQuery("#html5email, #html5number").remove(); jQuery("#html5email, #html5number").remove();
@ -1094,6 +1088,18 @@ test("load(String, Function) - check file with only a script tag", function() {
}); });
}); });
test("load(String, Function) - dataFilter in ajaxSettings", function() {
expect(2);
stop();
jQuery.ajaxSetup({ dataFilter: function() { return "Hello World"; } });
var div = jQuery("<div/>").load(url("data/name.html"), function(responseText) {
strictEqual( div.html(), "Hello World" , "Test div was filled with filtered data" );
strictEqual( responseText, "Hello World" , "Test callback receives filtered data" );
jQuery.ajaxSetup({ dataFilter: 0 });
start();
});
});
test("load(String, Object, Function)", function() { test("load(String, Object, Function)", function() {
expect(2); expect(2);
stop(); stop();
@ -1149,17 +1155,20 @@ test("jQuery.getScript(String, Function) - no callback", function() {
}); });
}); });
test("jQuery.ajax() - JSONP, Local", function() { jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
expect(9);
test("jQuery.ajax() - JSONP, " + label, function() {
expect(17);
var count = 0; var count = 0;
function plus(){ if ( ++count == 9 ) start(); } function plus(){ if ( ++count == 17 ) start(); }
stop(); stop();
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" ); ok( data.data, "JSON results returned (GET, no callback)" );
plus(); plus();
@ -1173,6 +1182,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php?callback=?", url: "data/jsonp.php?callback=?",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, url callback)" ); ok( data.data, "JSON results returned (GET, url callback)" );
plus(); plus();
@ -1186,6 +1196,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
data: "callback=?", data: "callback=?",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, data callback)" ); ok( data.data, "JSON results returned (GET, data callback)" );
@ -1197,9 +1208,84 @@ test("jQuery.ajax() - JSONP, Local", function() {
} }
}); });
jQuery.ajax({
url: "data/jsonp.php?callback=??",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (GET, url context-free callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, url context-free callback)" );
plus();
}
});
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
data: "callback=??",
success: function(data){
ok( data.data, "JSON results returned (GET, data context-free callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data context-free callback)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php/??",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (GET, REST-like)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, REST-like)" );
plus();
}
});
jQuery.ajax({
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)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, REST-like with param)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
data: {
callback: "?"
},
success: function(data){
ok( data.data, "JSON results returned (GET, processed data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, processed data callback)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
jsonp: "callback", jsonp: "callback",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, data obj callback)" ); ok( data.data, "JSON results returned (GET, data obj callback)" );
@ -1211,9 +1297,16 @@ test("jQuery.ajax() - JSONP, Local", function() {
} }
}); });
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
plus();
};
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
jsonpCallback: "jsonpResults", jsonpCallback: "jsonpResults",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name)" ); ok( data.data, "JSON results returned (GET, custom callback name)" );
@ -1229,6 +1322,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
type: "POST", type: "POST",
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, no callback)" ); ok( data.data, "JSON results returned (POST, no callback)" );
plus(); plus();
@ -1244,6 +1338,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
url: "data/jsonp.php", url: "data/jsonp.php",
data: "callback=?", data: "callback=?",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, data callback)" ); ok( data.data, "JSON results returned (POST, data callback)" );
plus(); plus();
@ -1259,6 +1354,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
url: "data/jsonp.php", url: "data/jsonp.php",
jsonp: "callback", jsonp: "callback",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, data obj callback)" ); ok( data.data, "JSON results returned (POST, data obj callback)" );
plus(); plus();
@ -1273,93 +1369,35 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
beforeSend: function(){ beforeSend: function(){
strictEqual( this.cache, false, "cache must be false on JSON request" ); strictEqual( this.cache, false, "cache must be false on JSON request" );
plus(); plus();
return false; return false;
} }
}); });
});
test("jQuery.ajax() - JSONP - Custom JSONP Callback", function() {
expect(1);
stop();
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
start();
};
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php?callback=XXX",
dataType: "jsonp",
jsonpCallback: "jsonpResults"
});
});
test("jQuery.ajax() - JSONP, Remote", function() {
expect(4);
var count = 0;
function plus(){ if ( ++count == 4 ) start(); }
var base = window.location.href.replace(/[^\/]*$/, "");
stop();
jQuery.ajax({
url: base + "data/jsonp.php",
dataType: "jsonp", 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)" );
plus();
},
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" ); ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
plus(); plus();
}, },
error: function(data){ error: function(data){
ok( false, "Ajax error JSON (GET, no callback)" ); ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
plus(); plus();
} }
}); });
jQuery.ajax({
url: base + "data/jsonp.php?callback=?",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (GET, url callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, url callback)" );
plus();
}
});
jQuery.ajax({
url: base + "data/jsonp.php",
dataType: "jsonp",
data: "callback=?",
success: function(data){
ok( data.data, "JSON results returned (GET, data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data callback)" );
plus();
}
});
jQuery.ajax({
url: base + "data/jsonp.php",
dataType: "jsonp",
jsonp: "callback",
success: function(data){
ok( data.data, "JSON results returned (GET, data obj callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data obj callback)" );
plus();
}
}); });
}); });
@ -1482,12 +1520,12 @@ test("jQuery.ajax() - json by content-type disabled with options", function() {
jQuery.ajax({ jQuery.ajax({
url: url("data/json.php"), url: url("data/json.php"),
data: { header: "json", json: "array" }, data: { header: "json", json: "array" },
autoDataType: { contents: {
json: false json: false
}, },
success: function( text ) { success: function( text ) {
equals( typeof text , "string" , "json wasn't auto-determined" ); equals( typeof text , "string" , "json wasn't auto-determined" );
var json = this.dataConverters["text => json"]( text ); var json = jQuery.parseJSON( text );
ok( json.length >= 2, "Check length"); ok( json.length >= 2, "Check length");
equals( json[0].name, 'John', 'Check JSON: first, name' ); equals( json[0].name, 'John', 'Check JSON: first, name' );
equals( json[0].age, 21, 'Check JSON: first, age' ); equals( json[0].age, 21, 'Check JSON: first, age' );
@ -1714,7 +1752,7 @@ test("data option: evaluate function values (#2806)", function() {
equals( result, "key=value" ); equals( result, "key=value" );
start(); start();
} }
}) });
}); });
test("data option: empty bodies for non-GET requests", function() { test("data option: empty bodies for non-GET requests", function() {
@ -1727,7 +1765,7 @@ test("data option: empty bodies for non-GET requests", function() {
equals( result, "" ); equals( result, "" );
start(); start();
} }
}) });
}); });
test("jQuery.ajax - If-Modified-Since support", function() { test("jQuery.ajax - If-Modified-Since support", function() {
@ -1752,7 +1790,7 @@ test("jQuery.ajax - If-Modified-Since support", function() {
ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')."); ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
} else { } else {
equals(status, "notmodified"); equals(status, "notmodified");
ok(data == null, "response body should be empty") ok(data == null, "response body should be empty");
} }
start(); start();
}, },
@ -1799,7 +1837,7 @@ test("jQuery.ajax - Etag support", function() {
ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match')."); ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
} else { } else {
equals(status, "notmodified"); equals(status, "notmodified");
ok(data == null, "response body should be empty") ok(data == null, "response body should be empty");
} }
start(); start();
}, },
@ -1832,7 +1870,7 @@ test("jQuery ajax - failing cross-domain", function() {
var i = 2; var i = 2;
jQuery.ajax({ jQuery.ajax({
url: 'http://somewebsitethatdoesnotexist.com', url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
success: function(){ ok( false , "success" ); }, success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); }, error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); } complete: function() { if ( ! --i ) start(); }
@ -1860,10 +1898,6 @@ test("jQuery ajax - atom+xml", function() {
}); });
test("jQuery.ajax - active counter", function() {
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
});
test( "jQuery.ajax - Location object as url (#7531)", 1, function () { test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
var success = false; var success = false;
try { try {
@ -1875,6 +1909,150 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
ok( success, "document.location did not generate exception" ); ok( success, "document.location did not generate exception" );
}); });
test( "jQuery.ajax - statusCode" , function() {
var count = 12;
expect( 20 );
stop();
function countComplete() {
if ( ! --count ) {
start();
}
}
function createStatusCodes( name , isSuccess ) {
name = "Test " + name + " " + ( isSuccess ? "success" : "error" );
return {
200: function() {
ok( isSuccess , name );
},
404: function() {
ok( ! isSuccess , name );
}
};
}
jQuery.each( {
"data/name.html": true,
"data/someFileThatDoesNotExist.html": false
} , function( uri , isSuccess ) {
jQuery.ajax( url( uri ) , {
statusCode: createStatusCodes( "in options" , isSuccess ),
complete: countComplete
});
jQuery.ajax( url( uri ) , {
complete: countComplete
}).statusCode( createStatusCodes( "immediately with method" , isSuccess ) );
jQuery.ajax( url( uri ) , {
complete: function(jXHR) {
jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) );
countComplete();
}
});
jQuery.ajax( url( uri ) , {
complete: function(jXHR) {
setTimeout( function() {
jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) );
countComplete();
} , 100 );
}
});
jQuery.ajax( url( uri ) , {
statusCode: createStatusCodes( "all (options)" , isSuccess ),
complete: function(jXHR) {
jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) );
setTimeout( function() {
jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) );
countComplete();
} , 100 );
}
}).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) );
var testString = "";
jQuery.ajax( url( uri ), {
success: function( a , b , jXHR ) {
ok( isSuccess , "success" );
var statusCode = {};
statusCode[ jXHR.status ] = function() {
testString += "B";
};
jXHR.statusCode( statusCode );
testString += "A";
},
error: function( jXHR ) {
ok( ! isSuccess , "error" );
var statusCode = {};
statusCode[ jXHR.status ] = function() {
testString += "B";
};
jXHR.statusCode( statusCode );
testString += "A";
},
complete: function() {
strictEqual( testString , "AB" , "Test statusCode callbacks are ordered like " +
( isSuccess ? "success" : "error" ) + " callbacks" );
countComplete();
}
} );
});
});
test("jQuery.ajax - transitive conversions", function() {
expect( 8 );
stop();
jQuery.when(
jQuery.ajax( url("data/json.php") , {
converters: {
"json myjson": function( data ) {
ok( true , "converter called" );
return data;
}
},
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" );
}
}),
jQuery.ajax( url("data/json.php") , {
converters: {
"json myjson": function( data ) {
ok( true , "converter called (*)" );
return data;
}
},
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 (*)" );
}
})
).then( start , start );
});
test("jQuery.ajax - active counter", function() {
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
});
} }
//} //}

View file

@ -1,4 +1,4 @@
module("attributes"); module("attributes", { teardown: moduleTeardown });
var bareObj = function(value) { return value; }; var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); }; var functionReturningObj = function(value) { return (function() { return value; }); };
@ -703,12 +703,12 @@ var testToggleClass = function(valueObj) {
// toggleClass storage // toggleClass storage
e.toggleClass(true); e.toggleClass(true);
ok( e.get(0).className === "", "Assert class is empty (data was empty)" ); ok( e[0].className === "", "Assert class is empty (data was empty)" );
e.addClass("testD testE"); e.addClass("testD testE");
ok( e.is(".testD.testE"), "Assert class present" ); ok( e.is(".testD.testE"), "Assert class present" );
e.toggleClass(); e.toggleClass();
ok( !e.is(".testD.testE"), "Assert class not present" ); ok( !e.is(".testD.testE"), "Assert class not present" );
ok( e.data('__className__') === 'testD testE', "Assert data was stored" ); ok( jQuery._data(e[0], '__className__') === 'testD testE', "Assert data was stored" );
e.toggleClass(); e.toggleClass();
ok( e.is(".testD.testE"), "Assert class present (restored from data)" ); ok( e.is(".testD.testE"), "Assert class present (restored from data)" );
e.toggleClass(false); e.toggleClass(false);
@ -720,11 +720,9 @@ var testToggleClass = function(valueObj) {
e.toggleClass(); e.toggleClass();
ok( e.is(".testD.testE"), "Assert class present (restored from data)" ); ok( e.is(".testD.testE"), "Assert class present (restored from data)" );
// Cleanup // Cleanup
e.removeClass("testD"); e.removeClass("testD");
e.removeData('__className__'); jQuery.removeData(e[0], '__className__', true);
}; };
test("toggleClass(String|boolean|undefined[, boolean])", function() { test("toggleClass(String|boolean|undefined[, boolean])", function() {
@ -785,7 +783,7 @@ test("toggleClass(Fucntion[, boolean]) with incoming value", function() {
// Cleanup // Cleanup
e.removeClass("test"); e.removeClass("test");
e.removeData('__className__'); jQuery.removeData(e[0], '__className__', true);
}); });
test("addClass, removeClass, hasClass", function() { test("addClass, removeClass, hasClass", function() {

View file

@ -1,4 +1,4 @@
module("core"); module("core", { teardown: moduleTeardown });
test("Basic requirements", function() { test("Basic requirements", function() {
expect(7); expect(7);
@ -12,7 +12,7 @@ test("Basic requirements", function() {
}); });
test("jQuery()", function() { test("jQuery()", function() {
expect(23); expect(24);
// Basic constructor's behavior // Basic constructor's behavior
@ -21,7 +21,7 @@ test("jQuery()", function() {
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" ); equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" ); equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
var obj = jQuery("div") var obj = jQuery("div");
equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" ); equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );
// can actually yield more than one, when iframes are included, the window is an array as well // can actually yield more than one, when iframes are included, the window is an array as well
@ -84,6 +84,17 @@ test("jQuery()", function() {
exec = true; exec = true;
elem.click(); elem.click();
// manually clean up detached elements
elem.remove();
for ( var i = 0; i < 3; ++i ) {
elem = jQuery("<input type='text' value='TEST' />");
}
equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" );
// manually clean up detached elements
elem.remove();
}); });
test("selector state", function() { test("selector state", function() {
@ -907,3 +918,290 @@ test("jQuery.parseJSON", function(){
ok( true, "Test malformed JSON string." ); ok( true, "Test malformed JSON string." );
} }
}); });
test("jQuery._Deferred()", function() {
expect( 10 );
var deferred,
object,
test;
deferred = jQuery._Deferred();
test = false;
deferred.done( function( value ) {
equals( value , "value" , "Test pre-resolve callback" );
test = true;
} );
deferred.resolve( "value" );
ok( test , "Test pre-resolve callbacks called right away" );
test = false;
deferred.done( function( value ) {
equals( value , "value" , "Test post-resolve callback" );
test = true;
} );
ok( test , "Test post-resolve callbacks called right away" );
deferred.cancel();
test = true;
deferred.done( function() {
ok( false , "Cancel was ignored" );
test = false;
} );
ok( test , "Test cancel" );
deferred = jQuery._Deferred().resolve();
try {
deferred.done( function() {
throw "Error";
} , function() {
ok( true , "Test deferred do not cancel on exception" );
} );
} catch( e ) {
strictEqual( e , "Error" , "Test deferred propagates exceptions");
deferred.done();
}
test = "";
deferred = jQuery._Deferred().done( function() {
test += "A";
}, function() {
test += "B";
} ).resolve();
strictEqual( test , "AB" , "Test multiple done parameters" );
test = "";
deferred.done( function() {
deferred.done( function() {
test += "C";
} );
test += "A";
}, function() {
test += "B";
} );
strictEqual( test , "ABC" , "Test done callbacks order" );
deferred = jQuery._Deferred();
deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
});
});
test("jQuery.Deferred()", function() {
expect( 10 );
jQuery.Deferred( function( defer ) {
strictEqual( this , defer , "Defer passed as this & first argument" );
this.resolve( "done" );
}).then( function( value ) {
strictEqual( value , "done" , "Passed function executed" );
});
jQuery.Deferred().resolve().then( function() {
ok( true , "Success on resolve" );
}, function() {
ok( false , "Error on resolve" );
});
jQuery.Deferred().reject().then( function() {
ok( false , "Success on reject" );
}, function() {
ok( true , "Error on reject" );
});
( new jQuery.Deferred( function( defer ) {
strictEqual( this , defer , "Defer passed as this & first argument (new)" );
this.resolve( "done" );
}) ).then( function( value ) {
strictEqual( value , "done" , "Passed function executed (new)" );
});
( new jQuery.Deferred() ).resolve().then( function() {
ok( true , "Success on resolve (new)" );
}, function() {
ok( false , "Error on resolve (new)" );
});
( new jQuery.Deferred() ).reject().then( function() {
ok( false , "Success on reject (new)" );
}, function() {
ok( true , "Error on reject (new)" );
});
var tmp = jQuery.Deferred();
strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
});
test("jQuery.when()", function() {
expect( 23 );
// Some other objects
jQuery.each( {
"an empty string": "",
"a non-empty string": "some string",
"zero": 0,
"a number other than zero": 1,
"true": true,
"false": false,
"null": null,
"undefined": undefined,
"a plain object": {}
} , function( message , value ) {
ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
} ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
} );
ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
} ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
var cache, i;
for( i = 1 ; i < 4 ; i++ ) {
jQuery.when( cache || jQuery.Deferred( function() {
this.resolve( i );
}) ).then( function( value ) {
strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
cache = value;
}, function() {
ok( false , "Fail called" );
});
}
});
test("jQuery.when() - joined", function() {
expect(8);
jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
}).fail( function() {
ok( false , "Test the created deferred was resolved - non-observables");
});
var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
}).fail( function() {
ok( false , "Test the created deferred was resolved - resolved observable");
});
jQuery.when( 1 , errorDeferred , 3 ).done( function() {
ok( false , "Test the created deferred was rejected - rejected observable");
}).fail( function( error , errorParam ) {
strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
});
});
test("jQuery.subclass", function(){
expect(378);
var Subclass = jQuery.subclass(),
SubclassSubclass = Subclass.subclass(),
jQueryDocument = jQuery(document),
selectors, contexts, methods, method, arg, description;
jQueryDocument.toString = function(){ return 'jQueryDocument'; };
Subclass.fn.subclassMethod = function(){};
SubclassSubclass.fn.subclassSubclassMethod = function(){};
selectors = [
'body',
'html, body',
'<div></div>'
];
methods = [ // all methods that return a new jQuery instance
['eq', 1],
['add', document],
['end'],
['has'],
['closest', 'div'],
['filter', document],
['find', 'div']
];
contexts = [undefined, document, jQueryDocument];
jQuery.each(selectors, function(i, selector){
jQuery.each(methods, function(){
method = this[0];
arg = this[1];
jQuery.each(contexts, function(i, context){
description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')';
same(
jQuery(selector, context)[method](arg).subclassMethod, undefined,
'jQuery'+description+' doesnt have Subclass methods'
);
same(
jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined,
'jQuery'+description+' doesnt have SubclassSubclass methods'
);
same(
Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
'Subclass'+description+' has Subclass methods'
);
same(
Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
'Subclass'+description+' doesnt have SubclassSubclass methods'
);
same(
SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
'SubclassSubclass'+description+' has Subclass methods'
);
same(
SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
'SubclassSubclass'+description+' has SubclassSubclass methods'
);
});
});
});
});

View file

@ -1,4 +1,4 @@
module("css"); module("css", { teardown: moduleTeardown });
test("css(String|Hash)", function() { test("css(String|Hash)", function() {
expect(41); expect(41);
@ -320,3 +320,16 @@ test(":visible selector works properly on children with a hidden parent (bug #45
jQuery('#table').css('display', 'none').html('<tr><td>cell</td><td>cell</td></tr>'); jQuery('#table').css('display', 'none').html('<tr><td>cell</td><td>cell</td></tr>');
equals(jQuery('#table td:visible').length, 0, "hidden cell children not perceived as visible"); equals(jQuery('#table td:visible').length, 0, "hidden cell children not perceived as visible");
}); });
test("internal ref to elem.runtimeStyle (bug #7608)", function () {
expect(1);
var result = true;
try {
jQuery("#foo").css( { width: "0%" } ).css("width");
} catch (e) {
result = false;
}
ok( result, "elem.runtimeStyle does not throw exception" );
});

View file

@ -1,22 +1,159 @@
module("data"); module("data", { teardown: moduleTeardown });
test("expando", function(){ test("expando", function(){
expect(6); expect(1);
equals("expando" in jQuery, true, "jQuery is exposing the expando"); equals("expando" in jQuery, true, "jQuery is exposing the expando");
});
var obj = {}; function dataTests (elem) {
equals( jQuery.data(obj), obj, "jQuery.data(obj) returns the object"); // expect(32)
equals( jQuery.expando in obj, false, "jQuery.data(obj) did not add an expando to the object" );
obj = {}; function getCacheLength() {
jQuery.data(obj, 'test'); var cacheLength = 0;
equals( jQuery.expando in obj, false, "jQuery.data(obj,key) did not add an expando to the object" ); for (var i in jQuery.cache) {
++cacheLength;
}
obj = {}; return cacheLength;
jQuery.data(obj, "foo", "bar"); }
equals( jQuery.expando in obj, false, "jQuery.data(obj,key,value) did not add an expando to the object" );
equals( obj.foo, "bar", "jQuery.data(obj,key,value) sets fields directly on the object." ); equals( jQuery.data(elem, "foo"), undefined, "No data exists initially" );
strictEqual( jQuery.hasData(elem), false, "jQuery.hasData agrees no data exists initially" );
var dataObj = jQuery.data(elem);
equals( typeof dataObj, "object", "Calling data with no args gives us a data object reference" );
strictEqual( jQuery.data(elem), dataObj, "Calling jQuery.data returns the same data object when called multiple times" );
strictEqual( jQuery.hasData(elem), false, "jQuery.hasData agrees no data exists even when an empty data obj exists" );
dataObj.foo = "bar";
equals( jQuery.data(elem, "foo"), "bar", "Data is readable by jQuery.data when set directly on a returned data object" );
strictEqual( jQuery.hasData(elem), true, "jQuery.hasData agrees data exists when data exists" );
jQuery.data(elem, "foo", "baz");
equals( jQuery.data(elem, "foo"), "baz", "Data can be changed by jQuery.data" );
equals( dataObj.foo, "baz", "Changes made through jQuery.data propagate to referenced data object" );
jQuery.data(elem, "foo", undefined);
equals( jQuery.data(elem, "foo"), "baz", "Data is not unset by passing undefined to jQuery.data" );
jQuery.data(elem, "foo", null);
strictEqual( jQuery.data(elem, "foo"), null, "Setting null using jQuery.data works OK" );
jQuery.data(elem, "foo", "foo1");
jQuery.data(elem, { "bar" : "baz", "boom" : "bloz" });
strictEqual( jQuery.data(elem, "foo"), "foo1", "Passing an object extends the data object instead of replacing it" );
equals( jQuery.data(elem, "boom"), "bloz", "Extending the data object works" );
jQuery._data(elem, "foo", "foo2");
equals( jQuery._data(elem, "foo"), "foo2", "Setting internal data works" );
equals( jQuery.data(elem, "foo"), "foo1", "Setting internal data does not override user data" );
var internalDataObj = jQuery.data(elem, jQuery.expando);
strictEqual( jQuery._data(elem), internalDataObj, "Internal data object is accessible via jQuery.expando property" );
notStrictEqual( dataObj, internalDataObj, "Internal data object is not the same as user data object" );
strictEqual( elem.boom, undefined, "Data is never stored directly on the object" );
jQuery.removeData(elem, "foo");
strictEqual( jQuery.data(elem, "foo"), undefined, "jQuery.removeData removes single properties" );
jQuery.removeData(elem);
strictEqual( jQuery.data(elem, jQuery.expando), internalDataObj, "jQuery.removeData does not remove internal data if it exists" );
jQuery.removeData(elem, undefined, true);
strictEqual( jQuery.data(elem, jQuery.expando), undefined, "jQuery.removeData on internal data works" );
strictEqual( jQuery.hasData(elem), false, "jQuery.hasData agrees all data has been removed from object" );
jQuery._data(elem, "foo", "foo2");
strictEqual( jQuery.hasData(elem), true, "jQuery.hasData shows data exists even if it is only internal data" );
jQuery.data(elem, "foo", "foo1");
equals( jQuery._data(elem, "foo"), "foo2", "Setting user data does not override internal data" );
jQuery.removeData(elem, undefined, true);
equals( jQuery.data(elem, "foo"), "foo1", "jQuery.removeData for internal data does not remove user data" );
if (elem.nodeType) {
var oldCacheLength = getCacheLength();
jQuery.removeData(elem, "foo");
equals( getCacheLength(), oldCacheLength - 1, "Removing the last item in the data object destroys it" );
}
else {
jQuery.removeData(elem, "foo");
var expected, actual;
if (jQuery.support.deleteExpando) {
expected = false;
actual = jQuery.expando in elem;
}
else {
expected = null;
actual = elem[ jQuery.expando ];
}
equals( actual, expected, "Removing the last item in the data object destroys it" );
}
jQuery.data(elem, "foo", "foo1");
jQuery._data(elem, "foo", "foo2");
equals( jQuery.data(elem, "foo"), "foo1", "(sanity check) Ensure data is set in user data object" );
equals( jQuery._data(elem, "foo"), "foo2", "(sanity check) Ensure data is set in internal data object" );
jQuery.removeData(elem, "foo", true);
strictEqual( jQuery.data(elem, jQuery.expando), undefined, "Removing the last item in internal data destroys the internal data object" );
jQuery._data(elem, "foo", "foo2");
equals( jQuery._data(elem, "foo"), "foo2", "(sanity check) Ensure data is set in internal data object" );
jQuery.removeData(elem, "foo");
equals( jQuery._data(elem, "foo"), "foo2", "(sanity check) jQuery.removeData for user data does not remove internal data" );
if (elem.nodeType) {
oldCacheLength = getCacheLength();
jQuery.removeData(elem, "foo", true);
equals( getCacheLength(), oldCacheLength - 1, "Removing the last item in the internal data object also destroys the user data object when it is empty" );
}
else {
jQuery.removeData(elem, "foo", true);
if (jQuery.support.deleteExpando) {
expected = false;
actual = jQuery.expando in elem;
}
else {
expected = null;
actual = elem[ jQuery.expando ];
}
equals( actual, expected, "Removing the last item in the internal data object also destroys the user data object when it is empty" );
}
}
test("jQuery.data", function() {
expect(128);
var div = document.createElement("div");
dataTests(div);
dataTests({});
// remove bound handlers from window object to stop potential false positives caused by fix for #5280 in
// transports/xhr.js
jQuery(window).unbind("unload");
dataTests(window);
dataTests(document);
// clean up unattached element
jQuery(div).remove();
}); });
test("jQuery.acceptData", function() { test("jQuery.acceptData", function() {
@ -37,53 +174,11 @@ test("jQuery.acceptData", function() {
ok( !jQuery.acceptData( applet ), "applet" ); ok( !jQuery.acceptData( applet ), "applet" );
}); });
test("jQuery.data", function() {
expect(15);
var div = document.createElement("div");
ok( jQuery.data(div, "test") === undefined, "Check for no data exists" );
jQuery.data(div, "test", "success");
equals( jQuery.data(div, "test"), "success", "Check for added data" );
ok( jQuery.data(div, "notexist") === undefined, "Check for no data exists" );
var data = jQuery.data(div);
same( data, { "test": "success" }, "Return complete data set" );
jQuery.data(div, "test", "overwritten");
equals( jQuery.data(div, "test"), "overwritten", "Check for overwritten data" );
jQuery.data(div, "test", undefined);
equals( jQuery.data(div, "test"), "overwritten", "Check that data wasn't removed");
jQuery.data(div, "test", null);
ok( jQuery.data(div, "test") === null, "Check for null data");
jQuery.data(div, "test3", "orig");
jQuery.data(div, { "test": "in", "test2": "in2" });
equals( jQuery.data(div, "test"), "in", "Verify setting an object in data" );
equals( jQuery.data(div, "test2"), "in2", "Verify setting an object in data" );
equals( jQuery.data(div, "test3"), "orig", "Verify original not overwritten" );
var obj = {};
jQuery.data( obj, "prop", true );
ok( obj.prop, "Data is being stored on the object" );
equals( jQuery.data( obj, "prop" ), true, "Make sure the right value is retrieved" );
jQuery.data( window, "BAD", true );
ok( !window[ jQuery.expando ], "Make sure there is no expando on the window object." );
ok( !window.BAD, "And make sure that the property wasn't set directly on the window." );
ok( jQuery.data( window, "BAD" ), "Make sure that the value was set." );
});
test(".data()", function() { test(".data()", function() {
expect(5); expect(5);
var div = jQuery("#foo"); var div = jQuery("#foo");
strictEqual( div.data("foo"), undefined, "Make sure that missing result is undefined" ); strictEqual( div.data("foo"), undefined, "Make sure that missing result is undefined" );
div.data("test", "success"); div.data("test", "success");
same( div.data(), {test: "success"}, "data() get the entire data object" ); same( div.data(), {test: "success"}, "data() get the entire data object" );
strictEqual( div.data("foo"), undefined, "Make sure that missing result is still undefined" ); strictEqual( div.data("foo"), undefined, "Make sure that missing result is still undefined" );
@ -92,7 +187,7 @@ test(".data()", function() {
equals( nodiv.data(), null, "data() on empty set returns null" ); equals( nodiv.data(), null, "data() on empty set returns null" );
var obj = { foo: "bar" }; var obj = { foo: "bar" };
equals( jQuery(obj).data(), obj, "Retrieve data object from a wrapped JS object (#7524)" ); deepEqual( jQuery(obj).data(), {}, "Retrieve data object from a wrapped JS object (#7524)" );
}) })
test(".data(String) and .data(String, Object)", function() { test(".data(String) and .data(String, Object)", function() {
@ -179,11 +274,14 @@ test(".data(String) and .data(String, Object)", function() {
equals( $elem.data('null',null).data('null'), null, "null's are preserved"); equals( $elem.data('null',null).data('null'), null, "null's are preserved");
equals( $elem.data('emptyString','').data('emptyString'), '', "Empty strings are preserved"); equals( $elem.data('emptyString','').data('emptyString'), '', "Empty strings are preserved");
equals( $elem.data('false',false).data('false'), false, "false's are preserved"); equals( $elem.data('false',false).data('false'), false, "false's are preserved");
equals( $elem.data('exists'), true, "Existing data is returned" ); equals( $elem.data('exists'), undefined, "Existing data is not returned" );
// Clean up // Clean up
$elem.removeData(); $elem.removeData();
ok( jQuery.isEmptyObject( $elem[0] ), "removeData clears the object" ); deepEqual( $elem[0], {exists:true}, "removeData does not clear the object" );
// manually clean up detached elements
parent.remove();
}); });
test("data-* attributes", function() { test("data-* attributes", function() {
@ -203,6 +301,8 @@ test("data-* attributes", function() {
div.data("attr", "internal").attr("data-attr", "external"); div.data("attr", "internal").attr("data-attr", "external");
equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" ); equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" );
div.remove();
child.appendTo('#main'); child.appendTo('#main');
equals( child.data("myobj"), "old data", "Value accessed from data-* attribute"); equals( child.data("myobj"), "old data", "Value accessed from data-* attribute");
@ -214,6 +314,8 @@ test("data-* attributes", function() {
var obj = child.data(), obj2 = dummy.data(), check = [ "myobj", "ignored", "other" ], num = 0, num2 = 0; var obj = child.data(), obj2 = dummy.data(), check = [ "myobj", "ignored", "other" ], num = 0, num2 = 0;
dummy.remove();
for ( var i = 0, l = check.length; i < l; i++ ) { for ( var i = 0, l = check.length; i < l; i++ ) {
ok( obj[ check[i] ], "Make sure data- property exists when calling data-." ); ok( obj[ check[i] ], "Make sure data- property exists when calling data-." );
ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." ); ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." );
@ -308,13 +410,17 @@ test(".data(Object)", function() {
var obj = {test:"unset"}, var obj = {test:"unset"},
jqobj = jQuery(obj); jqobj = jQuery(obj);
jqobj.data("test", "unset");
jqobj.data({ "test": "in", "test2": "in2" }); jqobj.data({ "test": "in", "test2": "in2" });
equals( obj.test, "in", "Verify setting an object on an object extends the object" ); equals( jQuery.data(obj).test, "in", "Verify setting an object on an object extends the data object" );
equals( obj.test2, "in2", "Verify setting an object on an object extends the object" ); equals( obj.test2, undefined, "Verify setting an object on an object does not extend the object" );
// manually clean up detached elements
div.remove();
}); });
test("jQuery.removeData", function() { test("jQuery.removeData", function() {
expect(7); expect(6);
var div = jQuery("#foo")[0]; var div = jQuery("#foo")[0];
jQuery.data(div, "test", "testing"); jQuery.data(div, "test", "testing");
jQuery.removeData(div, "test"); jQuery.removeData(div, "test");
@ -327,10 +433,9 @@ test("jQuery.removeData", function() {
var obj = {}; var obj = {};
jQuery.data(obj, "test", "testing"); jQuery.data(obj, "test", "testing");
equals( obj.test, "testing", "verify data on plain object"); equals( jQuery(obj).data("test"), "testing", "verify data on plain object");
jQuery.removeData(obj, "test"); jQuery.removeData(obj, "test");
equals( jQuery.data(obj, "test"), undefined, "Check removal of data on plain object" ); equals( jQuery.data(obj, "test"), undefined, "Check removal of data on plain object" );
equals( obj.test, undefined, "Check removal of data directly from plain object" );
jQuery.data( window, "BAD", true ); jQuery.data( window, "BAD", true );
jQuery.removeData( window, "BAD" ); jQuery.removeData( window, "BAD" );

View file

@ -1,4 +1,4 @@
module("dimensions"); module("dimensions", { teardown: moduleTeardown });
function pass( val ) { function pass( val ) {
return val; return val;
@ -33,6 +33,8 @@ function testWidth( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." ); equals( blah.width( val(10) ), blah, "Make sure that setting a width on an empty set returns the set." );
equals( blah.width(), null, "Make sure 'null' is returned on an empty set"); equals( blah.width(), null, "Make sure 'null' is returned on an empty set");
jQuery.removeData($div[0], 'olddisplay', true);
} }
test("width()", function() { test("width()", function() {
@ -80,6 +82,8 @@ function testHeight( val ) {
var blah = jQuery("blah"); var blah = jQuery("blah");
equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." ); equals( blah.height( val(10) ), blah, "Make sure that setting a height on an empty set returns the set." );
equals( blah.height(), null, "Make sure 'null' is returned on an empty set"); equals( blah.height(), null, "Make sure 'null' is returned on an empty set");
jQuery.removeData($div[0], 'olddisplay', true);
} }
test("height()", function() { test("height()", function() {
@ -126,6 +130,9 @@ test("innerWidth()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerWidth(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("innerHeight()", function() { test("innerHeight()", function() {
@ -152,6 +159,9 @@ test("innerHeight()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.innerHeight(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("outerWidth()", function() { test("outerWidth()", function() {
@ -179,6 +189,9 @@ test("outerWidth()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerWidth(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });
test("outerHeight()", function() { test("outerHeight()", function() {
@ -205,4 +218,7 @@ test("outerHeight()", function() {
// Temporarily require 0 for backwards compat - should be auto // Temporarily require 0 for backwards compat - should be auto
equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." ); equals( div.outerHeight(), 0, "Make sure that disconnected nodes are handled." );
div.remove();
jQuery.removeData($div[0], 'olddisplay', true);
}); });

91
test/unit/effects.js vendored
View file

@ -1,4 +1,4 @@
module("effects"); module("effects", { teardown: moduleTeardown });
test("sanity check", function() { test("sanity check", function() {
expect(1); expect(1);
@ -14,7 +14,7 @@ test("show()", function() {
equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." ); equals( hiddendiv.css("display"), "block", "Make sure a pre-hidden div is visible." );
var div = jQuery("<div>").hide().appendTo("body").show(); var div = jQuery("<div>").hide().appendTo("#main").show();
equal( div.css("display"), "block", "Make sure pre-hidden divs show" ); equal( div.css("display"), "block", "Make sure pre-hidden divs show" );
@ -130,6 +130,45 @@ test("show(Number) - other displays", function() {
}); });
}); });
// Supports #7397
test("Persist correct display value", function() {
expect(3);
QUnit.reset();
stop();
// #show-tests * is set display: none in CSS
jQuery("#main").append('<div id="show-tests"><span style="position:absolute;">foo</span></div>');
var $span = jQuery("#show-tests span"),
displayNone = $span.css("display"),
display = '', num = 0;
$span.show();
display = $span.css("display");
$span.hide();
$span.fadeIn(100, function() {
equals($span.css("display"), display, "Expecting display: " + display);
$span.fadeOut(100, function () {
equals($span.css("display"), displayNone, "Expecting display: " + displayNone);
$span.fadeIn(100, function() {
equals($span.css("display"), display, "Expecting display: " + display);
start();
});
});
});
});
test("animate(Hash, Object, Function)", function() { test("animate(Hash, Object, Function)", function() {
expect(1); expect(1);
stop(); stop();
@ -364,13 +403,16 @@ test("animate duration 0", function() {
$elem.hide(0, function(){ $elem.hide(0, function(){
ok(true, "Hide callback with no duration"); ok(true, "Hide callback with no duration");
}); });
// manually clean up detached elements
$elem.remove();
}); });
test("animate hyphenated properties", function(){ test("animate hyphenated properties", function(){
expect(1); expect(1);
stop(); stop();
jQuery("#nothiddendiv") jQuery("#foo")
.css("font-size", 10) .css("font-size", 10)
.animate({"font-size": 20}, 200, function(){ .animate({"font-size": 20}, 200, function(){
equals( this.style.fontSize, "20px", "The font-size property was animated." ); equals( this.style.fontSize, "20px", "The font-size property was animated." );
@ -394,7 +436,7 @@ test("stop()", function() {
expect(3); expect(3);
stop(); stop();
var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
@ -407,6 +449,8 @@ test("stop()", function() {
nw = $foo.width(); nw = $foo.width();
notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px"); notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
setTimeout(function(){ setTimeout(function(){
$foo.removeData();
$foo.removeData(undefined, true);
equals( nw, $foo.width(), "The animation didn't continue" ); equals( nw, $foo.width(), "The animation didn't continue" );
start(); start();
}, 100); }, 100);
@ -417,7 +461,7 @@ test("stop() - several in queue", function() {
expect(3); expect(3);
stop(); stop();
var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
@ -442,7 +486,7 @@ test("stop(clearQueue)", function() {
expect(4); expect(4);
stop(); stop();
var $foo = jQuery("#nothiddendiv"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
@ -469,7 +513,7 @@ test("stop(clearQueue, gotoEnd)", function() {
expect(1); expect(1);
stop(); stop();
var $foo = jQuery("#nothiddendivchild"); var $foo = jQuery("#foo");
var w = 0; var w = 0;
$foo.hide().width(200).width(); $foo.hide().width(200).width();
@ -497,7 +541,7 @@ test("stop(clearQueue, gotoEnd)", function() {
test("toggle()", function() { test("toggle()", function() {
expect(6); expect(6);
var x = jQuery("#nothiddendiv"); var x = jQuery("#foo");
ok( x.is(":visible"), "is visible" ); ok( x.is(":visible"), "is visible" );
x.toggle(); x.toggle();
ok( x.is(":hidden"), "is hidden" ); ok( x.is(":hidden"), "is hidden" );
@ -521,6 +565,23 @@ jQuery.checkOverflowDisplay = function(){
start(); start();
} }
test("support negative values < -10000 (bug #7193)", function () {
expect(1);
stop();
jQuery.extend(jQuery.fx.step, {
"marginBottom": function(fx) {
equals( fx.cur(), -11000, "Element has margin-bottom of -11000" );
delete jQuery.fx.step.marginBottom;
}
});
jQuery("#main").css("marginBottom", "-11000px").animate({ marginBottom: "-11001px" }, {
duration: 1,
complete: start
});
});
test("JS Overflow and Display", function() { test("JS Overflow and Display", function() {
expect(2); expect(2);
stop(); stop();
@ -681,6 +742,9 @@ jQuery.each( {
} }
} }
// manually remove generated element
jQuery(this).remove();
start(); start();
}); });
}); });
@ -707,6 +771,10 @@ jQuery.checkState = function(){
var cur = self.style[ c ] || jQuery.css(self, c); var cur = self.style[ c ] || jQuery.css(self, c);
equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")"); equals( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")");
}); });
// manually clean data on modified element
jQuery.removeData(this, 'olddisplay', true);
start(); start();
} }
@ -773,9 +841,6 @@ jQuery.makeTest = function( text ){
jQuery("<h4></h4>") jQuery("<h4></h4>")
.text( text ) .text( text )
.appendTo("#fx-tests") .appendTo("#fx-tests")
.click(function(){
jQuery(this).next().toggle();
})
.after( elem ); .after( elem );
return elem; return elem;
@ -839,7 +904,7 @@ test("hide hidden elements (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main"); var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" ); equals( div.css("display"), "none", "Element is hidden by default" );
div.hide(); div.hide();
ok( !div.data("olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
div.show(); div.show();
equals( div.css("display"), "block", "Show a double-hidden element" ); equals( div.css("display"), "block", "Show a double-hidden element" );
@ -854,7 +919,7 @@ test("hide hidden elements, with animation (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main"); var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" ); equals( div.css("display"), "none", "Element is hidden by default" );
div.hide(1, function () { div.hide(1, function () {
ok( !div.data("olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" );
div.show(1, function () { div.show(1, function () {
equals( div.css("display"), "block", "Show a double-hidden element" ); equals( div.css("display"), "block", "Show a double-hidden element" );
start(); start();

View file

@ -1,4 +1,4 @@
module("event"); module("event", { teardown: moduleTeardown });
test("null or undefined handler", function() { test("null or undefined handler", function() {
expect(2); expect(2);
@ -28,7 +28,7 @@ test("bind(), with data", function() {
}; };
jQuery("#firstp").bind("click", {foo: "bar"}, handler).click().unbind("click", handler); jQuery("#firstp").bind("click", {foo: "bar"}, handler).click().unbind("click", handler);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
}); });
test("click(), with data", function() { test("click(), with data", function() {
@ -39,7 +39,7 @@ test("click(), with data", function() {
}; };
jQuery("#firstp").click({foo: "bar"}, handler).click().unbind("click", handler); jQuery("#firstp").click({foo: "bar"}, handler).click().unbind("click", handler);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data." );
}); });
test("bind(), with data, trigger with data", function() { test("bind(), with data, trigger with data", function() {
@ -80,6 +80,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "focusin"; cur = "focusin";
div.trigger("focusin.a"); div.trigger("focusin.a");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("click mouseover", obj, function(e) { div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
equals( e.type, cur, "Verify right multi event was fired." ); equals( e.type, cur, "Verify right multi event was fired." );
equals( e.data, obj, "Make sure the data came in correctly." ); equals( e.data, obj, "Make sure the data came in correctly." );
@ -91,6 +94,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "mouseover"; cur = "mouseover";
div.trigger("mouseover"); div.trigger("mouseover");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) { div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
equals( e.type, cur, "Verify right multi event was fired." ); equals( e.type, cur, "Verify right multi event was fired." );
}); });
@ -100,6 +106,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "focusout"; cur = "focusout";
div.trigger("focusout.b"); div.trigger("focusout.b");
// manually clean up detached elements
div.remove();
}); });
test("bind(), namespace with special add", function() { test("bind(), namespace with special add", function() {
@ -295,6 +304,49 @@ test("live/delegate immediate propagation", function() {
$p.undelegate( "click" ); $p.undelegate( "click" );
}); });
test("bind/delegate bubbling, isDefaultPrevented", function() {
expect(2);
var $anchor2 = jQuery( "#anchor2" ),
$main = jQuery( "#main" ),
fakeClick = function($jq) {
// Use a native click so we don't get jQuery simulated bubbling
if ( document.createEvent ) {
var e = document.createEvent( 'MouseEvents' );
e.initEvent( "click", true, true );
$jq[0].dispatchEvent(e);
}
else if ( $jq[0].click ) {
$jq[0].click(); // IE
}
};
$anchor2.click(function(e) {
e.preventDefault();
});
$main.delegate("#foo", "click", function(e) {
var orig = e.originalEvent;
if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig.getPreventDefault ) {
equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
} else {
// Opera < 11 doesn't implement any interface we can use, so give it a pass
ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
}
});
fakeClick( $anchor2 );
$anchor2.unbind( "click" );
$main.undelegate( "click" );
$anchor2.click(function(e) {
// Let the default action occur
});
$main.delegate("#foo", "click", function(e) {
equals( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
});
fakeClick( $anchor2 );
$anchor2.unbind( "click" );
$main.undelegate( "click" );
});
test("bind(), iframes", function() { test("bind(), iframes", function() {
// events don't work with iframes, see #939 - this test fails in IE because of contentDocument // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
var doc = jQuery("#loadediframe").contents(); var doc = jQuery("#loadediframe").contents();
@ -470,7 +522,7 @@ test("bind(), with different this object", function() {
.bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1) .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
.bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2); .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2);
ok( !jQuery.data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." ); ok( !jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data." );
}); });
test("bind(name, false), unbind(name, false)", function() { test("bind(name, false), unbind(name, false)", function() {
@ -490,6 +542,9 @@ test("bind(name, false), unbind(name, false)", function() {
jQuery("#ap").unbind("click", false); jQuery("#ap").unbind("click", false);
jQuery("#ap").trigger("click"); jQuery("#ap").trigger("click");
equals( main, 1, "Verify that the trigger happened correctly." ); equals( main, 1, "Verify that the trigger happened correctly." );
// manually clean up events from elements outside the fixture
jQuery("#main").unbind("click");
}); });
test("bind()/trigger()/unbind() on plain object", function() { test("bind()/trigger()/unbind() on plain object", function() {
@ -512,7 +567,7 @@ test("bind()/trigger()/unbind() on plain object", function() {
} }
}); });
var events = jQuery(obj).data("__events__"); var events = jQuery._data(obj, "events");
ok( events, "Object has events bound." ); ok( events, "Object has events bound." );
equals( obj.events, undefined, "Events object on plain objects is not events" ); equals( obj.events, undefined, "Events object on plain objects is not events" );
equals( typeof events, "function", "'events' expando is a function on plain objects." ); equals( typeof events, "function", "'events' expando is a function on plain objects." );
@ -532,7 +587,9 @@ test("bind()/trigger()/unbind() on plain object", function() {
// Make sure it doesn't complain when no events are found // Make sure it doesn't complain when no events are found
jQuery(obj).unbind("test"); jQuery(obj).unbind("test");
equals( obj.__events__, undefined, "Make sure events object is removed" ); equals( obj && obj[ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ] &&
obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" );
}); });
test("unbind(type)", function() { test("unbind(type)", function() {
@ -626,13 +683,18 @@ test("hover()", function() {
test("trigger() shortcuts", function() { test("trigger() shortcuts", function() {
expect(6); expect(6);
jQuery('<li><a href="#">Change location</a></li>').prependTo('#firstUL').find('a').bind('click', function() {
var elem = jQuery('<li><a href="#">Change location</a></li>').prependTo('#firstUL');
elem.find('a').bind('click', function() {
var close = jQuery('spanx', this); // same with jQuery(this).find('span'); var close = jQuery('spanx', this); // same with jQuery(this).find('span');
equals( close.length, 0, "Context element does not exist, length must be zero" ); equals( close.length, 0, "Context element does not exist, length must be zero" );
ok( !close[0], "Context element does not exist, direct access to element must return undefined" ); ok( !close[0], "Context element does not exist, direct access to element must return undefined" );
return false; return false;
}).click(); }).click();
// manually clean up detached elements
elem.remove();
jQuery("#check1").click(function() { jQuery("#check1").click(function() {
ok( true, "click event handler for checkbox gets fired twice, see #815" ); ok( true, "click event handler for checkbox gets fired twice, see #815" );
}).click(); }).click();
@ -651,9 +713,12 @@ test("trigger() shortcuts", function() {
jQuery('#simon1').click(); jQuery('#simon1').click();
equals( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" ); equals( clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also" );
jQuery('<img />').load(function(){ elem = jQuery('<img />').load(function(){
ok( true, "Trigger the load event, using the shortcut .load() (#2819)"); ok( true, "Trigger the load event, using the shortcut .load() (#2819)");
}).load(); }).load();
// manually clean up detached elements
elem.remove();
}); });
test("trigger() bubbling", function() { test("trigger() bubbling", function() {
@ -688,6 +753,10 @@ test("trigger() bubbling", function() {
equals( body, 2, "ap bubble" ); equals( body, 2, "ap bubble" );
equals( main, 1, "ap bubble" ); equals( main, 1, "ap bubble" );
equals( ap, 1, "ap bubble" ); equals( ap, 1, "ap bubble" );
// manually clean up events from elements outside the fixture
jQuery(document).unbind("click");
jQuery("html, body, #main").unbind("click");
}); });
test("trigger(type, [data], [fn])", function() { test("trigger(type, [data], [fn])", function() {
@ -731,7 +800,7 @@ test("trigger(type, [data], [fn])", function() {
pass = true; pass = true;
try { try {
jQuery('table:first').bind('test:test', function(){}).trigger('test:test'); jQuery('#main table:first').bind('test:test', function(){}).trigger('test:test');
} catch (e) { } catch (e) {
pass = false; pass = false;
} }
@ -912,9 +981,12 @@ test("toggle(Function, Function, ...)", function() {
equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2"); equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2");
$div.unbind('click',fns[0]); $div.unbind('click',fns[0]);
var data = jQuery.data( $div[0], 'events' ); var data = jQuery._data( $div[0], 'events' );
ok( !data, "Unbinding one function from toggle unbinds them all"); ok( !data, "Unbinding one function from toggle unbinds them all");
// manually clean up detached elements
$div.remove();
// Test Multi-Toggles // Test Multi-Toggles
var a = [], b = []; var a = [], b = [];
$div = jQuery("<div/>"); $div = jQuery("<div/>");
@ -930,6 +1002,9 @@ test("toggle(Function, Function, ...)", function() {
$div.click(); $div.click();
same( a, [1,2,1], "Check that a click worked with a second toggle, second click." ); same( a, [1,2,1], "Check that a click worked with a second toggle, second click." );
same( b, [1,2], "Check that a click worked with a second toggle, second click." ); same( b, [1,2], "Check that a click worked with a second toggle, second click." );
// manually clean up detached elements
$div.remove();
}); });
test(".live()/.die()", function() { test(".live()/.die()", function() {
@ -1030,7 +1105,7 @@ test(".live()/.die()", function() {
equals( clicked, 2, "live with a context" ); equals( clicked, 2, "live with a context" );
// Make sure the event is actually stored on the context // Make sure the event is actually stored on the context
ok( jQuery.data(container, "events").live, "live with a context" ); ok( jQuery._data(container, "events").live, "live with a context" );
// Test unbinding with a different context // Test unbinding with a different context
jQuery("#foo", container).die("click"); jQuery("#foo", container).die("click");
@ -1240,6 +1315,9 @@ test("live with multiple events", function(){
div.trigger("submit"); div.trigger("submit");
equals( count, 2, "Make sure both the click and submit were triggered." ); equals( count, 2, "Make sure both the click and submit were triggered." );
// manually clean up events from elements outside the fixture
div.die();
}); });
test("live with namespaces", function(){ test("live with namespaces", function(){
@ -1543,7 +1621,7 @@ test(".delegate()/.undelegate()", function() {
equals( clicked, 2, "delegate with a context" ); equals( clicked, 2, "delegate with a context" );
// Make sure the event is actually stored on the context // Make sure the event is actually stored on the context
ok( jQuery.data(container, "events").live, "delegate with a context" ); ok( jQuery._data(container, "events").live, "delegate with a context" );
// Test unbinding with a different context // Test unbinding with a different context
jQuery("#main").undelegate("#foo", "click"); jQuery("#main").undelegate("#foo", "click");
@ -1872,27 +1950,7 @@ test("window resize", function() {
ok( true, "Resize event fired." ); ok( true, "Resize event fired." );
}).resize().unbind("resize"); }).resize().unbind("resize");
ok( !jQuery(window).data("__events__"), "Make sure all the events are gone." ); ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
});
test("focusin bubbles", function() {
//create an input and focusin on it
var input = jQuery("<input/>"), order = 0;
input.prependTo("body");
jQuery("body").bind("focusin.focusinBubblesTest",function(){
equals(1,order++,"focusin on the body second")
});
input.bind("focusin.focusinBubblesTest",function(){
equals(0,order++,"focusin on the element first")
});
input[0].focus();
input.remove();
jQuery("body").unbind("focusin.focusinBubblesTest");
}); });
/* /*

View file

@ -1,4 +1,7 @@
module("manipulation"); module("manipulation", { teardown: moduleTeardown });
// Ensure that an extended Array prototype doesn't break jQuery
Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); };
var bareObj = function(value) { return value; }; var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); }; var functionReturningObj = function(value) { return (function() { return value; }); };
@ -51,7 +54,7 @@ test("text(Function) with incoming value", function() {
}); });
var testWrap = function(val) { var testWrap = function(val) {
expect(18); expect(19);
var defaultText = 'Try them out:' var defaultText = 'Try them out:'
var result = jQuery('#first').wrap(val( '<div class="red"><span></span></div>' )).text(); var result = jQuery('#first').wrap(val( '<div class="red"><span></span></div>' )).text();
equals( defaultText, result, 'Check for wrapping of on-the-fly html' ); equals( defaultText, result, 'Check for wrapping of on-the-fly html' );
@ -80,10 +83,20 @@ var testWrap = function(val) {
equals( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" ); equals( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" );
// Try wrapping a disconnected node // Try wrapping a disconnected node
var cacheLength = 0;
for (var i in jQuery.cache) {
cacheLength++;
}
j = jQuery("<label/>").wrap(val( "<li/>" )); j = jQuery("<label/>").wrap(val( "<li/>" ));
equals( j[0].nodeName.toUpperCase(), "LABEL", "Element is a label" ); equals( j[0].nodeName.toUpperCase(), "LABEL", "Element is a label" );
equals( j[0].parentNode.nodeName.toUpperCase(), "LI", "Element has been wrapped" ); equals( j[0].parentNode.nodeName.toUpperCase(), "LI", "Element has been wrapped" );
for (i in jQuery.cache) {
cacheLength--;
}
equals(cacheLength, 0, "No memory leak in jQuery.cache (bug #7165)");
// Wrap an element containing a text node // Wrap an element containing a text node
j = jQuery("<span/>").wrap("<div>test</div>"); j = jQuery("<span/>").wrap("<div>test</div>");
equals( j[0].previousSibling.nodeType, 3, "Make sure the previous node is a text element" ); equals( j[0].previousSibling.nodeType, 3, "Make sure the previous node is a text element" );
@ -102,12 +115,19 @@ var testWrap = function(val) {
// Wrap an element with a jQuery set and event // Wrap an element with a jQuery set and event
result = jQuery("<div></div>").click(function(){ result = jQuery("<div></div>").click(function(){
ok(true, "Event triggered."); ok(true, "Event triggered.");
// Remove handlers on detached elements
result.unbind();
jQuery(this).unbind();
}); });
j = jQuery("<span/>").wrap(result); j = jQuery("<span/>").wrap(result);
equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." ); equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." );
j.parent().trigger("click"); j.parent().trigger("click");
// clean up attached elements
QUnit.reset();
} }
test("wrap(String|Element)", function() { test("wrap(String|Element)", function() {
@ -382,7 +402,7 @@ test("append(Function) with incoming value", function() {
}); });
test("append the same fragment with events (Bug #6997, 5566)", function () { test("append the same fragment with events (Bug #6997, 5566)", function () {
expect(4 + (document.fireEvent ? 1 : 0)); expect(2 + (document.fireEvent ? 1 : 0));
stop(1000); stop(1000);
var element; var element;
@ -395,8 +415,12 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
ok(true, "Event exists on original after being unbound on clone"); ok(true, "Event exists on original after being unbound on clone");
jQuery(this).unbind('click'); jQuery(this).unbind('click');
}); });
element.clone(true).unbind('click')[0].fireEvent('onclick'); var clone = element.clone(true).unbind('click');
clone[0].fireEvent('onclick');
element[0].fireEvent('onclick'); element[0].fireEvent('onclick');
// manually clean up detached elements
clone.remove();
} }
element = jQuery("<a class='test6997'></a>").click(function () { element = jQuery("<a class='test6997'></a>").click(function () {
@ -413,14 +437,6 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
jQuery("#listWithTabIndex li").before(element); jQuery("#listWithTabIndex li").before(element);
jQuery("#listWithTabIndex li.test6997").eq(1).click(); jQuery("#listWithTabIndex li.test6997").eq(1).click();
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
}); });
test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() { test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() {
@ -856,7 +872,7 @@ test("replaceAll(String|Element|Array&lt;Element&gt;|jQuery)", function() {
}); });
test("clone()", function() { test("clone()", function() {
expect(36); expect(37);
equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' ); equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' );
var clone = jQuery('#yahoo').clone(); var clone = jQuery('#yahoo').clone();
equals( 'Try them out:Yahoo', jQuery('#first').append(clone).text(), 'Check for clone' ); equals( 'Try them out:Yahoo', jQuery('#first').append(clone).text(), 'Check for clone' );
@ -881,20 +897,36 @@ test("clone()", function() {
ok( true, "Bound event still exists." ); ok( true, "Bound event still exists." );
}); });
div = div.clone(true).clone(true); clone = div.clone(true);
// manually clean up detached elements
div.remove();
div = clone.clone(true);
// manually clean up detached elements
clone.remove();
equals( div.length, 1, "One element cloned" ); equals( div.length, 1, "One element cloned" );
equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.trigger("click"); div.trigger("click");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]); div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]);
div.find("table").click(function(){ div.find("table").click(function(){
ok( true, "Bound event still exists." ); ok( true, "Bound event still exists." );
}); });
div = div.clone(true); clone = div.clone(true);
equals( div.length, 1, "One element cloned" ); equals( clone.length, 1, "One element cloned" );
equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.find("table:last").trigger("click"); clone.find("table:last").trigger("click");
// manually clean up detached elements
div.remove();
clone.remove();
// this is technically an invalid object, but because of the special // this is technically an invalid object, but because of the special
// classid instantiation it is the only kind that IE has trouble with, // classid instantiation it is the only kind that IE has trouble with,
@ -914,10 +946,16 @@ test("clone()", function() {
equals( clone.html(), div.html(), "Element contents cloned" ); equals( clone.html(), div.html(), "Element contents cloned" );
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div = jQuery("<div/>").data({ a: true, b: true }); div = jQuery("<div/>").data({ a: true });
div = div.clone(true); clone = div.clone(true);
equals( div.data("a"), true, "Data cloned." ); equals( clone.data("a"), true, "Data cloned." );
equals( div.data("b"), true, "Data cloned." ); clone.data("a", false);
equals( clone.data("a"), false, "Ensure cloned element data object was correctly modified" );
equals( div.data("a"), true, "Ensure cloned element data object is copied, not referenced" );
// manually clean up detached elements
div.remove();
clone.remove();
var form = document.createElement("form"); var form = document.createElement("form");
form.action = "/test/"; form.action = "/test/";
@ -930,6 +968,28 @@ test("clone()", function() {
equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" ); equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
}); });
test("clone(form element) (Bug #3879, #6655)", function() {
expect(6);
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
element = jQuery("<input type='checkbox' value='foo'>").attr('checked', 'checked');
clone = element.clone();
equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" );
element = jQuery("<input type='text' value='foo'>");
clone = element.clone();
equals( clone[0].defaultValue, "foo", "Text input defaultValue cloned correctly" );
element = jQuery("<textarea>foo</textarea>");
clone = element.clone();
equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
});
if (!isLocal) { if (!isLocal) {
test("clone() on XML nodes", function() { test("clone() on XML nodes", function() {
expect(2); expect(2);
@ -1126,15 +1186,21 @@ var testRemove = function(method) {
jQuery("#nonnodes").contents()[method](); jQuery("#nonnodes").contents()[method]();
equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" ); equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" );
// manually clean up detached elements
if (method === "detach") {
first.remove();
}
QUnit.reset(); QUnit.reset();
var count = 0; var count = 0;
var first = jQuery("#ap").children(":first"); var first = jQuery("#ap").children(":first");
var cleanUp = first.click(function() { count++ })[method]().appendTo("body").click(); var cleanUp = first.click(function() { count++ })[method]().appendTo("#main").click();
equals( method == "remove" ? 0 : 1, count ); equals( method == "remove" ? 0 : 1, count );
cleanUp.detach(); // manually clean up detached elements
cleanUp.remove();
}; };
test("remove()", function() { test("remove()", function() {
@ -1232,3 +1298,20 @@ test("jQuery.cleanData", function() {
return div; return div;
} }
}); });
test("jQuery.buildFragment - no plain-text caching (Bug #6779)", function() {
expect(1);
// DOM manipulation fails if added text matches an Object method
var $f = jQuery( "<div />" ).appendTo( "#main" ),
bad = [ "start-", "toString", "hasOwnProperty", "append", "here&there!", "-end" ];
for ( var i=0; i < bad.length; i++ ) {
try {
$f.append( bad[i] );
}
catch(e) {}
}
equals($f.text(), bad.join(''), "Cached strings that match Object properties");
$f.remove();
});

View file

@ -1,4 +1,4 @@
module("offset"); module("offset", { teardown: moduleTeardown });
test("disconnected node", function() { test("disconnected node", function() {
expect(2); expect(2);

View file

@ -1,4 +1,4 @@
module("queue"); module("queue", { teardown: moduleTeardown });
test("queue() with other types",function() { test("queue() with other types",function() {
expect(9); expect(9);

View file

@ -1,4 +1,4 @@
module("selector"); module("selector", { teardown: moduleTeardown });
test("element", function() { test("element", function() {
expect(21); expect(21);
@ -58,7 +58,8 @@ if ( location.protocol != "file:" ) {
} }
test("broken", function() { test("broken", function() {
expect(8); expect(19);
function broken(name, selector) { function broken(name, selector) {
try { try {
jQuery(selector); jQuery(selector);
@ -77,10 +78,31 @@ test("broken", function() {
broken( "Broken Selector", "<>", [] ); broken( "Broken Selector", "<>", [] );
broken( "Broken Selector", "{}", [] ); broken( "Broken Selector", "{}", [] );
broken( "Doesn't exist", ":visble", [] ); broken( "Doesn't exist", ":visble", [] );
broken( "Nth-child", ":nth-child", [] );
broken( "Nth-child", ":nth-child(-)", [] );
// Sigh. WebKit thinks this is a real selector in qSA
// They've already fixed this and it'll be coming into
// current browsers soon.
//broken( "Nth-child", ":nth-child(asdf)", [] );
broken( "Nth-child", ":nth-child(2n+-0)", [] );
broken( "Nth-child", ":nth-child(2+0)", [] );
broken( "Nth-child", ":nth-child(- 1n)", [] );
broken( "Nth-child", ":nth-child(-1 n)", [] );
broken( "First-child", ":first-child(n)", [] );
broken( "Last-child", ":last-child(n)", [] );
broken( "Only-child", ":only-child(n)", [] );
// Make sure attribute value quoting works correctly. See: #6093
var attrbad = jQuery('<input type="hidden" value="2" name="foo.baz" id="attrbad1"/><input type="hidden" value="2" name="foo[baz]" id="attrbad2"/>').appendTo("body");
broken( "Attribute not escaped", "input[name=foo.baz]", [] );
broken( "Attribute not escaped", "input[name=foo[baz]]", [] );
attrbad.remove();
}); });
test("id", function() { test("id", function() {
expect(28); expect(29);
t( "ID Selector", "#body", ["body"] ); t( "ID Selector", "#body", ["body"] );
t( "ID Selector w/ Element", "body#body", ["body"] ); t( "ID Selector w/ Element", "body#body", ["body"] );
t( "ID Selector w/ Element", "ul#first", [] ); t( "ID Selector w/ Element", "ul#first", [] );
@ -116,6 +138,9 @@ test("id", function() {
same( jQuery("body").find("div#form").get(), [], "ID selector within the context of another element" ); same( jQuery("body").find("div#form").get(), [], "ID selector within the context of another element" );
//#7533
equal( jQuery("<div id=\"A'B~C.D[E]\"><p>foo</p></div>").find("p").length, 1, "Find where context root is a node and has an ID with CSS3 meta characters" );
t( "Underscore ID", "#types_all", ["types_all"] ); t( "Underscore ID", "#types_all", ["types_all"] );
t( "Dash ID", "#fx-queue", ["fx-queue"] ); t( "Dash ID", "#fx-queue", ["fx-queue"] );
@ -202,7 +227,7 @@ test("multiple", function() {
}); });
test("child and adjacent", function() { test("child and adjacent", function() {
expect(27); expect(31);
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", "p >a", ["simon1","google","groups","mark","yahoo","simon"] ); t( "Child", "p >a", ["simon1","google","groups","mark","yahoo","simon"] );
@ -210,20 +235,25 @@ test("child and adjacent", function() {
t( "Child w/ Class", "p > a.blog", ["mark","simon"] ); t( "Child w/ Class", "p > a.blog", ["mark","simon"] );
t( "All Children", "code > *", ["anchor1","anchor2"] ); t( "All Children", "code > *", ["anchor1","anchor2"] );
t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] ); t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] );
t( "Adjacent", "#main a + a", ["groups"] ); t( "Adjacent", "a + a", ["groups"] );
t( "Adjacent", "#main a +a", ["groups"] ); t( "Adjacent", "a +a", ["groups"] );
t( "Adjacent", "#main a+ a", ["groups"] ); t( "Adjacent", "a+ a", ["groups"] );
t( "Adjacent", "#main a+a", ["groups"] ); t( "Adjacent", "a+a", ["groups"] );
t( "Adjacent", "p + p", ["ap","en","sap"] ); t( "Adjacent", "p + p", ["ap","en","sap"] );
t( "Adjacent", "p#firstp + p", ["ap"] ); t( "Adjacent", "p#firstp + p", ["ap"] );
t( "Adjacent", "p[lang=en] + p", ["sap"] ); t( "Adjacent", "p[lang=en] + p", ["sap"] );
t( "Adjacent", "a.GROUPS + code + a", ["mark"] ); t( "Adjacent", "a.GROUPS + code + a", ["mark"] );
t( "Comma, Child, and Adjacent", "#main a + a, code > a", ["groups","anchor1","anchor2"] ); t( "Comma, Child, and Adjacent", "a + a, code > a", ["groups","anchor1","anchor2"] );
t( "Element Preceded By", "p ~ div", ["foo", "moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] ); t( "Element Preceded By", "p ~ div", ["foo", "moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] );
t( "Element Preceded By", "#first ~ div", ["moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] ); t( "Element Preceded By", "#first ~ div", ["moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] );
t( "Element Preceded By", "#groups ~ a", ["mark"] ); t( "Element Preceded By", "#groups ~ a", ["mark"] );
t( "Element Preceded By", "#length ~ input", ["idTest"] ); t( "Element Preceded By", "#length ~ input", ["idTest"] );
t( "Element Preceded By", "#siblingfirst ~ em", ["siblingnext"] ); t( "Element Preceded By", "#siblingfirst ~ em", ["siblingnext"] );
same( jQuery("#siblingfirst").find("~ em").get(), q("siblingnext"), "Element Preceded By with a context." );
same( jQuery("#siblingfirst").find("+ em").get(), q("siblingnext"), "Element Directly Preceded By with a context." );
var a = jQuery("<div id='foo'></div><p id='bar'></p><p id='bar2'></p>");
same( jQuery("~ p", a[0]).get(), [a[1], a[2]], "Detached Element Directly Preceded By with a context." );
same( jQuery("+ p", a[0]).get(), [a[1]], "Detached Element Preceded By with a context." );
t( "Verify deep class selector", "div.blah > p > a", [] ); t( "Verify deep class selector", "div.blah > p > a", [] );
@ -237,7 +267,8 @@ test("child and adjacent", function() {
}); });
test("attributes", function() { test("attributes", function() {
expect(39); expect(41);
t( "Attribute Exists", "a[title]", ["google"] ); t( "Attribute Exists", "a[title]", ["google"] );
t( "Attribute Exists", "*[title]", ["google"] ); t( "Attribute Exists", "*[title]", ["google"] );
t( "Attribute Exists", "[title]", ["google"] ); t( "Attribute Exists", "[title]", ["google"] );
@ -294,10 +325,18 @@ test("attributes", function() {
t("Select options via :selected", "#select3 option:selected", ["option3b", "option3c"] ); t("Select options via :selected", "#select3 option:selected", ["option3b", "option3c"] );
t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] ); t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
// Make sure attribute value quoting works correctly. See: #6093
var attrbad = jQuery('<input type="hidden" value="2" name="foo.baz" id="attrbad1"/><input type="hidden" value="2" name="foo[baz]" id="attrbad2"/>').appendTo("body");
t("Find escaped attribute value", "input[name=foo\\.baz]", ["attrbad1"]);
t("Find escaped attribute value", "input[name=foo\\[baz\\]]", ["attrbad2"]);
attrbad.remove();
}); });
test("pseudo - child", function() { test("pseudo - child", function() {
expect(31); expect(38);
t( "First Child", "p:first-child", ["firstp","sndp"] ); t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Last Child", "p:last-child", ["sap"] ); t( "Last Child", "p:last-child", ["sap"] );
t( "Only Child", "#main a:only-child", ["simon1","anchor1","yahoo","anchor2","liveLink1","liveLink2"] ); t( "Only Child", "#main a:only-child", ["simon1","anchor1","yahoo","anchor2","liveLink1","liveLink2"] );
@ -306,6 +345,7 @@ test("pseudo - child", function() {
t( "First Child", "p:first-child", ["firstp","sndp"] ); t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Nth Child", "p:nth-child(1)", ["firstp","sndp"] ); t( "Nth Child", "p:nth-child(1)", ["firstp","sndp"] );
t( "Nth Child With Whitespace", "p:nth-child( 1 )", ["firstp","sndp"] );
t( "Not Nth Child", "p:not(:nth-child(1))", ["ap","en","sap","first"] ); t( "Not Nth Child", "p:not(:nth-child(1))", ["ap","en","sap","first"] );
// Verify that the child position isn't being cached improperly // Verify that the child position isn't being cached improperly
@ -322,15 +362,19 @@ test("pseudo - child", function() {
t( "Nth-child", "#main form#form > *:nth-child(2)", ["text1"] ); t( "Nth-child", "#main form#form > *:nth-child(2)", ["text1"] );
t( "Nth-child", "#main form#form > :nth-child(2)", ["text1"] ); t( "Nth-child", "#main form#form > :nth-child(2)", ["text1"] );
t( "Nth-child", "#form select:first option:nth-child(-1)", [] );
t( "Nth-child", "#form select:first option:nth-child(3)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(0n+3)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(0n+3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(1n+0)", ["option1a", "option1b", "option1c", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(1n+0)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(1n)", ["option1a", "option1b", "option1c", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(1n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(n)", ["option1a", "option1b", "option1c", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(+n)", ["option1a", "option1b", "option1c", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(even)", ["option1b", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(even)", ["option1b", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(odd)", ["option1a", "option1c"] ); t( "Nth-child", "#form select:first option:nth-child(odd)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(2n)", ["option1b", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(2n)", ["option1b", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(2n+1)", ["option1a", "option1c"] ); t( "Nth-child", "#form select:first option:nth-child(2n+1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(2n + 1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(+2n + 1)", ["option1a", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(3n)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n+1)", ["option1a", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(3n+1)", ["option1a", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(3n+2)", ["option1b"] ); t( "Nth-child", "#form select:first option:nth-child(3n+2)", ["option1b"] );
@ -339,7 +383,9 @@ test("pseudo - child", function() {
t( "Nth-child", "#form select:first option:nth-child(3n-2)", ["option1a", "option1d"] ); t( "Nth-child", "#form select:first option:nth-child(3n-2)", ["option1a", "option1d"] );
t( "Nth-child", "#form select:first option:nth-child(3n-3)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(3n-3)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(3n+0)", ["option1c"] ); t( "Nth-child", "#form select:first option:nth-child(3n+0)", ["option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-1n+3)", ["option1a", "option1b", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-n+3)", ["option1a", "option1b", "option1c"] ); t( "Nth-child", "#form select:first option:nth-child(-n+3)", ["option1a", "option1b", "option1c"] );
t( "Nth-child", "#form select:first option:nth-child(-1n + 3)", ["option1a", "option1b", "option1c"] );
}); });
test("pseudo - misc", function() { test("pseudo - misc", function() {

View file

@ -1,4 +1,4 @@
module("traversing"); module("traversing", { teardown: moduleTeardown });
test("find(String)", function() { test("find(String)", function() {
expect(5); expect(5);
@ -441,11 +441,12 @@ test("add(String|Element|Array|undefined)", function() {
test("add(String, Context)", function() { test("add(String, Context)", function() {
expect(6); expect(6);
equals( jQuery(document).add("#form").length, 2, "Make sure that using regular context document still works." ); deepEqual( jQuery( "#firstp" ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add selector to selector " );
equals( jQuery(document.body).add("#form").length, 2, "Using a body context." ); deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add gEBId to selector" );
equals( jQuery(document.body).add("#html").length, 1, "Using a body context." ); deepEqual( jQuery( document.getElementById("firstp") ).add( document.getElementById("ap") ).get(), q( "firstp", "ap" ), "Add gEBId to gEBId" );
equals( jQuery(document).add("#form", document).length, 2, "Use a passed in document context." ); var ctx = document.getElementById("firstp");
equals( jQuery(document).add("#form", document.body).length, 2, "Use a passed in body context." ); deepEqual( jQuery( "#firstp" ).add( "#ap", ctx ).get(), q( "firstp" ), "Add selector to selector " );
equals( jQuery(document).add("#html", document.body).length, 1, "Use a passed in body context." ); 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" );
}); });

View file

@ -1 +1 @@
1.4.5pre 1.5pre