aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--build/lib/parse-js.js40
-rw-r--r--build/lib/process.js96
-rw-r--r--build/post-compile.js2
-rw-r--r--build/release-notes.js4
-rw-r--r--build/release.js2
-rw-r--r--build/uglify.js176
-rw-r--r--src/attributes.js188
-rw-r--r--src/core.js7
-rw-r--r--src/data.js2
-rw-r--r--src/deferred.js2
-rw-r--r--src/effects.js37
-rw-r--r--src/event.js4
-rw-r--r--src/manipulation.js8
-rw-r--r--src/queue.js3
-rw-r--r--src/support.js12
-rw-r--r--test/data/support/boxModelIE.html27
-rw-r--r--test/data/support/hiddenIFrameFF.html25
-rw-r--r--test/data/testrunner.js11
-rw-r--r--test/data/versioncheck.js8
-rw-r--r--test/index.html7
-rw-r--r--test/unit/attributes.js230
-rw-r--r--test/unit/core.js21
-rw-r--r--test/unit/css.js10
-rw-r--r--test/unit/deferred.js12
-rw-r--r--test/unit/effects.js80
-rw-r--r--test/unit/event.js16
-rw-r--r--test/unit/manipulation.js13
-rw-r--r--test/unit/support.js32
-rw-r--r--version.txt2
30 files changed, 778 insertions, 301 deletions
diff --git a/README.md b/README.md
index 5d147a555..a54a02df5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[jQuery](http://jquery.com/) - New Wave Javascript
+[jQuery](http://jquery.com/) - New Wave JavaScript
==================================================
What you need to build your own jQuery
diff --git a/build/lib/parse-js.js b/build/lib/parse-js.js
index 9f90dfeec..8edecb733 100644
--- a/build/lib/parse-js.js
+++ b/build/lib/parse-js.js
@@ -751,14 +751,17 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);
};
- var statement = embed_tokens ? function() {
- var start = S.token;
- var ast = $statement.apply(this, arguments);
- ast[0] = add_tokens(ast[0], start, prev());
- return ast;
- } : $statement;
-
- function $statement() {
+ function maybe_embed_tokens(parser) {
+ if (embed_tokens) return function() {
+ var start = S.token;
+ var ast = parser.apply(this, arguments);
+ ast[0] = add_tokens(ast[0], start, prev());
+ return ast;
+ };
+ else return parser;
+ };
+
+ var statement = maybe_embed_tokens(function() {
if (is("operator", "/")) {
S.peeked = null;
S.token = S.input(true); // force regexp
@@ -852,7 +855,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
unexpected();
}
}
- };
+ });
function labeled_statement(label) {
S.labels.push(label);
@@ -910,14 +913,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return as("for-in", init, lhs, obj, in_loop(statement));
};
- var function_ = embed_tokens ? function() {
- var start = prev();
- var ast = $function_.apply(this, arguments);
- ast[0] = add_tokens(ast[0], start, prev());
- return ast;
- } : $function_;
-
- function $function_(in_statement) {
+ var function_ = maybe_embed_tokens(function(in_statement) {
var name = is("name") ? prog1(S.token.value, next) : null;
if (in_statement && !name)
unexpected();
@@ -945,7 +941,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
S.in_loop = loop;
return a;
})());
- };
+ });
function if_() {
var cond = parenthesised(), body = statement(), belse;
@@ -1053,7 +1049,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return subscripts(as("new", newexp, args), true);
};
- function expr_atom(allow_calls) {
+ var expr_atom = maybe_embed_tokens(function(allow_calls) {
if (is("operator", "new")) {
next();
return new_();
@@ -1088,7 +1084,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return subscripts(prog1(atom, next), allow_calls);
}
unexpected();
- };
+ });
function expr_list(closing, allow_trailing_comma, allow_empty) {
var first = true, a = [];
@@ -1228,7 +1224,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return left;
};
- function expression(commas, no_in) {
+ var expression = maybe_embed_tokens(function(commas, no_in) {
if (arguments.length == 0)
commas = true;
var expr = maybe_assign(no_in);
@@ -1237,7 +1233,7 @@ function parse($TEXT, exigent_mode, embed_tokens) {
return as("seq", expr, expression(true, no_in));
}
return expr;
- };
+ });
function in_loop(cont) {
try {
diff --git a/build/lib/process.js b/build/lib/process.js
index 09cbc2ad8..3878c8d62 100644
--- a/build/lib/process.js
+++ b/build/lib/process.js
@@ -75,6 +75,12 @@ function ast_walker(ast) {
return a;
}) ];
};
+ function _block(statements) {
+ var out = [ this[0] ];
+ if (statements != null)
+ out.push(MAP(statements, walk));
+ return out;
+ };
var walkers = {
"string": function(str) {
return [ this[0], str ];
@@ -88,12 +94,8 @@ function ast_walker(ast) {
"toplevel": function(statements) {
return [ this[0], MAP(statements, walk) ];
},
- "block": function(statements) {
- var out = [ this[0] ];
- if (statements != null)
- out.push(MAP(statements, walk));
- return out;
- },
+ "block": _block,
+ "splice": _block,
"var": _vardefs,
"const": _vardefs,
"try": function(t, c, f) {
@@ -377,7 +379,9 @@ function ast_add_scope(ast) {
};
function _lambda(name, args, body) {
- return [ this[0], this[0] == "defun" ? define(name) : name, args, with_new_scope(function(){
+ var is_defun = this[0] == "defun";
+ return [ this[0], is_defun ? define(name) : name, args, with_new_scope(function(){
+ if (!is_defun) define(name);
MAP(args, define);
return MAP(body, walk);
})];
@@ -463,9 +467,22 @@ function ast_mangle(ast, options) {
return scope.get_mangled(name, newMangle);
};
+ function get_define(name) {
+ // we always lookup a defined symbol for the current scope FIRST, so declared
+ // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value
+ if (!scope.has(name)) {
+ if (HOP(options.defines, name)) {
+ return options.defines[name];
+ }
+ }
+ return null;
+ };
+
function _lambda(name, args, body) {
- if (name) name = get_mangled(name);
+ var is_defun = this[0] == "defun";
+ if (is_defun && name) name = get_mangled(name);
body = with_scope(body.scope, function(){
+ if (!is_defun && name) name = get_mangled(name);
args = MAP(args, function(name){ return get_mangled(name) });
return MAP(body, walk);
});
@@ -507,7 +524,7 @@ function ast_mangle(ast, options) {
"var": _vardefs,
"const": _vardefs,
"name": function(name) {
- return [ this[0], get_mangled(name) ];
+ return get_define(name) || [ this[0], get_mangled(name) ];
},
"try": function(t, c, f) {
return [ this[0],
@@ -583,11 +600,18 @@ function boolean_expr(expr) {
};
function make_conditional(c, t, e) {
+ var make_real_conditional = function() {
if (c[0] == "unary-prefix" && c[1] == "!") {
- return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
+ return e ? [ "conditional", c[2], e, t ] : [ "binary", "||", c[2], t ];
} else {
- return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
+ return e ? [ "conditional", c, t, e ] : [ "binary", "&&", c, t ];
}
+ };
+ // shortcut the conditional if the expression has a constant value
+ return when_constant(c, function(ast, val){
+ warn_unreachable(val ? e : t);
+ return (val ? t : e);
+ }, make_real_conditional);
};
function empty(b) {
@@ -676,6 +700,18 @@ var when_constant = (function(){
|| (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {
expr[1] = expr[1].substr(0, 2);
}
+ else if (no && expr[0] == "binary"
+ && (expr[1] == "||" || expr[1] == "&&")) {
+ // the whole expression is not constant but the lval may be...
+ try {
+ var lval = evaluate(expr[2]);
+ expr = ((expr[1] == "&&" && (lval ? expr[3] : lval)) ||
+ (expr[1] == "||" && (lval ? lval : expr[3])) ||
+ expr);
+ } catch(ex2) {
+ // IGNORE... lval is not constant
+ }
+ }
return no ? no.call(expr, expr) : null;
}
else throw ex;
@@ -751,9 +787,14 @@ function ast_squeeze(ast, options) {
};
function _lambda(name, args, body) {
- return [ this[0], name, args, with_scope(body.scope, function(){
- return tighten(MAP(body, walk), "lambda");
- }) ];
+ var is_defun = this[0] == "defun";
+ body = with_scope(body.scope, function(){
+ var ret = tighten(MAP(body, walk), "lambda");
+ if (!is_defun && name && !HOP(scope.refs, name))
+ name = null;
+ return ret;
+ });
+ return [ this[0], name, args, body ];
};
// we get here for blocks that have been already transformed.
@@ -959,13 +1000,7 @@ function ast_squeeze(ast, options) {
return [ branch[0] ? walk(branch[0]) : null, block ];
}) ];
},
- "function": function() {
- var ret = _lambda.apply(this, arguments);
- if (ret[1] && !HOP(scope.refs, ret[1])) {
- ret[1] = null;
- }
- return ret;
- },
+ "function": _lambda,
"defun": _lambda,
"block": function(body) {
if (body) return rmblock([ "block", tighten(MAP(body, walk)) ]);
@@ -1067,6 +1102,8 @@ function to_ascii(str) {
});
};
+var SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ "if", "while", "do", "for", "for-in", "with" ]);
+
function gen_code(ast, options) {
options = defaults(options, {
indent_start : 0,
@@ -1197,6 +1234,19 @@ function gen_code(ast, options) {
return make_block_statements(statements)
.join(newline + newline);
},
+ "splice": function(statements) {
+ var parent = $stack[$stack.length - 2][0];
+ if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {
+ // we need block brackets in this case
+ return make_block.apply(this, arguments);
+ } else {
+ return MAP(make_block_statements(statements, true),
+ function(line, i) {
+ // the first line is already indented
+ return i > 0 ? indent(line) : line;
+ }).join(newline);
+ }
+ },
"block": make_block,
"var": function(defs) {
return "var " + add_commas(MAP(defs, make_1vardef)) + ";";
@@ -1437,7 +1487,7 @@ function gen_code(ast, options) {
return add_spaces([ out, make_block(body) ]);
};
- function make_block_statements(statements) {
+ function make_block_statements(statements, noindent) {
for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {
var stat = statements[i];
var code = make(stat);
@@ -1455,7 +1505,7 @@ function gen_code(ast, options) {
a.push(code);
}
}
- return MAP(a, indent);
+ return noindent ? a : MAP(a, indent);
};
function make_switch_block(body) {
diff --git a/build/post-compile.js b/build/post-compile.js
index 4bcafe814..1bbeaa6f4 100644
--- a/build/post-compile.js
+++ b/build/post-compile.js
@@ -4,4 +4,4 @@ var print = require("sys").print,
src = require("fs").readFileSync(process.argv[2], "utf8");
// Previously done in sed but reimplemented here due to portability issues
-print(src.replace(/^(\s*\*\/)(.+)/m, "$1\n$2;"));
+print( src.replace( /^(\s*\*\/)(.+)/m, "$1\n$2" ) + ";" );
diff --git a/build/release-notes.js b/build/release-notes.js
index c81060a8d..37b9d3897 100644
--- a/build/release-notes.js
+++ b/build/release-notes.js
@@ -9,8 +9,8 @@ var fs = require("fs"),
extract = /<a href="\/ticket\/(\d+)" title="View ticket">(.*?)<[^"]+"component">\s*(\S+)/g;
var opts = {
- version: "1.6 RC 1",
- short_version: "1.6rc1",
+ version: "1.6",
+ short_version: "1.6",
final_version: "1.6",
categories: []
};
diff --git a/build/release.js b/build/release.js
index 09f917b48..7a42f998b 100644
--- a/build/release.js
+++ b/build/release.js
@@ -86,7 +86,7 @@ function setNextVersion( newVersion ) {
} else if ( /^\d+\.\d+\.?(\d*)$/.test( newVersion ) ) {
newVersion = newVersion.replace( /^(\d+\.\d+\.?)(\d*)$/, function( all, pre, num ) {
- return pre + (num ? parseFloat( num ) + 1 : 1) + "pre";
+ return pre + (pre.charAt( pre.length - 1 ) !== "." ? "." : "") + (num ? parseFloat( num ) + 1 : 1) + "pre";
});
isFinal = true;
diff --git a/build/uglify.js b/build/uglify.js
index 943ddd806..aad18e8ca 100644
--- a/build/uglify.js
+++ b/build/uglify.js
@@ -1,14 +1,10 @@
#! /usr/bin/env node
-// -*- js2 -*-
+// -*- js -*-
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 fs = require("fs");
+var jsp = require("./lib/parse-js"),
+ pro = require("./lib/process");
var options = {
ast: false,
@@ -17,13 +13,16 @@ var options = {
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: {
+ max_line_length: 32 * 1024,
+ unsafe: false,
+ reserved_names: null,
+ defines: { },
+ codegen_options: {
+ ascii_only: false,
+ beautify: false,
indent_level: 4,
indent_start: 0,
quote_keys: false,
@@ -40,15 +39,15 @@ out: while (args.length > 0) {
switch (v) {
case "-b":
case "--beautify":
- options.beautify = true;
+ options.codegen_options.beautify = true;
break;
case "-i":
case "--indent":
- options.beautify_options.indent_level = args.shift();
+ options.codegen_options.indent_level = args.shift();
break;
case "-q":
case "--quote-keys":
- options.beautify_options.quote_keys = true;
+ options.codegen_options.quote_keys = true;
break;
case "-mt":
case "--mangle-toplevel":
@@ -86,23 +85,109 @@ out: while (args.length > 0) {
case "--ast":
options.ast = true;
break;
- case "--extra":
- options.extra = true;
- break;
case "--unsafe":
options.unsafe = true;
break;
+ case "--max-line-len":
+ options.max_line_length = parseInt(args.shift(), 10);
+ break;
+ case "--reserved-names":
+ options.reserved_names = args.shift().split(",");
+ break;
+ case "-d":
+ case "--define":
+ var defarg = args.shift();
+ try {
+ var defsym = function(sym) {
+ // KEYWORDS_ATOM doesn't include NaN or Infinity - should we check
+ // for them too ?? We don't check reserved words and the like as the
+ // define values are only substituted AFTER parsing
+ if (jsp.KEYWORDS_ATOM.hasOwnProperty(sym)) {
+ throw "Don't define values for inbuilt constant '"+sym+"'";
+ }
+ return sym;
+ },
+ defval = function(v) {
+ if (v.match(/^"(.*)"$/) || v.match(/^'(.*)'$/)) {
+ return [ "string", RegExp.$1 ];
+ }
+ else if (!isNaN(parseFloat(v))) {
+ return [ "num", parseFloat(v) ];
+ }
+ else if (v.match(/^[a-z\$_][a-z\$_0-9]*$/i)) {
+ return [ "name", v ];
+ }
+ else if (!v.match(/"/)) {
+ return [ "string", v ];
+ }
+ else if (!v.match(/'/)) {
+ return [ "string", v ];
+ }
+ throw "Can't understand the specified value: "+v;
+ };
+ if (defarg.match(/^([a-z_\$][a-z_\$0-9]*)(=(.*))?$/i)) {
+ var sym = defsym(RegExp.$1),
+ val = RegExp.$2 ? defval(RegExp.$2.substr(1)) : [ 'name', 'true' ];
+ options.defines[sym] = val;
+ }
+ else {
+ throw "The --define option expects SYMBOL[=value]";
+ }
+ } catch(ex) {
+ sys.print("ERROR: In option --define "+defarg+"\n"+ex+"\n");
+ process.exit(1);
+ }
+ break;
+ case "--define-from-module":
+ var defmodarg = args.shift(),
+ defmodule = require(defmodarg),
+ sym,
+ val;
+ for (sym in defmodule) {
+ if (defmodule.hasOwnProperty(sym)) {
+ options.defines[sym] = function(val) {
+ if (typeof val == "string")
+ return [ "string", val ];
+ if (typeof val == "number")
+ return [ "num", val ];
+ if (val === true)
+ return [ 'name', 'true' ];
+ if (val === false)
+ return [ 'name', 'false' ];
+ if (val === null)
+ return [ 'name', 'null' ];
+ if (val === undefined)
+ return [ 'name', 'undefined' ];
+ sys.print("ERROR: In option --define-from-module "+defmodarg+"\n");
+ sys.print("ERROR: Unknown object type for: "+sym+"="+val+"\n");
+ process.exit(1);
+ return null;
+ }(defmodule[sym]);
+ }
+ }
+ break;
+ case "--ascii":
+ options.codegen_options.ascii_only = true;
+ break;
default:
filename = v;
break out;
}
}
+if (options.verbose) {
+ pro.set_logger(function(msg){
+ sys.debug(msg);
+ });
+}
+
+jsp.set_logger(function(msg){
+ sys.debug(msg);
+});
+
if (filename) {
fs.readFile(filename, "utf8", function(err, text){
- if (err) {
- throw err;
- }
+ if (err) throw err;
output(squeeze_it(text));
});
} else {
@@ -131,7 +216,9 @@ function output(text) {
});
}
out.write(text);
- out.end();
+ if (options.output !== true) {
+ out.end();
+ }
};
// --------- main ends here.
@@ -152,36 +239,35 @@ function show_copyright(comments) {
function squeeze_it(code) {
var result = "";
if (options.show_copyright) {
- var initial_comments = [];
- // keep first comment
- var tok = jsp.tokenizer(code, false), c;
+ var tok = jsp.tokenizer(code), 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);
+ result += show_copyright(c.comments_before);
}
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.mangle) ast = time_it("mangle", function(){
+ return pro.ast_mangle(ast, {
+ toplevel: options.mangle_toplevel,
+ defines: options.defines,
+ except: options.reserved_names
+ });
+ });
+ if (options.squeeze) ast = time_it("squeeze", function(){
+ ast = pro.ast_squeeze(ast, {
+ make_seqs : options.make_seqs,
+ dead_code : options.dead_code,
+ keep_comps : !options.unsafe
});
+ 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) });
+ result += time_it("generate", function(){ return pro.gen_code(ast, options.codegen_options) });
+ if (!options.codegen_options.beautify && options.max_line_length) {
+ result = time_it("split", function(){ return pro.split_lines(result, options.max_line_length) });
+ }
return result;
} catch(ex) {
sys.debug(ex.stack);
diff --git a/src/attributes.js b/src/attributes.js
index 43d72ae9b..bc26d735a 100644
--- a/src/attributes.js
+++ b/src/attributes.js
@@ -1,13 +1,14 @@
(function( jQuery ) {
var rclass = /[\n\t\r]/g,
- rspaces = /\s+/,
+ rspace = /\s+/,
rreturn = /\r/g,
rtype = /^(?:button|input)$/i,
rfocusable = /^(?:button|input|object|select|textarea)$/i,
rclickable = /^a(?:rea)?$/i,
- rspecial = /^(?:data-|aria-)/,
- formHook;
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ rinvalidChar = /\:/,
+ formHook, boolHook;
jQuery.fn.extend({
attr: function( name, value ) {
@@ -25,6 +26,7 @@ jQuery.fn.extend({
},
removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
return this.each(function() {
// try/catch handles cases where IE balks (such as removing a property on window)
try {
@@ -43,7 +45,7 @@ jQuery.fn.extend({
}
if ( value && typeof value === "string" ) {
- var classNames = (value || "").split( rspaces );
+ var classNames = (value || "").split( rspace );
for ( var i = 0, l = this.length; i < l; i++ ) {
var elem = this[i];
@@ -79,7 +81,7 @@ jQuery.fn.extend({
}
if ( (value && typeof value === "string") || value === undefined ) {
- var classNames = (value || "").split( rspaces );
+ var classNames = (value || "").split( rspace );
for ( var i = 0, l = this.length; i < l; i++ ) {
var elem = this[i];
@@ -120,7 +122,7 @@ jQuery.fn.extend({
i = 0,
self = jQuery( this ),
state = stateVal,
- classNames = value.split( rspaces );
+ classNames = value.split( rspace );
while ( (className = classNames[ i++ ]) ) {
// check each className given, space seperated list
@@ -198,7 +200,7 @@ jQuery.fn.extend({
hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
// If set returns undefined, fall back to normal setting
- if ( !hooks || ("set" in hooks && hooks.set( this, val, "value" ) === undefined) ) {
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
this.value = val;
}
});
@@ -217,7 +219,8 @@ jQuery.extend({
},
select: {
get: function( elem ) {
- var index = elem.selectedIndex,
+ var value,
+ index = elem.selectedIndex,
values = [],
options = elem.options,
one = elem.type === "select-one";
@@ -284,8 +287,7 @@ jQuery.extend({
attrFix: {
// Always normalize to ensure hook usage
- tabindex: "tabIndex",
- readonly: "readOnly"
+ tabindex: "tabIndex"
},
attr: function( elem, name, value, pass ) {
@@ -299,20 +301,36 @@ jQuery.extend({
if ( pass && name in jQuery.attrFn ) {
return jQuery( elem )[ name ]( value );
}
-
+
+ // Fallback to prop when attributes are not supported
+ if ( !("getAttribute" in elem) ) {
+ return jQuery.prop( elem, name, value );
+ }
+
var ret, hooks,
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
+
// Normalize the name if needed
name = notxml && jQuery.attrFix[ name ] || name;
- // Get the appropriate hook, or the formHook
- // if getSetAttribute is not supported and we have form objects in IE6/7
- hooks = jQuery.attrHooks[ name ] || ( jQuery.nodeName( elem, "form" ) && formHook );
+ hooks = jQuery.attrHooks[ name ];
+
+ if ( !hooks ) {
+ // Use boolHook for boolean attributes
+ if ( rboolean.test( name ) &&
+ (typeof value === "boolean" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) {
+
+ hooks = boolHook;
+
+ // Use formHook for forms and if the name contains certain characters
+ } else if ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) {
+ hooks = formHook;
+ }
+ }
if ( value !== undefined ) {
- if ( value === null || (value === false && !rspecial.test( name )) ) {
+ if ( value === null ) {
jQuery.removeAttr( elem, name );
return undefined;
@@ -320,34 +338,26 @@ jQuery.extend({
return ret;
} else {
-
- // Set boolean attributes to the same name
- if ( value === true && !rspecial.test( name ) ) {
- value = name;
- }
-
elem.setAttribute( name, "" + value );
return value;
}
- } else {
-
- if ( hooks && "get" in hooks && notxml ) {
- return hooks.get( elem, name );
+ } else if ( hooks && "get" in hooks && notxml ) {
+ return hooks.get( elem, name );
- } else {
+ } else {
- ret = elem.getAttribute( name );
+ ret = elem.getAttribute( name );
- // Non-existent attributes return null, we normalize to undefined
- return ret === null ?
- undefined :
- ret;
- }
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
}
},
-
+
removeAttr: function( elem, name ) {
+ var propName;
if ( elem.nodeType === 1 ) {
name = jQuery.attrFix[ name ] || name;
@@ -358,6 +368,11 @@ jQuery.extend({
jQuery.attr( elem, name, "" );
elem.removeAttributeNode( elem.getAttributeNode( name ) );
}
+
+ // Set corresponding property to false for boolean attributes
+ if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
+ elem[ propName ] = false;
+ }
}
},
@@ -371,7 +386,7 @@ jQuery.extend({
// Setting the type on a radio button after the value resets the value in IE6-9
// Reset value to it's default in case type is set after value
// This is for element creation
- var val = elem.getAttribute("value");
+ var val = elem.value;
elem.setAttribute( "type", value );
if ( val ) {
elem.value = val;
@@ -394,37 +409,50 @@ jQuery.extend({
}
}
},
-
- propFix: {},
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
prop: function( elem, name, value ) {
var nType = elem.nodeType;
-
+
// don't get/set properties on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return undefined;
}
-
+
var ret, hooks,
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
+
// Try to normalize/fix the name
name = notxml && jQuery.propFix[ name ] || name;
hooks = jQuery.propHooks[ name ];
-
+
if ( value !== undefined ) {
if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;
-
+
} else {
return (elem[ name ] = value);
}
-
+
} else {
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
return ret;
-
+
} else {
return elem[ name ];
}
@@ -434,29 +462,65 @@ jQuery.extend({
propHooks: {}
});
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ return elem[ jQuery.propFix[ name ] || name ] ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = value;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// Use the value property for back compat
+// Use the formHook for button elements in IE6/7 (#1954)
+jQuery.attrHooks.value = {
+ get: function( elem, name ) {
+ if ( formHook && jQuery.nodeName( elem, "button" ) ) {
+ return formHook.get( elem, name );
+ }
+ return elem.value;
+ },
+ set: function( elem, value, name ) {
+ if ( formHook && jQuery.nodeName( elem, "button" ) ) {
+ return formHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+};
+
// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !jQuery.support.getSetAttribute ) {
- jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
- "for": "htmlFor",
- "class": "className",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- cellpadding: "cellPadding",
- rowspan: "rowSpan",
- colspan: "colSpan",
- usemap: "useMap",
- frameborder: "frameBorder"
- });
+
+ // propFix is more comprehensive and contains all fixes
+ jQuery.attrFix = jQuery.propFix;
// Use this for any attribute on a form in IE6/7
- formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
+ formHook = jQuery.attrHooks.name = jQuery.valHooks.button = {
get: function( elem, name ) {
- if ( name === "value" && !jQuery.nodeName( elem, "button" ) ) {
- return elem.getAttribute( name );
- }
- var ret = elem.getAttributeNode( name );
- // Return undefined if not specified instead of empty string
- return ret && ret.specified ?
+ var ret;
+ ret = elem.getAttributeNode( name );
+ // Return undefined if nodeValue is empty string
+ return ret && ret.nodeValue !== "" ?
ret.nodeValue :
undefined;
},
diff --git a/src/core.js b/src/core.js
index 8d812e384..056fb88fb 100644
--- a/src/core.js
+++ b/src/core.js
@@ -96,9 +96,10 @@ jQuery.fn = jQuery.prototype = {
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
- if ( selector.length > 1024 ) {
- // Assume very large strings are HTML and skip the regex check
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];
+
} else {
match = quickExpr.exec( selector );
}
@@ -719,7 +720,7 @@ jQuery.extend({
i = 0,
length = elems.length,
// jquery objects are treated as arrays
- isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || jQuery.isArray( elems ) ) ;
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
// Go through the array, translating each of the items to their
if ( isArray ) {
diff --git a/src/data.js b/src/data.js
index c2fd558f0..9e5d1ab0b 100644
--- a/src/data.js
+++ b/src/data.js
@@ -284,7 +284,7 @@ function dataAttr( elem, key, data ) {
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) {
- name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
+ var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
data = elem.getAttribute( name );
diff --git a/src/deferred.js b/src/deferred.js
index 02f92b26c..5cc5fb5be 100644
--- a/src/deferred.js
+++ b/src/deferred.js
@@ -119,7 +119,7 @@ jQuery.extend({
if ( jQuery.isFunction( fn ) ) {
deferred[ handler ](function() {
returned = fn.apply( this, arguments );
- if ( jQuery.isFunction( returned.promise ) ) {
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise().then( newDefer.resolve, newDefer.reject );
} else {
newDefer[ action ]( returned );
diff --git a/src/effects.js b/src/effects.js
index 956005089..38d5a0119 100644
--- a/src/effects.js
+++ b/src/effects.js
@@ -126,6 +126,9 @@ jQuery.fn.extend({
return this.each( optall.complete, [ false ] );
}
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
+
return this[ optall.queue === false ? "each" : "queue" ](function() {
// XXX 'this' does not always have a nodeName when running the
// test suite
@@ -134,7 +137,7 @@ jQuery.fn.extend({
jQuery._mark( this );
}
- var opt = jQuery.extend({}, optall),
+ var opt = jQuery.extend( {}, optall ),
isElement = this.nodeType === 1,
hidden = isElement && jQuery(this).is(":hidden"),
name, val, p,
@@ -153,10 +156,18 @@ jQuery.fn.extend({
delete prop[ p ];
}
- val = prop[name];
+ val = prop[ name ];
+
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
+ } else {
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+ }
if ( val === "hide" && hidden || val === "show" && !hidden ) {
- return opt.complete.call(this);
+ return opt.complete.call( this );
}
if ( isElement && ( name === "height" || name === "width" ) ) {
@@ -175,7 +186,7 @@ jQuery.fn.extend({
this.style.display = "inline-block";
} else {
- display = defaultDisplay(this.nodeName);
+ display = defaultDisplay( this.nodeName );
// inline-level elements accept inline-block;
// block-level elements need to be inline with layout
@@ -189,11 +200,6 @@ jQuery.fn.extend({
}
}
}
-
- // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
- opt.animatedProperties[name] = jQuery.isArray( val ) ?
- val[1]:
- opt.specialEasing && opt.specialEasing[name] || opt.easing || 'swing';
}
if ( opt.overflow != null ) {
@@ -202,19 +208,18 @@ jQuery.fn.extend({
for ( p in prop ) {
e = new jQuery.fx( this, opt, p );
-
- val = prop[p];
+ val = prop[ p ];
if ( rfxtypes.test(val) ) {
e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
} else {
- parts = rfxnum.exec(val);
+ parts = rfxnum.exec( val );
start = e.cur();
if ( parts ) {
end = parseFloat( parts[2] );
- unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
// We need to compute starting value
if ( unit !== "px" ) {
@@ -225,7 +230,7 @@ jQuery.fn.extend({
// If a +=/-= token was provided, we're doing a relative animation
if ( parts[1] ) {
- end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
}
e.custom( start, end, unit );
@@ -500,10 +505,10 @@ jQuery.fx.prototype = {
this.now = t;
} else {
n = t - this.startTime;
-
this.state = n / options.duration;
+
// Perform the easing function, defaults to swing
- this.pos = jQuery.easing[options.animatedProperties[this.prop]](this.state, n, 0, 1, options.duration);
+ this.pos = jQuery.easing[ options.animatedProperties[ this.prop ] ]( this.state, n, 0, 1, options.duration );
this.now = this.start + ((this.end - this.start) * this.pos);
}
// Perform the next step of the animation
diff --git a/src/event.js b/src/event.js
index 0f09241c9..05e79d358 100644
--- a/src/event.js
+++ b/src/event.js
@@ -4,7 +4,7 @@ var hasOwn = Object.prototype.hasOwnProperty,
rnamespaces = /\.(.*)$/,
rformElems = /^(?:textarea|input|select)$/i,
rperiod = /\./g,
- rspace = / /g,
+ rspaces = / /g,
rescape = /[^\w\s.|`]/g,
fcleanup = function( nm ) {
return nm.replace(rescape, "\\$&");
@@ -1177,7 +1177,7 @@ function liveHandler( event ) {
}
function liveConvert( type, selector ) {
- return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
+ return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
}
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
diff --git a/src/manipulation.js b/src/manipulation.js
index 610d19b7a..e9b1ee538 100644
--- a/src/manipulation.js
+++ b/src/manipulation.js
@@ -582,7 +582,7 @@ jQuery.extend({
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
}
- var ret = [];
+ var ret = [], j;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
if ( typeof elem === "number" ) {
@@ -628,7 +628,7 @@ jQuery.extend({
div.childNodes :
[];
- for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
tbody[ j ].parentNode.removeChild( tbody[ j ] );
}
@@ -649,8 +649,8 @@ jQuery.extend({
var len;
if ( !jQuery.support.appendChecked ) {
if ( elem[0] && typeof (len = elem.length) === "number" ) {
- for ( i = 0; i < len; i++ ) {
- findInputs( elem[i] );
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
}
} else {
findInputs( elem );
diff --git a/src/queue.js b/src/queue.js
index ce2305426..66383c190 100644
--- a/src/queue.js
+++ b/src/queue.js
@@ -148,7 +148,8 @@ jQuery.fn.extend({
count = 1,
deferDataKey = type + "defer",
queueDataKey = type + "queue",
- markDataKey = type + "mark";
+ markDataKey = type + "mark",
+ tmp;
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
diff --git a/src/support.js b/src/support.js
index ea14bac63..9ffad2803 100644
--- a/src/support.js
+++ b/src/support.js
@@ -3,6 +3,7 @@
jQuery.support = (function() {
var div = document.createElement( "div" ),
+ documentElement = document.documentElement,
all,
a,
select,
@@ -142,13 +143,15 @@ jQuery.support = (function() {
width: 0,
height: 0,
border: 0,
- margin: 0
+ margin: 0,
+ // Set background to avoid IE crashes when removing (#9028)
+ background: "none"
};
for ( i in bodyStyle ) {
body.style[ i ] = bodyStyle[ i ];
}
body.appendChild( div );
- document.documentElement.appendChild( body );
+ documentElement.insertBefore( body, documentElement.firstChild );
// Check if a disconnected checkbox will retain its checked
// value of true after appended to the DOM (IE6/7)
@@ -203,11 +206,12 @@ jQuery.support = (function() {
marginDiv.style.marginRight = "0";
div.appendChild( marginDiv );
support.reliableMarginRight =
- ( parseInt( document.defaultView.getComputedStyle( marginDiv, null ).marginRight, 10 ) || 0 ) === 0;
+ ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
}
// Remove the body element we added
- document.documentElement.removeChild( body );
+ body.innerHTML = "";
+ documentElement.removeChild( body );
// Technique from Juriy Zaytsev
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
diff --git a/test/data/support/boxModelIE.html b/test/data/support/boxModelIE.html
new file mode 100644
index 000000000..1b11d2a59
--- /dev/null
+++ b/test/data/support/boxModelIE.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<body>
+ <script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.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>
+ <script>
+ window.top.supportCallback( document.compatMode, jQuery.support.boxModel );
+ </script>
+</body>
+</html>
diff --git a/test/data/support/hiddenIFrameFF.html b/test/data/support/hiddenIFrameFF.html
new file mode 100644
index 000000000..000ac851a
--- /dev/null
+++ b/test/data/support/hiddenIFrameFF.html
@@ -0,0 +1,25 @@
+<html>
+ <head>
+ <script src="../../../src/core.js"></script>
+ <script src="../../../src/deferred.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>
+ </body>
+</html>
diff --git a/test/data/testrunner.js b/test/data/testrunner.js
index beb0fe2ab..6d44b460c 100644
--- a/test/data/testrunner.js
+++ b/test/data/testrunner.js
@@ -2,8 +2,9 @@ jQuery.noConflict(); // Allow the test to run with other libs or jQuery's.
// jQuery-specific QUnit.reset
(function() {
- var reset = QUnit.reset;
- var ajaxSettings = jQuery.ajaxSettings
+ var reset = QUnit.reset,
+ ajaxSettings = jQuery.ajaxSettings;
+
QUnit.reset = function() {
reset.apply(this, arguments);
jQuery.event.global = {};
@@ -24,3 +25,9 @@ jQuery.noConflict(); // Allow the test to run with other libs or jQuery's.
document.write("<scr" + "ipt src='http://swarm.jquery.org/js/inject.js?" + (new Date).getTime() + "'></scr" + "ipt>");
})();
+
+// QUnit Aliases
+(function() {
+ window.equals = window.equal;
+ window.same = window.deepEqual;
+})();
diff --git a/test/data/versioncheck.js b/test/data/versioncheck.js
new file mode 100644
index 000000000..f4b7790da
--- /dev/null
+++ b/test/data/versioncheck.js
@@ -0,0 +1,8 @@
+// Run minified source from dist (do make first)
+// Should be loaded before QUnit but after src
+(function() {
+ if ( /jquery\=min/.test( window.location.search ) ) {
+ jQuery.noConflict( true );
+ document.write(unescape("%3Cscript%20src%3D%27../dist/jquery.min.js%27%3E%3C/script%3E"));
+ }
+})(); \ No newline at end of file
diff --git a/test/index.html b/test/index.html
index b19673d99..4b4c98552 100644
--- a/test/index.html
+++ b/test/index.html
@@ -28,10 +28,13 @@
<script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script>
+ <script src="data/versioncheck.js"></script>
+
<script src="qunit/qunit/qunit.js"></script>
<script src="data/testrunner.js"></script>
<script src="unit/core.js"></script>
+ <script src="unit/support.js"></script>
<script src="unit/deferred.js"></script>
<script src="unit/data.js"></script>
<script src="unit/queue.js"></script>
@@ -48,7 +51,9 @@
</head>
<body id="body">
- <h1 id="qunit-header">jQuery Test Suite</h1>
+ <h1 id="qunit-header"><a href="/jquery/test/index.html">jQuery Test Suite</a>
+ <a href="?jquery=min">(minified)</a>
+ </h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
diff --git a/test/unit/attributes.js b/test/unit/attributes.js
index cfe676a63..d2d43475d 100644
--- a/test/unit/attributes.js
+++ b/test/unit/attributes.js
@@ -4,16 +4,14 @@ var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); };
-test("jQuery.attrFix integrity test", function() {
- expect(1);
+test("jQuery.attrFix/jQuery.propFix integrity test", function() {
+ expect(2);
// This must be maintained and equal jQuery.attrFix when appropriate
// Ensure that accidental or erroneous property
// overwrites don't occur
// This is simply for better code coverage and future proofing.
- var propsShouldBe;
- if ( !jQuery.support.getSetAttribute ) {
- propsShouldBe = {
+ var props = {
tabindex: "tabIndex",
readonly: "readOnly",
"for": "htmlFor",
@@ -24,60 +22,25 @@ test("jQuery.attrFix integrity test", function() {
rowspan: "rowSpan",
colspan: "colSpan",
usemap: "useMap",
- frameborder: "frameBorder"
- };
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+ propsShouldBe;
+
+ if ( !jQuery.support.getSetAttribute ) {
+ propsShouldBe = props;
} else {
propsShouldBe = {
- tabindex: "tabIndex",
- readonly: "readOnly"
+ tabindex: "tabIndex"
};
}
- same(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check");
-});
-
-test("prop(String, Object)", function() {
- expect(19);
- equals( jQuery("#text1").prop("value"), "Test", "Check for value attribute" );
- equals( jQuery("#text1").prop("value", "Test2").prop("defaultValue"), "Test", "Check for defaultValue attribute" );
- equals( jQuery("#select2").prop("selectedIndex"), 3, "Check for selectedIndex attribute" );
- equals( jQuery("#foo").prop("nodeName").toUpperCase(), "DIV", "Check for nodeName attribute" );
- equals( jQuery("#foo").prop("tagName").toUpperCase(), "DIV", "Check for tagName attribute" );
- equals( jQuery("<option/>").prop("selected"), false, "Check selected attribute on disconnected element." );
-
- var body = document.body, $body = jQuery( body );
- ok( $body.prop("nextSibling") === null, "Make sure a null expando returns null" );
- body.foo = "bar";
- equals( $body.prop("foo"), "bar", "Make sure the expando is preferred over the dom attribute" );
- body.foo = undefined;
- ok( $body.prop("foo") === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
-
- var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option");
- optgroup.appendChild( option );
- select.appendChild( optgroup );
-
- equals( jQuery(option).prop("selected"), true, "Make sure that a single option is selected, even when in an optgroup." );
- equals( jQuery(document).prop("nodeName"), "#document", "prop works correctly on document nodes (bug #7451)." );
-
- var attributeNode = document.createAttribute("irrelevant"),
- commentNode = document.createComment("some comment"),
- textNode = document.createTextNode("some text"),
- obj = {};
- jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) {
- strictEqual( jQuery(ele).prop("nonexisting"), undefined, "prop works correctly for non existing attributes (bug #7500)." );
- });
-
- var obj = {};
- jQuery.each( [document, obj], function( i, ele ) {
- var $ele = jQuery( ele );
- $ele.prop( "nonexisting", "foo" );
- equal( $ele.prop("nonexisting"), "foo", "prop(name, value) works correctly for non existing attributes (bug #7500)." );
- });
- jQuery( document ).removeProp("nonexisting");
+ deepEqual(propsShouldBe, jQuery.attrFix, "jQuery.attrFix passes integrity check");
+ deepEqual(props, jQuery.propFix, "jQuery.propFix passes integrity check");
});
test("attr(String)", function() {
- expect(35);
+ expect(37);
equals( jQuery("#text1").attr("type"), "text", "Check for type attribute" );
equals( jQuery("#radio1").attr("type"), "radio", "Check for type attribute" );
@@ -142,6 +105,10 @@ test("attr(String)", function() {
equals( $button.attr("value"), "foobar", "Value retrieval on a button does not return innerHTML" );
equals( $button.attr("value", "baz").html(), "text", "Setting the value does not change innerHTML" );
+ // Attributes with a colon on a table element (#1591)
+ equals( jQuery("#table").attr("test:attrib"), undefined, "Retrieving a non-existent attribute on a table with a colon does not throw an error." );
+ equals( jQuery("#table").attr("test:attrib", "foobar").attr("test:attrib"), "foobar", "Setting an attribute on a table with a colon does not throw an error." );
+
ok( jQuery("<div/>").attr("doesntexist") === undefined, "Make sure undefined is returned when no attribute is found." );
ok( jQuery().attr("doesntexist") === undefined, "Make sure undefined is returned when no element is there." );
});
@@ -150,9 +117,9 @@ if ( !isLocal ) {
test("attr(String) in XML Files", function() {
expect(2);
stop();
- jQuery.get("data/dashboard.xml", function(xml) {
- equals( jQuery("locations", xml).attr("class"), "foo", "Check class attribute in XML document" );
- equals( jQuery("location", xml).attr("for"), "bar", "Check for attribute in XML document" );
+ jQuery.get("data/dashboard.xml", function( xml ) {
+ equals( jQuery( "locations", xml ).attr("class"), "foo", "Check class attribute in XML document" );
+ equals( jQuery( "location", xml ).attr("for"), "bar", "Check for attribute in XML document" );
start();
});
});
@@ -171,13 +138,13 @@ test("attr(Hash)", function() {
if ( this.getAttribute("foo") != "baz" && this.getAttribute("zoo") != "ping" ) pass = false;
});
ok( pass, "Set Multiple Attributes" );
- equals( jQuery("#text1").attr({value: function() { return this.id; }})[0].value, "text1", "Set attribute to computed value #1" );
- equals( jQuery("#text1").attr({title: function(i) { return i; }}).attr("title"), "0", "Set attribute to computed value #2");
+ equals( jQuery("#text1").attr({value: function() { return this.id; }})[0].value, "text1", "Set attribute to computed value #1" );
+ equals( jQuery("#text1").attr({title: function(i) { return i; }}).attr("title"), "0", "Set attribute to computed value #2");
});
test("attr(String, Object)", function() {
- expect(35);
+ expect(66);
var div = jQuery("div").attr("foo", "bar"),
fail = false;
@@ -191,45 +158,85 @@ test("attr(String, Object)", function() {
equals( fail, false, "Set Attribute, the #" + fail + " element didn't get the attribute 'foo'" );
- // Fails on IE since recent changes to .attr()
- // ok( jQuery("#foo").attr({"width": null}), "Try to set an attribute to nothing" );
+ ok( jQuery("#foo").attr({ "width": null }), "Try to set an attribute to nothing" );
jQuery("#name").attr("name", "something");
equals( jQuery("#name").attr("name"), "something", "Set name attribute" );
jQuery("#name").attr("name", null);
equals( jQuery("#name").attr("name"), undefined, "Remove name attribute" );
- jQuery("#check2").attr("checked", true);
+ var $input = jQuery("<input>", { name: "something" });
+ equals( $input.attr("name"), "something", "Check element creation gets/sets the name attribute." );
+
+ jQuery("#check2").prop("checked", true).prop("checked", false).attr("checked", true);
equals( document.getElementById("check2").checked, true, "Set checked attribute" );
+ equals( jQuery("#check2").prop("checked"), true, "Set checked attribute" );
+ equals( jQuery("#check2").attr("checked"), "checked", "Set checked attribute" );
jQuery("#check2").attr("checked", false);
equals( document.getElementById("check2").checked, false, "Set checked attribute" );
+ equals( jQuery("#check2").prop("checked"), false, "Set checked attribute" );
+ equals( jQuery("#check2").attr("checked"), undefined, "Set checked attribute" );
jQuery("#text1").attr("readonly", true);
equals( document.getElementById("text1").readOnly, true, "Set readonly attribute" );
+ equals( jQuery("#text1").prop("readOnly"), true, "Set readonly attribute" );
+ equals( jQuery("#text1").attr("readonly"), "readonly", "Set readonly attribute" );
jQuery("#text1").attr("readonly", false);
equals( document.getElementById("text1").readOnly, false, "Set readonly attribute" );
+ equals( jQuery("#text1").prop("readOnly"), false, "Set readonly attribute" );
+ equals( jQuery("#text1").attr("readonly"), undefined, "Set readonly attribute" );
+
+ jQuery("#check2").prop("checked", true);
+ equals( document.getElementById("check2").checked, true, "Set checked attribute" );
+ equals( jQuery("#check2").prop("checked"), true, "Set checked attribute" );
+ equals( jQuery("#check2").attr("checked"), "checked", "Set checked attribute" );
+ jQuery("#check2").prop("checked", false);
+ equals( document.getElementById("check2").checked, false, "Set checked attribute" );
+ equals( jQuery("#check2").prop("checked"), false, "Set checked attribute" );
+ equals( jQuery("#check2").attr("checked"), undefined, "Set checked attribute" );
+
+ jQuery("#text1").prop("readOnly", true);
+ equals( document.getElementById("text1").readOnly, true, "Set readonly attribute" );
+ equals( jQuery("#text1").prop("readOnly"), true, "Set readonly attribute" );
+ equals( jQuery("#text1").attr("readonly"), "readonly", "Set readonly attribute" );
+ jQuery("#text1").prop("readOnly", false);
+ equals( document.getElementById("text1").readOnly, false, "Set readonly attribute" );
+ equals( jQuery("#text1").prop("readOnly"), false, "Set readonly attribute" );
+ equals( jQuery("#text1").attr("readonly"), undefined, "Set readonly attribute" );
+
jQuery("#name").attr("maxlength", "5");
equals( document.getElementById("name").maxLength, 5, "Set maxlength attribute" );
jQuery("#name").attr("maxLength", "10");
equals( document.getElementById("name").maxLength, 10, "Set maxlength attribute" );
- var $p = jQuery("#firstp").attr("nonexisting", "foo");
- equals( $p.attr("nonexisting"), "foo", "attr(name, value) works correctly for non existing attributes (bug #7500).");
- $p.removeAttr("nonexisting");
var $text = jQuery("#text1").attr("autofocus", true);
- equals( $text.attr("autofocus"), "autofocus", "Set boolean attributes to the same name");
+ if ( "autofocus" in $text[0] ) {
+ equals( $text.attr("autofocus"), "autofocus", "Set boolean attributes to the same name");
+ } else {
+ equals( $text.attr("autofocus"), undefined, "autofocus stays undefined in browsers that do not support it(F<4)");
+ }
equals( $text.attr("autofocus", false).attr("autofocus"), undefined, "Setting autofocus attribute to false removes it");
equals( $text.attr("data-something", true).data("something"), true, "Setting data attributes are not affected by boolean settings");
equals( $text.attr("data-another", false).data("another"), false, "Setting data attributes are not affected by boolean settings" );
equals( $text.attr("aria-disabled", false).attr("aria-disabled"), "false", "Setting aria attributes are not affected by boolean settings");
$text.removeData("something").removeData("another").removeAttr("aria-disabled");
+ jQuery("#foo").attr("contenteditable", true);
+ equals( jQuery("#foo").attr("contenteditable"), "true", "Enumerated attributes are set properly" );
+
var attributeNode = document.createAttribute("irrelevant"),
commentNode = document.createComment("some comment"),
- textNode = document.createTextNode("some text");
+ textNode = document.createTextNode("some text"),
+ obj = {};
- jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) {
- var $ele = jQuery( ele );
- $ele.attr( "nonexisting", "foo" );
- strictEqual( $ele.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." );
+ jQuery.each( [commentNode, textNode, attributeNode], function( i, elem ) {
+ var $elem = jQuery( elem );
+ $elem.attr( "nonexisting", "foo" );
+ strictEqual( $elem.attr("nonexisting"), undefined, "attr(name, value) works correctly on comment and text nodes (bug #7500)." );
+ });
+
+ jQuery.each( [window, document, obj, "#firstp"], function( i, elem ) {
+ var $elem = jQuery( elem );
+ strictEqual( $elem.attr("nonexisting"), undefined, "attr works correctly for non existing attributes (bug #7500)." );
+ equal( $elem.attr("something", "foo" ).attr("something"), "foo", "attr falls back to prop on unsupported arguments" );
});
var table = jQuery("#table").append("<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>"),
@@ -241,6 +248,8 @@ test("attr(String, Object)", function() {
table.attr("cellspacing", "2");
equals( table[0].cellSpacing, "2", "Check cellspacing is correctly set" );
+ equals( jQuery("#area1").attr("value"), "foobar", "Value attribute retrieves the property for backwards compatibility." );
+
// for #1070
jQuery("#name").attr("someAttr", "0");
equals( jQuery("#name").attr("someAttr"), "0", "Set attribute to a string of \"0\"" );
@@ -345,10 +354,10 @@ if ( !isLocal ) {
test("attr(String, Object) - Loaded via XML document", function() {
expect(2);
stop();
- jQuery.get("data/dashboard.xml", function(xml) {
+ jQuery.get("data/dashboard.xml", function( xml ) {
var titles = [];
- jQuery("tab", xml).each(function() {
- titles.push(jQuery(this).attr("title"));
+ jQuery( "tab", xml ).each(function() {
+ titles.push( jQuery(this).attr("title") );
});
equals( titles[0], "Location", "attr() in XML context: Check first title" );
equals( titles[1], "Users", "attr() in XML context: Check second title" );
@@ -413,12 +422,79 @@ test("attr('tabindex', value)", function() {
});
test("removeAttr(String)", function() {
- expect(5);
+ expect(7);
equals( jQuery("#mark").removeAttr( "class" )[0].className, "", "remove class" );
equals( jQuery("#form").removeAttr("id").attr("id"), undefined, "Remove id" );
equals( jQuery("#foo").attr("style", "position:absolute;").removeAttr("style").attr("style"), undefined, "Check removing style attribute" );
equals( jQuery("#form").attr("style", "position:absolute;").removeAttr("style").attr("style"), undefined, "Check removing style attribute on a form" );
equals( jQuery("#fx-test-group").attr("height", "3px").removeAttr("height").css("height"), "1px", "Removing height attribute has no effect on height set with style attribute" );
+
+ jQuery("#check1").removeAttr("checked").prop("checked", true).removeAttr("checked");
+ equals( document.getElementById("check1").checked, false, "removeAttr sets boolean properties to false" );
+ jQuery("#text1").prop("readOnly", true).removeAttr("readonly");
+ equals( document.getElementById("text1").readOnly, false, "removeAttr sets boolean properties to false" );
+});
+
+test("prop(String, Object)", function() {
+ expect(30);
+
+ equals( jQuery("#text1").prop("value"), "Test", "Check for value attribute" );
+ equals( jQuery("#text1").prop("value", "Test2").prop("defaultValue"), "Test", "Check for defaultValue attribute" );
+ equals( jQuery("#select2").prop("selectedIndex"), 3, "Check for selectedIndex attribute" );
+ equals( jQuery("#foo").prop("nodeName").toUpperCase(), "DIV", "Check for nodeName attribute" );
+ equals( jQuery("#foo").prop("tagName").toUpperCase(), "DIV", "Check for tagName attribute" );
+ equals( jQuery("<option/>").prop("selected"), false, "Check selected attribute on disconnected element." );
+
+ equals( jQuery("#listWithTabIndex").prop("tabindex"), 5, "Check retrieving tabindex" );
+ jQuery("#text1").prop("readonly", true);
+ equals( document.getElementById("text1").readOnly, true, "Check setting readOnly property with 'readonly'" );
+ equals( jQuery("#label-for").prop("for"), "action", "Check retrieving htmlFor" );
+ jQuery("#text1").prop("class", "test");
+ equals( document.getElementById("text1").className, "test", "Check setting className with 'class'" );
+ equals( jQuery("#text1").prop("maxlength"), 30, "Check retrieving maxLength" );
+ jQuery("#table").prop("cellspacing", 1);
+ equals( jQuery("#table").prop("cellSpacing"), "1", "Check setting and retrieving cellSpacing" );
+ jQuery("#table").prop("cellpadding", 1);
+ equals( jQuery("#table").prop("cellPadding"), "1", "Check setting and retrieving cellPadding" );
+ jQuery("#table").prop("rowspan", 1);
+ equals( jQuery("#table").prop("rowSpan"), 1, "Check setting and retrieving rowSpan" );
+ jQuery("#table").prop("colspan", 1);
+ equals( jQuery("#table").prop("colSpan"), 1, "Check setting and retrieving colSpan" );
+ jQuery("#table").prop("usemap", 1);
+ equals( jQuery("#table").prop("useMap"), 1, "Check setting and retrieving useMap" );
+ jQuery("#table").prop("frameborder", 1);
+ equals( jQuery("#table").prop("frameBorder"), 1, "Check setting and retrieving frameBorder" );
+ QUnit.reset();
+
+ var body = document.body, $body = jQuery( body );
+ ok( $body.prop("nextSibling") === null, "Make sure a null expando returns null" );
+ body.foo = "bar";
+ equals( $body.prop("foo"), "bar", "Make sure the expando is preferred over the dom attribute" );
+ body.foo = undefined;
+ ok( $body.prop("foo") === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
+
+ var select = document.createElement("select"), optgroup = document.createElement("optgroup"), option = document.createElement("option");
+ optgroup.appendChild( option );
+ select.appendChild( optgroup );
+
+ equals( jQuery(option).prop("selected"), true, "Make sure that a single option is selected, even when in an optgroup." );
+ equals( jQuery(document).prop("nodeName"), "#document", "prop works correctly on document nodes (bug #7451)." );
+
+ var attributeNode = document.createAttribute("irrelevant"),
+ commentNode = document.createComment("some comment"),
+ textNode = document.createTextNode("some text"),
+ obj = {};
+ jQuery.each( [document, attributeNode, commentNode, textNode, obj, "#firstp"], function( i, ele ) {
+ strictEqual( jQuery(ele).prop("nonexisting"), undefined, "prop works correctly for non existing attributes (bug #7500)." );
+ });
+
+ var obj = {};
+ jQuery.each( [document, obj], function( i, ele ) {
+ var $ele = jQuery( ele );
+ $ele.prop( "nonexisting", "foo" );
+ equal( $ele.prop("nonexisting"), "foo", "prop(name, value) works correctly for non existing attributes (bug #7500)." );
+ });
+ jQuery( document ).removeProp("nonexisting");
});
test("removeProp(String)", function() {
@@ -436,14 +512,14 @@ test("removeProp(String)", function() {
strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug #7500)." );
});
jQuery.each( [commentNode, textNode, attributeNode], function( i, ele ) {
- $ele = jQuery( ele );
+ var $ele = jQuery( ele );
$ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" );
strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug #7500)." );
});
});
test("val()", function() {
- expect(25);
+ expect(26);
document.getElementById("text1").value = "bla";
equals( jQuery("#text1").val(), "bla", "Check for modified value of input element" );
@@ -509,6 +585,8 @@ test("val()", function() {
var $button = jQuery("<button value='foobar'>text</button>").insertAfter("#button");
equals( $button.val(), "foobar", "Value retrieval on a button does not return innerHTML" );
equals( $button.val("baz").html(), "text", "Setting the value does not change innerHTML" );
+
+ equals( jQuery("<option/>").val("test").attr("value"), "test", "Setting value sets the value attribute" );
});
var testVal = function(valueObj) {
@@ -913,4 +991,4 @@ test("addClass, removeClass, hasClass", function() {
ok( jq.hasClass("cla.ss3")==false, "Check the dotted class has been removed" );
jq.removeClass("class4");
ok( jq.hasClass("class4")==false, "Check the class has been properly removed" );
-}); \ No newline at end of file
+});
diff --git a/test/unit/core.js b/test/unit/core.js
index f0bf24cd5..75d3e0e2c 100644
--- a/test/unit/core.js
+++ b/test/unit/core.js
@@ -12,7 +12,7 @@ test("Basic requirements", function() {
});
test("jQuery()", function() {
- expect(25);
+ expect(29);
// Basic constructor's behavior
@@ -96,6 +96,17 @@ test("jQuery()", function() {
// manually clean up detached elements
elem.remove();
+
+ equals( jQuery(" <div/> ").length, 1, "Make sure whitespace is trimmed." );
+ equals( jQuery(" a<div/>b ").length, 1, "Make sure whitespace and other characters are trimmed." );
+
+ var long = "";
+ for ( var i = 0; i < 128; i++ ) {
+ long += "12345678";
+ }
+
+ equals( jQuery(" <div>" + long + "</div> ").length, 1, "Make sure whitespace is trimmed on long strings." );
+ equals( jQuery(" a<div>" + long + "</div>b ").length, 1, "Make sure whitespace and other characters are trimmed on long strings." );
});
test("selector state", function() {
@@ -642,7 +653,7 @@ test("first()/last()", function() {
});
test("map()", function() {
- expect(7);
+ expect(8);
same(
jQuery("#ap").map(function(){
@@ -683,6 +694,12 @@ test("map()", function() {
});
equals( mapped.length, scripts.length, "Map an array(-like) to a hash" );
+ var nonsense = document.getElementsByTagName("asdf");
+ var mapped = jQuery.map( nonsense, function( v, k ){
+ return v;
+ });
+ equals( mapped.length, nonsense.length, "Map an empty array(-like) to a hash" );
+
var flat = jQuery.map( Array(4), function( v, k ){
return k % 2 ? k : [k,k,k];//try mixing array and regular returns
});
diff --git a/test/unit/css.js b/test/unit/css.js
index ba0fab9f3..380709d12 100644
--- a/test/unit/css.js
+++ b/test/unit/css.js
@@ -397,7 +397,7 @@ test("jQuery.cssProps behavior, (bug #8402)", function() {
test("widows & orphans #8936", function () {
- var $p = jQuery("<p>").appendTo("#main").end();
+ var $p = jQuery("<p>").appendTo("#qunit-fixture");
if ( "widows" in $p[0].style ) {
expect(4);
@@ -406,16 +406,16 @@ test("widows & orphans #8936", function () {
orphans: 0
});
- equal( $p.css("widows"), 0, "widows correctly start with value 0");
- equal( $p.css("orphans"), 0, "orphans correctly start with value 0");
+ equal( $p.css("widows") || jQuery.style( $p[0], "widows" ), 0, "widows correctly start with value 0");
+ equal( $p.css("orphans") || jQuery.style( $p[0], "orphans" ), 0, "orphans correctly start with value 0");
$p.css({
widows: 3,
orphans: 3
});
- equal( $p.css("widows"), 3, "widows correctly set to 3");
- equal( $p.css("orphans"), 3, "orphans correctly set to 3");
+ equal( $p.css("widows") || jQuery.style( $p[0], "widows" ), 3, "widows correctly set to 3");
+ equal( $p.css("orphans") || jQuery.style( $p[0], "orphans" ), 3, "orphans correctly set to 3");
} else {
expect(1);
diff --git a/test/unit/deferred.js b/test/unit/deferred.js
index c71fbdbe7..89c9c612d 100644
--- a/test/unit/deferred.js
+++ b/test/unit/deferred.js
@@ -145,7 +145,7 @@ jQuery.each( [ "", " - new operator" ], function( _, withNew ) {
test( "jQuery.Deferred.pipe - filtering (done)", function() {
- expect(3);
+ expect(4);
var defer = jQuery.Deferred(),
piped = defer.pipe(function( a, b ) {
@@ -173,11 +173,15 @@ test( "jQuery.Deferred.pipe - filtering (done)", function() {
jQuery.Deferred().reject().pipe(function() {
ok( false, "pipe should not be called on reject" );
});
+
+ jQuery.Deferred().resolve().pipe( jQuery.noop ).done(function( value ) {
+ strictEqual( value, undefined, "pipe done callback can return undefined/null" );
+ });
});
test( "jQuery.Deferred.pipe - filtering (fail)", function() {
- expect(3);
+ expect(4);
var defer = jQuery.Deferred(),
piped = defer.pipe( null, function( a, b ) {
@@ -205,6 +209,10 @@ test( "jQuery.Deferred.pipe - filtering (fail)", function() {
jQuery.Deferred().resolve().pipe( null, function() {
ok( false, "pipe should not be called on resolve" );
} );
+
+ jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail(function( value ) {
+ strictEqual( value, undefined, "pipe fail callback can return undefined/null" );
+ });
});
test( "jQuery.Deferred.pipe - deferred (done)", function() {
diff --git a/test/unit/effects.js b/test/unit/effects.js
index 6fbbbfe39..864c4a400 100644
--- a/test/unit/effects.js
+++ b/test/unit/effects.js
@@ -32,7 +32,8 @@ test("show()", function() {
hiddendiv.css("display","");
- var pass = true, div = jQuery("#qunit-fixture div");
+ var pass = true;
+ div = jQuery("#qunit-fixture div");
div.show().each(function(){
if ( this.style.display == "none" ) pass = false;
});
@@ -582,7 +583,7 @@ jQuery.checkOverflowDisplay = function(){
equals(jQuery.css( this, "display" ), "inline", "Display shouldn't be tampered with.");
start();
-}
+};
test( "jQuery.fx.prototype.cur()", 6, function() {
var div = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" ).css({
@@ -694,8 +695,8 @@ jQuery.each( {
jQuery(elem).css(prop,prop == "opacity" ? 0 : "0px");
return 0;
}
-}, function(fn, f){
- jQuery.each( {
+}, function( fn, f ) {
+ jQuery.each({
"show": function(elem,prop){
jQuery(elem).hide().addClass("wide"+prop);
return "show";
@@ -901,7 +902,7 @@ jQuery.makeTest = function( text ){
.after( elem );
return elem;
-}
+};
jQuery.makeTest.id = 1;
@@ -922,34 +923,42 @@ test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function ()
test("animate with per-property easing", function(){
- expect(3);
+ expect(5);
stop();
- var _test1_called = false;
- var _test2_called = false;
- var _default_test_called = false;
-
- jQuery.easing["_test1"] = function() {
+ var data = { a:0, b:0, c:0 },
+ _test1_called = false,
+ _test2_called = false,
+ _default_test_called = false,
+ props = {
+ a: [ 100, "_test1" ],
+ b: [ 100, "_test2" ],
+ c: 100
+ };
+
+ jQuery.easing["_test1"] = function(p) {
_test1_called = true;
+ return p;
};
- jQuery.easing["_test2"] = function() {
+ jQuery.easing["_test2"] = function(p) {
_test2_called = true;
+ return p;
};
- jQuery.easing["_default_test"] = function() {
+ jQuery.easing["_default_test"] = function(p) {
_default_test_called = true;
+ return p;
};
- jQuery({a:0,b:0,c:0}).animate({
- a: [100, "_test1"],
- b: [100, "_test2"],
- c: 100
- }, 400, "_default_test", function(){
+ jQuery(data).animate( props, 400, "_default_test", function(){
start();
- ok(_test1_called, "Easing function (1) called");
- ok(_test2_called, "Easing function (2) called");
- ok(_default_test_called, "Easing function (_default) called");
+
+ ok( _test1_called, "Easing function (_test1) called" );
+ ok( _test2_called, "Easing function (_test2) called" );
+ ok( _default_test_called, "Easing function (_default) called" );
+ equal( props.a[ 1 ], "_test1", "animate does not change original props (per-property easing would be lost)");
+ equal( props.b[ 1 ], "_test2", "animate does not change original props (per-property easing would be lost)");
});
});
@@ -994,6 +1003,33 @@ test("animate unit-less properties (#4966)", 2, function() {
});
});
+test( "animate properties missing px w/ opacity as last (#9074)", 2, function() {
+ expect( 6 );
+ stop();
+ var div = jQuery( "<div style='position: absolute; margin-left: 0; left: 0px;'></div>" )
+ .appendTo( "#qunit-fixture" );
+ function cssInt( prop ) {
+ return parseInt( div.css( prop ), 10 );
+ }
+ equal( cssInt( "marginLeft" ), 0, "Margin left is 0" );
+ equal( cssInt( "left" ), 0, "Left is 0" );
+ div.animate({
+ left: 200,
+ marginLeft: 200,
+ opacity: 0
+ }, 1000);
+ setTimeout(function() {
+ var ml = cssInt( "marginLeft" ),
+ l = cssInt( "left" );
+ notEqual( ml, 0, "Margin left is not 0 after partial animate" );
+ notEqual( ml, 200, "Margin left is not 200 after partial animate" );
+ notEqual( l, 0, "Left is not 0 after partial animate" );
+ notEqual( l, 200, "Left is not 200 after partial animate" );
+ div.stop().remove();
+ start();
+ }, 100);
+});
+
test("callbacks should fire in correct order (#9100)", function() {
stop();
var a = 1,
@@ -1008,4 +1044,4 @@ test("callbacks should fire in correct order (#9100)", function() {
start();
}
});
-}); \ No newline at end of file
+});
diff --git a/test/unit/event.js b/test/unit/event.js
index 0424538d6..13877e019 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -68,6 +68,22 @@ test("bind(), multiple events at once", function() {
equals( mouseoverCounter, 1, "bind() with multiple events at once" );
});
+test("bind(), five events at once", function() {
+ expect(1);
+
+ var count = 0,
+ handler = function(event) {
+ count++;
+ };
+
+ jQuery("#firstp").bind("click mouseover foo bar baz", handler)
+ .trigger("click").trigger("mouseover")
+ .trigger("foo").trigger("bar")
+ .trigger("baz");
+
+ equals( count, 5, "bind() five events at once" );
+});
+
test("bind(), multiple events at once and namespaces", function() {
expect(7);
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js
index b71b6962e..972cfaf91 100644
--- a/test/unit/manipulation.js
+++ b/test/unit/manipulation.js
@@ -227,7 +227,7 @@ test("unwrap()", function() {
});
var testAppend = function(valueObj) {
- expect(40);
+ expect(41);
var defaultText = "Try them out:"
var result = jQuery("#first").append(valueObj("<b>buga</b>"));
equals( result.text(), defaultText + "buga", "Check if text appending works" );
@@ -344,6 +344,17 @@ var testAppend = function(valueObj) {
equals( $radio[0].checked, true, "Reappending radios uphold which radio is checked" );
equals( $radioNot[0].checked, false, "Reappending radios uphold not being checked" );
QUnit.reset();
+
+ var prev = jQuery("#sap").children().length;
+
+ jQuery("#sap").append(
+ "<span></span>",
+ "<span></span>",
+ "<span></span>"
+ );
+
+ equals( jQuery("#sap").children().length, prev + 3, "Make sure that multiple arguments works." );
+ QUnit.reset();
}
test("append(String|Element|Array&lt;Element&gt;|jQuery)", function() {
diff --git a/test/unit/support.js b/test/unit/support.js
new file mode 100644
index 000000000..9d99529a1
--- /dev/null
+++ b/test/unit/support.js
@@ -0,0 +1,32 @@
+module("support", { teardown: moduleTeardown });
+
+function supportIFrameTest( title, url, noDisplay, func ) {
+
+ if ( noDisplay !== true ) {
+ func = noDisplay;
+ noDisplay = false;
+ }
+
+ test( title, function() {
+ var iframe;
+
+ stop();
+ window.supportCallback = function() {
+ var self = this,
+ args = arguments;
+ setTimeout( function() {
+ window.supportCallback = undefined;
+ iframe.remove();
+ func.apply( self, args );
+ start();
+ }, 0 );
+ };
+ iframe = jQuery( "<div/>" ).css( "display", noDisplay ? "none" : "block" ).append(
+ jQuery( "<iframe/>" ).attr( "src", "data/support/" + url + ".html" )
+ ).appendTo( "body" );
+ });
+}
+
+supportIFrameTest( "proper boxModel in compatMode CSS1Compat (IE6 and IE7)", "boxModelIE", function( compatMode, boxModel ) {
+ ok( compatMode !== "CSS1Compat" || boxModel, "boxModel properly detected" );
+});
diff --git a/version.txt b/version.txt
index 0a0196e21..29349dd55 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.6pre \ No newline at end of file
+1.6.1pre \ No newline at end of file