Commit cb1f7eea authored by scottjehl's avatar scottjehl

Merge remote branch 'upstream/master'

parents 73d060b5 265cf0ef
...@@ -7,11 +7,8 @@ BUILD_DIR = build ...@@ -7,11 +7,8 @@ BUILD_DIR = build
PREFIX = . PREFIX = .
DIST_DIR = ${PREFIX}/dist DIST_DIR = ${PREFIX}/dist
RHINO ?= java -jar ${BUILD_DIR}/js.jar JS_ENGINE ?= `which node nodejs`
COMPILER = ${JS_ENGINE} ${BUILD_DIR}/uglify.js --unsafe
CLOSURE_COMPILER = ${BUILD_DIR}/google-compiler-20100917.jar
MINJAR ?= java -jar ${CLOSURE_COMPILER}
BASE_FILES = ${SRC_DIR}/core.js\ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/support.js\ ${SRC_DIR}/support.js\
...@@ -93,17 +90,13 @@ ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js ...@@ -93,17 +90,13 @@ ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
lint: ${JQ} lint: ${JQ}
@@echo "Checking jQuery against JSLint..." @@echo "Checking jQuery against JSLint..."
@@${RHINO} build/jslint-check.js @@${JS_ENGINE} build/jslint-check.js
min: ${JQ_MIN} min: ${JQ_MIN}
${JQ_MIN}: ${JQ} ${JQ_MIN}: ${JQ}
@@echo "Building" ${JQ_MIN} @@echo "Building" ${JQ_MIN}
@@${COMPILER} ${JQ} > ${JQ_MIN}
@@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
clean: clean:
@@echo "Removing Distribution directory:" ${DIST_DIR} @@echo "Removing Distribution directory:" ${DIST_DIR}
......
[jQuery](http://jquery.com/) - New Wave Javascript [jQuery](http://jquery.com/) - New Wave Javascript
================================ ==================================================
What you need to build your own jQuery What you need to build your own jQuery
--------------------------------------- --------------------------------------
* Make sure that you have Java installed (if you want to build a minified version of jQuery).
If not, [go to this page](http://java.sun.com/javase/downloads/index.jsp) and download "Java Runtime Environment (JRE) 5.0"
Build Options In order to build jQuery, you need to have GNU make 3.8 or later, Node.js 0.2 or later, and git 1.7 or later.
-------------- (Earlier versions might work OK, but are not tested.)
You now have **three** options for building jQuery: Windows users have two options:
* **`make`**: If you have access to common UNIX commands (like `make`, `mkdir`, `rm`, `cat`, and `echo`) then simply type `make` to build all the components. 1. Install [msysgit](https://code.google.com/p/msysgit/) (Full installer for official Git),
[GNU make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm), and a
[binary version of Node.js](http://node-js.prcn.co.cc/). Make sure all three packages are installed to the same
location (by default, this is C:\Program Files\Git).
2. Install [Cygwin](http://cygwin.com/) (make sure you install the git, make, and which packages), then either follow
the [Node.js build instructions](https://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29) or install
the [binary version of Node.js](http://node-js.prcn.co.cc/).
* **`rake`**: If you have Ruby Rake installed (on either Windows or UNIX/Linux), you can simply type `rake` to build all the components. Mac OS users should install Xcode (comes on your Mac OS install DVD, or downloadable from
[Apple's Xcode site](http://developer.apple.com/technologies/xcode.html)) and
[http://mxcl.github.com/homebrew/](Homebrew). Once Homebrew is installed, run `brew install git` to install git,
and `brew install node` to install Node.js.
* **`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]. 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.
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.*
In the main directory of the distribution (the one that this file is in), type
the following to make all versions of jQuery:
make
*Here are the individual items that are buildable from the Makefile:*
make init
Pull in all the external dependencies (QUnit, Sizzle) for the project.
make jquery
The standard, uncompressed, jQuery code. How to build your own jQuery
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. First, clone a copy of the main jQuery git repo by running `git clone git://github.com/jquery/jquery.git`.
make selector 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`.
Builds the selector library for jQuery from Sizzle. The built version of jQuery will be put in the `dist/` subdirectory.
Makes: `./src/selector.js`
Finally, you can remove all the built files using the command: To remove all built files, run `make clean`.
make clean
Building to a different directory Building to a different directory
---------------------------------- ---------------------------------
If you want to build jQuery to a directory that is different from the default location, you can...
**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/` 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]`
**Rake only:** Define the DIST_DIR directory, for example: With this example, the output files would end up in `/home/jquery/test/dist/`.
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? Questions?
---------- ----------
If you have any questions, please feel free to ask them on the Developing jQuery Core If you have any questions, please feel free to ask on the
forum, which can be found here: [Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.
[http://forum.jquery.com/developing-jquery-core](http://forum.jquery.com/developing-jquery-core)
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
<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>
load("build/jslint.js"); var JSLINT = require("./lib/jslint").JSLINT,
print = require("sys").print,
var src = readFile("dist/jquery.js"); src = require("fs").readFileSync("dist/jquery.js", "utf8");
JSLINT(src, { evil: true, forin: true, maxerr: 100 }); JSLINT(src, { evil: true, forin: true, maxerr: 100 });
...@@ -29,8 +29,8 @@ for ( var i = 0; i < e.length; i++ ) { ...@@ -29,8 +29,8 @@ for ( var i = 0; i < e.length; i++ ) {
} }
if ( found > 0 ) { if ( found > 0 ) {
print( "\n" + found + " Error(s) found." ); print( "\n" + found + " Error(s) found.\n" );
} else { } else {
print( "JSLint check passed." ); print( "JSLint check passed.\n" );
} }
...@@ -5495,6 +5495,10 @@ loop: for (;;) { ...@@ -5495,6 +5495,10 @@ loop: for (;;) {
itself.edition = '2010-02-20'; itself.edition = '2010-02-20';
if (typeof exports !== "undefined") {
exports.JSLINT = itself;
}
return itself; return itself;
}()); }());
This diff is collapsed.
This diff is collapsed.
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;
#! /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."); }
};
...@@ -175,11 +175,12 @@ jQuery.extend({ ...@@ -175,11 +175,12 @@ jQuery.extend({
timeout: 0, timeout: 0,
data: null, data: null,
dataType: null, dataType: null,
dataTypes: null,
username: null, username: null,
password: null, password: null,
cache: null, cache: null,
traditional: false, traditional: false,
headers: {},
crossDomain: null,
*/ */
xhr: function() { xhr: function() {
return new window.XMLHttpRequest(); return new window.XMLHttpRequest();
...@@ -306,9 +307,7 @@ jQuery.extend({ ...@@ -306,9 +307,7 @@ jQuery.extend({
// (match is used internally) // (match is used internally)
getResponseHeader: function( key , match ) { getResponseHeader: function( key , match ) {
if ( state !== 2 ) { if ( state === 2 ) {
return null;
}
if ( responseHeaders === undefined ) { if ( responseHeaders === undefined ) {
...@@ -321,15 +320,22 @@ jQuery.extend({ ...@@ -321,15 +320,22 @@ jQuery.extend({
} }
} }
} }
return responseHeaders[ key.toLowerCase() ]; match = responseHeaders[ key.toLowerCase() ];
} else {
match = null;
}
return match;
}, },
// Cancel the request // Cancel the request
abort: function( statusText ) { abort: function( statusText ) {
if ( transport && state !== 2 ) { if ( transport ) {
transport.abort( statusText || "abort" ); transport.abort( statusText || "abort" );
done( 0 , statusText );
} }
done( 0 , statusText );
return this; return this;
} }
}; };
...@@ -347,6 +353,10 @@ jQuery.extend({ ...@@ -347,6 +353,10 @@ jQuery.extend({
// State is "done" now // State is "done" now
state = 2; state = 2;
// Dereference transport for early garbage collection
// (no matter how long the jXHR transport will be used
transport = 0;
// Set readyState // Set readyState
jXHR.readyState = status ? 4 : 0; jXHR.readyState = status ? 4 : 0;
...@@ -574,12 +584,6 @@ jQuery.extend({ ...@@ -574,12 +584,6 @@ jQuery.extend({
// Remove hash character (#7531: and string promotion) // Remove hash character (#7531: and string promotion)
s.url = ( "" + s.url ).replace( rhash , "" ); 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 // Extract dataTypes list
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ ); s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );
...@@ -595,26 +599,24 @@ jQuery.extend({ ...@@ -595,26 +599,24 @@ jQuery.extend({
} }
// Convert data if not already a string // 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 ); s.data = jQuery.param( s.data , s.traditional );
} }
// Get transport // Apply prefilters
transport = jQuery.ajaxPrefilter( s , options ).ajaxTransport( s ); 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 // Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) { if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" ); jQuery.event.trigger( "ajaxStart" );
} }
// If no transport, we auto-abort
if ( ! transport ) {
done( 0 , "transport not found" );
jXHR = false;
} else {
// More options handling for requests with no content // More options handling for requests with no content
if ( ! s.hasContent ) { if ( ! s.hasContent ) {
...@@ -665,19 +667,30 @@ jQuery.extend({ ...@@ -665,19 +667,30 @@ jQuery.extend({
// Abort if not done already // Abort if not done already
done( 0 , "abort" ); done( 0 , "abort" );
// Return false
jXHR = false; jXHR = false;
} else { } else {
// Set state as sending
state = 1;
jXHR.readyState = 1;
// Install callbacks on deferreds // Install callbacks on deferreds
for ( i in { success:1, error:1, complete:1 } ) { for ( i in { success:1, error:1, complete:1 } ) {
jXHR[ i ]( s[ i ] ); jXHR[ i ]( s[ i ] );
} }
// Get transport
transport = jQuery.ajaxTransport( s );
// If no transport, we auto-abort
if ( ! transport ) {
done( 0 , "notransport" );
} else {
// Set state as sending
state = jXHR.readyState = 1;
// Send global event // Send global event
if ( s.global ) { if ( s.global ) {
globalEventContext.trigger( "ajaxSend" , [ jXHR , s ] ); globalEventContext.trigger( "ajaxSend" , [ jXHR , s ] );
......
(function( jQuery ) { (function( jQuery ) {
var jsc = jQuery.now(), var jsc = jQuery.now(),
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i, jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i;
rquery_jsonp = /\?/;
// Default jsonp settings // Default jsonp settings
jQuery.ajaxSetup({ jQuery.ajaxSetup({
...@@ -11,38 +10,41 @@ jQuery.ajaxSetup({ ...@@ -11,38 +10,41 @@ jQuery.ajaxSetup({
return "jsonp" + jsc++; return "jsonp" + jsc++;
} }
// Normalize jsonp queries // Detect, normalize options and install callbacks for jsonp requests
// 1) put callback parameter in url or data // (dataIsString is used internally)
// 2) sneakily ensure transportDataType is always jsonp for jsonp requests }).ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
}).ajaxPrefilter("json jsonp", function(s, originalSettings) {
dataIsString = ( typeof(s.data) === "string" );
if ( s.dataTypes[ 0 ] === "jsonp" || if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonp ||
originalSettings.jsonpCallback || originalSettings.jsonpCallback ||
jsre.test(s.url) || originalSettings.jsonp != null ||
typeof(s.data) === "string" && jsre.test(s.data) ) { 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, jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
url = s.url.replace(jsre, "$1" + jsonpCallback + "$2"), previous = window[ jsonpCallback ],
data = s.url === url && typeof(s.data) === "string" ? s.data.replace(jsre, "$1" + jsonpCallback + "$2") : s.data; url = s.url,
data = s.data,
if ( url === s.url && data === s.data ) { replace = "$1" + jsonpCallback + "$2";
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.url = url;
s.data = data; s.data = data;
s.dataTypes[ 0 ] = "jsonp";
}
// Bind transport to jsonp dataType
}).ajaxTransport("jsonp", function(s) {
// Put callback in place
var responseContainer,
jsonpCallback = s.jsonpCallback,
previous = window[ jsonpCallback ];
window [ jsonpCallback ] = function( response ) { window [ jsonpCallback ] = function( response ) {
responseContainer = [response]; responseContainer = [response];
...@@ -65,9 +67,6 @@ jQuery.ajaxSetup({ ...@@ -65,9 +67,6 @@ jQuery.ajaxSetup({
}, 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 // Use data converter to retrieve json after script execution
s.converters["script json"] = function() { s.converters["script json"] = function() {
if ( ! responseContainer ) { if ( ! responseContainer ) {
...@@ -76,8 +75,12 @@ jQuery.ajaxSetup({ ...@@ -76,8 +75,12 @@ jQuery.ajaxSetup({
return responseContainer[ 0 ]; return responseContainer[ 0 ];
}; };
// Delegate to script transport // force json dataType
s.dataTypes[ 0 ] = "json";
// Delegate to script
return "script"; return "script";
}
}); });
})( jQuery ); })( jQuery );
...@@ -15,18 +15,23 @@ jQuery.ajaxSetup({ ...@@ -15,18 +15,23 @@ jQuery.ajaxSetup({
"text script": jQuery.globalEval "text script": jQuery.globalEval
} }
// Bind script tag hack transport // Handle cache's special case and global
}).ajaxTransport("script", function(s) { }).ajaxPrefilter("script", function(s) {
// Handle cache special case
if ( s.cache === undefined ) { if ( s.cache === undefined ) {
s.cache = false; s.cache = false;
} }
// This transport only deals with cross domain get requests if ( s.crossDomain ) {
if ( s.crossDomain && s.async && ( s.type === "GET" || ! s.data ) ) { s.type = "GET";
s.global = false; s.global = false;
}
// Bind script tag hack transport
}).ajaxTransport("script", function(s) {
// This transport only deals with cross domain requests
if ( s.crossDomain ) {
var script, var script,
head = document.getElementsByTagName("head")[0] || document.documentElement; head = document.getElementsByTagName("head")[0] || document.documentElement;
......
...@@ -133,11 +133,11 @@ jQuery.fn.extend({ ...@@ -133,11 +133,11 @@ jQuery.fn.extend({
} else if ( type === "undefined" || type === "boolean" ) { } else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) { if ( this.className ) {
// store className if set // store className if set
jQuery.data( this, "__className__", this.className ); jQuery._data( this, "__className__", this.className );
} }
// toggle whole className // toggle whole className
this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
} }
}); });
}, },
......
...@@ -3,7 +3,7 @@ var jQuery = (function() { ...@@ -3,7 +3,7 @@ var jQuery = (function() {
// Define a local copy of jQuery // Define a local copy of jQuery
var jQuery = function( selector, context ) { var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced' // The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context ); return new jQuery.fn.init( selector, context, rootjQuery );
}, },
// Map over jQuery in case of overwrite // Map over jQuery in case of overwrite
...@@ -19,12 +19,8 @@ var jQuery = function( selector, context ) { ...@@ -19,12 +19,8 @@ var jQuery = function( selector, context ) {
// (both of which we optimize for) // (both of which we optimize for)
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/,
// Check if a string has a non-whitespace character in it // Check if a string has a non-whitespace character in it
rnotwhite = /\S/, rnotwhite = /\S/,
rwhite = /\s/,
// Used for trimming whitespace // Used for trimming whitespace
trimLeft = /^\s+/, trimLeft = /^\s+/,
...@@ -63,6 +59,9 @@ var jQuery = function( selector, context ) { ...@@ -63,6 +59,9 @@ var jQuery = function( selector, context ) {
// The deferred used on DOM ready // The deferred used on DOM ready
readyList, readyList,
// Promise methods
promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
// The ready event handler // The ready event handler
DOMContentLoaded, DOMContentLoaded,
...@@ -78,7 +77,8 @@ var jQuery = function( selector, context ) { ...@@ -78,7 +77,8 @@ var jQuery = function( selector, context ) {
class2type = {}; class2type = {};
jQuery.fn = jQuery.prototype = { jQuery.fn = jQuery.prototype = {
init: function( selector, context ) { constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc; var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined) // Handle $(""), $(null), or $(undefined)
...@@ -112,6 +112,7 @@ jQuery.fn = jQuery.prototype = { ...@@ -112,6 +112,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(html) -> $(array) // HANDLE: $(html) -> $(array)
if ( match[1] ) { if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = (context ? context.ownerDocument || context : document); doc = (context ? context.ownerDocument || context : document);
// If a single string is passed in and it's a single tag // If a single string is passed in and it's a single tag
...@@ -171,7 +172,7 @@ jQuery.fn = jQuery.prototype = { ...@@ -171,7 +172,7 @@ jQuery.fn = jQuery.prototype = {
// HANDLE: $(expr, context) // HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr) // (which is just equivalent to: $(context).find(expr)
} else { } else {
return jQuery( context ).find( selector ); return this.constructor( context ).find( selector );
} }
// HANDLE: $(function) // HANDLE: $(function)
...@@ -222,7 +223,7 @@ jQuery.fn = jQuery.prototype = { ...@@ -222,7 +223,7 @@ jQuery.fn = jQuery.prototype = {
// (returning the new matched element set) // (returning the new matched element set)
pushStack: function( elems, name, selector ) { pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set // Build a new jQuery matched element set
var ret = jQuery(); var ret = this.constructor();
if ( jQuery.isArray( elems ) ) { if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems ); push.apply( ret, elems );
...@@ -287,7 +288,7 @@ jQuery.fn = jQuery.prototype = { ...@@ -287,7 +288,7 @@ jQuery.fn = jQuery.prototype = {
}, },
end: function() { end: function() {
return this.prevObject || jQuery(null); return this.prevObject || this.constructor(null);
}, },
// For internal use only. // For internal use only.
...@@ -578,7 +579,7 @@ jQuery.extend({ ...@@ -578,7 +579,7 @@ jQuery.extend({
script.type = "text/javascript"; script.type = "text/javascript";
if ( jQuery.support.scriptEval ) { if ( jQuery.support.scriptEval() ) {
script.appendChild( document.createTextNode( data ) ); script.appendChild( document.createTextNode( data ) );
} else { } else {
script.text = data; script.text = data;
...@@ -896,9 +897,10 @@ jQuery.extend({ ...@@ -896,9 +897,10 @@ jQuery.extend({
Deferred: function( func ) { Deferred: function( func ) {
var deferred = jQuery._Deferred(), 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 , { jQuery.extend( deferred , {
then: function( doneCallbacks , failCallbacks ) { then: function( doneCallbacks , failCallbacks ) {
...@@ -911,14 +913,18 @@ jQuery.extend({ ...@@ -911,14 +913,18 @@ jQuery.extend({
isRejected: failDeferred.isResolved, isRejected: failDeferred.isResolved,
// Get a promise for this deferred // Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object // If obj is provided, the promise aspect is added to the object
promise: function( obj ) { // (i is used internally)
obj = obj || {}; promise: function( obj , i ) {
jQuery.each( "then done fail isResolved isRejected".split( " " ) , function( _ , method ) { if ( obj == null ) {
obj[ method ] = deferred[ method ]; if ( promise ) {
}); return promise;
obj.promise = function() { }
return obj; promise = obj = {};
}; }
i = promiseMethods.length;
while( i-- ) {
obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
}
return obj; return obj;
} }
...@@ -940,10 +946,32 @@ jQuery.extend({ ...@@ -940,10 +946,32 @@ jQuery.extend({
// Deferred helper // Deferred helper
when: function( object ) { when: function( object ) {
object = object && jQuery.isFunction( object.promise ) ? var args = arguments,
length = args.length,
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
object : object :
jQuery.Deferred().resolve( object ); jQuery.Deferred(),
return object.promise(); 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. // Use of jQuery.browser is frowned upon.
...@@ -960,6 +988,25 @@ jQuery.extend({ ...@@ -960,6 +988,25 @@ jQuery.extend({
return { browser: match[1] || "", version: match[2] || "0" }; return { browser: match[1] || "", version: match[2] || "0" };
}, },
subclass: function(){
function jQuerySubclass( selector, context ) {
return new jQuerySubclass.fn.init( selector, context );
}
jQuerySubclass.superclass = this;
jQuerySubclass.fn = jQuerySubclass.prototype = this();
jQuerySubclass.fn.constructor = jQuerySubclass;
jQuerySubclass.subclass = this.subclass;
jQuerySubclass.fn.init = function init( selector, context ) {
if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){
context = jQuerySubclass(context);
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
};
jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
var rootjQuerySubclass = jQuerySubclass(document);
return jQuerySubclass;
},
browser: {} browser: {}
}); });
...@@ -988,9 +1035,8 @@ if ( indexOf ) { ...@@ -988,9 +1035,8 @@ if ( indexOf ) {
}; };
} }
// Verify that \s matches non-breaking spaces // IE doesn't match non-breaking spaces with \s
// (IE fails on this test) if ( rnotwhite.test( "\xA0" ) ) {
if ( !rwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/; trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/; trimRight = /[\s\xA0]+$/;
} }
......
...@@ -12,6 +12,9 @@ var ralpha = /alpha\([^)]*\)/i, ...@@ -12,6 +12,9 @@ var ralpha = /alpha\([^)]*\)/i,
cssHeight = [ "Top", "Bottom" ], cssHeight = [ "Top", "Bottom" ],
curCSS, curCSS,
getComputedStyle,
currentStyle,
fcamelCase = function( all, letter ) { fcamelCase = function( all, letter ) {
return letter.toUpperCase(); return letter.toUpperCase();
}; };
...@@ -169,6 +172,10 @@ jQuery.each(["height", "width"], function( i, name ) { ...@@ -169,6 +172,10 @@ jQuery.each(["height", "width"], function( i, name ) {
if ( val <= 0 ) { if ( val <= 0 ) {
val = curCSS( elem, name, name ); val = curCSS( elem, name, name );
if ( val === "0px" && currentStyle ) {
val = currentStyle( elem, name, name );
}
if ( val != null ) { if ( val != null ) {
// Should return "auto" instead of 0, use 0 for // Should return "auto" instead of 0, use 0 for
// temporary backwards-compat // temporary backwards-compat
...@@ -234,7 +241,7 @@ if ( !jQuery.support.opacity ) { ...@@ -234,7 +241,7 @@ if ( !jQuery.support.opacity ) {
} }
if ( document.defaultView && document.defaultView.getComputedStyle ) { if ( document.defaultView && document.defaultView.getComputedStyle ) {
curCSS = function( elem, newName, name ) { getComputedStyle = function( elem, newName, name ) {
var ret, defaultView, computedStyle; var ret, defaultView, computedStyle;
name = name.replace( rupper, "-$1" ).toLowerCase(); name = name.replace( rupper, "-$1" ).toLowerCase();
...@@ -252,10 +259,13 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) { ...@@ -252,10 +259,13 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
return ret; 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 ], ret = elem.currentStyle && elem.currentStyle[ name ],
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
style = elem.style; style = elem.style;
// From the awesome hack by Dean Edwards // From the awesome hack by Dean Edwards
...@@ -266,22 +276,27 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) { ...@@ -266,22 +276,27 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
// Remember the original values // Remember the original values
left = style.left; left = style.left;
rsLeft = elem.runtimeStyle.left;
// Put in the new values to get a computed value out // Put in the new values to get a computed value out
if ( rsLeft ) {
elem.runtimeStyle.left = elem.currentStyle.left; elem.runtimeStyle.left = elem.currentStyle.left;
}
style.left = name === "fontSize" ? "1em" : (ret || 0); style.left = name === "fontSize" ? "1em" : (ret || 0);
ret = style.pixelLeft + "px"; ret = style.pixelLeft + "px";
// Revert the changed values // Revert the changed values
style.left = left; style.left = left;
if ( rsLeft ) {
elem.runtimeStyle.left = rsLeft; elem.runtimeStyle.left = rsLeft;
} }
}
return ret === "" ? "auto" : ret; return ret === "" ? "auto" : ret;
}; };
} }
curCSS = getComputedStyle || currentStyle;
function getWH( elem, name, extra ) { function getWH( elem, name, extra ) {
var which = name === "width" ? cssWidth : cssHeight, var which = name === "width" ? cssWidth : cssHeight,
val = name === "width" ? elem.offsetWidth : elem.offsetHeight; val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
......
(function( jQuery ) { (function( jQuery ) {
var windowData = {}, var rbrace = /^(?:\{.*\}|\[.*\])$/;
rbrace = /^(?:\{.*\}|\[.*\])$/;
jQuery.extend({ jQuery.extend({
cache: {}, cache: {},
...@@ -23,110 +22,170 @@ jQuery.extend({ ...@@ -23,110 +22,170 @@ jQuery.extend({
}, },
hasData: function( elem ) { hasData: function( elem ) {
if ( elem.nodeType ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
elem = jQuery.cache[ elem[jQuery.expando] ];
}
return !!elem && !jQuery.isEmptyObject(elem); return !!elem && !jQuery.isEmptyObject(elem);
}, },
data: function( elem, name, data ) { data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
windowData :
elem; // We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
var isNode = elem.nodeType, // Only defining an ID for JS objects if its cache already exists allows
id = isNode ? elem[ jQuery.expando ] : null, // the code to shortcut on the same path as a DOM node with no cache
cache = jQuery.cache, thisCache; id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
if ( isNode && !id && typeof name === "string" && data === undefined ) { // Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
return; return;
} }
// Get the data from the object directly if ( !id ) {
if ( !isNode ) { // Only DOM nodes need a new unique ID for each element since their data
cache = elem; // ends up in the global cache
if ( isNode ) {
// Compute a unique ID for the element
} else if ( !id ) {
elem[ jQuery.expando ] = id = ++jQuery.uuid; elem[ jQuery.expando ] = id = ++jQuery.uuid;
} else {
id = jQuery.expando;
}
} }
// Avoid generating a new cache unless none exists and we if ( !cache[ id ] ) {
// want to manipulate it. cache[ id ] = {};
if ( typeof name === "object" ) { }
if ( isNode ) {
cache[ id ] = jQuery.extend(cache[ id ], name);
// 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 { } else {
jQuery.extend( cache, name ); cache[ id ] = jQuery.extend(cache[ id ], name);
}
} }
} else if ( isNode && !cache[ id ] ) { thisCache = cache[ id ];
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 = isNode ? cache[ id ] : cache; thisCache = thisCache[ internalKey ];
}
// Prevent overriding the named cache with undefined values
if ( data !== undefined ) { if ( data !== undefined ) {
thisCache[ name ] = data; thisCache[ name ] = data;
} }
return typeof name === "string" ? thisCache[ name ] : thisCache; // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
// not attempt to inspect the internal events object using jQuery.data, as this
// internal data object is undocumented and subject to change.
if ( name === "events" && !thisCache[name] ) {
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
}
return getByName ? thisCache[ name ] : thisCache;
}, },
removeData: function( elem, name ) { removeData: function( elem, name, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;
} }
elem = elem == window ? var internalKey = jQuery.expando, isNode = elem.nodeType,
windowData :
elem; // See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
var isNode = elem.nodeType, // See jQuery.data for more information
id = isNode ? elem[ jQuery.expando ] : elem, id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
cache = jQuery.cache,
thisCache = isNode ? cache[ id ] : id; // If there is already no cache entry for this object, there is no
// purpose in continuing
if ( !cache[ id ] ) {
return;
}
// If we want to remove a specific section of the element's data
if ( name ) { if ( name ) {
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
if ( thisCache ) { if ( thisCache ) {
// Remove the section of cache data
delete thisCache[ name ]; delete thisCache[ name ];
// If we've removed all the data, remove the element's cache // If there is no data left in the cache, we want to continue
if ( isNode && jQuery.isEmptyObject(thisCache) ) { // and let the cache object itself get destroyed
jQuery.removeData( elem ); if ( !jQuery.isEmptyObject(thisCache) ) {
return;
}
} }
} }
// Otherwise, we want to remove all of the element's data // See jQuery.data for more information
} else { if ( pvt ) {
if ( isNode && jQuery.support.deleteExpando ) { delete cache[ id ][ internalKey ];
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) { // Don't destroy the parent cache unless the internal data object
elem.removeAttribute( jQuery.expando ); // had been the only thing left in it
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
return;
}
}
// Completely remove the data cache var internalCache = cache[ id ][ internalKey ];
} else if ( isNode ) {
delete cache[ id ];
// Remove all fields from the object // Browsers that fail expando deletion also refuse to delete expandos on
// the window, but it will allow it on all other JS objects; other browsers
// don't care
if ( jQuery.support.deleteExpando || cache != window ) {
delete cache[ id ];
} else { } else {
for ( var n in elem ) { cache[ id ] = null;
delete elem[ n ];
} }
// 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 // A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) { acceptData: function( elem ) {
if ( elem.nodeName ) { if ( elem.nodeName ) {
......
...@@ -27,7 +27,7 @@ jQuery.fn.extend({ ...@@ -27,7 +27,7 @@ jQuery.fn.extend({
// Reset the inline display of this element to learn if it is // Reset the inline display of this element to learn if it is
// being hidden by cascaded rules or not // being hidden by cascaded rules or not
if ( !jQuery.data(elem, "olddisplay") && display === "none" ) { if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
display = elem.style.display = ""; display = elem.style.display = "";
} }
...@@ -35,7 +35,7 @@ jQuery.fn.extend({ ...@@ -35,7 +35,7 @@ jQuery.fn.extend({
// in a stylesheet to whatever the default browser style is // in a stylesheet to whatever the default browser style is
// for such an element // for such an element
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName)); jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
} }
} }
...@@ -46,7 +46,7 @@ jQuery.fn.extend({ ...@@ -46,7 +46,7 @@ jQuery.fn.extend({
display = elem.style.display; display = elem.style.display;
if ( display === "" || display === "none" ) { if ( display === "" || display === "none" ) {
elem.style.display = jQuery.data(elem, "olddisplay") || ""; elem.style.display = jQuery._data(elem, "olddisplay") || "";
} }
} }
...@@ -62,8 +62,8 @@ jQuery.fn.extend({ ...@@ -62,8 +62,8 @@ jQuery.fn.extend({
for ( var i = 0, j = this.length; i < j; i++ ) { for ( var i = 0, j = this.length; i < j; i++ ) {
var display = jQuery.css( this[i], "display" ); var display = jQuery.css( this[i], "display" );
if ( display !== "none" && !jQuery.data( this[i], "olddisplay" ) ) { if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
jQuery.data( this[i], "olddisplay", display ); jQuery._data( this[i], "olddisplay", display );
} }
} }
......
...@@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/, ...@@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/,
fcleanup = function( nm ) { fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&"); 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. * A number of helper functions used for managing events.
...@@ -50,7 +51,7 @@ jQuery.event = { ...@@ -50,7 +51,7 @@ jQuery.event = {
} }
// Init the element's event structure // Init the element's event structure
var elemData = jQuery.data( elem ); var elemData = jQuery._data( elem );
// If no elemData is found then we must be trying to bind to one of the // If no elemData is found then we must be trying to bind to one of the
// banned noData elements // banned noData elements
...@@ -58,10 +59,7 @@ jQuery.event = { ...@@ -58,10 +59,7 @@ jQuery.event = {
return; return;
} }
// Use a key less likely to result in collisions for plain JS objects. var events = elemData[ eventKey ],
// Fixes bug #7150.
var eventKey = elem.nodeType ? "events" : "__events__",
events = elemData[ eventKey ],
eventHandle = elemData.handle; eventHandle = elemData.handle;
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
...@@ -177,8 +175,7 @@ jQuery.event = { ...@@ -177,8 +175,7 @@ jQuery.event = {
} }
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
eventKey = elem.nodeType ? "events" : "__events__", elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
elemData = jQuery.data( elem ),
events = elemData && elemData[ eventKey ]; events = elemData && elemData[ eventKey ];
if ( !elemData || !events ) { if ( !elemData || !events ) {
...@@ -290,10 +287,10 @@ jQuery.event = { ...@@ -290,10 +287,10 @@ jQuery.event = {
delete elemData.handle; delete elemData.handle;
if ( typeof elemData === "function" ) { if ( typeof elemData === "function" ) {
jQuery.removeData( elem, eventKey ); jQuery.removeData( elem, eventKey, true );
} else if ( jQuery.isEmptyObject( elemData ) ) { } else if ( jQuery.isEmptyObject( elemData ) ) {
jQuery.removeData( elem ); jQuery.removeData( elem, undefined, true );
} }
} }
}, },
...@@ -325,9 +322,16 @@ jQuery.event = { ...@@ -325,9 +322,16 @@ jQuery.event = {
// Only trigger if we've ever bound an event for it // Only trigger if we've ever bound an event for it
if ( jQuery.event.global[ type ] ) { if ( jQuery.event.global[ type ] ) {
// XXX This code smells terrible. event.js should not be directly
// inspecting the data cache
jQuery.each( jQuery.cache, function() { jQuery.each( jQuery.cache, function() {
if ( this.events && this.events[type] ) { // internalKey variable is just used to make it easier to find
jQuery.event.trigger( event, data, this.handle.elem ); // and potentially change this stuff later; currently it just
// points to jQuery.expando
var internalKey = jQuery.expando,
internalCache = this[ internalKey ];
if ( internalCache && internalCache.events && internalCache.events[type] ) {
jQuery.event.trigger( event, data, internalCache.handle.elem );
} }
}); });
} }
...@@ -353,8 +357,8 @@ jQuery.event = { ...@@ -353,8 +357,8 @@ jQuery.event = {
// Trigger the event, it is assumed that "handle" is a function // Trigger the event, it is assumed that "handle" is a function
var handle = elem.nodeType ? var handle = elem.nodeType ?
jQuery.data( elem, "handle" ) : jQuery._data( elem, "handle" ) :
(jQuery.data( elem, "__events__" ) || {}).handle; (jQuery._data( elem, eventKey ) || {}).handle;
if ( handle ) { if ( handle ) {
handle.apply( elem, data ); handle.apply( elem, data );
...@@ -432,7 +436,7 @@ jQuery.event = { ...@@ -432,7 +436,7 @@ jQuery.event = {
event.namespace = event.namespace || namespace_sort.join("."); event.namespace = event.namespace || namespace_sort.join(".");
events = jQuery.data(this, this.nodeType ? "events" : "__events__"); events = jQuery._data(this, eventKey);
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
...@@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) { ...@@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) {
return; return;
} }
data = jQuery.data( elem, "_change_data" ); data = jQuery._data( elem, "_change_data" );
val = getVal(elem); val = getVal(elem);
// the current data will be also retrieved by beforeactivate // the current data will be also retrieved by beforeactivate
if ( e.type !== "focusout" || elem.type !== "radio" ) { if ( e.type !== "focusout" || elem.type !== "radio" ) {
jQuery.data( elem, "_change_data", val ); jQuery._data( elem, "_change_data", val );
} }
if ( data === undefined || val === data ) { if ( data === undefined || val === data ) {
...@@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) { ...@@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) {
// information // information
beforeactivate: function( e ) { beforeactivate: function( e ) {
var elem = e.target; var elem = e.target;
jQuery.data( elem, "_change_data", getVal(elem) ); jQuery._data( elem, "_change_data", getVal(elem) );
} }
}, },
...@@ -986,8 +990,8 @@ jQuery.fn.extend({ ...@@ -986,8 +990,8 @@ jQuery.fn.extend({
return this.click( jQuery.proxy( fn, function( event ) { return this.click( jQuery.proxy( fn, function( event ) {
// Figure out which function to execute // Figure out which function to execute
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
// Make sure that clicks stop // Make sure that clicks stop
event.preventDefault(); event.preventDefault();
...@@ -1075,7 +1079,7 @@ function liveHandler( event ) { ...@@ -1075,7 +1079,7 @@ function liveHandler( event ) {
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
elems = [], elems = [],
selectors = [], selectors = [],
events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); events = jQuery._data( this, eventKey );
if ( typeof events === "function" ) { if ( typeof events === "function" ) {
events = events.events; events = events.events;
......
...@@ -346,7 +346,7 @@ jQuery.fn.extend({ ...@@ -346,7 +346,7 @@ jQuery.fn.extend({
table ? table ?
root(this[i], first) : root(this[i], first) :
this[i], this[i],
i > 0 || results.cacheable || this.length > 1 ? i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
jQuery(fragment).clone(true)[0] : jQuery(fragment).clone(true)[0] :
fragment fragment
); );
...@@ -381,9 +381,15 @@ function cloneCopyEvent(orig, ret) { ...@@ -381,9 +381,15 @@ function cloneCopyEvent(orig, ret) {
throw "Cloned data mismatch"; throw "Cloned data mismatch";
} }
var oldData = jQuery.data( orig[nodeIndex] ), var internalKey = jQuery.expando,
curData = jQuery.data( this, oldData ), oldData = jQuery.data( orig[nodeIndex] ),
events = oldData && oldData.events; curData = jQuery.data( this, oldData );
// Switch to use the internal data object, if it exists, for the next
// stage of data copying
if ( (oldData = oldData[ internalKey ]) ) {
var events = oldData.events;
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
if ( events ) { if ( events ) {
delete curData.handle; delete curData.handle;
...@@ -395,6 +401,7 @@ function cloneCopyEvent(orig, ret) { ...@@ -395,6 +401,7 @@ function cloneCopyEvent(orig, ret) {
} }
} }
} }
}
}); });
} }
...@@ -608,8 +615,7 @@ jQuery.extend({ ...@@ -608,8 +615,7 @@ jQuery.extend({
}, },
cleanData: function( elems ) { cleanData: function( elems ) {
var data, id, cache = jQuery.cache, var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando; deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
...@@ -620,13 +626,14 @@ jQuery.extend({ ...@@ -620,13 +626,14 @@ jQuery.extend({
id = elem[ jQuery.expando ]; id = elem[ jQuery.expando ];
if ( id ) { if ( id ) {
data = cache[ id ]; data = cache[ id ] && cache[ id ][ internalKey ];
if ( data && data.events ) { if ( data && data.events ) {
for ( var type in data.events ) { for ( var type in data.events ) {
if ( special[ type ] ) { if ( special[ type ] ) {
jQuery.event.remove( elem, type ); jQuery.event.remove( elem, type );
// This is a shortcut to avoid jQuery.event.remove's overhead
} else { } else {
jQuery.removeEvent( elem, type, data.handle ); jQuery.removeEvent( elem, type, data.handle );
} }
......
...@@ -30,7 +30,7 @@ if ( "getBoundingClientRect" in document.documentElement ) { ...@@ -30,7 +30,7 @@ if ( "getBoundingClientRect" in document.documentElement ) {
// Make sure we're not dealing with a disconnected DOM node // Make sure we're not dealing with a disconnected DOM node
if ( !box || !jQuery.contains( docElem, elem ) ) { if ( !box || !jQuery.contains( docElem, elem ) ) {
return box || { top: 0, left: 0 }; return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
} }
var body = doc.body, var body = doc.body,
......
...@@ -7,7 +7,7 @@ jQuery.extend({ ...@@ -7,7 +7,7 @@ jQuery.extend({
} }
type = (type || "fx") + "queue"; type = (type || "fx") + "queue";
var q = jQuery.data( elem, type ); var q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup // Speed up dequeue by getting out quickly if this is just a lookup
if ( !data ) { if ( !data ) {
...@@ -15,7 +15,7 @@ jQuery.extend({ ...@@ -15,7 +15,7 @@ jQuery.extend({
} }
if ( !q || jQuery.isArray(data) ) { if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data) ); q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else { } else {
q.push( data ); q.push( data );
...@@ -46,6 +46,10 @@ jQuery.extend({ ...@@ -46,6 +46,10 @@ jQuery.extend({
jQuery.dequeue(elem, type); jQuery.dequeue(elem, type);
}); });
} }
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue", true );
}
} }
}); });
......
...@@ -4,10 +4,7 @@ ...@@ -4,10 +4,7 @@
jQuery.support = {}; jQuery.support = {};
var root = document.documentElement, var div = document.createElement("div");
script = document.createElement("script"),
div = document.createElement("div"),
id = "script" + jQuery.now();
div.style.display = "none"; div.style.display = "none";
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
...@@ -64,7 +61,7 @@ ...@@ -64,7 +61,7 @@
deleteExpando: true, deleteExpando: true,
optDisabled: false, optDisabled: false,
checkClone: false, checkClone: false,
scriptEval: false, _scriptEval: null,
noCloneEvent: true, noCloneEvent: true,
boxModel: null, boxModel: null,
inlineBlockNeedsLayout: false, inlineBlockNeedsLayout: false,
...@@ -77,6 +74,12 @@ ...@@ -77,6 +74,12 @@
select.disabled = true; select.disabled = true;
jQuery.support.optDisabled = !opt.disabled; jQuery.support.optDisabled = !opt.disabled;
jQuery.support.scriptEval = function() {
if ( jQuery.support._scriptEval === null ) {
var root = document.documentElement,
script = document.createElement("script"),
id = "script" + jQuery.now();
script.type = "text/javascript"; script.type = "text/javascript";
try { try {
script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
...@@ -88,21 +91,29 @@ ...@@ -88,21 +91,29 @@
// tag with appendChild/createTextNode // tag with appendChild/createTextNode
// (IE doesn't support this, fails, and uses .text instead) // (IE doesn't support this, fails, and uses .text instead)
if ( window[ id ] ) { if ( window[ id ] ) {
jQuery.support.scriptEval = true; jQuery.support._scriptEval = true;
delete window[ id ]; delete window[ id ];
} else {
jQuery.support._scriptEval = false;
}
root.removeChild( script );
// release memory in IE
root = script = id = null;
} }
return jQuery.support._scriptEval;
};
// Test to see if it's possible to delete an expando from an element // Test to see if it's possible to delete an expando from an element
// Fails in Internet Explorer // Fails in Internet Explorer
try { try {
delete script.test; delete div.test;
} catch(e) { } catch(e) {
jQuery.support.deleteExpando = false; jQuery.support.deleteExpando = false;
} }
root.removeChild( script );
if ( div.attachEvent && div.fireEvent ) { if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() { div.attachEvent("onclick", function click() {
// Cloning a node shouldn't copy over any // Cloning a node shouldn't copy over any
...@@ -177,6 +188,14 @@ ...@@ -177,6 +188,14 @@
var el = document.createElement("div"); var el = document.createElement("div");
eventName = "on" + eventName; eventName = "on" + eventName;
// We only care about the case where non-standard event systems
// are used, namely in IE. Short-circuiting here helps us to
// avoid an eval call (in setAttribute) which can cause CSP
// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
if ( !el.attachEvent ) {
return true;
}
var isSupported = (eventName in el); var isSupported = (eventName in el);
if ( !isSupported ) { if ( !isSupported ) {
el.setAttribute(eventName, "return;"); el.setAttribute(eventName, "return;");
...@@ -191,6 +210,6 @@ ...@@ -191,6 +210,6 @@
jQuery.support.changeBubbles = eventSupported("change"); jQuery.support.changeBubbles = eventSupported("change");
// release memory in IE // release memory in IE
root = script = div = all = a = null; div = all = a = null;
})(); })();
})( jQuery ); })( jQuery );
...@@ -6,7 +6,14 @@ var runtil = /Until$/, ...@@ -6,7 +6,14 @@ var runtil = /Until$/,
rmultiselector = /,/, rmultiselector = /,/,
isSimple = /^.[^:#\[\.,]*$/, isSimple = /^.[^:#\[\.,]*$/,
slice = Array.prototype.slice, slice = Array.prototype.slice,
POS = jQuery.expr.match.POS; POS = jQuery.expr.match.POS,
// methods guaranteed to produce a unique set when starting from a unique set
guaranteedUnique = {
children: true,
contents: true,
next: true,
prev: true
};
jQuery.fn.extend({ jQuery.fn.extend({
find: function( selector ) { find: function( selector ) {
...@@ -196,7 +203,12 @@ jQuery.each({ ...@@ -196,7 +203,12 @@ jQuery.each({
} }
}, function( name, fn ) { }, function( name, fn ) {
jQuery.fn[ name ] = function( until, selector ) { jQuery.fn[ name ] = function( until, selector ) {
var ret = jQuery.map( this, fn, until ); var ret = jQuery.map( this, fn, until ),
// The variable 'args' was introduced in
// https://github.com/jquery/jquery/commit/52a0238
// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
// http://code.google.com/p/v8/issues/detail?id=1050
args = slice.call(arguments);
if ( !runtil.test( name ) ) { if ( !runtil.test( name ) ) {
selector = until; selector = until;
...@@ -206,13 +218,13 @@ jQuery.each({ ...@@ -206,13 +218,13 @@ jQuery.each({
ret = jQuery.filter( selector, ret ); ret = jQuery.filter( selector, ret );
} }
ret = this.length > 1 ? jQuery.unique( ret ) : ret; ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
ret = ret.reverse(); ret = ret.reverse();
} }
return this.pushStack( ret, name, slice.call(arguments).join(",") ); return this.pushStack( ret, name, args.join(",") );
}; };
}); });
......
<?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>
...@@ -45,3 +45,52 @@ function t(a,b,c) { ...@@ -45,3 +45,52 @@ function t(a,b,c) {
function url(value) { function url(value) {
return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000); return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
} }
(function () {
// Store the old counts so that we only assert on tests that have actually leaked,
// instead of asserting every time a test has leaked sometime in the past
var oldCacheLength = 0,
oldFragmentsLength = 0,
oldTimersLength = 0,
oldActive = 0;
/**
* Ensures that tests have cleaned up properly after themselves. Should be passed as the
* teardown function on all modules' lifecycle object.
*/
this.moduleTeardown = function () {
var i, fragmentsLength = 0, cacheLength = 0;
// Allow QUnit.reset to clean up any attached elements before checking for leaks
QUnit.reset();
for ( i in jQuery.cache ) {
++cacheLength;
}
jQuery.fragments = {};
for ( i in jQuery.fragments ) {
++fragmentsLength;
}
// Because QUnit doesn't have a mechanism for retrieving the number of expected assertions for a test,
// if we unconditionally assert any of these, the test will fail with too many assertions :|
if ( cacheLength !== oldCacheLength ) {
equals( cacheLength, oldCacheLength, "No unit tests leak memory in jQuery.cache" );
oldCacheLength = cacheLength;
}
if ( fragmentsLength !== oldFragmentsLength ) {
equals( fragmentsLength, oldFragmentsLength, "No unit tests leak memory in jQuery.fragments" );
oldFragmentsLength = fragmentsLength;
}
if ( jQuery.timers.length !== oldTimersLength ) {
equals( jQuery.timers.length, oldTimersLength, "No timers are still running" );
oldTimersLength = jQuery.timers.length;
}
if ( jQuery.active !== oldActive ) {
equals( jQuery.active, 0, "No AJAX requests are still active" );
oldActive = jQuery.active;
}
}
}());
\ No newline at end of file
module("ajax"); module("ajax", { teardown: moduleTeardown });
// Safari 3 randomly crashes when running these tests, // Safari 3 randomly crashes when running these tests,
// but only in the full suite - you can run just the Ajax // but only in the full suite - you can run just the Ajax
...@@ -1114,17 +1114,20 @@ test("jQuery.getScript(String, Function) - no callback", function() { ...@@ -1114,17 +1114,20 @@ test("jQuery.getScript(String, Function) - no callback", function() {
}); });
}); });
test("jQuery.ajax() - JSONP, Local", function() { jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
expect(14);
test("jQuery.ajax() - JSONP, " + label, function() {
expect(17);
var count = 0; var count = 0;
function plus(){ if ( ++count == 14 ) start(); } function plus(){ if ( ++count == 17 ) start(); }
stop(); stop();
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, no callback)" ); ok( data.data, "JSON results returned (GET, no callback)" );
plus(); plus();
...@@ -1138,6 +1141,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1138,6 +1141,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php?callback=?", url: "data/jsonp.php?callback=?",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, url callback)" ); ok( data.data, "JSON results returned (GET, url callback)" );
plus(); plus();
...@@ -1151,6 +1155,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1151,6 +1155,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
data: "callback=?", data: "callback=?",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, data callback)" ); ok( data.data, "JSON results returned (GET, data callback)" );
...@@ -1165,6 +1170,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1165,6 +1170,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php?callback=??", url: "data/jsonp.php?callback=??",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, url context-free callback)" ); ok( data.data, "JSON results returned (GET, url context-free callback)" );
plus(); plus();
...@@ -1178,6 +1184,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1178,6 +1184,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
data: "callback=??", data: "callback=??",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, data context-free callback)" ); ok( data.data, "JSON results returned (GET, data context-free callback)" );
...@@ -1192,6 +1199,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1192,6 +1199,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php/??", url: "data/jsonp.php/??",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, REST-like)" ); ok( data.data, "JSON results returned (GET, REST-like)" );
plus(); plus();
...@@ -1205,6 +1213,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1205,6 +1213,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php/???json=1", url: "data/jsonp.php/???json=1",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
strictEqual( jQuery.type(data), "array", "JSON results returned (GET, REST-like with param)" ); strictEqual( jQuery.type(data), "array", "JSON results returned (GET, REST-like with param)" );
plus(); plus();
...@@ -1218,6 +1227,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1218,6 +1227,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
data: { data: {
callback: "?" callback: "?"
}, },
...@@ -1234,6 +1244,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1234,6 +1244,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
jsonp: "callback", jsonp: "callback",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, data obj callback)" ); ok( data.data, "JSON results returned (GET, data obj callback)" );
...@@ -1245,9 +1256,16 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1245,9 +1256,16 @@ test("jQuery.ajax() - JSONP, Local", function() {
} }
}); });
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
plus();
};
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
jsonpCallback: "jsonpResults", jsonpCallback: "jsonpResults",
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (GET, custom callback name)" ); ok( data.data, "JSON results returned (GET, custom callback name)" );
...@@ -1263,6 +1281,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1263,6 +1281,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
type: "POST", type: "POST",
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, no callback)" ); ok( data.data, "JSON results returned (POST, no callback)" );
plus(); plus();
...@@ -1278,6 +1297,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1278,6 +1297,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
url: "data/jsonp.php", url: "data/jsonp.php",
data: "callback=?", data: "callback=?",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, data callback)" ); ok( data.data, "JSON results returned (POST, data callback)" );
plus(); plus();
...@@ -1293,6 +1313,7 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1293,6 +1313,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
url: "data/jsonp.php", url: "data/jsonp.php",
jsonp: "callback", jsonp: "callback",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
success: function(data){ success: function(data){
ok( data.data, "JSON results returned (POST, data obj callback)" ); ok( data.data, "JSON results returned (POST, data obj callback)" );
plus(); plus();
...@@ -1307,93 +1328,35 @@ test("jQuery.ajax() - JSONP, Local", function() { ...@@ -1307,93 +1328,35 @@ test("jQuery.ajax() - JSONP, Local", function() {
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
crossDomain: crossDomain,
beforeSend: function(){ beforeSend: function(){
strictEqual( this.cache, false, "cache must be false on JSON request" ); strictEqual( this.cache, false, "cache must be false on JSON request" );
plus(); plus();
return false; return false;
} }
}); });
});
test("jQuery.ajax() - JSONP - Custom JSONP Callback", function() {
expect(1);
stop();
window.jsonpResults = function(data) {
ok( data.data, "JSON results returned (GET, custom callback function)" );
window.jsonpResults = undefined;
start();
};
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php?callback=XXX",
dataType: "jsonp", dataType: "jsonp",
jsonpCallback: "jsonpResults" jsonp: false,
}); jsonpCallback: "XXX",
}); crossDomain: crossDomain,
beforeSend: function() {
test("jQuery.ajax() - JSONP, Remote", function() { ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ) ,
expect(4); "The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
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(); 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){ success: function(data){
ok( data.data, "JSON results returned (GET, data callback)" ); ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
plus(); plus();
}, },
error: function(data){ error: function(data){
ok( false, "Ajax error JSON (GET, data callback)" ); ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
plus(); 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() { ...@@ -1865,25 +1828,19 @@ test("jQuery ajax - failing cross-domain", function() {
var i = 2; var i = 2;
if ( jQuery.ajax({ jQuery.ajax({
url: 'http://somewebsitethatdoesnotexist-67864863574657654.com', url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
success: function(){ ok( false , "success" ); }, success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); }, error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); } complete: function() { if ( ! --i ) start(); }
}) === false ) { });
ok( true , "no transport" );
if ( ! --i ) start();
}
if ( jQuery.ajax({ jQuery.ajax({
url: 'http://www.google.com', url: 'http://www.google.com',
success: function(){ ok( false , "success" ); }, success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); }, error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); } complete: function() { if ( ! --i ) start(); }
}) === false ) { });
ok( true , "no transport" );
if ( ! --i ) start();
}
}); });
...@@ -1937,7 +1894,7 @@ test( "jQuery.ajax - statusCode" , function() { ...@@ -1937,7 +1894,7 @@ test( "jQuery.ajax - statusCode" , function() {
404: function() { 404: function() {
ok( ! isSuccess , name ); ok( ! isSuccess , name );
} }
} };
} }
jQuery.each( { jQuery.each( {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
module("offset"); module("offset", { teardown: moduleTeardown });
test("disconnected node", function() { test("disconnected node", function() {
expect(2); expect(2);
......
module("queue"); module("queue", { teardown: moduleTeardown });
test("queue() with other types",function() { test("queue() with other types",function() {
expect(9); expect(9);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment