Merge remote branch 'upstream/master'

This commit is contained in:
scottjehl 2011-01-19 12:32:57 -05:00
commit cb1f7eeac5
43 changed files with 4413 additions and 1097 deletions

View file

@ -7,11 +7,8 @@ BUILD_DIR = build
PREFIX = .
DIST_DIR = ${PREFIX}/dist
RHINO ?= java -jar ${BUILD_DIR}/js.jar
CLOSURE_COMPILER = ${BUILD_DIR}/google-compiler-20100917.jar
MINJAR ?= java -jar ${CLOSURE_COMPILER}
JS_ENGINE ?= `which node nodejs`
COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/support.js\
@ -93,17 +90,13 @@ ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
lint: ${JQ}
@@echo "Checking jQuery against JSLint..."
@@${RHINO} build/jslint-check.js
@@${JS_ENGINE} build/jslint-check.js
min: ${JQ_MIN}
${JQ_MIN}: ${JQ}
@@echo "Building" ${JQ_MIN}
@@head -15 ${JQ} > ${JQ_MIN}
@@${MINJAR} --js ${JQ} --warning_level QUIET --js_output_file ${JQ_MIN}.tmp
@@cat ${JQ_MIN}.tmp >> ${JQ_MIN}
@@rm -f ${JQ_MIN}.tmp
@@${COMPILER} ${JQ} > ${JQ_MIN}
clean:
@@echo "Removing Distribution directory:" ${DIST_DIR}

View file

