Merge branch 'master' into proxy-native-bind
* master: (194 commits) Revert "Make sure that focusin/focusout bubbles in non-IE browsers." This was causing problems with the focusin event, see: #7340. Replaces "text in-between" technique with a full-fledged one-level transitive search for converters (unit tests added). Also cleans up auto dataType determination and adds converter checks in order to guess the best dataType possible. Moves determineResponse logic into main ajax callback. Puts responseXXX fields definitions into ajaxSettings. Removes misleading comment. Bring jQuery('#id') and jQuery('body') logic back into core (while leaving it in Sizzle at the same time). Was causing too much of a performance hit to leave it all to Sizzle. Renames Deferred's fire and fireReject methods as resolveWith and rejectWith respectively. Fix typo in regex tweak from previous commit. Renames determineDataType as determineResponse. Makes it more generic as a first step into integrating the logic into the main ajax done callback. Also fixes some comments in ajax/xhr.js. Move jQuery(...) selector speed-up logic into Sizzle(...) qSA handling. Additionally add in a new catch for Sizzle('.class') (avoid using qSA and use getElementsByClassName instead, where applicable). Revises the way arguments are handled in ajax. Makes sure statusCode callbacks are ordered in the same way success and error callbacks are. Unit tests added. Cleans up and simplifies code shared by ajaxPrefilter and ajaxTransport. Removes chainability of ajaxSetup, ajaxPrefilter and ajaxTransport. Also makes sure context is handled properly by ajaxSetup (unit test added). Rework unit tests to check actual result elements. Moves active counter test after all other ajax tests where it should be. Revised the Nokia support fallback. It turns out that Nokia supports the documentElement property but does not define document.compatMode. Adding this third fallback allows Nokia to run jQuery error-free and return proper values for window width and height. Moves things around to make jsLint happier. Fixes crossDomain test so that it assumes port to be 80 for http and 443 for https when it is not provided. Moves determineDataType into ajaxSettings so that it is accessible to transports without the need for a second argument and so that we can now pass the original options to the transport instead. Also ensures the original options are actually propagated to prefilters (they were not). Re-adds hastily removed variable and simplifies statusCode based callbacks handling. Use undefined instead of 0 to deference transport for clarity. ... Conflicts: src/event.js
This commit is contained in:
commit
a03f040dbf
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2010 John Resig, http://jquery.com/
|
||||
Copyright (c) 2011 John Resig, http://jquery.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
29
Makefile
29
Makefile
|
@ -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\
|
||||
|
@ -24,10 +21,9 @@ BASE_FILES = ${SRC_DIR}/core.js\
|
|||
${SRC_DIR}/manipulation.js\
|
||||
${SRC_DIR}/css.js\
|
||||
${SRC_DIR}/ajax.js\
|
||||
${SRC_DIR}/xhr.js\
|
||||
${SRC_DIR}/transports/jsonp.js\
|
||||
${SRC_DIR}/transports/script.js\
|
||||
${SRC_DIR}/transports/xhr.js\
|
||||
${SRC_DIR}/ajax/jsonp.js\
|
||||
${SRC_DIR}/ajax/script.js\
|
||||
${SRC_DIR}/ajax/xhr.js\
|
||||
${SRC_DIR}/effects.js\
|
||||
${SRC_DIR}/offset.js\
|
||||
${SRC_DIR}/dimensions.js
|
||||
|
@ -79,13 +75,13 @@ init:
|
|||
jquery: ${JQ}
|
||||
jq: ${JQ}
|
||||
|
||||
${JQ}: ${MODULES} ${DIST_DIR}
|
||||
${JQ}: ${MODULES} | ${DIST_DIR}
|
||||
@@echo "Building" ${JQ}
|
||||
|
||||
@@cat ${MODULES} | \
|
||||
sed 's/.function..jQuery...{//' | \
|
||||
sed 's/}...jQuery..;//' | \
|
||||
sed 's/Date:./&'"${DATE}"'/' | \
|
||||
sed 's/@DATE/'"${DATE}"'/' | \
|
||||
${VER} > ${JQ};
|
||||
|
||||
${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js
|
||||
|
@ -94,17 +90,16 @@ ${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}.tmp
|
||||
@@echo ";" >> ${JQ_MIN}.tmp
|
||||
@@sed 's/\*\/(/*\/ʩ(/' ${JQ_MIN}.tmp | tr "ʩ" "\n" > ${JQ_MIN}
|
||||
@@rm -rf ${JQ_MIN}.tmp
|
||||
|
||||
clean:
|
||||
@@echo "Removing Distribution directory:" ${DIST_DIR}
|
||||
|
|
95
README.md
95
README.md
|
@ -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:
|
||||
With this example, the output files would end up in `/home/jquery/test/dist/`.
|
||||
|
||||
make PREFIX=/home/john/test/ [command]
|
||||
|
||||
With this example, the output files would be contained in `/home/john/test/dist/`
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
**Rake only:** Define the DIST_DIR directory, for example:
|
||||
Sometimes, the various git repositories get into an inconsistent state where builds don't complete properly
|
||||
(usually this results in the jquery.js or jquery.min.js being 0 bytes). If this happens, run `make clean`, then
|
||||
run `make` again.
|
||||
|
||||
rake DIST_DIR=/home/john/test/ [command]
|
||||
|
||||
With this example, the output files would be contained in `/home/john/test/`
|
||||
|
||||
*In both examples, `[command]` is optional.*
|
||||
|
||||
**Ant only:** You cannot currently build to another directory when using Ant.
|
||||
|
||||
Questions?
|
||||
----------
|
||||
|
||||
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.
|
||||
|
|
138
Rakefile
138
Rakefile
|
@ -1,138 +0,0 @@
|
|||
prefix = File.dirname( __FILE__ )
|
||||
|
||||
# Directory variables
|
||||
src_dir = File.join( prefix, 'src' )
|
||||
build_dir = File.join( prefix, 'build' )
|
||||
test_dir = File.join( prefix, 'test' )
|
||||
|
||||
# A different destination directory can be set by
|
||||
# setting DIST_DIR before calling rake
|
||||
dist_dir = ENV['DIST_DIR'] || File.join( prefix, 'dist' )
|
||||
|
||||
base_files = %w{intro core support data queue attributes event selector traversing manipulation css ajax xhr transports/jsonp transports/script transports/xhr effects offset dimensions outro}.map { |js| File.join( src_dir, "#{js}.js" ) }
|
||||
|
||||
# Sizzle, QUnit and jQuery files/dirs
|
||||
sizzle_dir = File.join( src_dir, "sizzle" )
|
||||
sizzle = File.join( sizzle_dir, "sizzle.js" )
|
||||
selector = File.join( src_dir, "selector.js" )
|
||||
|
||||
qunit_dir = File.join( test_dir, "qunit" )
|
||||
qunit = File.join( qunit_dir, "qunit", "qunit.js" )
|
||||
|
||||
jq = File.join( dist_dir, "jquery.js" )
|
||||
jq_min = File.join( dist_dir, "jquery.min.js" )
|
||||
|
||||
# General Variables
|
||||
date = `git log -1`[/^Date:\s+(.+)$/, 1]
|
||||
version = File.read( File.join( prefix, 'version.txt' ) ).strip
|
||||
|
||||
# Build tools
|
||||
rhino = "java -jar #{build_dir}/js.jar"
|
||||
minfier = "java -jar #{build_dir}/google-compiler-20100917.jar"
|
||||
|
||||
# Turn off output other than needed from `sh` and file commands
|
||||
verbose(false)
|
||||
|
||||
# Tasks
|
||||
task :default => "all"
|
||||
|
||||
desc "Builds jQuery; Tests with JSLint; Minifies jQuery"
|
||||
task :all => [:jquery, :lint, :min] do
|
||||
puts "jQuery build complete."
|
||||
end
|
||||
|
||||
desc "Builds jQuery: jquery.js (Default task)"
|
||||
task :jquery => [:selector, jq]
|
||||
|
||||
desc "Builds a minified version of jQuery: jquery.min.js"
|
||||
task :min => jq_min
|
||||
|
||||
|
||||
task :init => [sizzle, qunit] do
|
||||
sizzle_git = File.join(sizzle_dir, '.git')
|
||||
qunit_git = File.join(qunit_dir, '.git')
|
||||
|
||||
puts "Updating SizzleJS with latest..."
|
||||
sh "git --git-dir=#{sizzle_git} pull -q origin master"
|
||||
|
||||
puts "Updating QUnit with latest..."
|
||||
sh "git --git-dir=#{qunit_git} pull -q origin master"
|
||||
end
|
||||
|
||||
desc "Removes dist folder, selector.js, and Sizzle/QUnit"
|
||||
task :clean do
|
||||
puts "Removing Distribution directory: #{dist_dir}..."
|
||||
rm_rf dist_dir
|
||||
|
||||
puts "Removing built copy of Sizzle..."
|
||||
rm_rf selector
|
||||
|
||||
puts "Removing cloned directories..."
|
||||
rm_rf qunit_dir
|
||||
rm_rf sizzle_dir
|
||||
end
|
||||
|
||||
desc "Rebuilds selector.js from SizzleJS"
|
||||
task :selector => [:init, selector]
|
||||
|
||||
desc "Tests built jquery.js against JSLint"
|
||||
task :lint => jq do
|
||||
puts "Checking jQuery against JSLint..."
|
||||
sh "#{rhino} " + File.join(build_dir, 'jslint-check.js')
|
||||
end
|
||||
|
||||
|
||||
# File and Directory Dependencies
|
||||
directory dist_dir
|
||||
|
||||
file jq => [dist_dir, base_files].flatten do
|
||||
puts "Building jquery.js..."
|
||||
|
||||
File.open(jq, 'w') do |f|
|
||||
f.write cat(base_files).gsub(/(Date:.)/, "\\1#{date}" ).gsub(/@VERSION/, version)
|
||||
end
|
||||
end
|
||||
|
||||
file jq_min => jq do
|
||||
puts "Building jquery.min.js..."
|
||||
|
||||
sh "#{minfier} --js #{jq} --warning_level QUIET --js_output_file #{jq_min}"
|
||||
|
||||
min = File.read( jq_min )
|
||||
|
||||
# Equivilent of "head"
|
||||
File.open(jq_min, 'w') do |f|
|
||||
f.write File.readlines(jq)[0..14].join()
|
||||
f.write min
|
||||
end
|
||||
end
|
||||
|
||||
file selector => [sizzle, :init] do
|
||||
puts "Building selector code from Sizzle..."
|
||||
|
||||
File.open(selector, 'w') do |f|
|
||||
f.write File.read(sizzle).gsub(
|
||||
/^.+EXPOSE$\n/,
|
||||
'\0' + File.read( File.join( src_dir, 'sizzle-jquery.js' ))
|
||||
).gsub(
|
||||
/^window.Sizzle.+$\n/, ''
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
file sizzle do
|
||||
puts "Retrieving SizzleJS from Github..."
|
||||
sh "git clone git://github.com/jeresig/sizzle.git #{sizzle_dir}"
|
||||
end
|
||||
|
||||
file qunit do
|
||||
puts "Retrieving QUnit from Github..."
|
||||
sh "git clone git://github.com/jquery/qunit.git #{qunit_dir}"
|
||||
end
|
||||
|
||||
|
||||
def cat( files )
|
||||
files.map do |file|
|
||||
File.read(file)
|
||||
end.join('')
|
||||
end
|
133
build.xml
133
build.xml
|
@ -1,133 +0,0 @@
|
|||
<project name="jQuery" default="all" basedir=".">
|
||||
|
||||
<loadfile property="version" srcfile="version.txt" />
|
||||
<property name="PREFIX" value="." />
|
||||
<property description="Folder for jquery and min target" name="dist" value="${PREFIX}/dist" />
|
||||
|
||||
<property name="JQ" value="${dist}/jquery.js" />
|
||||
<property name="JQ_MIN" value="${dist}/jquery.min.js" />
|
||||
|
||||
<loadfile property="sizzle-exports" srcfile="src/sizzle-jquery.js" />
|
||||
|
||||
<available property="qunit" file="test/qunit" />
|
||||
<available property="sizzle" file="src/sizzle" />
|
||||
|
||||
<target name="all" depends="jquery,lint,min" />
|
||||
|
||||
<target name="qunit-clone" unless="qunit">
|
||||
<exec executable="git" outputproperty="git-qunit" >
|
||||
<arg line="clone git://github.com/jquery/qunit.git test/qunit" />
|
||||
</exec>
|
||||
<echo message="git clone qunit: ${git-qunit}" />
|
||||
</target>
|
||||
<target name="qunit-pull" if="qunit">
|
||||
<exec executable="git" outputproperty="git-qunit" dir="test/qunit" >
|
||||
<arg line="pull origin master" />
|
||||
</exec>
|
||||
<echo message="git pull sizzle: ${git-qunit}" />
|
||||
</target>
|
||||
<target name="sizzle-clone" unless="sizzle">
|
||||
<exec executable="git" outputproperty="git-sizzle" >
|
||||
<arg line="clone git://github.com/jeresig/sizzle.git src/sizzle" />
|
||||
</exec>
|
||||
<echo message="git clone sizzle: ${git-sizzle}" />
|
||||
</target>
|
||||
<target name="sizzle-pull" if="sizzle">
|
||||
<exec executable="git" outputproperty="git-sizzle" dir="src/sizzle" >
|
||||
<arg line="pull origin master" />
|
||||
</exec>
|
||||
<echo message="git pull sizzle: ${git-sizzle}" />
|
||||
</target>
|
||||
|
||||
<target name="init" depends="qunit-clone,qunit-pull,sizzle-clone,sizzle-pull" />
|
||||
|
||||
<target name="selector" depends="init" description="Builds the selector library for jQuery from Sizzle.">
|
||||
<copy file="src/sizzle/sizzle.js" tofile="src/selector.js" overwrite="true" />
|
||||
<replaceregexp match="// EXPOSE(.*) " replace="// EXPOSE\1 ${sizzle-exports}" file="src/selector.js" />
|
||||
<replaceregexp match="window.Sizzle(.*) " replace="" file="src/selector.js" />
|
||||
</target>
|
||||
|
||||
<target name="jquery" depends="init,selector" description="Main jquery build, concatenates source files and replaces @VERSION">
|
||||
<echo message="Building ${JQ}" />
|
||||
<mkdir dir="${dist}" />
|
||||
<concat destfile="${JQ}">
|
||||
<fileset file="src/intro.js" />
|
||||
<fileset file="src/core.js" />
|
||||
<fileset file="src/support.js" />
|
||||
<fileset file="src/data.js" />
|
||||
<fileset file="src/queue.js" />
|
||||
<fileset file="src/attributes.js" />
|
||||
<fileset file="src/event.js" />
|
||||
<fileset file="src/selector.js" />
|
||||
<fileset file="src/traversing.js" />
|
||||
<fileset file="src/manipulation.js" />
|
||||
<fileset file="src/css.js" />
|
||||
<fileset file="src/ajax.js" />
|
||||
<fileset file="src/xhr.js" />
|
||||
<fileset file="src/transports/jsonp.js" />
|
||||
<fileset file="src/transports/script.js" />
|
||||
<fileset file="src/transports/xhr.js" />
|
||||
<fileset file="src/effects.js" />
|
||||
<fileset file="src/offset.js" />
|
||||
<fileset file="src/dimensions.js" />
|
||||
<fileset file="src/outro.js" />
|
||||
</concat>
|
||||
<replaceregexp match="@VERSION" replace="${version}" flags="g" byline="true" file="${JQ}" />
|
||||
<exec executable="git" outputproperty="date">
|
||||
<arg line="log -1 --pretty=format:%ad" />
|
||||
</exec>
|
||||
<replaceregexp match="(\(\s*function\s*\(\s*jQuery\s*\)\s*\{)|(\}\s*\)\s*\(\s*jQuery\s*\)\s*;)" flags="g" replace="" file="${JQ}" />
|
||||
<replaceregexp match="Date: " replace="Date: ${date}" file="${JQ}" />
|
||||
<echo message="${JQ} built." />
|
||||
</target>
|
||||
|
||||
<target name="lint" depends="jquery" description="Check jQuery against JSLint">
|
||||
<exec executable="java">
|
||||
<arg line="-jar build/js.jar build/jslint-check.js" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="min" depends="jquery" description="Remove all comments and whitespace, no compression, great in combination with GZip">
|
||||
<echo message="Building ${JQ_MIN}" />
|
||||
<apply executable="java" parallel="false" verbose="true" dest="${dist}">
|
||||
<fileset dir="${dist}">
|
||||
<include name="jquery.js" />
|
||||
</fileset>
|
||||
<arg line="-jar" />
|
||||
<arg path="build/google-compiler-20100917.jar" />
|
||||
<arg value="--warning_level" />
|
||||
<arg value="QUIET" />
|
||||
<arg value="--js_output_file" />
|
||||
<targetfile />
|
||||
<arg value="--js" />
|
||||
<mapper type="glob" from="jquery.js" to="tmpmin" />
|
||||
</apply>
|
||||
<concat destfile="${JQ_MIN}">
|
||||
<filelist files="${JQ}, ${dist}/tmpmin" />
|
||||
<filterchain>
|
||||
<headfilter lines="15" />
|
||||
</filterchain>
|
||||
</concat>
|
||||
<concat destfile="${JQ_MIN}" append="yes">
|
||||
<filelist files="${dist}/tmpmin" />
|
||||
</concat>
|
||||
<delete file="${dist}/tmpmin" />
|
||||
<echo message="${JQ_MIN} built." />
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="${dist}" />
|
||||
<delete file="src/selector.js" />
|
||||
<delete dir="test/qunit" />
|
||||
<delete dir="src/sizzle" />
|
||||
</target>
|
||||
|
||||
<target name="openAjaxMetadata">
|
||||
<property name="target" value="openAjaxMetadata-jquery-${version}.xml" />
|
||||
<delete file="${dist}/jquery-*.xml" />
|
||||
<get src="http://www.exfer.net/jquery/createjQueryXMLDocs.py?version=1.3" dest="${target}" />
|
||||
<xslt includes="${target}" excludes="build.xml" destdir="./dist" style="build/style.xsl" extension=".xml" />
|
||||
<delete file="${target}" />
|
||||
</target>
|
||||
|
||||
</project>
|
Binary file not shown.
BIN
build/js.jar
BIN
build/js.jar
Binary file not shown.
|
@ -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" );
|
||||
}
|
||||
|
|
|
@ -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
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
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
22
build/lib/squeeze-more.js
Normal 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
199
build/uglify.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
#! /usr/bin/env node
|
||||
// -*- js2 -*-
|
||||
|
||||
global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util");
|
||||
var fs = require("fs"),
|
||||
jsp = require("./lib/parse-js"),
|
||||
pro = require("./lib/process");
|
||||
|
||||
pro.set_logger(function(msg){
|
||||
sys.debug(msg);
|
||||
});
|
||||
|
||||
var options = {
|
||||
ast: false,
|
||||
mangle: true,
|
||||
mangle_toplevel: false,
|
||||
squeeze: true,
|
||||
make_seqs: true,
|
||||
dead_code: true,
|
||||
beautify: false,
|
||||
verbose: false,
|
||||
show_copyright: true,
|
||||
out_same_file: false,
|
||||
extra: false,
|
||||
unsafe: false, // XXX: extra & unsafe? but maybe we don't want both, so....
|
||||
beautify_options: {
|
||||
indent_level: 4,
|
||||
indent_start: 0,
|
||||
quote_keys: false,
|
||||
space_colon: false
|
||||
},
|
||||
output: true // stdout
|
||||
};
|
||||
|
||||
var args = jsp.slice(process.argv, 2);
|
||||
var filename;
|
||||
|
||||
out: while (args.length > 0) {
|
||||
var v = args.shift();
|
||||
switch (v) {
|
||||
case "-b":
|
||||
case "--beautify":
|
||||
options.beautify = true;
|
||||
break;
|
||||
case "-i":
|
||||
case "--indent":
|
||||
options.beautify_options.indent_level = args.shift();
|
||||
break;
|
||||
case "-q":
|
||||
case "--quote-keys":
|
||||
options.beautify_options.quote_keys = true;
|
||||
break;
|
||||
case "-mt":
|
||||
case "--mangle-toplevel":
|
||||
options.mangle_toplevel = true;
|
||||
break;
|
||||
case "--no-mangle":
|
||||
case "-nm":
|
||||
options.mangle = false;
|
||||
break;
|
||||
case "--no-squeeze":
|
||||
case "-ns":
|
||||
options.squeeze = false;
|
||||
break;
|
||||
case "--no-seqs":
|
||||
options.make_seqs = false;
|
||||
break;
|
||||
case "--no-dead-code":
|
||||
options.dead_code = false;
|
||||
break;
|
||||
case "--no-copyright":
|
||||
case "-nc":
|
||||
options.show_copyright = false;
|
||||
break;
|
||||
case "-o":
|
||||
case "--output":
|
||||
options.output = args.shift();
|
||||
break;
|
||||
case "--overwrite":
|
||||
options.out_same_file = true;
|
||||
break;
|
||||
case "-v":
|
||||
case "--verbose":
|
||||
options.verbose = true;
|
||||
break;
|
||||
case "--ast":
|
||||
options.ast = true;
|
||||
break;
|
||||
case "--extra":
|
||||
options.extra = true;
|
||||
break;
|
||||
case "--unsafe":
|
||||
options.unsafe = true;
|
||||
break;
|
||||
default:
|
||||
filename = v;
|
||||
break out;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename) {
|
||||
fs.readFile(filename, "utf8", function(err, text){
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
output(squeeze_it(text));
|
||||
});
|
||||
} else {
|
||||
var stdin = process.openStdin();
|
||||
stdin.setEncoding("utf8");
|
||||
var text = "";
|
||||
stdin.on("data", function(chunk){
|
||||
text += chunk;
|
||||
});
|
||||
stdin.on("end", function() {
|
||||
output(squeeze_it(text));
|
||||
});
|
||||
}
|
||||
|
||||
function output(text) {
|
||||
var out;
|
||||
if (options.out_same_file && filename)
|
||||
options.output = filename;
|
||||
if (options.output === true) {
|
||||
out = process.stdout;
|
||||
} else {
|
||||
out = fs.createWriteStream(options.output, {
|
||||
flags: "w",
|
||||
encoding: "utf8",
|
||||
mode: 0644
|
||||
});
|
||||
}
|
||||
out.write(text);
|
||||
out.end();
|
||||
};
|
||||
|
||||
// --------- main ends here.
|
||||
|
||||
function show_copyright(comments) {
|
||||
var ret = "";
|
||||
for (var i = 0; i < comments.length; ++i) {
|
||||
var c = comments[i];
|
||||
if (c.type == "comment1") {
|
||||
ret += "//" + c.value + "\n";
|
||||
} else {
|
||||
ret += "/*" + c.value + "*/";
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
function squeeze_it(code) {
|
||||
var result = "";
|
||||
if (options.show_copyright) {
|
||||
var initial_comments = [];
|
||||
// keep first comment
|
||||
var tok = jsp.tokenizer(code, false), c;
|
||||
c = tok();
|
||||
var prev = null;
|
||||
while (/^comment/.test(c.type) && (!prev || prev == c.type)) {
|
||||
initial_comments.push(c);
|
||||
prev = c.type;
|
||||
c = tok();
|
||||
}
|
||||
result += show_copyright(initial_comments);
|
||||
}
|
||||
try {
|
||||
var ast = time_it("parse", function(){ return jsp.parse(code); });
|
||||
if (options.mangle)
|
||||
ast = time_it("mangle", function(){ return pro.ast_mangle(ast, options.mangle_toplevel); });
|
||||
if (options.squeeze)
|
||||
ast = time_it("squeeze", function(){
|
||||
ast = pro.ast_squeeze(ast, {
|
||||
make_seqs : options.make_seqs,
|
||||
dead_code : options.dead_code,
|
||||
extra : options.extra
|
||||
});
|
||||
if (options.unsafe)
|
||||
ast = pro.ast_squeeze_more(ast);
|
||||
return ast;
|
||||
});
|
||||
if (options.ast)
|
||||
return sys.inspect(ast, null, null);
|
||||
result += time_it("generate", function(){ return pro.gen_code(ast, options.beautify && options.beautify_options) });
|
||||
return result;
|
||||
} catch(ex) {
|
||||
sys.debug(ex.stack);
|
||||
sys.debug(sys.inspect(ex));
|
||||
sys.debug(JSON.stringify(ex));
|
||||
}
|
||||
};
|
||||
|
||||
function time_it(name, cont) {
|
||||
if (!options.verbose)
|
||||
return cont();
|
||||
var t1 = new Date().getTime();
|
||||
try { return cont(); }
|
||||
finally { sys.debug("// " + name + ": " + ((new Date().getTime() - t1) / 1000).toFixed(3) + " sec."); }
|
||||
};
|
815
src/ajax.js
815
src/ajax.js
|
@ -1,11 +1,20 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
||||
rselectTextarea = /^(?:select|textarea)/i,
|
||||
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
|
||||
var r20 = /%20/g,
|
||||
rbracket = /\[\]$/,
|
||||
rhash = /#.*$/,
|
||||
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
|
||||
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
|
||||
rnoContent = /^(?:GET|HEAD)$/,
|
||||
rquery = /\?/,
|
||||
r20 = /%20/g,
|
||||
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
|
||||
rselectTextarea = /^(?:select|textarea)/i,
|
||||
rts = /([?&])_=[^&]*/,
|
||||
rurl = /^(\w+:)?\/\/([^\/?#:]+)(?::(\d+))?/,
|
||||
rCRLF = /\r?\n/g,
|
||||
|
||||
// Slice function
|
||||
sliceFunc = Array.prototype.slice,
|
||||
|
||||
// Keep a copy of the old load method
|
||||
_load = jQuery.fn.load;
|
||||
|
@ -52,26 +61,34 @@ jQuery.fn.extend({
|
|||
type: type,
|
||||
dataType: "html",
|
||||
data: params,
|
||||
complete: function( res, status ) {
|
||||
// Complete callback (responseText is used internally)
|
||||
complete: function( jXHR, status, responseText ) {
|
||||
// Store the response as specified by the jXHR object
|
||||
responseText = jXHR.responseText;
|
||||
// If successful, inject the HTML into all the matched elements
|
||||
if ( status === "success" || status === "notmodified" ) {
|
||||
if ( jXHR.isResolved() ) {
|
||||
// #4825: Get the actual response in case
|
||||
// a dataFilter is present in ajaxSettings
|
||||
jXHR.done(function( r ) {
|
||||
responseText = r;
|
||||
});
|
||||
// See if a selector was specified
|
||||
self.html( selector ?
|
||||
// Create a dummy div to hold the results
|
||||
jQuery("<div>")
|
||||
// inject the contents of the document in, removing the scripts
|
||||
// to avoid any 'Permission Denied' errors in IE
|
||||
.append(res.responseText.replace(rscript, ""))
|
||||
.append(responseText.replace(rscript, ""))
|
||||
|
||||
// Locate the specified elements
|
||||
.find(selector) :
|
||||
|
||||
// If not, just inject the full result
|
||||
res.responseText );
|
||||
responseText );
|
||||
}
|
||||
|
||||
if ( callback ) {
|
||||
self.each( callback, [res.responseText, status, res] );
|
||||
self.each( callback, [responseText, status, jXHR] );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -99,9 +116,9 @@ jQuery.fn.extend({
|
|||
null :
|
||||
jQuery.isArray(val) ?
|
||||
jQuery.map( val, function(val, i){
|
||||
return {name: elem.name, value: val};
|
||||
return { name: elem.name, value: val.replace(rCRLF, "\r\n") };
|
||||
}) :
|
||||
{name: elem.name, value: val};
|
||||
{ name: elem.name, value: val.replace(rCRLF, "\r\n") };
|
||||
}).get();
|
||||
}
|
||||
});
|
||||
|
@ -113,9 +130,8 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp
|
|||
};
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
|
||||
get: function( url, data, callback, type ) {
|
||||
jQuery.each( [ "get", "post" ], function( i, method ) {
|
||||
jQuery[ method ] = function( url, data, callback, type ) {
|
||||
// shift arguments if data argument was omited
|
||||
if ( jQuery.isFunction( data ) ) {
|
||||
type = type || callback;
|
||||
|
@ -124,13 +140,16 @@ jQuery.extend({
|
|||
}
|
||||
|
||||
return jQuery.ajax({
|
||||
type: "GET",
|
||||
type: method,
|
||||
url: url,
|
||||
data: data,
|
||||
success: callback,
|
||||
dataType: type
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
|
||||
getScript: function( url, callback ) {
|
||||
return jQuery.get(url, null, callback, "script");
|
||||
|
@ -140,25 +159,11 @@ jQuery.extend({
|
|||
return jQuery.get(url, data, callback, "json");
|
||||
},
|
||||
|
||||
post: function( url, data, callback, type ) {
|
||||
// shift arguments if data argument was omited
|
||||
if ( jQuery.isFunction( data ) ) {
|
||||
type = type || callback;
|
||||
callback = data;
|
||||
data = {};
|
||||
}
|
||||
|
||||
return jQuery.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: data,
|
||||
success: callback,
|
||||
dataType: type
|
||||
});
|
||||
},
|
||||
|
||||
ajaxSetup: function( settings ) {
|
||||
jQuery.extend( jQuery.ajaxSettings, settings );
|
||||
jQuery.extend( true, jQuery.ajaxSettings, settings );
|
||||
if ( settings.context ) {
|
||||
jQuery.ajaxSettings.context = settings.context;
|
||||
}
|
||||
},
|
||||
|
||||
ajaxSettings: {
|
||||
|
@ -172,20 +177,13 @@ 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();
|
||||
},
|
||||
xhrResponseFields: {
|
||||
xml: "XML",
|
||||
text: "Text",
|
||||
json: "JSON"
|
||||
},
|
||||
|
||||
accepts: {
|
||||
xml: "application/xml, text/xml",
|
||||
|
@ -195,96 +193,603 @@ jQuery.extend({
|
|||
"*": "*/*"
|
||||
},
|
||||
|
||||
autoDataType: {
|
||||
contents: {
|
||||
xml: /xml/,
|
||||
html: /html/,
|
||||
json: /json/
|
||||
},
|
||||
|
||||
responseFields: {
|
||||
xml: "responseXML",
|
||||
text: "responseText"
|
||||
},
|
||||
|
||||
// Prefilters
|
||||
// 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example)
|
||||
// 2) These are called:
|
||||
// * BEFORE asking for a transport
|
||||
// * AFTER param serialization (s.data is a string if s.processData is true)
|
||||
// 3) They MUST be order agnostic
|
||||
prefilters: [],
|
||||
// 3) key is the dataType
|
||||
// 4) the catchall symbol "*" can be used
|
||||
// 5) execution will start with transport dataType and THEN continue down to "*" if needed
|
||||
prefilters: {},
|
||||
|
||||
// Transports bindings
|
||||
// 1) key is the dataType
|
||||
// 2) the catchall symbol "*" can be used
|
||||
// 3) selection will start with transport dataType and THEN go to "*" if needed
|
||||
transports: {
|
||||
},
|
||||
|
||||
// Checkers
|
||||
// 1) key is dataType
|
||||
// 2) they are called to control successful response
|
||||
// 3) error throws is used as error data
|
||||
dataCheckers: {
|
||||
|
||||
// Check if data is a string
|
||||
"text": function(data) {
|
||||
if ( typeof data != "string" ) {
|
||||
jQuery.error("typeerror");
|
||||
}
|
||||
},
|
||||
|
||||
// Check if xml has been properly parsed
|
||||
"xml": function(data) {
|
||||
var documentElement = data ? data.documentElement : data;
|
||||
if ( ! documentElement || ! documentElement.nodeName ) {
|
||||
jQuery.error("typeerror");
|
||||
}
|
||||
if ( documentElement.nodeName == "parsererror" ) {
|
||||
jQuery.error("parsererror");
|
||||
}
|
||||
}
|
||||
},
|
||||
transports: {},
|
||||
|
||||
// List of data converters
|
||||
// 1) key format is "source_type => destination_type" (spaces required)
|
||||
// 1) key format is "source_type destination_type" (a single space in-between)
|
||||
// 2) the catchall symbol "*" can be used for source_type
|
||||
dataConverters: {
|
||||
converters: {
|
||||
|
||||
// Convert anything to text
|
||||
"* => text": function(data) {
|
||||
return "" + data;
|
||||
},
|
||||
"* text": window.String,
|
||||
|
||||
// Text to html (no transformation)
|
||||
"text => html": function(data) {
|
||||
return data;
|
||||
},
|
||||
// Text to html (true = no transformation)
|
||||
"text html": true,
|
||||
|
||||
// Evaluate text as a json expression
|
||||
"text => json": jQuery.parseJSON,
|
||||
"text json": jQuery.parseJSON,
|
||||
|
||||
// Parse text as xml
|
||||
"text => xml": function(data) {
|
||||
var xml, parser;
|
||||
if ( window.DOMParser ) { // Standard
|
||||
parser = new DOMParser();
|
||||
xml = parser.parseFromString(data,"text/xml");
|
||||
} else { // IE
|
||||
xml = new ActiveXObject("Microsoft.XMLDOM");
|
||||
xml.async="false";
|
||||
xml.loadXML(data);
|
||||
}
|
||||
return xml;
|
||||
}
|
||||
"text xml": jQuery.parseXML
|
||||
}
|
||||
},
|
||||
|
||||
ajaxPrefilter: function( a , b ) {
|
||||
ajaxPrefilterOrTransport( "prefilters" , a , b );
|
||||
},
|
||||
|
||||
ajaxTransport: function( a , b ) {
|
||||
return ajaxPrefilterOrTransport( "transports" , a , b );
|
||||
},
|
||||
|
||||
// Main method
|
||||
ajax: function( url , s ) {
|
||||
ajax: function( url , options ) {
|
||||
|
||||
if ( arguments.length === 1 ) {
|
||||
s = url;
|
||||
url = s ? s.url : undefined;
|
||||
// If options is not an object,
|
||||
// we simulate pre-1.5 signature
|
||||
if ( typeof( options ) !== "object" ) {
|
||||
options = url;
|
||||
url = undefined;
|
||||
}
|
||||
|
||||
return jQuery.xhr().open( s ? s.type : undefined , url ).send( undefined , s );
|
||||
// Force options to be an object
|
||||
options = options || {};
|
||||
|
||||
var // Create the final options object
|
||||
s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ),
|
||||
// jQuery lists
|
||||
jQuery_lastModified = jQuery.lastModified,
|
||||
jQuery_etag = jQuery.etag,
|
||||
// Callbacks contexts
|
||||
// We force the original context if it exists
|
||||
// or take it from jQuery.ajaxSettings otherwise
|
||||
// (plain objects used as context get extended)
|
||||
callbackContext =
|
||||
( s.context = ( "context" in options ? options : jQuery.ajaxSettings ).context ) || s,
|
||||
globalEventContext = callbackContext === s ? jQuery.event : jQuery( callbackContext ),
|
||||
// Deferreds
|
||||
deferred = jQuery.Deferred(),
|
||||
completeDeferred = jQuery._Deferred(),
|
||||
// Status-dependent callbacks
|
||||
statusCode = s.statusCode || {},
|
||||
// Headers (they are sent all at once)
|
||||
requestHeaders = {},
|
||||
// Response headers
|
||||
responseHeadersString,
|
||||
responseHeaders,
|
||||
// transport
|
||||
transport,
|
||||
// timeout handle
|
||||
timeoutTimer,
|
||||
// Cross-domain detection vars
|
||||
loc = document.location,
|
||||
protocol = loc.protocol || "http:",
|
||||
parts,
|
||||
// The jXHR state
|
||||
state = 0,
|
||||
// Loop variable
|
||||
i,
|
||||
// Fake xhr
|
||||
jXHR = {
|
||||
|
||||
readyState: 0,
|
||||
|
||||
// Caches the header
|
||||
setRequestHeader: function(name,value) {
|
||||
if ( state === 0 ) {
|
||||
requestHeaders[ name.toLowerCase() ] = value;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Raw string
|
||||
getAllResponseHeaders: function() {
|
||||
return state === 2 ? responseHeadersString : null;
|
||||
},
|
||||
|
||||
// Builds headers hashtable if needed
|
||||
getResponseHeader: function( key ) {
|
||||
|
||||
var match;
|
||||
|
||||
if ( state === 2 ) {
|
||||
|
||||
if ( !responseHeaders ) {
|
||||
|
||||
responseHeaders = {};
|
||||
|
||||
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
|
||||
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
|
||||
}
|
||||
}
|
||||
match = responseHeaders[ key.toLowerCase() ];
|
||||
|
||||
}
|
||||
|
||||
return match || null;
|
||||
},
|
||||
|
||||
// Cancel the request
|
||||
abort: function( statusText ) {
|
||||
if ( transport ) {
|
||||
transport.abort( statusText || "abort" );
|
||||
}
|
||||
done( 0 , statusText );
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
// Callback for when everything is done
|
||||
// It is defined here because jslint complains if it is declared
|
||||
// at the end of the function (which would be more logical and readable)
|
||||
function done( status , statusText , responses , headers) {
|
||||
|
||||
// Called once
|
||||
if ( state === 2 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// State is "done" now
|
||||
state = 2;
|
||||
|
||||
// Dereference transport for early garbage collection
|
||||
// (no matter how long the jXHR object will be used)
|
||||
transport = undefined;
|
||||
|
||||
// Set readyState
|
||||
jXHR.readyState = status ? 4 : 0;
|
||||
|
||||
// Cache response headers
|
||||
responseHeadersString = headers || "";
|
||||
|
||||
// Clear timeout if it exists
|
||||
if ( timeoutTimer ) {
|
||||
clearTimeout(timeoutTimer);
|
||||
}
|
||||
|
||||
var // Reference dataTypes, converters and responseFields
|
||||
dataTypes = s.dataTypes,
|
||||
converters = s.converters,
|
||||
responseFields = s.responseFields,
|
||||
responseField,
|
||||
|
||||
// Flag to mark as success
|
||||
isSuccess,
|
||||
// Stored success
|
||||
success,
|
||||
// Stored error
|
||||
error,
|
||||
|
||||
// To keep track of statusCode based callbacks
|
||||
oldStatusCode,
|
||||
|
||||
// Actual response
|
||||
response;
|
||||
|
||||
// If we got responses:
|
||||
// - find the right one
|
||||
// - update dataTypes accordingly
|
||||
// - set responseXXX accordingly too
|
||||
if ( responses ) {
|
||||
|
||||
var contents = s.contents,
|
||||
transportDataType = dataTypes[0],
|
||||
ct,
|
||||
type,
|
||||
finalDataType,
|
||||
firstDataType;
|
||||
|
||||
// Auto (xml, json, script or text determined given headers)
|
||||
if ( transportDataType === "*" ) {
|
||||
|
||||
// Remove all auto types
|
||||
while( dataTypes[0] === "*" ) {
|
||||
dataTypes.shift();
|
||||
}
|
||||
transportDataTypes = dataTypes[0];
|
||||
|
||||
// Get content type
|
||||
ct = jXHR.getResponseHeader( "content-type" );
|
||||
|
||||
// Check if it's a known type
|
||||
for ( type in contents ) {
|
||||
if ( contents[ type ] && contents[ type ].test( ct ) ) {
|
||||
dataTypes.unshift( ( transportDataType = type ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if we have a response for the expected dataType
|
||||
if ( transportDataType in responses ) {
|
||||
finalDataType = transportDataType;
|
||||
} else {
|
||||
// Try convertible dataTypes
|
||||
for ( type in responses ) {
|
||||
if ( ! firstDataType ) {
|
||||
firstDataType = type;
|
||||
}
|
||||
if ( ! transportDataType || converters[ type + " " + transportDataType ] ) {
|
||||
finalDataType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Or just use first one
|
||||
finalDataType = finalDataType || firstDataType;
|
||||
}
|
||||
|
||||
// If we found a dataType
|
||||
// We get the corresponding response
|
||||
// and add the dataType to the list if needed
|
||||
if ( finalDataType ) {
|
||||
response = responses[ finalDataType ];
|
||||
if ( finalDataType !== transportDataType ) {
|
||||
dataTypes.unshift( finalDataType );
|
||||
}
|
||||
}
|
||||
|
||||
// Fill responseXXX fields
|
||||
for( type in responseFields ) {
|
||||
if ( type in responses ) {
|
||||
jXHR[ responseFields[ type ] ] = responses[ type ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If successful, handle type chaining
|
||||
if ( status >= 200 && status < 300 || status === 304 ) {
|
||||
|
||||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
||||
if ( s.ifModified ) {
|
||||
|
||||
var lastModified = jXHR.getResponseHeader("Last-Modified"),
|
||||
etag = jXHR.getResponseHeader("Etag");
|
||||
|
||||
if (lastModified) {
|
||||
jQuery_lastModified[ s.url ] = lastModified;
|
||||
}
|
||||
if (etag) {
|
||||
jQuery_etag[ s.url ] = etag;
|
||||
}
|
||||
}
|
||||
|
||||
// If not modified
|
||||
if ( status === 304 ) {
|
||||
|
||||
statusText = "notmodified";
|
||||
isSuccess = 1;
|
||||
|
||||
// If we have data
|
||||
} else {
|
||||
|
||||
statusText = "success";
|
||||
|
||||
// Chain data conversions and determine the final value
|
||||
// (if an exception is thrown in the process, it'll be notified as an error)
|
||||
try {
|
||||
|
||||
var i,
|
||||
tmp,
|
||||
// Current dataType
|
||||
current,
|
||||
// Previous dataType
|
||||
prev,
|
||||
// Conversion expression
|
||||
conversion,
|
||||
// Conversion function
|
||||
conv,
|
||||
// Conversion functions (when text is used in-between)
|
||||
conv1,
|
||||
conv2;
|
||||
|
||||
// For each dataType in the chain
|
||||
for( i = 0 ; i < dataTypes.length ; i++ ) {
|
||||
|
||||
current = dataTypes[ i ];
|
||||
|
||||
// If a responseXXX field for this dataType exists
|
||||
// and if it hasn't been set yet
|
||||
responseField = responseFields[ current ];
|
||||
if ( responseField && ! ( responseField in jXHR ) ) {
|
||||
jXHR[ responseField ] = response;
|
||||
}
|
||||
|
||||
// If this is not the first element
|
||||
if ( i ) {
|
||||
|
||||
// Get the dataType to convert from
|
||||
prev = dataTypes[ i - 1 ];
|
||||
|
||||
// If no auto and dataTypes are actually different
|
||||
if ( prev !== "*" && current !== "*" && prev !== current ) {
|
||||
|
||||
// Get the converter
|
||||
conversion = prev + " " + current;
|
||||
conv = converters[ conversion ] || converters[ "* " + current ];
|
||||
|
||||
// If there is no direct converter, search transitively
|
||||
if ( ! conv ) {
|
||||
conv1 = conv2 = undefined;
|
||||
|
||||
for( conv1 in converters ) {
|
||||
tmp = conv1.split( " " );
|
||||
if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
|
||||
conv2 = converters[ tmp[ 1 ] + " " + current ];
|
||||
if ( conv2 ) {
|
||||
conv1 = converters[ conv1 ];
|
||||
if ( conv1 === true ) {
|
||||
conv = conv2;
|
||||
} else if ( conv2 === true ) {
|
||||
conv = conv1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we found no converter, dispatch an error
|
||||
if ( ! ( conv || conv1 && conv2 ) ) {
|
||||
throw conversion;
|
||||
}
|
||||
// If found converter is not an equivalence
|
||||
if ( conv !== true ) {
|
||||
// Convert with 1 or 2 converters accordingly
|
||||
response = conv ? conv( response ) : conv2( conv1( response ) );
|
||||
}
|
||||
}
|
||||
// If it is the first element of the chain
|
||||
// and we have a dataFilter
|
||||
} else if ( s.dataFilter ) {
|
||||
// Apply the dataFilter
|
||||
response = s.dataFilter( response , current );
|
||||
// Get dataTypes again in case the filter changed them
|
||||
dataTypes = s.dataTypes;
|
||||
}
|
||||
}
|
||||
// End of loop
|
||||
|
||||
// We have a real success
|
||||
success = response;
|
||||
isSuccess = 1;
|
||||
|
||||
// If an exception was thrown
|
||||
} catch(e) {
|
||||
|
||||
// We have a parsererror
|
||||
statusText = "parsererror";
|
||||
error = "" + e;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// if not success, mark it as an error
|
||||
} else {
|
||||
error = statusText = statusText || "error";
|
||||
}
|
||||
|
||||
// Set data for the fake xhr object
|
||||
jXHR.status = status;
|
||||
jXHR.statusText = statusText;
|
||||
|
||||
// Success/Error
|
||||
if ( isSuccess ) {
|
||||
deferred.resolveWith( callbackContext , [ success , statusText , jXHR ] );
|
||||
} else {
|
||||
deferred.rejectWith( callbackContext , [ jXHR , statusText , error ] );
|
||||
}
|
||||
|
||||
// Status-dependent callbacks
|
||||
oldStatusCode = statusCode;
|
||||
statusCode = undefined;
|
||||
jXHR.statusCode( oldStatusCode );
|
||||
|
||||
if ( s.global ) {
|
||||
globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) ,
|
||||
[ jXHR , s , isSuccess ? success : error ] );
|
||||
}
|
||||
|
||||
// Complete
|
||||
completeDeferred.resolveWith( callbackContext, [ jXHR , statusText ] );
|
||||
|
||||
if ( s.global ) {
|
||||
globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] );
|
||||
// Handle the global AJAX counter
|
||||
if ( ! --jQuery.active ) {
|
||||
jQuery.event.trigger( "ajaxStop" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach deferreds
|
||||
deferred.promise( jXHR );
|
||||
jXHR.success = jXHR.done;
|
||||
jXHR.error = jXHR.fail;
|
||||
jXHR.complete = completeDeferred.done;
|
||||
|
||||
// Status-dependent callbacks
|
||||
jXHR.statusCode = function( map ) {
|
||||
if ( map ) {
|
||||
var tmp;
|
||||
if ( statusCode ) {
|
||||
for( tmp in map ) {
|
||||
statusCode[ tmp ] = [ statusCode[ tmp ] , map[ tmp ] ];
|
||||
}
|
||||
} else {
|
||||
tmp = map[ jXHR.status ];
|
||||
jXHR.done( tmp ).fail( tmp );
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
// Remove hash character (#7531: and string promotion)
|
||||
// We also use the url parameter if available
|
||||
s.url = ( "" + ( url || s.url ) ).replace( rhash , "" );
|
||||
|
||||
// Extract dataTypes list
|
||||
s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );
|
||||
|
||||
// Determine if a cross-domain request is in order
|
||||
if ( ! s.crossDomain ) {
|
||||
parts = rurl.exec( s.url.toLowerCase() );
|
||||
s.crossDomain = !!(
|
||||
parts &&
|
||||
( parts[ 1 ] && parts[ 1 ] != protocol ||
|
||||
parts[ 2 ] != loc.hostname ||
|
||||
( parts[ 3 ] || ( ( parts[ 1 ] || protocol ) === "http:" ? 80 : 443 ) ) !=
|
||||
( loc.port || ( protocol === "http:" ? 80 : 443 ) ) )
|
||||
);
|
||||
}
|
||||
|
||||
// Convert data if not already a string
|
||||
if ( s.data && s.processData && typeof s.data !== "string" ) {
|
||||
s.data = jQuery.param( s.data , s.traditional );
|
||||
}
|
||||
|
||||
// Apply prefilters
|
||||
jQuery.ajaxPrefilter( s , options );
|
||||
|
||||
// Uppercase the type
|
||||
s.type = s.type.toUpperCase();
|
||||
|
||||
// Determine if request has content
|
||||
s.hasContent = ! rnoContent.test( s.type );
|
||||
|
||||
// Watch for a new set of requests
|
||||
if ( s.global && jQuery.active++ === 0 ) {
|
||||
jQuery.event.trigger( "ajaxStart" );
|
||||
}
|
||||
|
||||
// More options handling for requests with no content
|
||||
if ( ! s.hasContent ) {
|
||||
|
||||
// If data is available, append data to url
|
||||
if ( s.data ) {
|
||||
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
|
||||
}
|
||||
|
||||
// Add anti-cache in url if needed
|
||||
if ( s.cache === false ) {
|
||||
|
||||
var ts = jQuery.now(),
|
||||
// try replacing _= if it is there
|
||||
ret = s.url.replace( rts , "$1_=" + ts );
|
||||
|
||||
// if nothing was replaced, add timestamp to the end
|
||||
s.url = ret + ( (ret == s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "");
|
||||
}
|
||||
}
|
||||
|
||||
// Set the correct header, if data is being sent
|
||||
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
|
||||
requestHeaders[ "content-type" ] = s.contentType;
|
||||
}
|
||||
|
||||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
||||
if ( s.ifModified ) {
|
||||
if ( jQuery_lastModified[ s.url ] ) {
|
||||
requestHeaders[ "if-modified-since" ] = jQuery_lastModified[ s.url ];
|
||||
}
|
||||
if ( jQuery_etag[ s.url ] ) {
|
||||
requestHeaders[ "if-none-match" ] = jQuery_etag[ s.url ];
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Accepts header for the server, depending on the dataType
|
||||
requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
|
||||
s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
|
||||
s.accepts[ "*" ];
|
||||
|
||||
// Check for headers option
|
||||
for ( i in s.headers ) {
|
||||
requestHeaders[ i.toLowerCase() ] = s.headers[ i ];
|
||||
}
|
||||
|
||||
// Allow custom headers/mimetypes and early abort
|
||||
if ( s.beforeSend && ( s.beforeSend.call( callbackContext , jXHR , s ) === false || state === 2 ) ) {
|
||||
|
||||
// Abort if not done already
|
||||
done( 0 , "abort" );
|
||||
|
||||
// Return false
|
||||
jXHR = false;
|
||||
|
||||
} else {
|
||||
|
||||
// Install callbacks on deferreds
|
||||
for ( i in { success:1, error:1, complete:1 } ) {
|
||||
jXHR[ i ]( s[ i ] );
|
||||
}
|
||||
|
||||
// Get transport
|
||||
transport = jQuery.ajaxTransport( s , options );
|
||||
|
||||
// If no transport, we auto-abort
|
||||
if ( ! transport ) {
|
||||
|
||||
done( 0 , "notransport" );
|
||||
|
||||
} else {
|
||||
|
||||
// Set state as sending
|
||||
state = jXHR.readyState = 1;
|
||||
|
||||
// Send global event
|
||||
if ( s.global ) {
|
||||
globalEventContext.trigger( "ajaxSend" , [ jXHR , s ] );
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if ( s.async && s.timeout > 0 ) {
|
||||
timeoutTimer = setTimeout(function(){
|
||||
jXHR.abort( "timeout" );
|
||||
}, s.timeout);
|
||||
}
|
||||
|
||||
// Try to send
|
||||
try {
|
||||
transport.send(requestHeaders, done);
|
||||
} catch (e) {
|
||||
// Propagate exception as error if not done
|
||||
if ( status === 1 ) {
|
||||
|
||||
done(0, "error", "" + e);
|
||||
jXHR = false;
|
||||
|
||||
// Simply rethrow otherwise
|
||||
} else {
|
||||
jQuery.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jXHR;
|
||||
},
|
||||
|
||||
// Serialize an array of form elements or a set of
|
||||
|
@ -343,7 +848,9 @@ function buildParams( prefix, obj, traditional, add ) {
|
|||
});
|
||||
|
||||
} else if ( !traditional && obj != null && typeof obj === "object" ) {
|
||||
if ( jQuery.isEmptyObject( obj ) ) {
|
||||
// If we see an array here, it is empty and should be treated as an empty
|
||||
// object
|
||||
if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) {
|
||||
add( prefix, "" );
|
||||
|
||||
// Serialize object item.
|
||||
|
@ -372,33 +879,97 @@ jQuery.extend({
|
|||
|
||||
});
|
||||
|
||||
/*
|
||||
* Create the request object; Microsoft failed to properly
|
||||
* implement the XMLHttpRequest in IE7 (can't request local files),
|
||||
* so we use the ActiveXObject when it is available
|
||||
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
|
||||
* we need a fallback.
|
||||
*/
|
||||
if ( window.ActiveXObject ) {
|
||||
jQuery.ajaxSettings.xhr = function() {
|
||||
if ( window.location.protocol !== "file:" ) {
|
||||
try {
|
||||
return new window.XMLHttpRequest();
|
||||
} catch( xhrError ) {}
|
||||
// Base function for both ajaxPrefilter and ajaxTransport
|
||||
function ajaxPrefilterOrTransport( arg0 , arg1 , arg2 ) {
|
||||
|
||||
var type = jQuery.type( arg1 ),
|
||||
structure = jQuery.ajaxSettings[ arg0 ],
|
||||
i,
|
||||
length;
|
||||
|
||||
// We have an options map so we have to inspect the structure
|
||||
if ( type === "object" ) {
|
||||
|
||||
var options = arg1,
|
||||
originalOptions = arg2,
|
||||
// When dealing with prefilters, we execute only
|
||||
// (no selection so we never stop when a function
|
||||
// returns a non-falsy, non-string value)
|
||||
executeOnly = ( arg0 === "prefilters" ),
|
||||
inspect = function( dataType, tested ) {
|
||||
|
||||
if ( ! tested[ dataType ] ) {
|
||||
|
||||
tested[ dataType ] = true;
|
||||
|
||||
var list = structure[ dataType ],
|
||||
selected;
|
||||
|
||||
for( i = 0, length = list ? list.length : 0 ; ( executeOnly || ! selected ) && i < length ; i++ ) {
|
||||
selected = list[ i ]( options , originalOptions );
|
||||
// If we got redirected to a different dataType,
|
||||
// we add it and switch to the corresponding list
|
||||
if ( typeof( selected ) === "string" && selected !== dataType ) {
|
||||
options.dataTypes.unshift( selected );
|
||||
selected = inspect( selected , tested );
|
||||
// We always break in order not to continue
|
||||
// to iterate in previous list
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we're only executing or nothing was selected
|
||||
// we try the catchall dataType
|
||||
if ( executeOnly || ! selected ) {
|
||||
selected = inspect( "*" , tested );
|
||||
}
|
||||
// This will be ignored by ajaxPrefilter
|
||||
// so it's safe to return no matter what
|
||||
return selected;
|
||||
}
|
||||
|
||||
try {
|
||||
return new window.ActiveXObject("Microsoft.XMLHTTP");
|
||||
} catch( activeError ) {}
|
||||
};
|
||||
|
||||
// Start inspection with current transport dataType
|
||||
return inspect( options.dataTypes[ 0 ] , {} );
|
||||
|
||||
} else {
|
||||
|
||||
// We're requested to add to the structure
|
||||
// Signature is ( dataTypeExpression , function )
|
||||
// with dataTypeExpression being optional and
|
||||
// defaulting to catchAll (*)
|
||||
type = type === "function";
|
||||
|
||||
if ( type ) {
|
||||
arg2 = arg1;
|
||||
arg1 = undefined;
|
||||
}
|
||||
arg1 = arg1 || "*";
|
||||
|
||||
var testXHR = jQuery.ajaxSettings.xhr();
|
||||
// We control that the second argument is really a function
|
||||
if ( type || jQuery.isFunction( arg2 ) ) {
|
||||
|
||||
// Does this browser support XHR requests?
|
||||
jQuery.support.ajax = !!testXHR;
|
||||
var dataTypes = arg1.split( /\s+/ ),
|
||||
functor = arg2,
|
||||
dataType,
|
||||
list,
|
||||
placeBefore;
|
||||
|
||||
// Does this browser support crossDomain XHR requests
|
||||
jQuery.support.cors = testXHR && "withCredentials" in testXHR;
|
||||
// For each dataType in the dataTypeExpression
|
||||
for( i = 0 , length = dataTypes.length ; i < length ; i++ ) {
|
||||
dataType = dataTypes[ i ];
|
||||
// We control if we're asked to add before
|
||||
// any existing element
|
||||
placeBefore = /^\+/.test( dataType );
|
||||
if ( placeBefore ) {
|
||||
dataType = dataType.substr( 1 );
|
||||
}
|
||||
list = structure[ dataType ] = structure[ dataType ] || [];
|
||||
// then we add to the structure accordingly
|
||||
list[ placeBefore ? "unshift" : "push" ]( functor );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})( jQuery );
|
||||
|
|
87
src/ajax/jsonp.js
Normal file
87
src/ajax/jsonp.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var jsc = jQuery.now(),
|
||||
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i;
|
||||
|
||||
// Default jsonp settings
|
||||
jQuery.ajaxSetup({
|
||||
jsonp: "callback",
|
||||
jsonpCallback: function() {
|
||||
return "jsonp" + jsc++;
|
||||
}
|
||||
});
|
||||
|
||||
// Detect, normalize options and install callbacks for jsonp requests
|
||||
// (dataIsString is used internally)
|
||||
jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
|
||||
|
||||
dataIsString = ( typeof(s.data) === "string" );
|
||||
|
||||
if ( s.dataTypes[ 0 ] === "jsonp" ||
|
||||
originalSettings.jsonpCallback ||
|
||||
originalSettings.jsonp != null ||
|
||||
s.jsonp !== false && ( jsre.test( s.url ) ||
|
||||
dataIsString && jsre.test( s.data ) ) ) {
|
||||
|
||||
var responseContainer,
|
||||
jsonpCallback = s.jsonpCallback =
|
||||
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
|
||||
previous = window[ jsonpCallback ],
|
||||
url = s.url,
|
||||
data = s.data,
|
||||
replace = "$1" + jsonpCallback + "$2";
|
||||
|
||||
if ( s.jsonp !== false ) {
|
||||
url = url.replace( jsre, replace );
|
||||
if ( s.url === url ) {
|
||||
if ( dataIsString ) {
|
||||
data = data.replace( jsre, replace );
|
||||
}
|
||||
if ( s.data === data ) {
|
||||
// Add callback manually
|
||||
url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.url = url;
|
||||
s.data = data;
|
||||
|
||||
window [ jsonpCallback ] = function( response ) {
|
||||
responseContainer = [response];
|
||||
};
|
||||
|
||||
s.complete = [function() {
|
||||
|
||||
// Set callback back to previous value
|
||||
window[ jsonpCallback ] = previous;
|
||||
|
||||
// Call if it was a function and we have a response
|
||||
if ( previous) {
|
||||
if ( responseContainer && jQuery.isFunction ( previous ) ) {
|
||||
window[ jsonpCallback ] ( responseContainer[0] );
|
||||
}
|
||||
} else {
|
||||
// else, more memory leak avoidance
|
||||
try{ delete window[ jsonpCallback ]; } catch(e){}
|
||||
}
|
||||
|
||||
}, s.complete ];
|
||||
|
||||
// Use data converter to retrieve json after script execution
|
||||
s.converters["script json"] = function() {
|
||||
if ( ! responseContainer ) {
|
||||
jQuery.error( jsonpCallback + " was not called" );
|
||||
}
|
||||
return responseContainer[ 0 ];
|
||||
};
|
||||
|
||||
// force json dataType
|
||||
s.dataTypes[ 0 ] = "json";
|
||||
|
||||
// Delegate to script
|
||||
return "script";
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery );
|
|
@ -1,33 +1,39 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
// Install text to script executor
|
||||
jQuery.extend( true, jQuery.ajaxSettings , {
|
||||
// Install script dataType
|
||||
jQuery.ajaxSetup({
|
||||
|
||||
accepts: {
|
||||
script: "text/javascript, application/javascript"
|
||||
},
|
||||
|
||||
autoDataType: {
|
||||
contents: {
|
||||
script: /javascript/
|
||||
},
|
||||
|
||||
dataConverters: {
|
||||
"text => script": jQuery.globalEval
|
||||
converters: {
|
||||
"text script": jQuery.globalEval
|
||||
}
|
||||
});
|
||||
|
||||
// Bind script tag hack transport
|
||||
jQuery.xhr.bindTransport("script", function(s) {
|
||||
// Handle cache's special case and global
|
||||
jQuery.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
|
||||
jQuery.ajaxTransport("script", function(s) {
|
||||
|
||||
// This transport only deals with cross domain requests
|
||||
if ( s.crossDomain ) {
|
||||
|
||||
var script,
|
||||
head = document.getElementsByTagName("head")[0] || document.documentElement;
|
||||
|
@ -47,10 +53,9 @@ jQuery.xhr.bindTransport("script", function(s) {
|
|||
script.src = s.url;
|
||||
|
||||
// Attach handlers for all browsers
|
||||
script.onload = script.onreadystatechange = function(statusText) {
|
||||
script.onload = script.onreadystatechange = function( _ , isAbort ) {
|
||||
|
||||
if ( (!script.readyState ||
|
||||
script.readyState === "loaded" || script.readyState === "complete") ) {
|
||||
if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) {
|
||||
|
||||
// Handle memory leak in IE
|
||||
script.onload = script.onreadystatechange = null;
|
||||
|
@ -60,10 +65,13 @@ jQuery.xhr.bindTransport("script", function(s) {
|
|||
head.removeChild( script );
|
||||
}
|
||||
|
||||
script = undefined;
|
||||
// Dereference the script
|
||||
script = 0;
|
||||
|
||||
// Callback & dereference
|
||||
callback(statusText ? 0 : 200, statusText || "success");
|
||||
// Callback if not abort
|
||||
if ( ! isAbort ) {
|
||||
callback( 200, "success" );
|
||||
}
|
||||
}
|
||||
};
|
||||
// Use insertBefore instead of appendChild to circumvent an IE6 bug.
|
||||
|
@ -71,9 +79,9 @@ jQuery.xhr.bindTransport("script", function(s) {
|
|||
head.insertBefore( script, head.firstChild );
|
||||
},
|
||||
|
||||
abort: function(statusText) {
|
||||
abort: function() {
|
||||
if ( script ) {
|
||||
script.onload(statusText);
|
||||
script.onload(0,1);
|
||||
}
|
||||
}
|
||||
};
|
225
src/ajax/xhr.js
Normal file
225
src/ajax/xhr.js
Normal file
|
@ -0,0 +1,225 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var // Next active xhr id
|
||||
xhrId = jQuery.now(),
|
||||
|
||||
// active xhrs
|
||||
xhrs = {},
|
||||
|
||||
// #5280: see below
|
||||
xhrUnloadAbortInstalled,
|
||||
|
||||
// XHR used to determine supports properties
|
||||
testXHR;
|
||||
|
||||
// Create the request object
|
||||
// (This is still attached to ajaxSettings for backward compatibility)
|
||||
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
|
||||
/* Microsoft failed to properly
|
||||
* implement the XMLHttpRequest in IE7 (can't request local files),
|
||||
* so we use the ActiveXObject when it is available
|
||||
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
|
||||
* we need a fallback.
|
||||
*/
|
||||
function() {
|
||||
if ( window.location.protocol !== "file:" ) {
|
||||
try {
|
||||
return new window.XMLHttpRequest();
|
||||
} catch( xhrError ) {}
|
||||
}
|
||||
|
||||
try {
|
||||
return new window.ActiveXObject("Microsoft.XMLHTTP");
|
||||
} catch( activeError ) {}
|
||||
} :
|
||||
// For all other browsers, use the standard XMLHttpRequest object
|
||||
function() {
|
||||
return new window.XMLHttpRequest();
|
||||
};
|
||||
|
||||
// Test if we can create an xhr object
|
||||
try {
|
||||
testXHR = jQuery.ajaxSettings.xhr();
|
||||
} catch( xhrCreationException ) {}
|
||||
|
||||
//Does this browser support XHR requests?
|
||||
jQuery.support.ajax = !!testXHR;
|
||||
|
||||
// Does this browser support crossDomain XHR requests
|
||||
jQuery.support.cors = testXHR && "withCredentials" in testXHR;
|
||||
|
||||
// No need for the temporary xhr anymore
|
||||
testXHR = undefined;
|
||||
|
||||
// Create transport if the browser can provide an xhr
|
||||
if ( jQuery.support.ajax ) {
|
||||
jQuery.ajaxTransport( function( s ) {
|
||||
|
||||
// Cross domain only allowed if supported through XMLHttpRequest
|
||||
if ( ! s.crossDomain || jQuery.support.cors ) {
|
||||
|
||||
var callback;
|
||||
|
||||
return {
|
||||
|
||||
send: function(headers, complete) {
|
||||
|
||||
// #5280: we need to abort on unload or IE will keep connections alive
|
||||
if ( ! xhrUnloadAbortInstalled ) {
|
||||
|
||||
xhrUnloadAbortInstalled = 1;
|
||||
|
||||
jQuery(window).bind( "unload" , function() {
|
||||
|
||||
// Abort all pending requests
|
||||
jQuery.each(xhrs, function(_, xhr) {
|
||||
if ( xhr.onreadystatechange ) {
|
||||
xhr.onreadystatechange( 1 );
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Get a new xhr
|
||||
var xhr = s.xhr(),
|
||||
handle;
|
||||
|
||||
// Open the socket
|
||||
// Passing null username, generates a login popup on Opera (#2865)
|
||||
if ( s.username ) {
|
||||
xhr.open(s.type, s.url, s.async, s.username, s.password);
|
||||
} else {
|
||||
xhr.open(s.type, s.url, s.async);
|
||||
}
|
||||
|
||||
// Requested-With header
|
||||
// Not set for crossDomain requests with no content
|
||||
// (see why at http://trac.dojotoolkit.org/ticket/9486)
|
||||
// Won't change header if already provided
|
||||
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
|
||||
headers["x-requested-with"] = "XMLHttpRequest";
|
||||
}
|
||||
|
||||
// Need an extra try/catch for cross domain requests in Firefox 3
|
||||
try {
|
||||
|
||||
jQuery.each(headers, function(key,value) {
|
||||
xhr.setRequestHeader(key,value);
|
||||
});
|
||||
|
||||
} catch(_) {}
|
||||
|
||||
// Do send the request
|
||||
try {
|
||||
xhr.send( ( s.hasContent && s.data ) || null );
|
||||
} catch(e) {
|
||||
complete(0, "error", "" + e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listener
|
||||
callback = function( _ , isAbort ) {
|
||||
|
||||
// Was never called and is aborted or complete
|
||||
if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
|
||||
|
||||
// Only called once
|
||||
callback = 0;
|
||||
|
||||
// Do not keep as active anymore
|
||||
if (handle) {
|
||||
xhr.onreadystatechange = jQuery.noop;
|
||||
delete xhrs[ handle ];
|
||||
}
|
||||
|
||||
// If it's an abort
|
||||
if ( isAbort ) {
|
||||
|
||||
// Abort it manually if needed
|
||||
if ( xhr.readyState !== 4 ) {
|
||||
xhr.abort();
|
||||
}
|
||||
} else {
|
||||
|
||||
// Get info
|
||||
var status = xhr.status,
|
||||
statusText,
|
||||
responseHeaders = xhr.getAllResponseHeaders(),
|
||||
responses = {},
|
||||
xml = xhr.responseXML;
|
||||
|
||||
// Construct response list
|
||||
if ( xml && xml.documentElement /* #4958 */ ) {
|
||||
responses.xml = xml;
|
||||
}
|
||||
responses.text = xhr.responseText;
|
||||
|
||||
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
|
||||
|
||||
statusText = xhr.statusText;
|
||||
|
||||
} catch( e ) {
|
||||
|
||||
statusText = ""; // We normalize with Webkit giving an empty statusText
|
||||
|
||||
}
|
||||
|
||||
// Filter status for non standard behaviours
|
||||
// (so many they seem to be the actual "standard")
|
||||
status =
|
||||
// Opera returns 0 when it should be 304
|
||||
// Webkit returns 0 for failing cross-domain no matter the real status
|
||||
status === 0 ?
|
||||
(
|
||||
! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests
|
||||
(
|
||||
responseHeaders ? // Opera: filter out real aborts #6060
|
||||
304
|
||||
:
|
||||
0
|
||||
)
|
||||
:
|
||||
302 // We assume 302 but could be anything cross-domain related
|
||||
)
|
||||
:
|
||||
(
|
||||
status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450)
|
||||
204
|
||||
:
|
||||
status
|
||||
);
|
||||
|
||||
// Call complete
|
||||
complete(status,statusText,responses,responseHeaders);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// if we're in sync mode
|
||||
// or it's in cache and has been retrieved directly (IE6 & IE7)
|
||||
// we need to manually fire the callback
|
||||
if ( ! s.async || xhr.readyState === 4 ) {
|
||||
|
||||
callback();
|
||||
|
||||
} else {
|
||||
|
||||
// Add to list of active xhrs
|
||||
handle = xhrId++;
|
||||
xhrs[ handle ] = xhr;
|
||||
xhr.onreadystatechange = callback;
|
||||
}
|
||||
},
|
||||
|
||||
abort: function() {
|
||||
if ( callback ) {
|
||||
callback(0,1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})( jQuery );
|
|
@ -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__" ) || "";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
285
src/core.js
285
src/core.js
|
@ -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+/,
|
||||
|
@ -60,8 +56,11 @@ var jQuery = function( selector, context ) {
|
|||
// Has the ready events already been bound?
|
||||
readyBound = false,
|
||||
|
||||
// The functions to execute on DOM ready
|
||||
readyList = [],
|
||||
// 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
|
||||
|
@ -129,7 +130,7 @@ jQuery.fn = jQuery.prototype = {
|
|||
|
||||
} else {
|
||||
ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
|
||||
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
|
||||
selector = (ret.cacheable ? jQuery(ret.fragment).clone()[0] : ret.fragment).childNodes;
|
||||
}
|
||||
|
||||
return jQuery.merge( this, selector );
|
||||
|
@ -157,13 +158,6 @@ jQuery.fn = jQuery.prototype = {
|
|||
return this;
|
||||
}
|
||||
|
||||
// HANDLE: $("TAG")
|
||||
} else if ( !context && !rnonword.test( selector ) ) {
|
||||
this.selector = selector;
|
||||
this.context = document;
|
||||
selector = document.getElementsByTagName( selector );
|
||||
return jQuery.merge( this, selector );
|
||||
|
||||
// HANDLE: $(expr, $(...))
|
||||
} else if ( !context || context.jquery ) {
|
||||
return (context || rootjQuery).find( selector );
|
||||
|
@ -171,7 +165,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 +216,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 );
|
||||
|
@ -253,22 +247,12 @@ jQuery.fn = jQuery.prototype = {
|
|||
return jQuery.each( this, callback, args );
|
||||
},
|
||||
|
||||
ready: function( fn ) {
|
||||
ready: function() {
|
||||
// Attach the listeners
|
||||
jQuery.bindReady();
|
||||
|
||||
// If the DOM is already ready
|
||||
if ( jQuery.isReady ) {
|
||||
// Execute the function immediately
|
||||
fn.call( document, jQuery );
|
||||
|
||||
// Otherwise, remember the function for later
|
||||
} else if ( readyList ) {
|
||||
// Add the function to the wait list
|
||||
readyList.push( fn );
|
||||
}
|
||||
|
||||
return this;
|
||||
// Change ready & apply
|
||||
return ( jQuery.fn.ready = readyList.done ).apply( this , arguments );
|
||||
},
|
||||
|
||||
eq: function( i ) {
|
||||
|
@ -297,7 +281,7 @@ jQuery.fn = jQuery.prototype = {
|
|||
},
|
||||
|
||||
end: function() {
|
||||
return this.prevObject || jQuery(null);
|
||||
return this.prevObject || this.constructor(null);
|
||||
},
|
||||
|
||||
// For internal use only.
|
||||
|
@ -415,25 +399,13 @@ jQuery.extend({
|
|||
}
|
||||
|
||||
// If there are functions bound, to execute
|
||||
if ( readyList ) {
|
||||
// Execute all of them
|
||||
var fn,
|
||||
i = 0,
|
||||
ready = readyList;
|
||||
|
||||
// Reset the list of functions
|
||||
readyList = null;
|
||||
|
||||
while ( (fn = ready[ i++ ]) ) {
|
||||
fn.call( document, jQuery );
|
||||
}
|
||||
readyList.resolveWith( document , [ jQuery ] );
|
||||
|
||||
// Trigger any bound ready events
|
||||
if ( jQuery.fn.trigger ) {
|
||||
jQuery( document ).trigger( "ready" ).unbind( "ready" );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
bindReady: function() {
|
||||
|
@ -566,6 +538,28 @@ jQuery.extend({
|
|||
}
|
||||
},
|
||||
|
||||
// Cross-browser xml parsing
|
||||
// (xml & tmp used internally)
|
||||
parseXML: function( data , xml , tmp ) {
|
||||
|
||||
if ( window.DOMParser ) { // Standard
|
||||
tmp = new DOMParser();
|
||||
xml = tmp.parseFromString( data , "text/xml" );
|
||||
} else { // IE
|
||||
xml = new ActiveXObject( "Microsoft.XMLDOM" );
|
||||
xml.async = "false";
|
||||
xml.loadXML( data );
|
||||
}
|
||||
|
||||
tmp = xml.documentElement;
|
||||
|
||||
if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
|
||||
jQuery.error( "Invalid XML: " + data );
|
||||
}
|
||||
|
||||
return xml;
|
||||
},
|
||||
|
||||
noop: function() {},
|
||||
|
||||
// Evalulates a script in a global context
|
||||
|
@ -578,7 +572,7 @@ jQuery.extend({
|
|||
|
||||
script.type = "text/javascript";
|
||||
|
||||
if ( jQuery.support.scriptEval ) {
|
||||
if ( jQuery.support.scriptEval() ) {
|
||||
script.appendChild( document.createTextNode( data ) );
|
||||
} else {
|
||||
script.text = data;
|
||||
|
@ -816,6 +810,178 @@ jQuery.extend({
|
|||
return (new Date()).getTime();
|
||||
},
|
||||
|
||||
// Create a simple deferred (one callbacks list)
|
||||
_Deferred: function() {
|
||||
|
||||
var // callbacks list
|
||||
callbacks = [],
|
||||
// stored [ context , args ]
|
||||
fired,
|
||||
// to avoid firing when already doing so
|
||||
firing,
|
||||
// flag to know if the deferred has been cancelled
|
||||
cancelled,
|
||||
// the deferred itself
|
||||
deferred = {
|
||||
|
||||
// done( f1, f2, ...)
|
||||
done: function () {
|
||||
|
||||
if ( ! cancelled ) {
|
||||
|
||||
var args = arguments,
|
||||
i,
|
||||
length,
|
||||
elem,
|
||||
type,
|
||||
_fired;
|
||||
|
||||
if ( fired ) {
|
||||
_fired = fired;
|
||||
fired = 0;
|
||||
}
|
||||
|
||||
for ( i = 0, length = args.length ; i < length ; i++ ) {
|
||||
elem = args[ i ];
|
||||
type = jQuery.type( elem );
|
||||
if ( type === "array" ) {
|
||||
deferred.done.apply( deferred , elem );
|
||||
} else if ( type === "function" ) {
|
||||
callbacks.push( elem );
|
||||
}
|
||||
}
|
||||
|
||||
if ( _fired ) {
|
||||
deferred.resolveWith( _fired[ 0 ] , _fired[ 1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// resolve with given context and args
|
||||
resolveWith: function( context , args ) {
|
||||
if ( ! cancelled && ! fired && ! firing ) {
|
||||
|
||||
firing = 1;
|
||||
|
||||
try {
|
||||
while( callbacks[ 0 ] ) {
|
||||
callbacks.shift().apply( context , args );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fired = [ context , args ];
|
||||
firing = 0;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// resolve with this as context and given arguments
|
||||
resolve: function() {
|
||||
deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments );
|
||||
return this;
|
||||
},
|
||||
|
||||
// Has this deferred been resolved?
|
||||
isResolved: function() {
|
||||
return !!( firing || fired );
|
||||
},
|
||||
|
||||
// Cancel
|
||||
cancel: function() {
|
||||
cancelled = 1;
|
||||
callbacks = [];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
return deferred;
|
||||
},
|
||||
|
||||
// Full fledged deferred (two callbacks list)
|
||||
// Typical success/error system
|
||||
Deferred: function( func ) {
|
||||
|
||||
var deferred = jQuery._Deferred(),
|
||||
failDeferred = jQuery._Deferred(),
|
||||
promise;
|
||||
|
||||
// Add errorDeferred methods, then and promise
|
||||
jQuery.extend( deferred , {
|
||||
|
||||
then: function( doneCallbacks , failCallbacks ) {
|
||||
deferred.done( doneCallbacks ).fail( failCallbacks );
|
||||
return this;
|
||||
},
|
||||
fail: failDeferred.done,
|
||||
rejectWith: failDeferred.resolveWith,
|
||||
reject: failDeferred.resolve,
|
||||
isRejected: failDeferred.isResolved,
|
||||
// Get a promise for this deferred
|
||||
// If obj is provided, the promise aspect is added to the object
|
||||
// (i is used internally)
|
||||
promise: function( obj , i ) {
|
||||
if ( obj == null ) {
|
||||
if ( promise ) {
|
||||
return promise;
|
||||
}
|
||||
promise = obj = {};
|
||||
}
|
||||
i = promiseMethods.length;
|
||||
while( i-- ) {
|
||||
obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
// Make sure only one callback list will be used
|
||||
deferred.then( failDeferred.cancel , deferred.cancel );
|
||||
|
||||
// Unexpose cancel
|
||||
delete deferred.cancel;
|
||||
|
||||
// Call given func if any
|
||||
if ( func ) {
|
||||
func.call( deferred , deferred );
|
||||
}
|
||||
|
||||
return deferred;
|
||||
},
|
||||
|
||||
// Deferred helper
|
||||
when: function( object ) {
|
||||
var args = arguments,
|
||||
length = args.length,
|
||||
deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
|
||||
object :
|
||||
jQuery.Deferred(),
|
||||
promise = deferred.promise(),
|
||||
resolveArray;
|
||||
|
||||
if ( length > 1 ) {
|
||||
resolveArray = new Array( length );
|
||||
jQuery.each( args, function( index, element, args ) {
|
||||
jQuery.when( element ).done( function( value ) {
|
||||
args = arguments;
|
||||
resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value;
|
||||
if( ! --length ) {
|
||||
deferred.resolveWith( promise, resolveArray );
|
||||
}
|
||||
}).fail( function() {
|
||||
deferred.rejectWith( promise, arguments );
|
||||
});
|
||||
return !deferred.isRejected();
|
||||
});
|
||||
} else if ( deferred !== object ) {
|
||||
deferred.resolve( object );
|
||||
}
|
||||
return promise;
|
||||
},
|
||||
|
||||
// Use of jQuery.browser is frowned upon.
|
||||
// More details: http://docs.jquery.com/Utilities/jQuery.browser
|
||||
uaMatch: function( ua ) {
|
||||
|
@ -830,9 +996,31 @@ 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: {}
|
||||
});
|
||||
|
||||
// Create readyList deferred
|
||||
readyList = jQuery._Deferred();
|
||||
|
||||
// Populate the class2type map
|
||||
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
|
||||
class2type[ "[object " + name + "]" ] = name.toLowerCase();
|
||||
|
@ -855,9 +1043,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]+$/;
|
||||
}
|
||||
|
|
|
@ -263,8 +263,9 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
|
|||
|
||||
if ( document.documentElement.currentStyle ) {
|
||||
currentStyle = function( elem, name ) {
|
||||
var left, rsLeft,
|
||||
var left,
|
||||
ret = elem.currentStyle && elem.currentStyle[ name ],
|
||||
rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
|
||||
style = elem.style;
|
||||
|
||||
// From the awesome hack by Dean Edwards
|
||||
|
@ -275,17 +276,20 @@ if ( document.documentElement.currentStyle ) {
|
|||
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
|
||||
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;
|
||||
if ( rsLeft ) {
|
||||
elem.runtimeStyle.left = rsLeft;
|
||||
}
|
||||
}
|
||||
|
||||
return ret === "" ? "auto" : ret;
|
||||
};
|
||||
|
|
178
src/data.js
178
src/data.js
|
@ -1,7 +1,6 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var windowData = {},
|
||||
rbrace = /^(?:\{.*\}|\[.*\])$/;
|
||||
var rbrace = /^(?:\{.*\}|\[.*\])$/;
|
||||
|
||||
jQuery.extend({
|
||||
cache: {},
|
||||
|
@ -10,7 +9,8 @@ jQuery.extend({
|
|||
uuid: 0,
|
||||
|
||||
// Unique for each copy of jQuery on the page
|
||||
expando: "jQuery" + jQuery.now(),
|
||||
// Non-digits removed to match rinlinejQuery
|
||||
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
|
||||
|
||||
// The following elements throw uncatchable exceptions if you
|
||||
// attempt to add expando properties to them.
|
||||
|
@ -21,103 +21,171 @@ jQuery.extend({
|
|||
"applet": true
|
||||
},
|
||||
|
||||
data: function( elem, name, data ) {
|
||||
hasData: function( elem ) {
|
||||
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
|
||||
|
||||
return !!elem && !jQuery.isEmptyObject(elem);
|
||||
},
|
||||
|
||||
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
|
||||
if ( !jQuery.acceptData( elem ) ) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Avoid generating a new cache unless none exists and we
|
||||
// want to manipulate it.
|
||||
if ( typeof name === "object" ) {
|
||||
if ( !id ) {
|
||||
// Only DOM nodes need a new unique ID for each element since their data
|
||||
// ends up in the global cache
|
||||
if ( isNode ) {
|
||||
cache[ id ] = jQuery.extend(cache[ id ], name);
|
||||
|
||||
elem[ jQuery.expando ] = id = ++jQuery.uuid;
|
||||
} else {
|
||||
jQuery.extend( cache, name );
|
||||
id = jQuery.expando;
|
||||
}
|
||||
}
|
||||
|
||||
} 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 );
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we want to remove all of the element's data
|
||||
// See jQuery.data for more information
|
||||
if ( pvt ) {
|
||||
delete cache[ id ][ internalKey ];
|
||||
|
||||
// Don't destroy the parent cache unless the internal data object
|
||||
// had been the only thing left in it
|
||||
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var internalCache = cache[ id ][ internalKey ];
|
||||
|
||||
// Browsers that fail expando deletion also refuse to delete expandos on
|
||||
// the window, but it will allow it on all other JS objects; other browsers
|
||||
// don't care
|
||||
if ( jQuery.support.deleteExpando || cache != window ) {
|
||||
delete cache[ id ];
|
||||
} else {
|
||||
if ( isNode && jQuery.support.deleteExpando ) {
|
||||
delete elem[ jQuery.expando ];
|
||||
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 );
|
||||
|
||||
// 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 ];
|
||||
}
|
||||
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
|
||||
acceptData: function( elem ) {
|
||||
if ( elem.nodeName ) {
|
||||
|
|
|
@ -35,8 +35,10 @@ jQuery.each([ "Height", "Width" ], function( i, name ) {
|
|||
|
||||
if ( jQuery.isWindow( elem ) ) {
|
||||
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
|
||||
return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
|
||||
elem.document.body[ "client" + name ];
|
||||
// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
|
||||
var docElemProp = elem.document.documentElement[ "client" + name ];
|
||||
return elem.document.compatMode === "CSS1Compat" && docElemProp ||
|
||||
elem.document.body[ "client" + name ] || docElemProp;
|
||||
|
||||
// Get document width or height
|
||||
} else if ( elem.nodeType === 9 ) {
|
||||
|
|
12
src/effects.js
vendored
12
src/effects.js
vendored
|
@ -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", display );
|
||||
if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
|
||||
jQuery._data( this[i], "olddisplay", display );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,7 @@ jQuery.fx.prototype = {
|
|||
}
|
||||
|
||||
var r = parseFloat( jQuery.css( this.elem, this.prop ) );
|
||||
return r && r > -10000 ? r : 0;
|
||||
return r || 0;
|
||||
},
|
||||
|
||||
// Start an animation from one number to another
|
||||
|
|
74
src/event.js
74
src/event.js
|
@ -8,7 +8,7 @@ var rnamespaces = /\.(.*)$/,
|
|||
fcleanup = function( nm ) {
|
||||
return nm.replace(rescape, "\\$&");
|
||||
},
|
||||
focusCounts = { focusin: 0, focusout: 0 };
|
||||
eventKey = "events";
|
||||
|
||||
/*
|
||||
* A number of helper functions used for managing events.
|
||||
|
@ -50,7 +50,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 +58,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 +174,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 +286,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 +321,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 +356,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 +435,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;
|
||||
|
@ -600,6 +603,12 @@ jQuery.Event = function( src ) {
|
|||
if ( src && src.type ) {
|
||||
this.originalEvent = src;
|
||||
this.type = src.type;
|
||||
|
||||
// Events bubbling up the document may have been marked as prevented
|
||||
// by a handler lower down the tree; reflect the correct value.
|
||||
this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
|
||||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
|
||||
|
||||
// Event type
|
||||
} else {
|
||||
this.type = src;
|
||||
|
@ -781,12 +790,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 ) {
|
||||
|
@ -831,7 +840,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) );
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -870,21 +879,17 @@ if ( document.addEventListener ) {
|
|||
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
|
||||
jQuery.event.special[ fix ] = {
|
||||
setup: function() {
|
||||
if ( focusCounts[fix]++ === 0 ) {
|
||||
document.addEventListener( orig, handler, true );
|
||||
}
|
||||
this.addEventListener( orig, handler, true );
|
||||
},
|
||||
teardown: function() {
|
||||
if ( --focusCounts[fix] === 0 ) {
|
||||
document.removeEventListener( orig, handler, true );
|
||||
}
|
||||
this.removeEventListener( orig, handler, true );
|
||||
}
|
||||
};
|
||||
|
||||
function handler( e ) {
|
||||
e = jQuery.event.fix( e );
|
||||
e.type = fix;
|
||||
return jQuery.event.trigger( e, null, e.target );
|
||||
return jQuery.event.handle.call( this, e );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1079,7 +1084,7 @@ function liveHandler( event ) {
|
|||
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
|
||||
elems = [],
|
||||
selectors = [],
|
||||
events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
|
||||
events = jQuery._data( this, eventKey );
|
||||
|
||||
if ( typeof events === "function" ) {
|
||||
events = events.events;
|
||||
|
@ -1187,21 +1192,4 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
|
|||
}
|
||||
});
|
||||
|
||||
// Prevent memory leaks in IE
|
||||
// Window isn't included so as not to unbind existing unload events
|
||||
// More info:
|
||||
// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
|
||||
if ( window.attachEvent && !window.addEventListener ) {
|
||||
jQuery(window).bind("unload", function() {
|
||||
for ( var id in jQuery.cache ) {
|
||||
if ( jQuery.cache[ id ].handle ) {
|
||||
// Try/Catch is to handle iframes being unloaded, see #4280
|
||||
try {
|
||||
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})( jQuery );
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date:
|
||||
* Date: @DATE
|
||||
*/
|
||||
(function( window, undefined ) {
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
@ -370,24 +370,35 @@ function root( elem, cur ) {
|
|||
}
|
||||
|
||||
function cloneCopyEvent(orig, ret) {
|
||||
var i = 0;
|
||||
|
||||
ret.each(function() {
|
||||
if ( this.nodeType !== 1 || this.nodeName !== (orig[i] && orig[i].nodeName) ) {
|
||||
ret.each(function (nodeIndex) {
|
||||
if ( this.nodeType !== 1 || !jQuery.hasData(orig[nodeIndex]) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldData = jQuery.data( orig[i++] ),
|
||||
curData = jQuery.data( this, oldData ),
|
||||
events = oldData && oldData.events;
|
||||
// XXX remove for 1.5 RC or merge back in if there is actually a reason for this check that has been
|
||||
// unexposed by unit tests
|
||||
if ( this.nodeName !== (orig[nodeIndex] && orig[nodeIndex].nodeName) ) {
|
||||
throw "Cloned data mismatch";
|
||||
}
|
||||
|
||||
var internalKey = jQuery.expando,
|
||||
oldData = jQuery.data( orig[nodeIndex] ),
|
||||
curData = jQuery.data( this, oldData );
|
||||
|
||||
// Switch to use the internal data object, if it exists, for the next
|
||||
// stage of data copying
|
||||
if ( (oldData = oldData[ internalKey ]) ) {
|
||||
var events = oldData.events;
|
||||
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
|
||||
|
||||
if ( events ) {
|
||||
delete curData.handle;
|
||||
curData.events = {};
|
||||
|
||||
for ( var type in events ) {
|
||||
for ( var handler in events[ type ] ) {
|
||||
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
|
||||
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
|
||||
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -415,18 +426,30 @@ function cloneFixAttributes(src, dest) {
|
|||
// attribute) to identify the type of content to display
|
||||
if ( nodeName === "object" ) {
|
||||
dest.outerHTML = src.outerHTML;
|
||||
|
||||
} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
|
||||
// IE6-8 fails to persist the checked state of a cloned checkbox
|
||||
// or radio button. Worse, IE6-7 fail to give the cloned element
|
||||
// a checked appearance if the defaultChecked value isn't also set
|
||||
if ( src.checked ) {
|
||||
dest.defaultChecked = dest.checked = src.checked;
|
||||
}
|
||||
|
||||
// IE6-8 fails to persist the checked state of a cloned checkbox
|
||||
// or radio button
|
||||
else if ( nodeName === "input" && src.checked ) {
|
||||
dest.defaultChecked = dest.checked = src.checked;
|
||||
// IE6-7 get confused and end up setting the value of a cloned
|
||||
// checkbox/radio button to an empty string instead of "on"
|
||||
if ( dest.value !== src.value ) {
|
||||
dest.value = src.value;
|
||||
}
|
||||
|
||||
// IE6-8 fails to return the selected option to the default selected
|
||||
// state when cloning options
|
||||
else if ( nodeName === "option" ) {
|
||||
} else if ( nodeName === "option" ) {
|
||||
dest.selected = src.defaultSelected;
|
||||
|
||||
// IE6-8 fails to set the defaultValue to the correct value when
|
||||
// cloning other types of input fields
|
||||
} else if ( nodeName === "input" || nodeName === "textarea" ) {
|
||||
dest.defaultValue = src.defaultValue;
|
||||
}
|
||||
|
||||
// Event data gets referenced instead of copied if the expando
|
||||
|
@ -438,12 +461,12 @@ jQuery.buildFragment = function( args, nodes, scripts ) {
|
|||
var fragment, cacheable, cacheresults,
|
||||
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
|
||||
|
||||
// Only cache "small" (1/2 KB) strings that are associated with the main document
|
||||
// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
|
||||
// Cloning options loses the selected state, so don't cache them
|
||||
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
|
||||
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
|
||||
if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
|
||||
!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
|
||||
args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
|
||||
|
||||
cacheable = true;
|
||||
cacheresults = jQuery.fragments[ args[0] ];
|
||||
|
@ -592,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++ ) {
|
||||
|
@ -604,17 +626,23 @@ 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 );
|
||||
}
|
||||
}
|
||||
|
||||
// Null the DOM reference to avoid IE6/7/8 leak (#7054)
|
||||
if ( data.handle ) {
|
||||
data.handle.elem = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ( deleteExpando ) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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'/>";
|
||||
|
@ -68,7 +65,7 @@
|
|||
deleteExpando: true,
|
||||
optDisabled: false,
|
||||
checkClone: false,
|
||||
scriptEval: false,
|
||||
_scriptEval: null,
|
||||
noCloneEvent: true,
|
||||
boxModel: null,
|
||||
inlineBlockNeedsLayout: false,
|
||||
|
@ -81,6 +78,12 @@
|
|||
select.disabled = true;
|
||||
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";
|
||||
try {
|
||||
script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
|
||||
|
@ -92,21 +95,29 @@
|
|||
// tag with appendChild/createTextNode
|
||||
// (IE doesn't support this, fails, and uses .text instead)
|
||||
if ( window[ id ] ) {
|
||||
jQuery.support.scriptEval = true;
|
||||
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
|
||||
|
@ -151,7 +162,7 @@
|
|||
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
|
||||
}
|
||||
|
||||
div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>";
|
||||
div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
|
||||
var tds = div.getElementsByTagName("td");
|
||||
|
||||
// Check if table cells still have offsetWidth/Height when they are set
|
||||
|
@ -181,6 +192,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;");
|
||||
|
@ -195,6 +214,6 @@
|
|||
jQuery.support.changeBubbles = eventSupported("change");
|
||||
|
||||
// release memory in IE
|
||||
root = script = div = all = a = null;
|
||||
div = all = a = null;
|
||||
})();
|
||||
})( jQuery );
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var jsc = jQuery.now(),
|
||||
jsre = /\=\?(&|$)/,
|
||||
rquery_jsonp = /\?/;
|
||||
|
||||
// Default jsonp callback name
|
||||
jQuery.ajaxSettings.jsonpCallback = function() {
|
||||
return "jsonp" + jsc++;
|
||||
};
|
||||
|
||||
// Normalize jsonp queries
|
||||
// 1) put callback parameter in url or data
|
||||
// 2) ensure transportDataType is json
|
||||
// 3) ensure options jsonp is always provided so that jsonp requests are always
|
||||
// json request with the jsonp option set
|
||||
jQuery.xhr.prefilter( function(s) {
|
||||
|
||||
var transportDataType = s.dataTypes[0];
|
||||
|
||||
if ( s.jsonp ||
|
||||
transportDataType === "jsonp" ||
|
||||
transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
|
||||
|
||||
var jsonp = s.jsonp = s.jsonp || "callback",
|
||||
jsonpCallback = s.jsonpCallback =
|
||||
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
|
||||
url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
|
||||
data = s.url == url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
|
||||
|
||||
if ( url == s.url && data == s.data ) {
|
||||
url = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
|
||||
}
|
||||
|
||||
s.url = url;
|
||||
s.data = data;
|
||||
|
||||
s.dataTypes[0] = "json";
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Bind transport to json dataType
|
||||
jQuery.xhr.bindTransport("json", function(s) {
|
||||
|
||||
if ( s.jsonp ) {
|
||||
|
||||
// Put callback in place
|
||||
var responseContainer,
|
||||
jsonpCallback = s.jsonpCallback,
|
||||
previous = window[ jsonpCallback ];
|
||||
|
||||
window [ jsonpCallback ] = function( response ) {
|
||||
responseContainer = [response];
|
||||
};
|
||||
|
||||
s.complete = [function() {
|
||||
|
||||
// Set callback back to previous value
|
||||
window[ jsonpCallback ] = previous;
|
||||
|
||||
// Call if it was a function and we have a response
|
||||
if ( previous) {
|
||||
if ( responseContainer && jQuery.isFunction ( previous ) ) {
|
||||
window[ jsonpCallback ] ( responseContainer[0] );
|
||||
}
|
||||
} else {
|
||||
// else, more memory leak avoidance
|
||||
try{ delete window[ jsonpCallback ]; } catch(e){}
|
||||
}
|
||||
|
||||
}, s.complete ];
|
||||
|
||||
// Use data converter to retrieve json after script execution
|
||||
s.dataConverters["script => json"] = function() {
|
||||
if ( ! responseContainer ) {
|
||||
jQuery.error("Callback '" + jsonpCallback + "' was not called");
|
||||
}
|
||||
return responseContainer[ 0 ];
|
||||
};
|
||||
|
||||
// Delegate to script transport
|
||||
return "script";
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})( jQuery );
|
|
@ -1,191 +0,0 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var // Next fake timer id
|
||||
xhrPollingId = jQuery.now(),
|
||||
|
||||
// Callbacks hashtable
|
||||
xhrs = {},
|
||||
|
||||
// #5280: see end of file
|
||||
xhrUnloadAbortMarker = [];
|
||||
|
||||
|
||||
jQuery.xhr.bindTransport( function( s , determineDataType ) {
|
||||
|
||||
// Cross domain only allowed if supported through XMLHttpRequest
|
||||
if ( ! s.crossDomain || jQuery.support.cors ) {
|
||||
|
||||
var callback;
|
||||
|
||||
return {
|
||||
|
||||
send: function(headers, complete) {
|
||||
|
||||
var xhr = s.xhr(),
|
||||
handle;
|
||||
|
||||
// Open the socket
|
||||
// Passing null username, generates a login popup on Opera (#2865)
|
||||
if ( s.username ) {
|
||||
xhr.open(s.type, s.url, s.async, s.username, s.password);
|
||||
} else {
|
||||
xhr.open(s.type, s.url, s.async);
|
||||
}
|
||||
|
||||
// Requested-With header
|
||||
// Not set for crossDomain requests with no content
|
||||
// (see why at http://trac.dojotoolkit.org/ticket/9486)
|
||||
// Won't change header if already provided in beforeSend
|
||||
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
|
||||
headers["x-requested-with"] = "XMLHttpRequest";
|
||||
}
|
||||
|
||||
// Need an extra try/catch for cross domain requests in Firefox 3
|
||||
try {
|
||||
|
||||
jQuery.each(headers, function(key,value) {
|
||||
xhr.setRequestHeader(key,value);
|
||||
});
|
||||
|
||||
} catch(_) {}
|
||||
|
||||
// Do send the request
|
||||
try {
|
||||
xhr.send( ( s.hasContent && s.data ) || null );
|
||||
} catch(e) {
|
||||
complete(0, "error", "" + e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listener
|
||||
callback = function ( abortStatusText ) {
|
||||
|
||||
// Was never called and is aborted or complete
|
||||
if ( callback && ( abortStatusText || xhr.readyState === 4 ) ) {
|
||||
|
||||
// Do not listen anymore
|
||||
if (handle) {
|
||||
xhr.onreadystatechange = jQuery.noop;
|
||||
delete xhrs[ handle ];
|
||||
handle = undefined;
|
||||
}
|
||||
|
||||
callback = 0;
|
||||
|
||||
// Get info
|
||||
var status, statusText, response, responseHeaders;
|
||||
|
||||
if ( abortStatusText ) {
|
||||
|
||||
if ( xhr.readyState !== 4 ) {
|
||||
xhr.abort();
|
||||
}
|
||||
|
||||
// Stop here if unloadAbort
|
||||
if ( abortStatusText === xhrUnloadAbortMarker ) {
|
||||
return;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
statusText = abortStatusText;
|
||||
|
||||
} else {
|
||||
|
||||
status = xhr.status;
|
||||
|
||||
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
|
||||
|
||||
statusText = xhr.statusText;
|
||||
|
||||
} catch( e ) {
|
||||
|
||||
statusText = ""; // We normalize with Webkit giving an empty statusText
|
||||
|
||||
}
|
||||
|
||||
responseHeaders = xhr.getAllResponseHeaders();
|
||||
|
||||
// Filter status for non standard behaviours
|
||||
// (so many they seem to be the actual "standard")
|
||||
status =
|
||||
// Opera returns 0 when it should be 304
|
||||
// Webkit returns 0 for failing cross-domain no matter the real status
|
||||
status === 0 ?
|
||||
(
|
||||
! s.crossDomain || statusText ? // Webkit, Firefox: filter out faulty cross-domain requests
|
||||
(
|
||||
responseHeaders ? // Opera: filter out real aborts #6060
|
||||
304
|
||||
:
|
||||
0
|
||||
)
|
||||
:
|
||||
302 // We assume 302 but could be anything cross-domain related
|
||||
)
|
||||
:
|
||||
(
|
||||
status == 1223 ? // IE sometimes returns 1223 when it should be 204 (see #1450)
|
||||
204
|
||||
:
|
||||
status
|
||||
);
|
||||
|
||||
// Guess response if needed & update datatype accordingly
|
||||
if ( status >= 200 && status < 300 ) {
|
||||
response =
|
||||
determineDataType(
|
||||
s,
|
||||
xhr.getResponseHeader("content-type"),
|
||||
xhr.responseText,
|
||||
xhr.responseXML );
|
||||
}
|
||||
}
|
||||
|
||||
// Call complete
|
||||
complete(status,statusText,response,responseHeaders);
|
||||
}
|
||||
};
|
||||
|
||||
// if we're in sync mode
|
||||
// or it's in cache and has been retrieved directly (IE6 & IE7)
|
||||
// we need to manually fire the callback
|
||||
if ( ! s.async || xhr.readyState === 4 ) {
|
||||
|
||||
callback();
|
||||
|
||||
} else {
|
||||
|
||||
// Listener is externalized to handle abort on unload
|
||||
handle = xhrPollingId++;
|
||||
xhrs[ handle ] = xhr;
|
||||
xhr.onreadystatechange = function() {
|
||||
callback();
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
abort: function(statusText) {
|
||||
if ( callback ) {
|
||||
callback(statusText);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// #5280: we need to abort on unload or IE will keep connections alive
|
||||
jQuery(window).bind( "unload" , function() {
|
||||
|
||||
// Abort all pending requests
|
||||
jQuery.each(xhrs, function(_, xhr) {
|
||||
if ( xhr.onreadystatechange ) {
|
||||
xhr.onreadystatechange( xhrUnloadAbortMarker );
|
||||
}
|
||||
});
|
||||
|
||||
// Resest polling structure to be safe
|
||||
xhrs = {};
|
||||
|
||||
});
|
||||
|
||||
})( jQuery );
|
|
@ -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 ) {
|
||||
|
@ -134,7 +141,7 @@ jQuery.fn.extend({
|
|||
|
||||
add: function( selector, context ) {
|
||||
var set = typeof selector === "string" ?
|
||||
jQuery( selector, context || this.context ) :
|
||||
jQuery( selector, context ) :
|
||||
jQuery.makeArray( selector ),
|
||||
all = jQuery.merge( this.get(), set );
|
||||
|
||||
|
@ -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(",") );
|
||||
};
|
||||
});
|
||||
|
||||
|
|
909
src/xhr.js
909
src/xhr.js
|
@ -1,909 +0,0 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var rquery_xhr = /\?/,
|
||||
rhash = /#.*$/,
|
||||
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
|
||||
rnoContent = /^(?:GET|HEAD)$/,
|
||||
rts = /([?&])_=[^&]*/,
|
||||
rurl = /^(\w+:)?\/\/([^\/?#]+)/,
|
||||
|
||||
sliceFunc = Array.prototype.slice,
|
||||
|
||||
isFunction = jQuery.isFunction;
|
||||
|
||||
// Creates a jQuery xhr object
|
||||
jQuery.xhr = function( _native ) {
|
||||
|
||||
if ( _native ) {
|
||||
return jQuery.ajaxSettings.xhr();
|
||||
}
|
||||
|
||||
function reset(force) {
|
||||
|
||||
// We only need to reset if we went through the init phase
|
||||
// (with the exception of object creation)
|
||||
if ( force || internal ) {
|
||||
|
||||
// Reset callbacks lists
|
||||
callbacksLists = {
|
||||
success: createCBList(),
|
||||
error: createCBList(),
|
||||
complete: createCBList()
|
||||
};
|
||||
|
||||
// Reset private variables
|
||||
requestHeaders = {};
|
||||
responseHeadersString = responseHeaders = internal = done = timeoutTimer = s = undefined;
|
||||
|
||||
// Reset state
|
||||
xhr.readyState = 0;
|
||||
sendFlag = 0;
|
||||
|
||||
// Remove responseX fields
|
||||
for ( var name in xhr ) {
|
||||
if ( /^response/.test(name) ) {
|
||||
delete xhr[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
var // Options extraction
|
||||
|
||||
// Remove hash character (#7531: first for string promotion)
|
||||
url = s.url = ( "" + s.url ).replace( rhash , "" ),
|
||||
|
||||
// Uppercase the type
|
||||
type = s.type = s.type.toUpperCase(),
|
||||
|
||||
// Determine if request has content
|
||||
hasContent = s.hasContent = ! rnoContent.test( type ),
|
||||
|
||||
// Extract dataTypes list
|
||||
dataType = s.dataType,
|
||||
dataTypes = s.dataTypes = dataType ? jQuery.trim(dataType).toLowerCase().split(/\s+/) : ["*"],
|
||||
|
||||
// Determine if a cross-domain request is in order
|
||||
parts = rurl.exec( url.toLowerCase() ),
|
||||
loc = location,
|
||||
crossDomain = s.crossDomain = !!( parts && ( parts[1] && parts[1] != loc.protocol || parts[2] != loc.host ) ),
|
||||
|
||||
// Get other options locally
|
||||
data = s.data,
|
||||
originalContentType = s.contentType,
|
||||
prefilters = s.prefilters,
|
||||
accepts = s.accepts,
|
||||
headers = s.headers,
|
||||
|
||||
// Other Variables
|
||||
transportDataType,
|
||||
i;
|
||||
|
||||
// Convert data if not already a string
|
||||
if ( data && s.processData && typeof data != "string" ) {
|
||||
data = s.data = jQuery.param( data , s.traditional );
|
||||
}
|
||||
|
||||
// Apply option prefilters
|
||||
for (i in prefilters) {
|
||||
prefilters[i](s);
|
||||
}
|
||||
|
||||
// Get internal
|
||||
internal = selectTransport( s );
|
||||
|
||||
// Re-actualize url & data
|
||||
url = s.url;
|
||||
data = s.data;
|
||||
|
||||
// If internal was found
|
||||
if ( internal ) {
|
||||
|
||||
// Get transportDataType
|
||||
transportDataType = dataTypes[0];
|
||||
|
||||
// More options handling for requests with no content
|
||||
if ( ! hasContent ) {
|
||||
|
||||
// If data is available, append data to url
|
||||
if ( data ) {
|
||||
url += (rquery_xhr.test(url) ? "&" : "?") + data;
|
||||
}
|
||||
|
||||
// Add anti-cache in url if needed
|
||||
if ( s.cache === false ) {
|
||||
|
||||
var ts = jQuery.now(),
|
||||
// try replacing _= if it is there
|
||||
ret = url.replace(rts, "$1_=" + ts );
|
||||
|
||||
// if nothing was replaced, add timestamp to the end
|
||||
url = ret + ((ret == url) ? (rquery_xhr.test(url) ? "&" : "?") + "_=" + ts : "");
|
||||
}
|
||||
|
||||
s.url = url;
|
||||
}
|
||||
|
||||
// Set the correct header, if data is being sent
|
||||
if ( ( data && hasContent ) || originalContentType ) {
|
||||
requestHeaders["content-type"] = s.contentType;
|
||||
}
|
||||
|
||||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
||||
if ( s.ifModified ) {
|
||||
if ( jQuery_lastModified[url] ) {
|
||||
requestHeaders["if-modified-since"] = jQuery_lastModified[url];
|
||||
}
|
||||
if ( jQuery_etag[url] ) {
|
||||
requestHeaders["if-none-match"] = jQuery_etag[url];
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Accepts header for the server, depending on the dataType
|
||||
requestHeaders.accept = transportDataType && accepts[ transportDataType ] ?
|
||||
accepts[ transportDataType ] + ( transportDataType !== "*" ? ", */*; q=0.01" : "" ) :
|
||||
accepts[ "*" ];
|
||||
|
||||
// Check for headers option
|
||||
for ( i in headers ) {
|
||||
requestHeaders[ i.toLowerCase() ] = headers[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
callbackContext = s.context || s;
|
||||
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
|
||||
|
||||
for ( i in callbacksLists ) {
|
||||
callbacksLists[i].bind(s[i]);
|
||||
}
|
||||
|
||||
// Watch for a new set of requests
|
||||
if ( s.global && jQuery.active++ === 0 ) {
|
||||
jQuery.event.trigger( "ajaxStart" );
|
||||
}
|
||||
|
||||
done = whenDone;
|
||||
}
|
||||
|
||||
function whenDone(status, statusText, response, headers) {
|
||||
|
||||
// Called once
|
||||
done = undefined;
|
||||
|
||||
// Reset sendFlag
|
||||
sendFlag = 0;
|
||||
|
||||
// Cache response headers
|
||||
responseHeadersString = headers || "";
|
||||
|
||||
// Clear timeout if it exists
|
||||
if ( timeoutTimer ) {
|
||||
clearTimeout(timeoutTimer);
|
||||
}
|
||||
|
||||
var // Reference url
|
||||
url = s.url,
|
||||
// and ifModified status
|
||||
ifModified = s.ifModified,
|
||||
|
||||
// Is it a success?
|
||||
isSuccess = 0,
|
||||
// Stored success
|
||||
success,
|
||||
// Stored error
|
||||
error = statusText;
|
||||
|
||||
// If not timeout, force a jQuery-compliant status text
|
||||
if ( statusText != "timeout" ) {
|
||||
statusText = ( status >= 200 && status < 300 ) ?
|
||||
"success" :
|
||||
( status === 304 ? "notmodified" : "error" );
|
||||
}
|
||||
|
||||
// If successful, handle type chaining
|
||||
if ( statusText === "success" || statusText === "notmodified" ) {
|
||||
|
||||
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
||||
if ( ifModified ) {
|
||||
var lastModified = xhr.getResponseHeader("Last-Modified"),
|
||||
etag = xhr.getResponseHeader("Etag");
|
||||
|
||||
if (lastModified) {
|
||||
jQuery_lastModified[url] = lastModified;
|
||||
}
|
||||
if (etag) {
|
||||
jQuery_etag[url] = etag;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ifModified && statusText === "notmodified" ) {
|
||||
|
||||
success = null;
|
||||
isSuccess = 1;
|
||||
|
||||
} else {
|
||||
// Chain data conversions and determine the final value
|
||||
// (if an exception is thrown in the process, it'll be notified as an error)
|
||||
try {
|
||||
|
||||
function checkData(data) {
|
||||
if ( data !== undefined ) {
|
||||
var testFunction = s.dataCheckers[srcDataType];
|
||||
if ( isFunction( testFunction ) ) {
|
||||
testFunction(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertData (data) {
|
||||
var conversionFunction = dataConverters[srcDataType+" => "+destDataType] ||
|
||||
dataConverters["* => "+destDataType],
|
||||
noFunction = ! isFunction( conversionFunction );
|
||||
if ( noFunction ) {
|
||||
if ( srcDataType != "text" && destDataType != "text" ) {
|
||||
// We try to put text inbetween
|
||||
var first = dataConverters[srcDataType+" => text"] ||
|
||||
dataConverters["* => text"],
|
||||
second = dataConverters["text => "+destDataType] ||
|
||||
dataConverters["* => "+destDataType],
|
||||
areFunctions = isFunction( first ) && isFunction( second );
|
||||
if ( areFunctions ) {
|
||||
conversionFunction = function (data) {
|
||||
return second( first ( data ) );
|
||||
};
|
||||
}
|
||||
noFunction = ! areFunctions;
|
||||
}
|
||||
if ( noFunction ) {
|
||||
jQuery.error( "no data converter between " + srcDataType + " and " + destDataType );
|
||||
}
|
||||
|
||||
}
|
||||
return conversionFunction(data);
|
||||
}
|
||||
|
||||
var dataTypes = s.dataTypes,
|
||||
i,
|
||||
length,
|
||||
data = response,
|
||||
dataConverters = s.dataConverters,
|
||||
srcDataType,
|
||||
destDataType,
|
||||
responseTypes = s.xhrResponseFields;
|
||||
|
||||
for ( i = 0, length = dataTypes.length ; i < length ; i++ ) {
|
||||
|
||||
destDataType = dataTypes[i];
|
||||
|
||||
if ( !srcDataType ) { // First time
|
||||
|
||||
// Copy type
|
||||
srcDataType = destDataType;
|
||||
// Check
|
||||
checkData(data);
|
||||
// Apply dataFilter
|
||||
if ( isFunction( s.dataFilter ) ) {
|
||||
data = s.dataFilter(data, s.dataType);
|
||||
// Recheck data
|
||||
checkData(data);
|
||||
}
|
||||
|
||||
} else { // Subsequent times
|
||||
|
||||
// handle auto
|
||||
// JULIAN: for reasons unknown to me === doesn't work here
|
||||
if (destDataType == "*") {
|
||||
|
||||
destDataType = srcDataType;
|
||||
|
||||
} else if ( srcDataType != destDataType ) {
|
||||
|
||||
// Convert
|
||||
data = convertData(data);
|
||||
// Copy type & check
|
||||
srcDataType = destDataType;
|
||||
checkData(data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Copy response into the xhr if it hasn't been already
|
||||
var responseDataType,
|
||||
responseType = responseTypes[srcDataType];
|
||||
|
||||
if ( responseType ) {
|
||||
|
||||
responseDataType = srcDataType;
|
||||
|
||||
} else {
|
||||
|
||||
responseType = responseTypes[ responseDataType = "text" ];
|
||||
|
||||
}
|
||||
|
||||
if ( responseType !== 1 ) {
|
||||
xhr[ "response" + responseType ] = data;
|
||||
responseTypes[ responseType ] = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We have a real success
|
||||
success = data;
|
||||
isSuccess = 1;
|
||||
|
||||
} catch(e) {
|
||||
|
||||
statusText = "parsererror";
|
||||
error = "" + e;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else { // if not success, mark it as an error
|
||||
|
||||
error = error || statusText;
|
||||
|
||||
}
|
||||
|
||||
// Set data for the fake xhr object
|
||||
xhr.status = status;
|
||||
xhr.statusText = statusText;
|
||||
|
||||
// Keep local copies of vars in case callbacks re-use the xhr
|
||||
var _s = s,
|
||||
_callbacksLists = callbacksLists,
|
||||
_callbackContext = callbackContext,
|
||||
_globalEventContext = globalEventContext;
|
||||
|
||||
// Set state if the xhr hasn't been re-used
|
||||
function _setState( value ) {
|
||||
if ( xhr.readyState && s === _s ) {
|
||||
setState( value );
|
||||
}
|
||||
}
|
||||
|
||||
// Really completed?
|
||||
if ( status && s.async ) {
|
||||
setState( 2 );
|
||||
_setState( 3 );
|
||||
}
|
||||
|
||||
// We're done
|
||||
_setState( 4 );
|
||||
|
||||
// Success
|
||||
_callbacksLists.success.fire( isSuccess , _callbackContext , success, statusText, xhr);
|
||||
if ( isSuccess && _s.global ) {
|
||||
_globalEventContext.trigger( "ajaxSuccess", [xhr, _s, success] );
|
||||
}
|
||||
// Error
|
||||
_callbacksLists.error.fire( ! isSuccess , _callbackContext , xhr, statusText, error);
|
||||
if ( !isSuccess && _s.global ) {
|
||||
_globalEventContext.trigger( "ajaxError", [xhr, _s, error] );
|
||||
}
|
||||
// Complete
|
||||
_callbacksLists.complete.fire( 1 , _callbackContext, xhr, statusText);
|
||||
if ( _s.global ) {
|
||||
_globalEventContext.trigger( "ajaxComplete", [xhr, _s] );
|
||||
// Handle the global AJAX counter
|
||||
if ( ! --jQuery.active ) {
|
||||
jQuery.event.trigger( "ajaxStop" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ready state control
|
||||
function checkState( expected , test ) {
|
||||
if ( expected !== true && ( expected === false || test === false || xhr.readyState !== expected ) ) {
|
||||
jQuery.error("INVALID_STATE_ERR");
|
||||
}
|
||||
}
|
||||
|
||||
// Ready state change
|
||||
function setState( value ) {
|
||||
xhr.readyState = value;
|
||||
if ( isFunction( xhr.onreadystatechange ) ) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
}
|
||||
|
||||
var // jQuery lists
|
||||
jQuery_lastModified = jQuery.lastModified,
|
||||
jQuery_etag = jQuery.etag,
|
||||
// Options object
|
||||
s,
|
||||
// Callback stuff
|
||||
callbackContext,
|
||||
globalEventContext,
|
||||
callbacksLists,
|
||||
// Headers (they are sent all at once)
|
||||
requestHeaders,
|
||||
// Response headers
|
||||
responseHeadersString,
|
||||
responseHeaders,
|
||||
// Done callback
|
||||
done,
|
||||
// transport
|
||||
internal,
|
||||
// timeout handle
|
||||
timeoutTimer,
|
||||
// The send flag
|
||||
sendFlag,
|
||||
// Fake xhr
|
||||
xhr = {
|
||||
// state
|
||||
readyState: 0,
|
||||
|
||||
// Callback
|
||||
onreadystatechange: null,
|
||||
|
||||
// Open
|
||||
open: function(type, url, async, username, password) {
|
||||
|
||||
xhr.abort();
|
||||
reset();
|
||||
|
||||
s = {
|
||||
type: type,
|
||||
url: url,
|
||||
async: async,
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
|
||||
setState(1);
|
||||
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// Send
|
||||
send: function(data, moreOptions) {
|
||||
|
||||
checkState(1 , !sendFlag);
|
||||
|
||||
s.data = data;
|
||||
|
||||
s = jQuery.extend( true,
|
||||
{},
|
||||
jQuery.ajaxSettings,
|
||||
s,
|
||||
moreOptions || ( moreOptions === false ? { global: false } : {} ) );
|
||||
|
||||
if ( moreOptions ) {
|
||||
// We force the original context
|
||||
// (plain objects used as context get extended)
|
||||
s.context = moreOptions.context;
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
// If not internal, abort
|
||||
if ( ! internal ) {
|
||||
done( 0 , "transport not found" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow custom headers/mimetypes and early abort
|
||||
if ( s.beforeSend ) {
|
||||
|
||||
var _s = s;
|
||||
|
||||
if ( s.beforeSend.call(callbackContext, xhr, s) === false || ! xhr.readyState || _s !== s ) {
|
||||
|
||||
// Abort if not done
|
||||
if ( xhr.readyState && _s === s ) {
|
||||
xhr.abort();
|
||||
}
|
||||
|
||||
// Handle the global AJAX counter
|
||||
if ( _s.global && ! --jQuery.active ) {
|
||||
jQuery.event.trigger( "ajaxStop" );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sendFlag = 1;
|
||||
|
||||
// Send global event
|
||||
if ( s.global ) {
|
||||
globalEventContext.trigger("ajaxSend", [xhr, s]);
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if ( s.async && s.timeout > 0 ) {
|
||||
timeoutTimer = setTimeout(function(){
|
||||
xhr.abort("timeout");
|
||||
}, s.timeout);
|
||||
}
|
||||
|
||||
if ( s.async ) {
|
||||
setState(1);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
internal.send(requestHeaders, done);
|
||||
return xhr;
|
||||
|
||||
} catch (e) {
|
||||
|
||||
if ( done ) {
|
||||
|
||||
done(0, "error", "" + e);
|
||||
|
||||
} else {
|
||||
|
||||
jQuery.error(e);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Caches the header
|
||||
setRequestHeader: function(name,value) {
|
||||
checkState(1, !sendFlag);
|
||||
requestHeaders[ name.toLowerCase() ] = value;
|
||||
return xhr;
|
||||
},
|
||||
|
||||
// Raw string
|
||||
getAllResponseHeaders: function() {
|
||||
return xhr.readyState <= 1 ? "" : responseHeadersString;
|
||||
},
|
||||
|
||||
// Builds headers hashtable if needed
|
||||
getResponseHeader: function( key ) {
|
||||
|
||||
if ( xhr.readyState <= 1 ) {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
if ( responseHeaders === undefined ) {
|
||||
|
||||
responseHeaders = {};
|
||||
|
||||
if ( typeof responseHeadersString === "string" ) {
|
||||
|
||||
var match;
|
||||
|
||||
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
|
||||
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseHeaders[ key.toLowerCase() ];
|
||||
},
|
||||
|
||||
// Cancel the request
|
||||
abort: function(statusText) {
|
||||
if (internal) {
|
||||
internal.abort( statusText || "abort" );
|
||||
}
|
||||
xhr.readyState = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Init data (so that we can bind callbacks early
|
||||
reset(1);
|
||||
|
||||
// Install callbacks related methods
|
||||
jQuery.each(callbacksLists, function(name) {
|
||||
var list;
|
||||
xhr[name] = function() {
|
||||
list = callbacksLists[name];
|
||||
if ( list ) {
|
||||
list.bind.apply(list, arguments );
|
||||
}
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
||||
// Return the xhr emulation
|
||||
return xhr;
|
||||
};
|
||||
|
||||
// Create a callback list
|
||||
function createCBList() {
|
||||
|
||||
var functors = [],
|
||||
autoFire = 0,
|
||||
fireArgs,
|
||||
list = {
|
||||
|
||||
fire: function( flag , context ) {
|
||||
|
||||
// Save info for later bindings
|
||||
fireArgs = arguments;
|
||||
|
||||
// Remove autoFire to keep bindings in order
|
||||
autoFire = 0;
|
||||
|
||||
var args = sliceFunc.call( fireArgs , 2 );
|
||||
|
||||
// Execute callbacks
|
||||
while ( flag && functors.length ) {
|
||||
flag = functors.shift().apply( context , args ) !== false;
|
||||
}
|
||||
|
||||
// Clean if asked to stop
|
||||
if ( ! flag ) {
|
||||
clean();
|
||||
}
|
||||
|
||||
// Set autoFire
|
||||
autoFire = 1;
|
||||
},
|
||||
|
||||
bind: function() {
|
||||
|
||||
var args = arguments,
|
||||
i = 0,
|
||||
length = args.length,
|
||||
func;
|
||||
|
||||
for ( ; i < length ; i++ ) {
|
||||
|
||||
func = args[ i ];
|
||||
|
||||
if ( jQuery.isArray(func) ) {
|
||||
|
||||
list.bind.apply( list , func );
|
||||
|
||||
} else if ( isFunction(func) ) {
|
||||
|
||||
// Add if not already in
|
||||
if ( ! pos( func ) ) {
|
||||
functors.push( func );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( autoFire ) {
|
||||
list.fire.apply( list , fireArgs );
|
||||
}
|
||||
},
|
||||
|
||||
unbind: function() {
|
||||
|
||||
var i = 0,
|
||||
args = arguments,
|
||||
length = args.length,
|
||||
func,
|
||||
position;
|
||||
|
||||
if ( length ) {
|
||||
|
||||
for( ; i < length ; i++ ) {
|
||||
func = args[i];
|
||||
if ( jQuery.isArray(func) ) {
|
||||
list.unbind.apply(list,func);
|
||||
} else if ( isFunction(func) ) {
|
||||
position = pos(func);
|
||||
if ( position ) {
|
||||
functors.splice(position-1,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
functors = [];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Get the index of the functor in the list (1-based)
|
||||
function pos( func ) {
|
||||
for (var i = 0, length = functors.length; i < length && functors[i] !== func; i++) {
|
||||
}
|
||||
return i < length ? ( i + 1 ) : 0;
|
||||
}
|
||||
|
||||
// Clean the object
|
||||
function clean() {
|
||||
// Empty callbacks list
|
||||
functors = [];
|
||||
// Inhibit methods
|
||||
for (var i in list) {
|
||||
list[i] = jQuery.noop;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
jQuery.extend(jQuery.xhr, {
|
||||
|
||||
// Add new prefilter
|
||||
prefilter: function (functor) {
|
||||
if ( isFunction(functor) ) {
|
||||
jQuery.ajaxSettings.prefilters.push( functor );
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Bind a transport to one or more dataTypes
|
||||
bindTransport: function () {
|
||||
|
||||
var args = arguments,
|
||||
i,
|
||||
start = 0,
|
||||
length = args.length,
|
||||
dataTypes = [ "*" ],
|
||||
functors = [],
|
||||
functor,
|
||||
first,
|
||||
append,
|
||||
list,
|
||||
transports = jQuery.ajaxSettings.transports;
|
||||
|
||||
if ( length ) {
|
||||
|
||||
if ( ! isFunction( args[ 0 ] ) ) {
|
||||
|
||||
dataTypes = args[ 0 ].toLowerCase().split(/\s+/);
|
||||
start = 1;
|
||||
|
||||
}
|
||||
|
||||
if ( dataTypes.length && start < length ) {
|
||||
|
||||
for ( i = start; i < length; i++ ) {
|
||||
functor = args[i];
|
||||
if ( isFunction(functor) ) {
|
||||
functors.push( functor );
|
||||
}
|
||||
}
|
||||
|
||||
if ( functors.length ) {
|
||||
|
||||
jQuery.each ( dataTypes, function( _ , dataType ) {
|
||||
|
||||
first = /^\+/.test( dataType );
|
||||
|
||||
if (first) {
|
||||
dataType = dataType.substr(1);
|
||||
}
|
||||
|
||||
if ( dataType !== "" ) {
|
||||
|
||||
append = Array.prototype[ first ? "unshift" : "push" ];
|
||||
|
||||
list = transports[ dataType ];
|
||||
|
||||
jQuery.each ( functors, function( _ , functor ) {
|
||||
|
||||
if ( ! list ) {
|
||||
|
||||
list = transports[ dataType ] = [ functor ];
|
||||
|
||||
} else {
|
||||
|
||||
append.call( list , functor );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
// Select a transport given options
|
||||
function selectTransport( s ) {
|
||||
|
||||
var dataTypes = s.dataTypes,
|
||||
transportDataType,
|
||||
transportsList,
|
||||
transport,
|
||||
i,
|
||||
length,
|
||||
checked = {},
|
||||
flag;
|
||||
|
||||
function initSearch( dataType ) {
|
||||
|
||||
flag = transportDataType !== dataType && ! checked[ dataType ];
|
||||
|
||||
if ( flag ) {
|
||||
|
||||
checked[ dataType ] = 1;
|
||||
transportDataType = dataType;
|
||||
transportsList = s.transports[ dataType ];
|
||||
i = -1;
|
||||
length = transportsList ? transportsList.length : 0 ;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
initSearch( dataTypes[ 0 ] );
|
||||
|
||||
for ( i = 0 ; ! transport && i <= length ; i++ ) {
|
||||
|
||||
if ( i === length ) {
|
||||
|
||||
initSearch( "*" );
|
||||
|
||||
} else {
|
||||
|
||||
transport = transportsList[ i ]( s , determineDataType );
|
||||
|
||||
// If we got redirected to another dataType
|
||||
// Search there (if not in progress or already tried)
|
||||
if ( typeof( transport ) === "string" &&
|
||||
initSearch( transport ) ) {
|
||||
|
||||
dataTypes.unshift( transport );
|
||||
transport = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transport;
|
||||
}
|
||||
|
||||
// Utility function that handles dataType when response is received
|
||||
// (for those transports that can give text or xml responses)
|
||||
function determineDataType( s , ct , text , xml ) {
|
||||
|
||||
var autoDataType = s.autoDataType,
|
||||
type,
|
||||
regexp,
|
||||
dataTypes = s.dataTypes,
|
||||
transportDataType = dataTypes[0],
|
||||
response;
|
||||
|
||||
// Auto (xml, json, script or text determined given headers)
|
||||
if ( transportDataType === "*" ) {
|
||||
|
||||
for ( type in autoDataType ) {
|
||||
if ( ( regexp = autoDataType[ type ] ) && regexp.test( ct ) ) {
|
||||
transportDataType = dataTypes[0] = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// xml and parsed as such
|
||||
if ( transportDataType === "xml" &&
|
||||
xml &&
|
||||
xml.documentElement /* #4958 */ ) {
|
||||
|
||||
response = xml;
|
||||
|
||||
// Text response was provided
|
||||
} else {
|
||||
|
||||
response = text;
|
||||
|
||||
// If it's not really text, defer to dataConverters
|
||||
if ( transportDataType !== "text" ) {
|
||||
dataTypes.unshift( "text" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
})( jQuery );
|
30
test/csp.php
Normal file
30
test/csp.php
Normal 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>
|
5
test/data/errorWithText.php
Normal file
5
test/data/errorWithText.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
header("HTTP/1.0 400 Bad Request");
|
||||
|
||||
echo "plain text message";
|
|
@ -6,15 +6,11 @@ $headers = array();
|
|||
|
||||
foreach( $_SERVER as $key => $value ) {
|
||||
|
||||
if ( substr( $key , 0 , 5 ) == "HTTP_" ) {
|
||||
|
||||
$key = str_replace( "_" , "-" , substr( $key , 5) );
|
||||
$key = str_replace( "_" , "-" , substr( $key , 0 , 5 ) == "HTTP_" ? substr( $key , 5 ) : $key );
|
||||
$headers[ $key ] = $value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) {
|
||||
echo "$key: " . $headers[ strtoupper( $key ) ] . "\n";
|
||||
echo "$key: " . @$headers[ strtoupper( $key ) ] . "\n";
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?php
|
||||
error_reporting(0);
|
||||
$callback = $_REQUEST['callback'];
|
||||
if ( ! $callback ) {
|
||||
$callback = explode("?",end(explode("/",$_SERVER['REQUEST_URI'])));
|
||||
$callback = $callback[0];
|
||||
}
|
||||
$json = $_REQUEST['json'];
|
||||
if($json) {
|
||||
echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}());
|
|
@ -20,10 +20,9 @@
|
|||
<script src="../src/manipulation.js"></script>
|
||||
<script src="../src/css.js"></script>
|
||||
<script src="../src/ajax.js"></script>
|
||||
<script src="../src/xhr.js"></script>
|
||||
<script src="../src/transports/jsonp.js"></script>
|
||||
<script src="../src/transports/script.js"></script>
|
||||
<script src="../src/transports/xhr.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>
|
||||
|
|
|
@ -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
|
||||
|
@ -70,44 +70,6 @@ test("jQuery.ajax() - success callbacks - (url, options) syntax", function() {
|
|||
}, 13);
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - success/error callbacks (remote)", function() {
|
||||
|
||||
var supports = jQuery.support.cors;
|
||||
|
||||
expect( supports ? 9 : 6 );
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 0 });
|
||||
|
||||
stop();
|
||||
|
||||
setTimeout(function(){
|
||||
jQuery('#foo').ajaxStart(function(){
|
||||
ok( true, "ajaxStart" );
|
||||
}).ajaxStop(function(){
|
||||
ok( true, "ajaxStop" );
|
||||
start();
|
||||
}).ajaxSend(function(){
|
||||
ok( supports , "ajaxSend" );
|
||||
}).ajaxComplete(function(){
|
||||
ok( true, "ajaxComplete" );
|
||||
}).ajaxError(function(){
|
||||
ok( ! supports, "ajaxError" );
|
||||
}).ajaxSuccess(function(){
|
||||
ok( supports, "ajaxSuccess" );
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
// JULIAN TODO: Get an url especially for jQuery
|
||||
url: "http://rockstarapps.com/test.php",
|
||||
dataType: "text",
|
||||
beforeSend: function(){ ok(supports, "beforeSend"); },
|
||||
success: function( val ){ ok(supports, "success"); ok(supports && val.length, "data received"); },
|
||||
error: function(_ , a , b ){ ok(!supports, "error"); },
|
||||
complete: function(){ ok(true, "complete"); }
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - success callbacks (late binding)", function() {
|
||||
expect( 8 );
|
||||
|
||||
|
@ -173,7 +135,7 @@ test("jQuery.ajax() - success callbacks (oncomplete binding)", function() {
|
|||
.error(function(){ ok(false, "error"); })
|
||||
.complete(function(){ start(); });
|
||||
}
|
||||
})
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
|
@ -211,7 +173,7 @@ test("jQuery.ajax() - success callbacks (very late binding)", function() {
|
|||
.complete(function(){ start(); });
|
||||
},100);
|
||||
}
|
||||
})
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
|
@ -278,6 +240,46 @@ test("jQuery.ajax() - error callbacks", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - responseText on error", function() {
|
||||
|
||||
expect( 1 );
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/errorWithText.php"),
|
||||
error: function(xhr) {
|
||||
strictEqual( xhr.responseText , "plain text message" , "Test jXHR.responseText is filled for HTTP errors" );
|
||||
},
|
||||
complete: function() {
|
||||
start();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test(".ajax() - retry with jQuery.ajax( this )", function() {
|
||||
|
||||
expect( 1 );
|
||||
|
||||
stop();
|
||||
|
||||
var firstTime = 1;
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/errorWithText.php"),
|
||||
error: function() {
|
||||
if ( firstTime ) {
|
||||
firstTime = 0;
|
||||
jQuery.ajax( this );
|
||||
} else {
|
||||
ok( true , "Test retrying with jQuery.ajax(this) works" );
|
||||
start();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test(".ajax() - headers" , function() {
|
||||
|
||||
expect( 2 );
|
||||
|
@ -314,6 +316,64 @@ test(".ajax() - headers" , function() {
|
|||
|
||||
});
|
||||
|
||||
test(".ajax() - Accept header" , function() {
|
||||
|
||||
expect( 1 );
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.ajax(url("data/headers.php?keys=accept"), {
|
||||
headers: {
|
||||
Accept: "very wrong accept value"
|
||||
},
|
||||
beforeSend: function( xhr ) {
|
||||
xhr.setRequestHeader( "Accept", "*/*" );
|
||||
},
|
||||
success: function( data ) {
|
||||
strictEqual( data , "accept: */*\n" , "Test Accept header is set to last value provided" );
|
||||
start();
|
||||
},
|
||||
error: function(){ ok(false, "error"); }
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test(".ajax() - contentType" , function() {
|
||||
|
||||
expect( 2 );
|
||||
|
||||
stop();
|
||||
|
||||
var count = 2;
|
||||
|
||||
function restart() {
|
||||
if ( ! --count ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
jQuery.ajax(url("data/headers.php?keys=content-type" ), {
|
||||
contentType: "test",
|
||||
success: function( data ) {
|
||||
strictEqual( data , "content-type: test\n" , "Test content-type is sent when options.contentType is set" );
|
||||
},
|
||||
complete: function() {
|
||||
restart();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax(url("data/headers.php?keys=content-type" ), {
|
||||
contentType: false,
|
||||
success: function( data ) {
|
||||
strictEqual( data , "content-type: \n" , "Test content-type is not sent when options.contentType===false" );
|
||||
},
|
||||
complete: function() {
|
||||
restart();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test(".ajax() - hash", function() {
|
||||
expect(3);
|
||||
|
||||
|
@ -343,6 +403,53 @@ test(".ajax() - hash", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test("jQuery ajax - cross-domain detection", function() {
|
||||
|
||||
expect( 4 );
|
||||
|
||||
var loc = document.location,
|
||||
otherPort = loc.port === 666 ? 667 : 666,
|
||||
otherProtocol = loc.protocol === "http:" ? "https:" : "http:";
|
||||
|
||||
jQuery.ajax({
|
||||
dataType: "jsonp",
|
||||
url: otherProtocol + "//" + loc.host,
|
||||
beforeSend: function( _ , s ) {
|
||||
ok( s.crossDomain , "Test different protocols are detected as cross-domain" );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
dataType: "jsonp",
|
||||
url: loc.protocol + '//somewebsitethatdoesnotexist-656329477541.com:' + ( loc.port || 80 ),
|
||||
beforeSend: function( _ , s ) {
|
||||
ok( s.crossDomain , "Test different hostnames are detected as cross-domain" );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
dataType: "jsonp",
|
||||
url: loc.protocol + "//" + loc.hostname + ":" + otherPort,
|
||||
beforeSend: function( _ , s ) {
|
||||
ok( s.crossDomain , "Test different ports are detected as cross-domain" );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
dataType: "jsonp",
|
||||
url: loc.protocol + "//" + loc.host,
|
||||
crossDomain: true,
|
||||
beforeSend: function( _ , s ) {
|
||||
ok( s.crossDomain , "Test forced crossDomain is detected as cross-domain" );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test(".ajax() - 304", function() {
|
||||
expect( 1 );
|
||||
stop();
|
||||
|
@ -409,136 +516,6 @@ test("jQuery.ajax() - abort", function() {
|
|||
equals( xhr.readyState, 0, "XHR readyState indicates successful abortion" );
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - readyState (success)", function() {
|
||||
expect( 1 );
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 0 });
|
||||
|
||||
stop();
|
||||
|
||||
var control = "";
|
||||
|
||||
setTimeout(function(){
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
beforeSend: function( xhr ) {
|
||||
xhr.onreadystatechange = function() {
|
||||
control += xhr.readyState;
|
||||
}
|
||||
},
|
||||
complete: function(){
|
||||
setTimeout( function() {
|
||||
equals( control , "1234" , "onreadystatechange was properly called" );
|
||||
}, 13 );
|
||||
start();
|
||||
}
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - readyState (abort)", function() {
|
||||
expect( 2 );
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 0 });
|
||||
|
||||
stop();
|
||||
|
||||
var control = "";
|
||||
|
||||
setTimeout(function(){
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 500 });
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/name.php?wait=5"),
|
||||
beforeSend: function( xhr ) {
|
||||
xhr.onreadystatechange = function() {
|
||||
control += xhr.readyState;
|
||||
}
|
||||
},
|
||||
complete: function( xhr ){
|
||||
setTimeout( function() {
|
||||
equals( control , "14" , "onreadystatechange was properly called" );
|
||||
equals( xhr.readyState, 0 , "readyState is 0" );
|
||||
}, 13 );
|
||||
start();
|
||||
}
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
test("jQuery.xhr() - reuse", function() {
|
||||
expect( 15 );
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 0 });
|
||||
|
||||
stop();
|
||||
|
||||
var number = 0;
|
||||
|
||||
setTimeout(function(){
|
||||
jQuery('#foo').ajaxStart(function(){
|
||||
ok( true, "ajaxStart" );
|
||||
}).ajaxStop(function(){
|
||||
ok( true, "ajaxStop" );
|
||||
start();
|
||||
}).ajaxSend(function(){
|
||||
number++;
|
||||
ok( true, "ajaxSend (" + number +")" );
|
||||
}).ajaxComplete(function(){
|
||||
ok( true, "ajaxComplete (" + number +")" );
|
||||
}).ajaxError(function(){
|
||||
ok( false, "ajaxError (" + number +")" );
|
||||
}).ajaxSuccess(function(){
|
||||
ok( true, "ajaxSuccess (" + number +")" );
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
beforeSend: function(){ ok(true, "beforeSend (1)"); },
|
||||
success: function( _1 , _2 , xhr ){
|
||||
ok(true, "success (1)");
|
||||
xhr.complete(function() {
|
||||
ok(true, "complete (1bis)");
|
||||
});
|
||||
xhr.open( "GET", url("data/name.html") );
|
||||
xhr.success( function(){ ok(true, "beforeSend (2)"); } )
|
||||
xhr.send( null, {
|
||||
success: function(){ ok(true, "success (2)"); },
|
||||
error: function(){ ok(false, "error (2)"); },
|
||||
complete: function(){ ok(true, "complete (2)"); }
|
||||
} );
|
||||
},
|
||||
error: function(){ ok(false, "error (1)"); },
|
||||
complete: function(){ ok(true, "complete (1)"); }
|
||||
});
|
||||
}, 13);
|
||||
});
|
||||
|
||||
test("jQuery.xhr() - early binding", function() {
|
||||
expect( 2 );
|
||||
|
||||
jQuery.ajaxSetup({ timeout: 0 });
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.xhr()
|
||||
.success( function(){ ok(true, "success"); } )
|
||||
.error( function(){ ok(false, "error"); } )
|
||||
.complete( function(){ ok(true, "complete"); start(); } )
|
||||
.open( "GET", url("data/name.html") )
|
||||
.send();
|
||||
});
|
||||
|
||||
test("jQuery.xhr() - get native implementation", function() {
|
||||
|
||||
var xhr = jQuery.xhr(true);
|
||||
|
||||
ok( xhr.readyState !== undefined , "implements XMLHttpRequest" );
|
||||
ok( ! jQuery.isFunction( xhr.success ) , "is not jQuery's abstraction" );
|
||||
|
||||
});
|
||||
|
||||
test("Ajax events with context", function() {
|
||||
expect(14);
|
||||
|
||||
|
@ -606,7 +583,7 @@ test("jQuery.ajax context modification", function() {
|
|||
|
||||
stop();
|
||||
|
||||
var obj = {}
|
||||
var obj = {};
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
|
@ -622,6 +599,47 @@ test("jQuery.ajax context modification", function() {
|
|||
equals( obj.test, "foo", "Make sure the original object is maintained." );
|
||||
});
|
||||
|
||||
test("jQuery.ajax context modification through ajaxSetup", function() {
|
||||
expect(4);
|
||||
|
||||
stop();
|
||||
|
||||
var obj = {};
|
||||
|
||||
jQuery.ajaxSetup({
|
||||
context: obj
|
||||
});
|
||||
|
||||
strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." );
|
||||
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
complete: function() {
|
||||
strictEqual( this, obj, "Make sure the original object is maintained." );
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
context: {},
|
||||
complete: function() {
|
||||
ok( this !== obj, "Make sure overidding context is possible." );
|
||||
jQuery.ajaxSetup({
|
||||
context: false
|
||||
});
|
||||
jQuery.ajax({
|
||||
url: url("data/name.html"),
|
||||
beforeSend: function(){
|
||||
this.test = "foo2";
|
||||
},
|
||||
complete: function() {
|
||||
ok( this !== obj, "Make sure unsetting context is possible." );
|
||||
start();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - disabled globals", function() {
|
||||
expect( 3 );
|
||||
stop();
|
||||
|
@ -653,34 +671,6 @@ test("jQuery.ajax() - disabled globals", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test("jQuery.xhr() - disabled globals through xhr.send(data , false)", function() {
|
||||
expect( 2 );
|
||||
stop();
|
||||
|
||||
jQuery('#foo').ajaxStart(function(){
|
||||
ok( false, "ajaxStart" );
|
||||
}).ajaxStop(function(){
|
||||
ok( false, "ajaxStop" );
|
||||
}).ajaxSend(function(){
|
||||
ok( false, "ajaxSend" );
|
||||
}).ajaxComplete(function(){
|
||||
ok( false, "ajaxComplete" );
|
||||
}).ajaxError(function(){
|
||||
ok( false, "ajaxError" );
|
||||
}).ajaxSuccess(function(){
|
||||
ok( false, "ajaxSuccess" );
|
||||
});
|
||||
|
||||
jQuery.xhr()
|
||||
.success(function(){ ok(true, "success"); })
|
||||
.error(function(){ ok(false, "error"); })
|
||||
.complete(function(){
|
||||
ok(true, "complete");
|
||||
setTimeout(function(){ start(); }, 13);
|
||||
})
|
||||
.open("GET", url("data/name.html")).send(undefined, false);
|
||||
});
|
||||
|
||||
test("jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() {
|
||||
expect(3);
|
||||
stop();
|
||||
|
@ -707,6 +697,10 @@ test("jQuery.ajax - xml: non-namespace elements inside namespaced elements (over
|
|||
equals( jQuery("jsconf", resp).length, 1, 'jsconf in responseXML' );
|
||||
equals( jQuery("thing", resp).length, 2, 'things in responseXML' );
|
||||
start();
|
||||
},
|
||||
error: function(_1,_2,error) {
|
||||
ok( false, error );
|
||||
start();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -842,20 +836,20 @@ test("serialize()", function() {
|
|||
'Check input serialization as query string');
|
||||
|
||||
equals( jQuery('#testForm').serialize(),
|
||||
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||
'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||
'Check form serialization as query string');
|
||||
|
||||
equals( jQuery('#testForm :input').serialize(),
|
||||
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||
'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||
'Check input serialization as query string');
|
||||
|
||||
equals( jQuery('#form, #testForm').serialize(),
|
||||
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||
'Multiple form serialization as query string');
|
||||
|
||||
/* Temporarily disabled. Opera 10 has problems with form serialization.
|
||||
equals( jQuery('#form, #testForm :input').serialize(),
|
||||
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||
'Mixed form/input serialization as query string');
|
||||
*/
|
||||
jQuery("#html5email, #html5number").remove();
|
||||
|
@ -1094,6 +1088,18 @@ test("load(String, Function) - check file with only a script tag", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test("load(String, Function) - dataFilter in ajaxSettings", function() {
|
||||
expect(2);
|
||||
stop();
|
||||
jQuery.ajaxSetup({ dataFilter: function() { return "Hello World"; } });
|
||||
var div = jQuery("<div/>").load(url("data/name.html"), function(responseText) {
|
||||
strictEqual( div.html(), "Hello World" , "Test div was filled with filtered data" );
|
||||
strictEqual( responseText, "Hello World" , "Test callback receives filtered data" );
|
||||
jQuery.ajaxSetup({ dataFilter: 0 });
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
test("load(String, Object, Function)", function() {
|
||||
expect(2);
|
||||
stop();
|
||||
|
@ -1149,17 +1155,20 @@ test("jQuery.getScript(String, Function) - no callback", function() {
|
|||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - JSONP, Local", function() {
|
||||
expect(9);
|
||||
jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
|
||||
|
||||
test("jQuery.ajax() - JSONP, " + label, function() {
|
||||
expect(17);
|
||||
|
||||
var count = 0;
|
||||
function plus(){ if ( ++count == 9 ) start(); }
|
||||
function plus(){ if ( ++count == 17 ) start(); }
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, no callback)" );
|
||||
plus();
|
||||
|
@ -1173,6 +1182,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
jQuery.ajax({
|
||||
url: "data/jsonp.php?callback=?",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, url callback)" );
|
||||
plus();
|
||||
|
@ -1186,6 +1196,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
jQuery.ajax({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
data: "callback=?",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, data callback)" );
|
||||
|
@ -1197,9 +1208,84 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php?callback=??",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, url context-free callback)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, url context-free callback)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
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/??",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, REST-like)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, REST-like)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php/???json=1",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
strictEqual( jQuery.type(data), "array", "JSON results returned (GET, REST-like with param)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, REST-like with param)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
data: {
|
||||
callback: "?"
|
||||
},
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, processed data callback)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, processed data callback)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
jsonp: "callback",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, data obj callback)" );
|
||||
|
@ -1211,9 +1297,16 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
}
|
||||
});
|
||||
|
||||
window.jsonpResults = function(data) {
|
||||
ok( data.data, "JSON results returned (GET, custom callback function)" );
|
||||
window.jsonpResults = undefined;
|
||||
plus();
|
||||
};
|
||||
|
||||
jQuery.ajax({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
jsonpCallback: "jsonpResults",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, custom callback name)" );
|
||||
|
@ -1229,6 +1322,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
type: "POST",
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (POST, no callback)" );
|
||||
plus();
|
||||
|
@ -1244,6 +1338,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
url: "data/jsonp.php",
|
||||
data: "callback=?",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (POST, data callback)" );
|
||||
plus();
|
||||
|
@ -1259,6 +1354,7 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
url: "data/jsonp.php",
|
||||
jsonp: "callback",
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (POST, data obj callback)" );
|
||||
plus();
|
||||
|
@ -1273,93 +1369,35 @@ test("jQuery.ajax() - JSONP, Local", function() {
|
|||
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;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
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({
|
||||
url: "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
jsonpCallback: "jsonpResults"
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax() - JSONP, Remote", function() {
|
||||
expect(4);
|
||||
|
||||
var count = 0;
|
||||
function plus(){ if ( ++count == 4 ) start(); }
|
||||
|
||||
var base = window.location.href.replace(/[^\/]*$/, "");
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.ajax({
|
||||
url: base + "data/jsonp.php",
|
||||
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, no callback)" );
|
||||
ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, no callback)" );
|
||||
ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: base + "data/jsonp.php?callback=?",
|
||||
dataType: "jsonp",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, url callback)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, url callback)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: base + "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
data: "callback=?",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, data callback)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, data callback)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax({
|
||||
url: base + "data/jsonp.php",
|
||||
dataType: "jsonp",
|
||||
jsonp: "callback",
|
||||
success: function(data){
|
||||
ok( data.data, "JSON results returned (GET, data obj callback)" );
|
||||
plus();
|
||||
},
|
||||
error: function(data){
|
||||
ok( false, "Ajax error JSON (GET, data obj callback)" );
|
||||
plus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1482,12 +1520,12 @@ test("jQuery.ajax() - json by content-type disabled with options", function() {
|
|||
jQuery.ajax({
|
||||
url: url("data/json.php"),
|
||||
data: { header: "json", json: "array" },
|
||||
autoDataType: {
|
||||
contents: {
|
||||
json: false
|
||||
},
|
||||
success: function( text ) {
|
||||
equals( typeof text , "string" , "json wasn't auto-determined" );
|
||||
var json = this.dataConverters["text => json"]( text );
|
||||
var json = jQuery.parseJSON( text );
|
||||
ok( json.length >= 2, "Check length");
|
||||
equals( json[0].name, 'John', 'Check JSON: first, name' );
|
||||
equals( json[0].age, 21, 'Check JSON: first, age' );
|
||||
|
@ -1714,7 +1752,7 @@ test("data option: evaluate function values (#2806)", function() {
|
|||
equals( result, "key=value" );
|
||||
start();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
test("data option: empty bodies for non-GET requests", function() {
|
||||
|
@ -1727,7 +1765,7 @@ test("data option: empty bodies for non-GET requests", function() {
|
|||
equals( result, "" );
|
||||
start();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax - If-Modified-Since support", function() {
|
||||
|
@ -1752,7 +1790,7 @@ test("jQuery.ajax - If-Modified-Since support", function() {
|
|||
ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
|
||||
} else {
|
||||
equals(status, "notmodified");
|
||||
ok(data == null, "response body should be empty")
|
||||
ok(data == null, "response body should be empty");
|
||||
}
|
||||
start();
|
||||
},
|
||||
|
@ -1799,7 +1837,7 @@ test("jQuery.ajax - Etag support", function() {
|
|||
ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
|
||||
} else {
|
||||
equals(status, "notmodified");
|
||||
ok(data == null, "response body should be empty")
|
||||
ok(data == null, "response body should be empty");
|
||||
}
|
||||
start();
|
||||
},
|
||||
|
@ -1832,7 +1870,7 @@ test("jQuery ajax - failing cross-domain", function() {
|
|||
var i = 2;
|
||||
|
||||
jQuery.ajax({
|
||||
url: 'http://somewebsitethatdoesnotexist.com',
|
||||
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(); }
|
||||
|
@ -1860,10 +1898,6 @@ test("jQuery ajax - atom+xml", function() {
|
|||
|
||||
});
|
||||
|
||||
test("jQuery.ajax - active counter", function() {
|
||||
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
|
||||
});
|
||||
|
||||
test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
|
||||
var success = false;
|
||||
try {
|
||||
|
@ -1875,6 +1909,150 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
|
|||
ok( success, "document.location did not generate exception" );
|
||||
});
|
||||
|
||||
test( "jQuery.ajax - statusCode" , function() {
|
||||
|
||||
var count = 12;
|
||||
|
||||
expect( 20 );
|
||||
stop();
|
||||
|
||||
function countComplete() {
|
||||
if ( ! --count ) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
function createStatusCodes( name , isSuccess ) {
|
||||
name = "Test " + name + " " + ( isSuccess ? "success" : "error" );
|
||||
return {
|
||||
200: function() {
|
||||
ok( isSuccess , name );
|
||||
},
|
||||
404: function() {
|
||||
ok( ! isSuccess , name );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
jQuery.each( {
|
||||
"data/name.html": true,
|
||||
"data/someFileThatDoesNotExist.html": false
|
||||
} , function( uri , isSuccess ) {
|
||||
|
||||
jQuery.ajax( url( uri ) , {
|
||||
statusCode: createStatusCodes( "in options" , isSuccess ),
|
||||
complete: countComplete
|
||||
});
|
||||
|
||||
jQuery.ajax( url( uri ) , {
|
||||
complete: countComplete
|
||||
}).statusCode( createStatusCodes( "immediately with method" , isSuccess ) );
|
||||
|
||||
jQuery.ajax( url( uri ) , {
|
||||
complete: function(jXHR) {
|
||||
jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) );
|
||||
countComplete();
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax( url( uri ) , {
|
||||
complete: function(jXHR) {
|
||||
setTimeout( function() {
|
||||
jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) );
|
||||
countComplete();
|
||||
} , 100 );
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.ajax( url( uri ) , {
|
||||
statusCode: createStatusCodes( "all (options)" , isSuccess ),
|
||||
complete: function(jXHR) {
|
||||
jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) );
|
||||
setTimeout( function() {
|
||||
jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) );
|
||||
countComplete();
|
||||
} , 100 );
|
||||
}
|
||||
}).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) );
|
||||
|
||||
var testString = "";
|
||||
|
||||
jQuery.ajax( url( uri ), {
|
||||
success: function( a , b , jXHR ) {
|
||||
ok( isSuccess , "success" );
|
||||
var statusCode = {};
|
||||
statusCode[ jXHR.status ] = function() {
|
||||
testString += "B";
|
||||
};
|
||||
jXHR.statusCode( statusCode );
|
||||
testString += "A";
|
||||
},
|
||||
error: function( jXHR ) {
|
||||
ok( ! isSuccess , "error" );
|
||||
var statusCode = {};
|
||||
statusCode[ jXHR.status ] = function() {
|
||||
testString += "B";
|
||||
};
|
||||
jXHR.statusCode( statusCode );
|
||||
testString += "A";
|
||||
},
|
||||
complete: function() {
|
||||
strictEqual( testString , "AB" , "Test statusCode callbacks are ordered like " +
|
||||
( isSuccess ? "success" : "error" ) + " callbacks" );
|
||||
countComplete();
|
||||
}
|
||||
} );
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.ajax - transitive conversions", function() {
|
||||
|
||||
expect( 8 );
|
||||
|
||||
stop();
|
||||
|
||||
jQuery.when(
|
||||
|
||||
jQuery.ajax( url("data/json.php") , {
|
||||
converters: {
|
||||
"json myjson": function( data ) {
|
||||
ok( true , "converter called" );
|
||||
return data;
|
||||
}
|
||||
},
|
||||
dataType: "myjson",
|
||||
success: function() {
|
||||
ok( true , "Transitive conversion worked" );
|
||||
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text" );
|
||||
strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType" );
|
||||
}
|
||||
}),
|
||||
|
||||
jQuery.ajax( url("data/json.php") , {
|
||||
converters: {
|
||||
"json myjson": function( data ) {
|
||||
ok( true , "converter called (*)" );
|
||||
return data;
|
||||
}
|
||||
},
|
||||
contents: false, /* headers are wrong so we ignore them */
|
||||
dataType: "* myjson",
|
||||
success: function() {
|
||||
ok( true , "Transitive conversion worked (*)" );
|
||||
strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text (*)" );
|
||||
strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType (*)" );
|
||||
}
|
||||
})
|
||||
|
||||
).then( start , start );
|
||||
|
||||
});
|
||||
|
||||
test("jQuery.ajax - active counter", function() {
|
||||
ok( jQuery.active == 0, "ajax active counter should be zero: " + jQuery.active );
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//}
|
|
@ -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() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module("core");
|
||||
module("core", { teardown: moduleTeardown });
|
||||
|
||||
test("Basic requirements", function() {
|
||||
expect(7);
|
||||
|
@ -12,7 +12,7 @@ test("Basic requirements", function() {
|
|||
});
|
||||
|
||||
test("jQuery()", function() {
|
||||
expect(23);
|
||||
expect(24);
|
||||
|
||||
// Basic constructor's behavior
|
||||
|
||||
|
@ -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
|
||||
|
@ -84,6 +84,17 @@ 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() {
|
||||
|
@ -907,3 +918,290 @@ test("jQuery.parseJSON", function(){
|
|||
ok( true, "Test malformed JSON string." );
|
||||
}
|
||||
});
|
||||
|
||||
test("jQuery._Deferred()", function() {
|
||||
|
||||
expect( 10 );
|
||||
|
||||
var deferred,
|
||||
object,
|
||||
test;
|
||||
|
||||
deferred = jQuery._Deferred();
|
||||
|
||||
test = false;
|
||||
|
||||
deferred.done( function( value ) {
|
||||
equals( value , "value" , "Test pre-resolve callback" );
|
||||
test = true;
|
||||
} );
|
||||
|
||||
deferred.resolve( "value" );
|
||||
|
||||
ok( test , "Test pre-resolve callbacks called right away" );
|
||||
|
||||
test = false;
|
||||
|
||||
deferred.done( function( value ) {
|
||||
equals( value , "value" , "Test post-resolve callback" );
|
||||
test = true;
|
||||
} );
|
||||
|
||||
ok( test , "Test post-resolve callbacks called right away" );
|
||||
|
||||
deferred.cancel();
|
||||
|
||||
test = true;
|
||||
|
||||
deferred.done( function() {
|
||||
ok( false , "Cancel was ignored" );
|
||||
test = false;
|
||||
} );
|
||||
|
||||
ok( test , "Test cancel" );
|
||||
|
||||
deferred = jQuery._Deferred().resolve();
|
||||
|
||||
try {
|
||||
deferred.done( function() {
|
||||
throw "Error";
|
||||
} , function() {
|
||||
ok( true , "Test deferred do not cancel on exception" );
|
||||
} );
|
||||
} catch( e ) {
|
||||
strictEqual( e , "Error" , "Test deferred propagates exceptions");
|
||||
deferred.done();
|
||||
}
|
||||
|
||||
test = "";
|
||||
deferred = jQuery._Deferred().done( function() {
|
||||
|
||||
test += "A";
|
||||
|
||||
}, function() {
|
||||
|
||||
test += "B";
|
||||
|
||||
} ).resolve();
|
||||
|
||||
strictEqual( test , "AB" , "Test multiple done parameters" );
|
||||
|
||||
test = "";
|
||||
|
||||
deferred.done( function() {
|
||||
|
||||
deferred.done( function() {
|
||||
|
||||
test += "C";
|
||||
|
||||
} );
|
||||
|
||||
test += "A";
|
||||
|
||||
}, function() {
|
||||
|
||||
test += "B";
|
||||
} );
|
||||
|
||||
strictEqual( test , "ABC" , "Test done callbacks order" );
|
||||
|
||||
deferred = jQuery._Deferred();
|
||||
|
||||
deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) {
|
||||
ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.Deferred()", function() {
|
||||
|
||||
expect( 10 );
|
||||
|
||||
jQuery.Deferred( function( defer ) {
|
||||
strictEqual( this , defer , "Defer passed as this & first argument" );
|
||||
this.resolve( "done" );
|
||||
}).then( function( value ) {
|
||||
strictEqual( value , "done" , "Passed function executed" );
|
||||
});
|
||||
|
||||
jQuery.Deferred().resolve().then( function() {
|
||||
ok( true , "Success on resolve" );
|
||||
}, function() {
|
||||
ok( false , "Error on resolve" );
|
||||
});
|
||||
|
||||
jQuery.Deferred().reject().then( function() {
|
||||
ok( false , "Success on reject" );
|
||||
}, function() {
|
||||
ok( true , "Error on reject" );
|
||||
});
|
||||
|
||||
( new jQuery.Deferred( function( defer ) {
|
||||
strictEqual( this , defer , "Defer passed as this & first argument (new)" );
|
||||
this.resolve( "done" );
|
||||
}) ).then( function( value ) {
|
||||
strictEqual( value , "done" , "Passed function executed (new)" );
|
||||
});
|
||||
|
||||
( new jQuery.Deferred() ).resolve().then( function() {
|
||||
ok( true , "Success on resolve (new)" );
|
||||
}, function() {
|
||||
ok( false , "Error on resolve (new)" );
|
||||
});
|
||||
|
||||
( new jQuery.Deferred() ).reject().then( function() {
|
||||
ok( false , "Success on reject (new)" );
|
||||
}, function() {
|
||||
ok( true , "Error on reject (new)" );
|
||||
});
|
||||
|
||||
var tmp = jQuery.Deferred();
|
||||
|
||||
strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
|
||||
strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
|
||||
});
|
||||
|
||||
test("jQuery.when()", function() {
|
||||
|
||||
expect( 23 );
|
||||
|
||||
// Some other objects
|
||||
jQuery.each( {
|
||||
|
||||
"an empty string": "",
|
||||
"a non-empty string": "some string",
|
||||
"zero": 0,
|
||||
"a number other than zero": 1,
|
||||
"true": true,
|
||||
"false": false,
|
||||
"null": null,
|
||||
"undefined": undefined,
|
||||
"a plain object": {}
|
||||
|
||||
} , function( message , value ) {
|
||||
|
||||
ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
|
||||
strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
|
||||
} ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
|
||||
|
||||
} );
|
||||
|
||||
ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
|
||||
strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
|
||||
} ).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" );
|
||||
|
||||
var cache, i;
|
||||
|
||||
for( i = 1 ; i < 4 ; i++ ) {
|
||||
jQuery.when( cache || jQuery.Deferred( function() {
|
||||
this.resolve( i );
|
||||
}) ).then( function( value ) {
|
||||
strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
|
||||
cache = value;
|
||||
}, function() {
|
||||
ok( false , "Fail called" );
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("jQuery.when() - joined", function() {
|
||||
|
||||
expect(8);
|
||||
|
||||
jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
|
||||
strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
|
||||
strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
|
||||
strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
|
||||
}).fail( function() {
|
||||
ok( false , "Test the created deferred was resolved - non-observables");
|
||||
});
|
||||
|
||||
var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
|
||||
errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
|
||||
|
||||
jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
|
||||
strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
|
||||
same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
|
||||
strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
|
||||
}).fail( function() {
|
||||
ok( false , "Test the created deferred was resolved - resolved observable");
|
||||
});
|
||||
|
||||
jQuery.when( 1 , errorDeferred , 3 ).done( function() {
|
||||
ok( false , "Test the created deferred was rejected - rejected observable");
|
||||
}).fail( function( error , errorParam ) {
|
||||
strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
|
||||
strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
|
||||
});
|
||||
});
|
||||
|
||||
test("jQuery.subclass", function(){
|
||||
expect(378);
|
||||
|
||||
var Subclass = jQuery.subclass(),
|
||||
SubclassSubclass = Subclass.subclass(),
|
||||
jQueryDocument = jQuery(document),
|
||||
selectors, contexts, methods, method, arg, description;
|
||||
|
||||
jQueryDocument.toString = function(){ return 'jQueryDocument'; };
|
||||
|
||||
Subclass.fn.subclassMethod = function(){};
|
||||
SubclassSubclass.fn.subclassSubclassMethod = function(){};
|
||||
|
||||
selectors = [
|
||||
'body',
|
||||
'html, body',
|
||||
'<div></div>'
|
||||
];
|
||||
|
||||
methods = [ // all methods that return a new jQuery instance
|
||||
['eq', 1],
|
||||
['add', document],
|
||||
['end'],
|
||||
['has'],
|
||||
['closest', 'div'],
|
||||
['filter', document],
|
||||
['find', 'div']
|
||||
];
|
||||
|
||||
contexts = [undefined, document, jQueryDocument];
|
||||
|
||||
jQuery.each(selectors, function(i, selector){
|
||||
|
||||
jQuery.each(methods, function(){
|
||||
method = this[0];
|
||||
arg = this[1];
|
||||
|
||||
jQuery.each(contexts, function(i, context){
|
||||
|
||||
description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')';
|
||||
|
||||
same(
|
||||
jQuery(selector, context)[method](arg).subclassMethod, undefined,
|
||||
'jQuery'+description+' doesnt have Subclass methods'
|
||||
);
|
||||
same(
|
||||
jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined,
|
||||
'jQuery'+description+' doesnt have SubclassSubclass methods'
|
||||
);
|
||||
same(
|
||||
Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
|
||||
'Subclass'+description+' has Subclass methods'
|
||||
);
|
||||
same(
|
||||
Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
|
||||
'Subclass'+description+' doesnt have SubclassSubclass methods'
|
||||
);
|
||||
same(
|
||||
SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
|
||||
'SubclassSubclass'+description+' has Subclass methods'
|
||||
);
|
||||
same(
|
||||
SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
|
||||
'SubclassSubclass'+description+' has SubclassSubclass methods'
|
||||
);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -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" );
|
||||
});
|
||||
|
|
|
@ -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,53 +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(".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" );
|
||||
|
@ -92,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() {
|
||||
|
@ -179,11 +274,14 @@ test(".data(String) and .data(String, Object)", function() {
|
|||
equals( $elem.data('null',null).data('null'), null, "null's are preserved");
|
||||
equals( $elem.data('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() {
|
||||
|
@ -203,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");
|
||||
|
||||
|
@ -214,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-." );
|
||||
|
@ -308,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");
|
||||
|
@ -327,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" );
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
91
test/unit/effects.js
vendored
91
test/unit/effects.js
vendored
|
@ -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" );
|
||||
|
||||
|
@ -130,6 +130,45 @@ test("show(Number) - other displays", function() {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Supports #7397
|
||||
test("Persist correct display value", function() {
|
||||
expect(3);
|
||||
QUnit.reset();
|
||||
stop();
|
||||
|
||||
// #show-tests * is set display: none in CSS
|
||||
jQuery("#main").append('<div id="show-tests"><span style="position:absolute;">foo</span></div>');
|
||||
|
||||
var $span = jQuery("#show-tests span"),
|
||||
displayNone = $span.css("display"),
|
||||
display = '', num = 0;
|
||||
|
||||
$span.show();
|
||||
|
||||
display = $span.css("display");
|
||||
|
||||
$span.hide();
|
||||
|
||||
$span.fadeIn(100, function() {
|
||||
|
||||
equals($span.css("display"), display, "Expecting display: " + display);
|
||||
|
||||
$span.fadeOut(100, function () {
|
||||
|
||||
equals($span.css("display"), displayNone, "Expecting display: " + displayNone);
|
||||
|
||||
$span.fadeIn(100, function() {
|
||||
|
||||
equals($span.css("display"), display, "Expecting display: " + display);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("animate(Hash, Object, Function)", function() {
|
||||
expect(1);
|
||||
stop();
|
||||
|
@ -364,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." );
|
||||
|
@ -394,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();
|
||||
|
||||
|
@ -407,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);
|
||||
|
@ -417,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();
|
||||
|
||||
|
@ -442,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();
|
||||
|
||||
|
@ -469,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();
|
||||
|
||||
|
@ -497,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" );
|
||||
|
@ -521,6 +565,23 @@ jQuery.checkOverflowDisplay = function(){
|
|||
start();
|
||||
}
|
||||
|
||||
test("support negative values < -10000 (bug #7193)", function () {
|
||||
expect(1);
|
||||
stop();
|
||||
|
||||
jQuery.extend(jQuery.fx.step, {
|
||||
"marginBottom": function(fx) {
|
||||
equals( fx.cur(), -11000, "Element has margin-bottom of -11000" );
|
||||
delete jQuery.fx.step.marginBottom;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery("#main").css("marginBottom", "-11000px").animate({ marginBottom: "-11001px" }, {
|
||||
duration: 1,
|
||||
complete: start
|
||||
});
|
||||
});
|
||||
|
||||
test("JS Overflow and Display", function() {
|
||||
expect(2);
|
||||
stop();
|
||||
|
@ -681,6 +742,9 @@ jQuery.each( {
|
|||
}
|
||||
}
|
||||
|
||||
// manually remove generated element
|
||||
jQuery(this).remove();
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
@ -707,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();
|
||||
}
|
||||
|
||||
|
@ -773,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;
|
||||
|
@ -839,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" );
|
||||
|
||||
|
@ -854,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();
|
||||
|
|
|
@ -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,6 +304,49 @@ test("live/delegate immediate propagation", function() {
|
|||
$p.undelegate( "click" );
|
||||
});
|
||||
|
||||
test("bind/delegate bubbling, isDefaultPrevented", function() {
|
||||
expect(2);
|
||||
var $anchor2 = jQuery( "#anchor2" ),
|
||||
$main = jQuery( "#main" ),
|
||||
fakeClick = function($jq) {
|
||||
// Use a native click so we don't get jQuery simulated bubbling
|
||||
if ( document.createEvent ) {
|
||||
var e = document.createEvent( 'MouseEvents' );
|
||||
e.initEvent( "click", true, true );
|
||||
$jq[0].dispatchEvent(e);
|
||||
}
|
||||
else if ( $jq[0].click ) {
|
||||
$jq[0].click(); // IE
|
||||
}
|
||||
};
|
||||
$anchor2.click(function(e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
$main.delegate("#foo", "click", function(e) {
|
||||
var orig = e.originalEvent;
|
||||
|
||||
if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig.getPreventDefault ) {
|
||||
equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
|
||||
|
||||
} else {
|
||||
// Opera < 11 doesn't implement any interface we can use, so give it a pass
|
||||
ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
|
||||
}
|
||||
});
|
||||
fakeClick( $anchor2 );
|
||||
$anchor2.unbind( "click" );
|
||||
$main.undelegate( "click" );
|
||||
$anchor2.click(function(e) {
|
||||
// Let the default action occur
|
||||
});
|
||||
$main.delegate("#foo", "click", function(e) {
|
||||
equals( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
|
||||
});
|
||||
fakeClick( $anchor2 );
|
||||
$anchor2.unbind( "click" );
|
||||
$main.undelegate( "click" );
|
||||
});
|
||||
|
||||
test("bind(), iframes", function() {
|
||||
// events don't work with iframes, see #939 - this test fails in IE because of contentDocument
|
||||
var doc = jQuery("#loadediframe").contents();
|
||||
|
@ -470,7 +522,7 @@ test("bind(), with different this object", function() {
|
|||
.bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1)
|
||||
.bind("click", 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() {
|
||||
|
@ -490,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() {
|
||||
|
@ -512,7 +567,7 @@ test("bind()/trigger()/unbind() on plain object", function() {
|
|||
}
|
||||
});
|
||||
|
||||
var events = jQuery(obj).data("__events__");
|
||||
var events = jQuery._data(obj, "events");
|
||||
ok( events, "Object has events bound." );
|
||||
equals( obj.events, undefined, "Events object on plain objects is not events" );
|
||||
equals( typeof events, "function", "'events' expando is a function on plain objects." );
|
||||
|
@ -532,7 +587,9 @@ test("bind()/trigger()/unbind() on plain object", function() {
|
|||
// Make sure it doesn't complain when no events are found
|
||||
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() {
|
||||
|
@ -626,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();
|
||||
|
@ -651,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() {
|
||||
|
@ -688,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() {
|
||||
|
@ -731,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;
|
||||
}
|
||||
|
@ -912,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/>");
|
||||
|
@ -930,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() {
|
||||
|
@ -1030,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");
|
||||
|
@ -1240,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(){
|
||||
|
@ -1543,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");
|
||||
|
@ -1872,27 +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." );
|
||||
});
|
||||
|
||||
test("focusin bubbles", function() {
|
||||
//create an input and focusin on it
|
||||
var input = jQuery("<input/>"), order = 0;
|
||||
|
||||
input.prependTo("body");
|
||||
|
||||
jQuery("body").bind("focusin.focusinBubblesTest",function(){
|
||||
equals(1,order++,"focusin on the body second")
|
||||
});
|
||||
|
||||
input.bind("focusin.focusinBubblesTest",function(){
|
||||
equals(0,order++,"focusin on the element first")
|
||||
});
|
||||
|
||||
input[0].focus();
|
||||
input.remove();
|
||||
|
||||
jQuery("body").unbind("focusin.focusinBubblesTest");
|
||||
ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." );
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
module("manipulation");
|
||||
module("manipulation", { teardown: moduleTeardown });
|
||||
|
||||
// Ensure that an extended Array prototype doesn't break jQuery
|
||||
Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); };
|
||||
|
||||
var bareObj = function(value) { return value; };
|
||||
var functionReturningObj = function(value) { return (function() { return value; }); };
|
||||
|
@ -51,7 +54,7 @@ test("text(Function) with incoming value", function() {
|
|||
});
|
||||
|
||||
var testWrap = function(val) {
|
||||
expect(18);
|
||||
expect(19);
|
||||
var defaultText = 'Try them out:'
|
||||
var result = jQuery('#first').wrap(val( '<div class="red"><span></span></div>' )).text();
|
||||
equals( defaultText, result, 'Check for wrapping of on-the-fly html' );
|
||||
|
@ -80,10 +83,20 @@ var testWrap = function(val) {
|
|||
equals( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" );
|
||||
|
||||
// Try wrapping a disconnected node
|
||||
var cacheLength = 0;
|
||||
for (var i in jQuery.cache) {
|
||||
cacheLength++;
|
||||
}
|
||||
|
||||
j = jQuery("<label/>").wrap(val( "<li/>" ));
|
||||
equals( j[0].nodeName.toUpperCase(), "LABEL", "Element is a label" );
|
||||
equals( j[0].parentNode.nodeName.toUpperCase(), "LI", "Element has been wrapped" );
|
||||
|
||||
for (i in jQuery.cache) {
|
||||
cacheLength--;
|
||||
}
|
||||
equals(cacheLength, 0, "No memory leak in jQuery.cache (bug #7165)");
|
||||
|
||||
// Wrap an element containing a text node
|
||||
j = jQuery("<span/>").wrap("<div>test</div>");
|
||||
equals( j[0].previousSibling.nodeType, 3, "Make sure the previous node is a text element" );
|
||||
|
@ -102,12 +115,19 @@ var testWrap = function(val) {
|
|||
// Wrap an element with a jQuery set and event
|
||||
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() {
|
||||
|
@ -382,7 +402,7 @@ test("append(Function) with incoming value", function() {
|
|||
});
|
||||
|
||||
test("append the same fragment with events (Bug #6997, 5566)", function () {
|
||||
expect(4 + (document.fireEvent ? 1 : 0));
|
||||
expect(2 + (document.fireEvent ? 1 : 0));
|
||||
stop(1000);
|
||||
|
||||
var element;
|
||||
|
@ -395,8 +415,12 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
|
|||
ok(true, "Event exists on original after being unbound on clone");
|
||||
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 () {
|
||||
|
@ -413,14 +437,6 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
|
|||
|
||||
jQuery("#listWithTabIndex li").before(element);
|
||||
jQuery("#listWithTabIndex li.test6997").eq(1).click();
|
||||
|
||||
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
|
||||
|
||||
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
|
||||
|
||||
element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
|
||||
|
||||
equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
|
||||
});
|
||||
|
||||
test("appendTo(String|Element|Array<Element>|jQuery)", function() {
|
||||
|
@ -856,7 +872,7 @@ test("replaceAll(String|Element|Array<Element>|jQuery)", function() {
|
|||
});
|
||||
|
||||
test("clone()", function() {
|
||||
expect(36);
|
||||
expect(37);
|
||||
equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' );
|
||||
var clone = jQuery('#yahoo').clone();
|
||||
equals( 'Try them out:Yahoo', jQuery('#first').append(clone).text(), 'Check for clone' );
|
||||
|
@ -881,20 +897,36 @@ test("clone()", function() {
|
|||
ok( true, "Bound event still exists." );
|
||||
});
|
||||
|
||||
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,
|
||||
|
@ -914,10 +946,16 @@ test("clone()", function() {
|
|||
equals( clone.html(), div.html(), "Element contents cloned" );
|
||||
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
|
||||
|
||||
div = jQuery("<div/>").data({ a: true, b: true });
|
||||
div = div.clone(true);
|
||||
equals( div.data("a"), true, "Data cloned." );
|
||||
equals( div.data("b"), true, "Data cloned." );
|
||||
div = jQuery("<div/>").data({ a: true });
|
||||
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/";
|
||||
|
@ -930,6 +968,28 @@ test("clone()", function() {
|
|||
equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
|
||||
});
|
||||
|
||||
test("clone(form element) (Bug #3879, #6655)", function() {
|
||||
expect(6);
|
||||
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
|
||||
|
||||
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
|
||||
|
||||
element = jQuery("<input type='checkbox' value='foo'>").attr('checked', 'checked');
|
||||
clone = element.clone();
|
||||
|
||||
equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
|
||||
equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
|
||||
equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" );
|
||||
|
||||
element = jQuery("<input type='text' value='foo'>");
|
||||
clone = element.clone();
|
||||
equals( clone[0].defaultValue, "foo", "Text input defaultValue cloned correctly" );
|
||||
|
||||
element = jQuery("<textarea>foo</textarea>");
|
||||
clone = element.clone();
|
||||
equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
|
||||
});
|
||||
|
||||
if (!isLocal) {
|
||||
test("clone() on XML nodes", function() {
|
||||
expect(2);
|
||||
|
@ -1126,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() {
|
||||
|
@ -1232,3 +1298,20 @@ test("jQuery.cleanData", function() {
|
|||
return div;
|
||||
}
|
||||
});
|
||||
|
||||
test("jQuery.buildFragment - no plain-text caching (Bug #6779)", function() {
|
||||
expect(1);
|
||||
|
||||
// DOM manipulation fails if added text matches an Object method
|
||||
var $f = jQuery( "<div />" ).appendTo( "#main" ),
|
||||
bad = [ "start-", "toString", "hasOwnProperty", "append", "here&there!", "-end" ];
|
||||
|
||||
for ( var i=0; i < bad.length; i++ ) {
|
||||
try {
|
||||
$f.append( bad[i] );
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
equals($f.text(), bad.join(''), "Cached strings that match Object properties");
|
||||
$f.remove();
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module("offset");
|
||||
module("offset", { teardown: moduleTeardown });
|
||||
|
||||
test("disconnected node", function() {
|
||||
expect(2);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module("queue");
|
||||
module("queue", { teardown: moduleTeardown });
|
||||
|
||||
test("queue() with other types",function() {
|
||||
expect(9);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module("selector");
|
||||
module("selector", { teardown: moduleTeardown });
|
||||
|
||||
test("element", function() {
|
||||
expect(21);
|
||||
|
@ -58,7 +58,8 @@ if ( location.protocol != "file:" ) {
|
|||
}
|
||||
|
||||
test("broken", function() {
|
||||
expect(8);
|
||||
expect(19);
|
||||
|
||||
function broken(name, selector) {
|
||||
try {
|
||||
jQuery(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"] );
|
||||
|
||||
|
@ -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() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module("traversing");
|
||||
module("traversing", { teardown: moduleTeardown });
|
||||
|
||||
test("find(String)", function() {
|
||||
expect(5);
|
||||
|
@ -441,11 +441,12 @@ test("add(String|Element|Array|undefined)", function() {
|
|||
test("add(String, Context)", function() {
|
||||
expect(6);
|
||||
|
||||
equals( jQuery(document).add("#form").length, 2, "Make sure that using regular context document still works." );
|
||||
equals( jQuery(document.body).add("#form").length, 2, "Using a body context." );
|
||||
equals( jQuery(document.body).add("#html").length, 1, "Using a body context." );
|
||||
deepEqual( jQuery( "#firstp" ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add selector to selector " );
|
||||
deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add gEBId to selector" );
|
||||
deepEqual( jQuery( document.getElementById("firstp") ).add( document.getElementById("ap") ).get(), q( "firstp", "ap" ), "Add gEBId to gEBId" );
|
||||
|
||||
equals( jQuery(document).add("#form", document).length, 2, "Use a passed in document context." );
|
||||
equals( jQuery(document).add("#form", document.body).length, 2, "Use a passed in body context." );
|
||||
equals( jQuery(document).add("#html", document.body).length, 1, "Use a passed in body context." );
|
||||
var ctx = document.getElementById("firstp");
|
||||
deepEqual( jQuery( "#firstp" ).add( "#ap", ctx ).get(), q( "firstp" ), "Add selector to selector " );
|
||||
deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", ctx ).get(), q( "firstp" ), "Add gEBId to selector, not in context" );
|
||||
deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", document.getElementsByTagName("body")[0] ).get(), q( "firstp", "ap" ), "Add gEBId to selector, in context" );
|
||||
});
|
||||
|
|
|
@ -1 +1 @@
|
|||
1.4.5pre
|
||||
1.5pre
|
Loading…
Reference in a new issue