@ -1,85 +1,64 @@
[jQuery](http://jquery.com/) - New Wave Javascript
================================
==================================================
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
-----------------------------
----------------------------
*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
the following to make all versions of jQuery:
Then, to get a complete, minified, jslinted version of jQuery, simply `cd` to the `jquery` directory and type
`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
----------------------------------
---------------------------------
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:
make PREFIX=/home/john/test/ [command]
With this example, the output files would be contained in `/home/john/test/dist/`
With this example, the output files would end up in `/home/jquery/test/dist/`.
**Rake only:** Define the DIST_DIR directory, for example:
rake DIST_DIR=/home/john/test/ [command]
With this example, the output files would be contained in `/home/john/test/`
Troubleshooting
---------------
*In both examples, `[command]` is optional.*
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.
**Ant only:** You cannot currently build to another directory when using Ant.
Questions?
----------
If you have any questions, please feel free to ask them on the Developing jQuery Core
forum, which can be found here:
[http://forum.jquery.com/developing-jquery-core](http://forum.jquery.com/developing-jquery-core)
If you have any questions, please feel free to ask on the
[Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.

162
Rakefile
View file

@ -1,162 +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
ajax/jsonp
ajax/script
ajax/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/, date).
gsub(/@VERSION/, version).
gsub(/.function..jQuery...\{/, '').
gsub(/\}...jQuery..;/, '')
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

132
build.xml
View file

@ -1,132 +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/ajax/jsonp.js" />
<fileset file="src/ajax/script.js" />
<fileset file="src/ajax/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}" 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 src = readFile("dist/jquery.js");
var JSLINT = require("./lib/jslint").JSLINT,
print = require("sys").print,
src = require("fs").readFileSync("dist/jquery.js", "utf8");
JSLINT(src, { evil: true, forin: true, maxerr: 100 });
@ -29,8 +29,8 @@ for ( var i = 0; i < e.length; i++ ) {
}
if ( found > 0 ) {
print( "\n" + found + " Error(s) found." );
print( "\n" + found + " Error(s) found.\n" );
} else {
print( "JSLint check passed." );
print( "JSLint check passed.\n" );
}

View file

@ -5495,6 +5495,10 @@ loop: for (;;) {
itself.edition = '2010-02-20';
if (typeof exports !== "undefined") {
exports.JSLINT = 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 + "*/\n";
}
}
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

@ -175,11 +175,12 @@ jQuery.extend({
timeout: 0,
data: null,
dataType: null,
dataTypes: null,
username: null,
password: null,
cache: null,
traditional: false,
headers: {},
crossDomain: null,
*/
xhr: function() {
return new window.XMLHttpRequest();
@ -306,30 +307,35 @@ jQuery.extend({
// (match is used internally)
getResponseHeader: function( key , match ) {
if ( state !== 2 ) {
return null;
}
if ( state === 2 ) {
if ( responseHeaders === undefined ) {
if ( responseHeaders === undefined ) {
responseHeaders = {};
responseHeaders = {};
if ( typeof responseHeadersString === "string" ) {
if ( typeof responseHeadersString === "string" ) {
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
}
}
}
match = responseHeaders[ key.toLowerCase() ];
} else {
match = null;
}
return responseHeaders[ key.toLowerCase() ];
return match;
},
// Cancel the request
abort: function( statusText ) {
if ( transport && state !== 2 ) {
if ( transport ) {
transport.abort( statusText || "abort" );
done( 0 , statusText );
}
done( 0 , statusText );
return this;
}
};
@ -347,6 +353,10 @@ jQuery.extend({
// State is "done" now
state = 2;
// Dereference transport for early garbage collection
// (no matter how long the jXHR transport will be used
transport = 0;
// Set readyState
jXHR.readyState = status ? 4 : 0;
@ -574,12 +584,6 @@ jQuery.extend({
// Remove hash character (#7531: and string promotion)
s.url = ( "" + s.url ).replace( rhash , "" );
// Uppercase the type
s.type = s.type.toUpperCase();
// Determine if request has content
s.hasContent = ! rnoContent.test( s.type );
// Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );
@ -595,88 +599,97 @@ jQuery.extend({
}
// Convert data if not already a string
if ( s.data && s.processData && typeof s.data != "string" ) {
if ( s.data && s.processData && typeof s.data !== "string" ) {
s.data = jQuery.param( s.data , s.traditional );
}
// Get transport
transport = jQuery.ajaxPrefilter( s , options ).ajaxTransport( s );
// 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" );
}
// If no transport, we auto-abort
if ( ! transport ) {
// More options handling for requests with no content
if ( ! s.hasContent ) {
done( 0 , "transport not found" );
jXHR = false;
// 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 {
// 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 : "");
}
// Install callbacks on deferreds
for ( i in { success:1, error:1, complete:1 } ) {
jXHR[ i ]( s[ i ] );
}
// Set the correct header, if data is being sent
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
requestHeaders[ "content-type" ] = s.contentType;
}
// Get transport
transport = jQuery.ajaxTransport( s );
// 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 ];
}
}
// If no transport, we auto-abort
if ( ! transport ) {
// 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" );
jXHR = false;
done( 0 , "notransport" );
} else {
// Set state as sending
state = 1;
jXHR.readyState = 1;
// Install callbacks on deferreds
for ( i in { success:1, error:1, complete:1 } ) {
jXHR[ i ]( s[ i ] );
}
state = jXHR.readyState = 1;
// Send global event
if ( s.global ) {

View file

@ -1,8 +1,7 @@
(function( jQuery ) {
var jsc = jQuery.now(),
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i,
rquery_jsonp = /\?/;
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i;
// Default jsonp settings
jQuery.ajaxSetup({
@ -11,73 +10,77 @@ jQuery.ajaxSetup({
return "jsonp" + jsc++;
}
// Normalize jsonp queries
// 1) put callback parameter in url or data
// 2) sneakily ensure transportDataType is always jsonp for jsonp requests
}).ajaxPrefilter("json jsonp", function(s, originalSettings) {
// Detect, normalize options and install callbacks for jsonp requests
// (dataIsString is used internally)
}).ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
dataIsString = ( typeof(s.data) === "string" );
if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonp ||
originalSettings.jsonpCallback ||
jsre.test(s.url) ||
typeof(s.data) === "string" && jsre.test(s.data) ) {
originalSettings.jsonp != null ||
s.jsonp !== false && ( jsre.test( s.url ) ||
dataIsString && jsre.test( s.data ) ) ) {
var jsonpCallback = s.jsonpCallback =
var responseContainer,
jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
url = s.url.replace(jsre, "$1" + jsonpCallback + "$2"),
data = s.url === url && typeof(s.data) === "string" ? s.data.replace(jsre, "$1" + jsonpCallback + "$2") : s.data;
previous = window[ jsonpCallback ],
url = s.url,
data = s.data,
replace = "$1" + jsonpCallback + "$2";
if ( url === s.url && data === s.data ) {
url += (rquery_jsonp.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
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;
s.dataTypes[ 0 ] = "jsonp";
}
// Bind transport to jsonp dataType
}).ajaxTransport("jsonp", function(s) {
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
// Put callback in place
var responseContainer,
jsonpCallback = s.jsonpCallback,
previous = window[ jsonpCallback ];
s.complete = [function() {
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
// Set callback back to previous value
window[ jsonpCallback ] = previous;
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] );
// 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){}
}
} else {
// else, more memory leak avoidance
try{ delete window[ jsonpCallback ]; } catch(e){}
}
}, s.complete ];
}, s.complete ];
// Sneakily ensure this will be handled as json
s.dataTypes[ 0 ] = "json";
// 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 ];
};
// 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 transport
return "script";
// Delegate to script
return "script";
}
});
})( jQuery );

View file

@ -15,18 +15,23 @@ jQuery.ajaxSetup({
"text script": jQuery.globalEval
}
// Bind script tag hack transport
}).ajaxTransport("script", function(s) {
// Handle cache's special case and global
}).ajaxPrefilter("script", function(s) {
// Handle cache special case
if ( s.cache === undefined ) {
s.cache = false;
}
// This transport only deals with cross domain get requests
if ( s.crossDomain && s.async && ( s.type === "GET" || ! s.data ) ) {
if ( s.crossDomain ) {
s.type = "GET";
s.global = false;
}
// Bind script tag hack transport
}).ajaxTransport("script", function(s) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
var script,
head = document.getElementsByTagName("head")[0] || document.documentElement;

View file

@ -133,11 +133,11 @@ jQuery.fn.extend({
} else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) {
// store className if set
jQuery.data( this, "__className__", this.className );
jQuery._data( this, "__className__", this.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
var jQuery = function( selector, context ) {
// 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
@ -19,12 +19,8 @@ var jQuery = function( selector, context ) {
// (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/,
// Check if a string has a non-whitespace character in it
rnotwhite = /\S/,
rwhite = /\s/,
// Used for trimming whitespace
trimLeft = /^\s+/,
@ -63,6 +59,9 @@ var jQuery = function( selector, context ) {
// The deferred used on DOM ready
readyList,
// Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
// The ready event handler
DOMContentLoaded,
@ -78,7 +77,8 @@ var jQuery = function( selector, context ) {
class2type = {};
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
@ -112,6 +112,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = (context ? context.ownerDocument || context : document);
// If a single string is passed in and it's a single tag
@ -171,7 +172,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return jQuery( context ).find( selector );
return this.constructor( context ).find( selector );
}
// HANDLE: $(function)
@ -222,7 +223,7 @@ jQuery.fn = jQuery.prototype = {
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
var ret = jQuery();
var ret = this.constructor();
if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems );
@ -287,7 +288,7 @@ jQuery.fn = jQuery.prototype = {
},
end: function() {
return this.prevObject || jQuery(null);
return this.prevObject || this.constructor(null);
},
// For internal use only.
@ -578,7 +579,7 @@ jQuery.extend({
script.type = "text/javascript";
if ( jQuery.support.scriptEval ) {
if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) );
} else {
script.text = data;
@ -896,9 +897,10 @@ jQuery.extend({
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred();
failDeferred = jQuery._Deferred(),
promise;
// Add errorDeferred methods and redefine cancel
// Add errorDeferred methods, then and promise
jQuery.extend( deferred , {
then: function( doneCallbacks , failCallbacks ) {
@ -911,14 +913,18 @@ jQuery.extend({
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
obj = obj || {};
jQuery.each( "then done fail isResolved isRejected".split( " " ) , function( _ , method ) {
obj[ method ] = deferred[ method ];
});
obj.promise = function() {
return obj;
};
// (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;
}
@ -940,10 +946,32 @@ jQuery.extend({
// Deferred helper
when: function( object ) {
object = object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred().resolve( object );
return object.promise();
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.fire( promise, resolveArray );
}
}).fail( function() {
deferred.fireReject( promise, arguments );
});
return !deferred.isRejected();
});
} else if ( deferred !== object ) {
deferred.resolve( object );
}
return promise;
},
// Use of jQuery.browser is frowned upon.
@ -960,6 +988,25 @@ jQuery.extend({
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: {}
});
@ -988,9 +1035,8 @@ if ( indexOf ) {
};
}
// Verify that \s matches non-breaking spaces
// (IE fails on this test)
if ( !rwhite.test( "\xA0" ) ) {
// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}

View file

@ -12,6 +12,9 @@ var ralpha = /alpha\([^)]*\)/i,
cssHeight = [ "Top", "Bottom" ],
curCSS,
getComputedStyle,
currentStyle,
fcamelCase = function( all, letter ) {
return letter.toUpperCase();
};
@ -169,6 +172,10 @@ jQuery.each(["height", "width"], function( i, name ) {
if ( val <= 0 ) {
val = curCSS( elem, name, name );
if ( val === "0px" && currentStyle ) {
val = currentStyle( elem, name, name );
}
if ( val != null ) {
// Should return "auto" instead of 0, use 0 for
// temporary backwards-compat
@ -234,7 +241,7 @@ if ( !jQuery.support.opacity ) {
}
if ( document.defaultView && document.defaultView.getComputedStyle ) {
curCSS = function( elem, newName, name ) {
getComputedStyle = function( elem, newName, name ) {
var ret, defaultView, computedStyle;
name = name.replace( rupper, "-$1" ).toLowerCase();
@ -252,10 +259,13 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
return ret;
};
} else if ( document.documentElement.currentStyle ) {
curCSS = function( elem, name ) {
var left, rsLeft,
}
if ( document.documentElement.currentStyle ) {
currentStyle = function( elem, name ) {
var left,
ret = elem.currentStyle && elem.currentStyle[ name ],
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
style = elem.style;
// From the awesome hack by Dean Edwards
@ -266,22 +276,27 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
// Remember the original values
left = style.left;
rsLeft = elem.runtimeStyle.left;
// Put in the new values to get a computed value out
elem.runtimeStyle.left = elem.currentStyle.left;
if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left;
}
style.left = name === "fontSize" ? "1em" : (ret || 0);
ret = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
elem.runtimeStyle.left = rsLeft;
if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft;
}
}
return ret === "" ? "auto" : ret;
};
}
curCSS = getComputedStyle || currentStyle;
function getWH( elem, name, extra ) {
var which = name === "width" ? cssWidth : cssHeight,
val = name === "width" ? elem.offsetWidth : elem.offsetHeight;

View file

@ -1,7 +1,6 @@
(function( jQuery ) {
var windowData = {},
rbrace = /^(?:\{.*\}|\[.*\])$/;
var rbrace = /^(?:\{.*\}|\[.*\])$/;
jQuery.extend({
cache: {},
@ -23,108 +22,168 @@ jQuery.extend({
},
hasData: function( elem ) {
if ( elem.nodeType ) {
elem = jQuery.cache[ elem[jQuery.expando] ];
}
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !jQuery.isEmptyObject(elem);
},
data: function( elem, name, data ) {
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
elem = elem == window ?
windowData :
elem;
var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
var isNode = elem.nodeType,
id = isNode ? elem[ jQuery.expando ] : null,
cache = jQuery.cache, thisCache;
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
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;
}
// Get the data from the object directly
if ( !isNode ) {
cache = elem;
// Compute a unique ID for the element
} else if ( !id ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else {
id = jQuery.expando;
}
}
// Avoid generating a new cache unless none exists and we
// want to manipulate it.
if ( typeof name === "object" ) {
if ( isNode ) {
cache[ id ] = jQuery.extend(cache[ id ], name);
} else {
jQuery.extend( cache, name );
}
} else if ( isNode && !cache[ id ] ) {
if ( !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 ) {
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 ) ) {
return;
}
elem = elem == window ?
windowData :
elem;
var internalKey = jQuery.expando, isNode = elem.nodeType,
var isNode = elem.nodeType,
id = isNode ? elem[ jQuery.expando ] : elem,
cache = jQuery.cache,
thisCache = isNode ? cache[ id ] : id;
// See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
// 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 ) {
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
if ( thisCache ) {
// Remove the section of cache data
delete thisCache[ name ];
// If we've removed all the data, remove the element's cache
if ( isNode && jQuery.isEmptyObject(thisCache) ) {
jQuery.removeData( elem );
}
}
// Otherwise, we want to remove all of the element's data
} else {
if ( isNode && jQuery.support.deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando );
// Completely remove the data cache
} else if ( isNode ) {
delete cache[ id ];
// Remove all fields from the object
} else {
for ( var n in elem ) {
delete elem[ n ];
// If there is no data left in the cache, we want to continue
// and let the cache object itself get destroyed
if ( !jQuery.isEmptyObject(thisCache) ) {
return;
}
}
}
// 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 {
cache[ id ] = null;
}
// 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 ) {
elem.removeAttribute( jQuery.expando );
} else {
elem[ jQuery.expando ] = null;
}
}
},
// For internal use only.
_data: function( elem, name, data ) {
return jQuery.data( elem, name, data, true );
},
// A method for determining if a DOM node can handle the data expando

10
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
// 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 = "";
}
@ -35,7 +35,7 @@ jQuery.fn.extend({
// in a stylesheet to whatever the default browser style is
// for such an element
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;
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++ ) {
var display = jQuery.css( this[i], "display" );
if ( display !== "none" && !jQuery.data( this[i], "olddisplay" ) ) {
jQuery.data( this[i], "olddisplay", display );
if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
jQuery._data( this[i], "olddisplay", display );
}
}

View file

@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/,
fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&");
},
focusCounts = { focusin: 0, focusout: 0 };
focusCounts = { focusin: 0, focusout: 0 },
eventKey = "events";
/*
* A number of helper functions used for managing events.
@ -50,7 +51,7 @@ jQuery.event = {
}
// 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
// banned noData elements
@ -58,10 +59,7 @@ jQuery.event = {
return;
}
// Use a key less likely to result in collisions for plain JS objects.
// Fixes bug #7150.
var eventKey = elem.nodeType ? "events" : "__events__",
events = elemData[ eventKey ],
var events = elemData[ eventKey ],
eventHandle = elemData.handle;
if ( typeof events === "function" ) {
@ -177,8 +175,7 @@ jQuery.event = {
}
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
eventKey = elem.nodeType ? "events" : "__events__",
elemData = jQuery.data( elem ),
elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) {
@ -290,10 +287,10 @@ jQuery.event = {
delete elemData.handle;
if ( typeof elemData === "function" ) {
jQuery.removeData( elem, eventKey );
jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem );
jQuery.removeData( elem, undefined, true );
}
}
},
@ -325,9 +322,16 @@ jQuery.event = {
// Only trigger if we've ever bound an event for it
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() {
if ( this.events && this.events[type] ) {
jQuery.event.trigger( event, data, this.handle.elem );
// internalKey variable is just used to make it easier to find
// 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 +357,8 @@ jQuery.event = {
// Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ?
jQuery.data( elem, "handle" ) :
(jQuery.data( elem, "__events__" ) || {}).handle;
jQuery._data( elem, "handle" ) :
(jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) {
handle.apply( elem, data );
@ -432,7 +436,7 @@ jQuery.event = {
event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery.data(this, this.nodeType ? "events" : "__events__");
events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) {
events = events.events;
@ -603,7 +607,7 @@ jQuery.Event = function( src ) {
// 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 ||
this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
// Event type
@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) {
return;
}
data = jQuery.data( elem, "_change_data" );
data = jQuery._data( elem, "_change_data" );
val = getVal(elem);
// the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery.data( elem, "_change_data", val );
jQuery._data( elem, "_change_data", val );
}
if ( data === undefined || val === data ) {
@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) {
// information
beforeactivate: function( e ) {
var elem = e.target;
jQuery.data( elem, "_change_data", getVal(elem) );
jQuery._data( elem, "_change_data", getVal(elem) );
}
},
@ -986,8 +990,8 @@ jQuery.fn.extend({
return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop
event.preventDefault();
@ -1075,7 +1079,7 @@ function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [],
selectors = [],
events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) {
events = events.events;

View file

@ -346,7 +346,7 @@ jQuery.fn.extend({
table ?
root(this[i], first) :
this[i],
i > 0 || results.cacheable || this.length > 1 ?
i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
jQuery(fragment).clone(true)[0] :
fragment
);
@ -381,17 +381,24 @@ function cloneCopyEvent(orig, ret) {
throw "Cloned data mismatch";
}
var oldData = jQuery.data( orig[nodeIndex] ),
curData = jQuery.data( this, oldData ),
events = oldData && oldData.events;
var internalKey = jQuery.expando,
oldData = jQuery.data( orig[nodeIndex] ),
curData = jQuery.data( this, oldData );
if ( events ) {
delete curData.handle;
curData.events = {};
// 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);
for ( var type in events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
if ( events ) {
delete curData.handle;
curData.events = {};
for ( var type in events ) {
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
}
}
}
}
@ -608,8 +615,7 @@ jQuery.extend({
},
cleanData: function( elems ) {
var data, id, cache = jQuery.cache,
special = jQuery.event.special,
var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
@ -620,13 +626,14 @@ jQuery.extend({
id = elem[ jQuery.expando ];
if ( id ) {
data = cache[ id ];
data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) {
for ( var type in data.events ) {
if ( special[ type ] ) {
jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
} else {
jQuery.removeEvent( elem, type, data.handle );
}

View file

@ -30,7 +30,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
// Make sure we're not dealing with a disconnected DOM node
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,

View file

@ -7,7 +7,7 @@ jQuery.extend({
}
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
if ( !data ) {
@ -15,7 +15,7 @@ jQuery.extend({
}
if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data) );
q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
q.push( data );
@ -46,6 +46,10 @@ jQuery.extend({
jQuery.dequeue(elem, type);
});
}
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
}
}
});

View file

@ -4,10 +4,7 @@
jQuery.support = {};
var root = document.documentElement,
script = document.createElement("script"),
div = document.createElement("div"),
id = "script" + jQuery.now();
var div = document.createElement("div");
div.style.display = "none";
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
@ -64,7 +61,7 @@
deleteExpando: true,
optDisabled: false,
checkClone: false,
scriptEval: false,
_scriptEval: null,
noCloneEvent: true,
boxModel: null,
inlineBlockNeedsLayout: false,
@ -77,32 +74,46 @@
select.disabled = true;
jQuery.support.optDisabled = !opt.disabled;
script.type = "text/javascript";
try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e) {}
jQuery.support.scriptEval = function() {
if ( jQuery.support._scriptEval === null ) {
var root = document.documentElement,
script = document.createElement("script"),
id = "script" + jQuery.now();
root.insertBefore( script, root.firstChild );
script.type = "text/javascript";
try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
} catch(e) {}
// Make sure that the execution of code works by injecting a script
// tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) {
jQuery.support.scriptEval = true;
delete window[ id ];
}
root.insertBefore( script, root.firstChild );
// Make sure that the execution of code works by injecting a script
// tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) {
jQuery.support._scriptEval = true;
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
// Fails in Internet Explorer
try {
delete script.test;
delete div.test;
} catch(e) {
jQuery.support.deleteExpando = false;
}
root.removeChild( script );
if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() {
// Cloning a node shouldn't copy over any
@ -177,6 +188,14 @@
var el = document.createElement("div");
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);
if ( !isSupported ) {
el.setAttribute(eventName, "return;");
@ -191,6 +210,6 @@
jQuery.support.changeBubbles = eventSupported("change");
// release memory in IE
root = script = div = all = a = null;
div = all = a = null;
})();
})( jQuery );

View file

@ -6,7 +6,14 @@ var runtil = /Until$/,
rmultiselector = /,/,
isSimple = /^.[^:#\[\.,]*$/,
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({
find: function( selector ) {
@ -196,7 +203,12 @@ jQuery.each({
}
}, function( name, fn ) {
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 ) ) {
selector = until;
@ -206,13 +218,13 @@ jQuery.each({
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 ) ) {
ret = ret.reverse();
}
return this.pushStack( ret, name, slice.call(arguments).join(",") );
return this.pushStack( ret, name, args.join(",") );
};
});

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

@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) {
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

@ -264,7 +264,7 @@ Z</textarea>
<div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div>
<div id="fadetogglein" class='chain test'>fadeToggleIn<div>fadeToggleIn</div></div>
<div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div>
<div id="fadetoggleout" class='chain test out'>fadeToggleOut<div>fadeToggleOut</div></div>
<div id="fadeto" class='chain test'>fadeTo<div>fadeTo</div></div>
</div>

View file

@ -1,4 +1,4 @@
module("ajax");
module("ajax", { teardown: moduleTeardown });
// Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax
@ -1114,286 +1114,249 @@ test("jQuery.getScript(String, Function) - no callback", function() {
});
});
test("jQuery.ajax() - JSONP, Local", function() {
expect(14);
jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
var count = 0;
function plus(){ if ( ++count == 14 ) start(); }
test("jQuery.ajax() - JSONP, " + label, function() {
expect(17);
stop();
var count = 0;
function plus(){ if ( ++count == 17 ) start(); }
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, no callback)" );
plus();
}
});
stop();
jQuery.ajax({
url: "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: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, no callback)" );
plus();
}
});
jQuery.ajax({
url: "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: "data/jsonp.php?callback=?",
dataType: "jsonp",
crossDomain: crossDomain,
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: "data/jsonp.php?callback=??",
dataType: "jsonp",
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({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
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: "data/jsonp.php",
dataType: "jsonp",
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?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({
url: "data/jsonp.php/??",
dataType: "jsonp",
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",
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/???json=1",
dataType: "jsonp",
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,
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",
dataType: "jsonp",
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/???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",
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();
}
});
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",
jsonpCallback: "jsonpResults",
success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, custom callback name)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
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();
}
});
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (POST, no callback)" );
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data obj callback)" );
plus();
}
});
};
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
data: "callback=?",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (POST, data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (POST, data callback)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
jsonpCallback: "jsonpResults",
success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, custom callback name)" );
plus();
}
});
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
jsonp: "callback",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (POST, data obj callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (POST, data obj callback)" );
plus();
}
});
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (POST, no callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data obj callback)" );
plus();
}
});
//#7578
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
beforeSend: function(){
strictEqual( this.cache, false, "cache must be false on JSON request" );
plus();
return false;
}
});
});
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
data: "callback=?",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (POST, data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (POST, data callback)" );
plus();
}
});
test("jQuery.ajax() - JSONP - Custom JSONP Callback", function() {
expect(1);
stop();
jQuery.ajax({
type: "POST",
url: "data/jsonp.php",
jsonp: "callback",
dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){
ok( data.data, "JSON results returned (POST, data obj callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (POST, data obj callback)" );
plus();
}
});
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
start();
};
//#7578
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
crossDomain: crossDomain,
beforeSend: function(){
strictEqual( this.cache, false, "cache must be false on JSON request" );
plus();
return false;
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
jsonpCallback: "jsonpResults"
});
});
jQuery.ajax({
url: "data/jsonp.php?callback=XXX",
dataType: "jsonp",
jsonp: false,
jsonpCallback: "XXX",
crossDomain: crossDomain,
beforeSend: function() {
ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ) ,
"The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
plus();
},
success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
plus();
}
});
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",
success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, no callback)" );
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();
}
});
});
@ -1865,25 +1828,19 @@ test("jQuery ajax - failing cross-domain", function() {
var i = 2;
if ( jQuery.ajax({
jQuery.ajax({
url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); }
}) === false ) {
ok( true , "no transport" );
if ( ! --i ) start();
}
});
if ( jQuery.ajax({
jQuery.ajax({
url: 'http://www.google.com',
success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); }
}) === false ) {
ok( true , "no transport" );
if ( ! --i ) start();
}
});
});
@ -1937,7 +1894,7 @@ test( "jQuery.ajax - statusCode" , function() {
404: function() {
ok( ! isSuccess , name );
}
}
};
}
jQuery.each( {

View file

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

View file

@ -1,4 +1,4 @@
module("core");
module("core", { teardown: moduleTeardown });
test("Basic requirements", function() {
expect(7);
@ -21,7 +21,7 @@ test("jQuery()", function() {
equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
var obj = jQuery("div")
var obj = jQuery("div");
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
@ -85,10 +85,16 @@ test("jQuery()", function() {
exec = true;
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() {
@ -1003,7 +1009,7 @@ test("jQuery._Deferred()", function() {
test("jQuery.Deferred()", function() {
expect( 4 );
expect( 10 );
jQuery.Deferred( function( defer ) {
strictEqual( this , defer , "Defer passed as this & first argument" );
@ -1023,11 +1029,35 @@ test("jQuery.Deferred()", function() {
}, 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( 21 );
expect( 23 );
// Some other objects
jQuery.each( {
@ -1050,6 +1080,10 @@ test("jQuery.when()", function() {
} );
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++ ) {
@ -1063,3 +1097,106 @@ test("jQuery.when()", function() {
});
}
});
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() {
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>');
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(){
expect(6);
expect(1);
equals("expando" in jQuery, true, "jQuery is exposing the expando");
});
var obj = {};
equals( jQuery.data(obj), obj, "jQuery.data(obj) returns the object");
equals( jQuery.expando in obj, false, "jQuery.data(obj) did not add an expando to the object" );
function dataTests (elem) {
// expect(32)
obj = {};
jQuery.data(obj, 'test');
equals( jQuery.expando in obj, false, "jQuery.data(obj,key) did not add an expando to the object" );
function getCacheLength() {
var cacheLength = 0;
for (var i in jQuery.cache) {
++cacheLength;
}
obj = {};
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." );
return cacheLength;
}
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() {
@ -37,68 +174,11 @@ test("jQuery.acceptData", function() {
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("jQuery.hasData", function() {
expect(6);
function testData(obj) {
equals( jQuery.hasData(obj), false, "No data exists" );
jQuery.data( obj, "foo", "bar" );
equals( jQuery.hasData(obj), true, "Data exists" );
jQuery.removeData( obj, "foo" );
equals( jQuery.hasData(obj), false, "Data was removed" );
}
testData(document.createElement('div'));
testData({});
});
test(".data()", function() {
expect(5);
var div = jQuery("#foo");
strictEqual( div.data("foo"), undefined, "Make sure that missing result is undefined" );
div.data("test", "success");
same( div.data(), {test: "success"}, "data() get the entire data object" );
strictEqual( div.data("foo"), undefined, "Make sure that missing result is still undefined" );
@ -107,7 +187,7 @@ test(".data()", function() {
equals( nodiv.data(), null, "data() on empty set returns null" );
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() {
@ -194,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('emptyString','').data('emptyString'), '', "Empty strings 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
$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() {
@ -218,6 +301,8 @@ test("data-* attributes", function() {
div.data("attr", "internal").attr("data-attr", "external");
equals( div.data("attr"), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" );
div.remove();
child.appendTo('#main');
equals( child.data("myobj"), "old data", "Value accessed from data-* attribute");
@ -229,6 +314,8 @@ test("data-* attributes", function() {
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++ ) {
ok( obj[ check[i] ], "Make sure data- property exists when calling data-." );
ok( obj2[ check[i] ], "Make sure data- property exists when calling data-." );
@ -323,13 +410,17 @@ test(".data(Object)", function() {
var obj = {test:"unset"},
jqobj = jQuery(obj);
jqobj.data("test", "unset");
jqobj.data({ "test": "in", "test2": "in2" });
equals( obj.test, "in", "Verify setting an object on an object extends the object" );
equals( obj.test2, "in2", "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, undefined, "Verify setting an object on an object does not extend the object" );
// manually clean up detached elements
div.remove();
});
test("jQuery.removeData", function() {
expect(7);
expect(6);
var div = jQuery("#foo")[0];
jQuery.data(div, "test", "testing");
jQuery.removeData(div, "test");
@ -342,10 +433,9 @@ test("jQuery.removeData", function() {
var obj = {};
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");
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.removeData( window, "BAD" );
@ -371,4 +461,4 @@ test(".removeData()", function() {
div.removeData("test.foo");
equals( div.data("test.foo"), undefined, "Make sure data is intact" );
});
});

View file

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

35
test/unit/effects.js vendored
View file

@ -1,4 +1,4 @@
module("effects");
module("effects", { teardown: moduleTeardown });
test("sanity check", function() {
expect(1);
@ -14,7 +14,7 @@ test("show()", function() {
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" );
@ -403,13 +403,16 @@ test("animate duration 0", function() {
$elem.hide(0, function(){
ok(true, "Hide callback with no duration");
});
// manually clean up detached elements
$elem.remove();
});
test("animate hyphenated properties", function(){
expect(1);
stop();
jQuery("#nothiddendiv")
jQuery("#foo")
.css("font-size", 10)
.animate({"font-size": 20}, 200, function(){
equals( this.style.fontSize, "20px", "The font-size property was animated." );
@ -433,7 +436,7 @@ test("stop()", function() {
expect(3);
stop();
var $foo = jQuery("#nothiddendiv");
var $foo = jQuery("#foo");
var w = 0;
$foo.hide().width(200).width();
@ -446,6 +449,8 @@ test("stop()", function() {
nw = $foo.width();
notEqual( nw, w, "Stop didn't reset the animation " + nw + "px " + w + "px");
setTimeout(function(){
$foo.removeData();
$foo.removeData(undefined, true);
equals( nw, $foo.width(), "The animation didn't continue" );
start();
}, 100);
@ -456,7 +461,7 @@ test("stop() - several in queue", function() {
expect(3);
stop();
var $foo = jQuery("#nothiddendivchild");
var $foo = jQuery("#foo");
var w = 0;
$foo.hide().width(200).width();
@ -481,7 +486,7 @@ test("stop(clearQueue)", function() {
expect(4);
stop();
var $foo = jQuery("#nothiddendiv");
var $foo = jQuery("#foo");
var w = 0;
$foo.hide().width(200).width();
@ -508,7 +513,7 @@ test("stop(clearQueue, gotoEnd)", function() {
expect(1);
stop();
var $foo = jQuery("#nothiddendivchild");
var $foo = jQuery("#foo");
var w = 0;
$foo.hide().width(200).width();
@ -536,7 +541,7 @@ test("stop(clearQueue, gotoEnd)", function() {
test("toggle()", function() {
expect(6);
var x = jQuery("#nothiddendiv");
var x = jQuery("#foo");
ok( x.is(":visible"), "is visible" );
x.toggle();
ok( x.is(":hidden"), "is hidden" );
@ -737,6 +742,9 @@ jQuery.each( {
}
}
// manually remove generated element
jQuery(this).remove();
start();
});
});
@ -763,6 +771,10 @@ jQuery.checkState = function(){
var cur = self.style[ c ] || jQuery.css(self, c);
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();
}
@ -829,9 +841,6 @@ jQuery.makeTest = function( text ){
jQuery("<h4></h4>")
.text( text )
.appendTo("#fx-tests")
.click(function(){
jQuery(this).next().toggle();
})
.after( elem );
return elem;
@ -895,7 +904,7 @@ test("hide hidden elements (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" );
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();
equals( div.css("display"), "block", "Show a double-hidden element" );
@ -910,7 +919,7 @@ test("hide hidden elements, with animation (bug #7141)", function() {
var div = jQuery("<div style='display:none'></div>").appendTo("#main");
equals( div.css("display"), "none", "Element is hidden by default" );
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 () {
equals( div.css("display"), "block", "Show a double-hidden element" );
start();

View file

@ -1,4 +1,4 @@
module("event");
module("event", { teardown: moduleTeardown });
test("null or undefined handler", function() {
expect(2);
@ -28,7 +28,7 @@ test("bind(), with data", function() {
};
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() {
@ -39,7 +39,7 @@ test("click(), with data", function() {
};
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() {
@ -80,6 +80,9 @@ test("bind(), multiple events at once and namespaces", function() {
cur = "focusin";
div.trigger("focusin.a");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("click mouseover", obj, function(e) {
equals( e.type, cur, "Verify right multi event was fired." );
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";
div.trigger("mouseover");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").bind("focusin.a focusout.b", function(e) {
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";
div.trigger("focusout.b");
// manually clean up detached elements
div.remove();
});
test("bind(), namespace with special add", function() {
@ -295,15 +304,15 @@ test("live/delegate immediate propagation", function() {
$p.undelegate( "click" );
});
test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
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 );
var e = document.createEvent( 'MouseEvents' );
e.initEvent( "click", true, true );
$jq[0].dispatchEvent(e);
}
else if ( $jq[0].click ) {
@ -314,7 +323,15 @@ test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
e.preventDefault();
});
$main.delegate("#foo", "click", function(e) {
equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
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" );
@ -505,7 +522,7 @@ test("bind(), with different this object", function() {
.bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
.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() {
@ -525,6 +542,9 @@ test("bind(name, false), unbind(name, false)", function() {
jQuery("#ap").unbind("click", false);
jQuery("#ap").trigger("click");
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() {
@ -547,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." );
equals( obj.events, undefined, "Events object on plain objects is not events" );
equals( typeof events, "function", "'events' expando is a function on plain objects." );
@ -567,7 +587,9 @@ test("bind()/trigger()/unbind() on plain object", function() {
// Make sure it doesn't complain when no events are found
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() {
@ -661,13 +683,18 @@ test("hover()", function() {
test("trigger() shortcuts", function() {
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');
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" );
return false;
}).click();
// manually clean up detached elements
elem.remove();
jQuery("#check1").click(function() {
ok( true, "click event handler for checkbox gets fired twice, see #815" );
}).click();
@ -686,9 +713,12 @@ test("trigger() shortcuts", function() {
jQuery('#simon1').click();
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)");
}).load();
// manually clean up detached elements
elem.remove();
});
test("trigger() bubbling", function() {
@ -723,6 +753,10 @@ test("trigger() bubbling", function() {
equals( body, 2, "ap bubble" );
equals( main, 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() {
@ -766,7 +800,7 @@ test("trigger(type, [data], [fn])", function() {
pass = true;
try {
jQuery('table:first').bind('test:test', function(){}).trigger('test:test');
jQuery('#main table:first').bind('test:test', function(){}).trigger('test:test');
} catch (e) {
pass = false;
}
@ -947,9 +981,12 @@ test("toggle(Function, Function, ...)", function() {
equals( turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2");
$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");
// manually clean up detached elements
$div.remove();
// Test Multi-Toggles
var a = [], b = [];
$div = jQuery("<div/>");
@ -965,6 +1002,9 @@ test("toggle(Function, Function, ...)", function() {
$div.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." );
// manually clean up detached elements
$div.remove();
});
test(".live()/.die()", function() {
@ -1065,7 +1105,7 @@ test(".live()/.die()", function() {
equals( clicked, 2, "live with a 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
jQuery("#foo", container).die("click");
@ -1275,6 +1315,9 @@ test("live with multiple events", function(){
div.trigger("submit");
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(){
@ -1578,7 +1621,7 @@ test(".delegate()/.undelegate()", function() {
equals( clicked, 2, "delegate with a 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
jQuery("#main").undelegate("#foo", "click");
@ -1907,7 +1950,7 @@ test("window resize", function() {
ok( true, "Resize event fired." );
}).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() {

View file

@ -1,4 +1,4 @@
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"); };
@ -115,12 +115,19 @@ var testWrap = function(val) {
// Wrap an element with a jQuery set and event
result = jQuery("<div></div>").click(function(){
ok(true, "Event triggered.");
// Remove handlers on detached elements
result.unbind();
jQuery(this).unbind();
});
j = jQuery("<span/>").wrap(result);
equals( j[0].parentNode.nodeName.toLowerCase(), "div", "Wrapping works." );
j.parent().trigger("click");
// clean up attached elements
QUnit.reset();
}
test("wrap(String|Element)", function() {
@ -408,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");
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');
// manually clean up detached elements
clone.remove();
}
element = jQuery("<a class='test6997'></a>").click(function () {
@ -886,20 +897,36 @@ test("clone()", function() {
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[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.trigger("click");
// manually clean up detached elements
div.remove();
div = jQuery("<div/>").append([ document.createElement("table"), document.createElement("table") ]);
div.find("table").click(function(){
ok( true, "Bound event still exists." );
});
div = div.clone(true);
equals( div.length, 1, "One element cloned" );
equals( div[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div.find("table:last").trigger("click");
clone = div.clone(true);
equals( clone.length, 1, "One element cloned" );
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
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
// classid instantiation it is the only kind that IE has trouble with,
@ -920,12 +947,16 @@ test("clone()", function() {
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div = jQuery("<div/>").data({ a: true });
var div2 = div.clone(true);
equals( div2.data("a"), true, "Data cloned." );
div2.data("a", false);
equals( div2.data("a"), false, "Ensure cloned element data object was correctly modified" );
clone = div.clone(true);
equals( clone.data("a"), 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");
form.action = "/test/";
var div = document.createElement("div");
@ -1155,15 +1186,21 @@ var testRemove = function(method) {
jQuery("#nonnodes").contents()[method]();
equals( jQuery("#nonnodes").contents().length, 0, "Check node,textnode,comment remove works" );
// manually clean up detached elements
if (method === "detach") {
first.remove();
}
QUnit.reset();
var count = 0;
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 );
cleanUp.detach();
// manually clean up detached elements
cleanUp.remove();
};
test("remove()", function() {

View file

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

View file

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

View file

@ -1,4 +1,4 @@
module("selector");
module("selector", { teardown: moduleTeardown });
test("element", function() {
expect(21);
@ -58,13 +58,14 @@ if ( location.protocol != "file:" ) {
}
test("broken", function() {
expect(8);
expect(19);
function broken(name, selector) {
try {
jQuery(selector);
ok( false, name + ": " + selector );
} catch(e){
ok( typeof e === "string" && e.indexOf("Syntax error") >= 0,
ok( typeof e === "string" && e.indexOf("Syntax error") >= 0,
name + ": " + selector );
}
}
@ -77,10 +78,31 @@ test("broken", function() {
broken( "Broken Selector", "<>", [] );
broken( "Broken Selector", "{}", [] );
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() {
expect(28);
expect(29);
t( "ID Selector", "#body", ["body"] );
t( "ID Selector w/ Element", "body#body", ["body"] );
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" );
//#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( "Dash ID", "#fx-queue", ["fx-queue"] );
@ -150,7 +175,7 @@ test("class", function() {
t( "Child escaped Class", "form > .test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
var div = document.createElement("div");
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
same( jQuery(".e", div).get(), [ div.firstChild ], "Finding a second class." );
div.lastChild.className = "e";
@ -202,7 +227,7 @@ test("multiple", 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"] );
@ -210,20 +235,25 @@ test("child and adjacent", function() {
t( "Child w/ Class", "p > a.blog", ["mark","simon"] );
t( "All Children", "code > *", ["anchor1","anchor2"] );
t( "All Grandchildren", "p > * > *", ["anchor1","anchor2"] );
t( "Adjacent", "#main a + a", ["groups"] );
t( "Adjacent", "#main a +a", ["groups"] );
t( "Adjacent", "#main a+ a", ["groups"] );
t( "Adjacent", "#main a+a", ["groups"] );
t( "Adjacent", "a + a", ["groups"] );
t( "Adjacent", "a +a", ["groups"] );
t( "Adjacent", "a+ a", ["groups"] );
t( "Adjacent", "a+a", ["groups"] );
t( "Adjacent", "p + p", ["ap","en","sap"] );
t( "Adjacent", "p#firstp + p", ["ap"] );
t( "Adjacent", "p[lang=en] + p", ["sap"] );
t( "Adjacent", "a.GROUPS + code + a", ["mark"] );
t( "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", "#first ~ div", ["moretests","tabindex-tests", "liveHandlerOrder", "siblingTest"] );
t( "Element Preceded By", "#groups ~ a", ["mark"] );
t( "Element Preceded By", "#length ~ input", ["idTest"] );
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", [] );
@ -237,7 +267,8 @@ test("child and adjacent", function() {
});
test("attributes", function() {
expect(39);
expect(41);
t( "Attribute Exists", "a[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( "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() {
expect(31);
expect(38);
t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Last Child", "p:last-child", ["sap"] );
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( "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"] );
// 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", "#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(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)", ["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(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+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+1)", ["option1a", "option1d"] );
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-3)", ["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(-1n + 3)", ["option1a", "option1b", "option1c"] );
});
test("pseudo - misc", function() {

View file

@ -1,4 +1,4 @@
module("traversing");
module("traversing", { teardown: moduleTeardown });
test("find(String)", function() {
expect(5);

View file

@ -1 +1 @@
1.4.5pre
1.5pre