From 52b1709b94cf631e0641eebfa4f76b101528d93b Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Sun, 26 Dec 2010 10:35:14 -0600 Subject: [PATCH 1/7] Fix reliableHiddenOffsets test was not working properly when table cells have borders, causing unnecessary slowness in some browsers. Thanks to matjas for his $.support test page. --- src/support.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/support.js b/src/support.js index 67b41c4a7..e4c3ea916 100644 --- a/src/support.js +++ b/src/support.js @@ -147,7 +147,7 @@ jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; } - div.innerHTML = "
t
"; + div.innerHTML = "
t
"; var tds = div.getElementsByTagName("td"); // Check if table cells still have offsetWidth/Height when they are set From 1830db422628d1556377621612b401bac5afa40e Mon Sep 17 00:00:00 2001 From: Ben Alman Date: Sun, 26 Dec 2010 18:51:29 +0000 Subject: [PATCH 2/7] WETness getting you down? Fear not, the $.get and $.post methods are now 866% DRYer. This fixes #7847. --- src/ajax.js | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/src/ajax.js b/src/ajax.js index 3f4f732bd..bac0ab182 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -113,9 +113,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.toLowerCase() ] = function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; @@ -124,13 +123,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,23 +142,6 @@ 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 ); }, From 78a6f5b152f40739769169c76726cead5cb7206b Mon Sep 17 00:00:00 2001 From: Ben Alman Date: Sun, 26 Dec 2010 22:49:01 +0000 Subject: [PATCH 3/7] Removed unnecessary upper/lowercase, it's all just lowercase now (since $.ajax will uppercase as-needed). --- src/ajax.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ajax.js b/src/ajax.js index bac0ab182..18ea203d0 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -113,8 +113,8 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp }; }); -jQuery.each( [ "GET", "POST" ], function( i, method ) { - jQuery[ method.toLowerCase() ] = 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; From faabb2c31883deabaddd5642eb5e708b5802f2b0 Mon Sep 17 00:00:00 2001 From: Alex Sexton Date: Mon, 11 Oct 2010 11:54:00 -0500 Subject: [PATCH 4/7] Changed the expando string to use a random number instead of the time, so collisions become less likely. Also added jQuery version to instantly differentiate separate versions of jQuery (a common use case for noConflict, etc, when two jQuery instances are on the page). Fixes #6842. --- src/data.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/data.js b/src/data.js index 732e9233b..bb7febfba 100644 --- a/src/data.js +++ b/src/data.js @@ -9,8 +9,9 @@ jQuery.extend({ // Please use with caution uuid: 0, - // Unique for each copy of jQuery on the page - expando: "jQuery" + jQuery.now(), + // Unique for each copy of jQuery on the page + // 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. From 6ffa730721a8ebcd128f3dc202706e46d9cfe249 Mon Sep 17 00:00:00 2001 From: jrburke Date: Mon, 27 Dec 2010 13:01:20 -0600 Subject: [PATCH 5/7] Register as a CommonJS async module if in that kind of environment. Fixes #7102. --- src/core.js | 5 +++++ test/data/testinit.js | 7 ++++++- test/unit/core.js | 46 ++++++++++++++++++++++--------------------- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/core.js b/src/core.js index 346e52d70..e75c86fab 100644 --- a/src/core.js +++ b/src/core.js @@ -886,6 +886,11 @@ function doScrollCheck() { jQuery.ready(); } +// Expose jQuery as an Asynchronous Module +if ( typeof define !== "undefined" ) { + define( "jquery", [], function () { return jQuery; } ); +} + // Expose jQuery to the global object return (window.jQuery = window.$ = jQuery); diff --git a/test/data/testinit.js b/test/data/testinit.js index a66f71d25..8f431fb5e 100644 --- a/test/data/testinit.js +++ b/test/data/testinit.js @@ -1,7 +1,12 @@ var jQuery = this.jQuery || "jQuery", // For testing .noConflict() $ = this.$ || "$", originaljQuery = jQuery, - original$ = $; + original$ = $, + commonJSDefined; + +function define(module, dependencies, callback) { + commonJSDefined = callback(); +} /** * Returns an array of elements with the given IDs, eg. diff --git a/test/unit/core.js b/test/unit/core.js index 705778370..5c80569ca 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -12,7 +12,9 @@ test("Basic requirements", function() { }); test("jQuery()", function() { - expect(23); + expect(24); + + strictEqual( commonJSDefined, jQuery, "CommonJS registered (Bug #7102)" ); // Basic constructor's behavior @@ -151,7 +153,7 @@ test("selector state", function() { test = jQuery("#main").eq(0); equals( test.selector, "#main.slice(0,1)", "#main eq Selector" ); equals( test.context, document, "#main eq Context" ); - + var d = "
"; equals( jQuery(d).appendTo(jQuery(d)).selector, @@ -253,38 +255,38 @@ test("isPlainObject", function() { // The use case that we want to match ok(jQuery.isPlainObject({}), "{}"); - + // Not objects shouldn't be matched ok(!jQuery.isPlainObject(""), "string"); ok(!jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number"); ok(!jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean"); ok(!jQuery.isPlainObject(null), "null"); ok(!jQuery.isPlainObject(undefined), "undefined"); - + // Arrays shouldn't be matched ok(!jQuery.isPlainObject([]), "array"); - + // Instantiated objects shouldn't be matched ok(!jQuery.isPlainObject(new Date), "new Date"); - + var fn = function(){}; - + // Functions shouldn't be matched ok(!jQuery.isPlainObject(fn), "fn"); - + // Again, instantiated objects shouldn't be matched ok(!jQuery.isPlainObject(new fn), "new fn (no methods)"); - + // Makes the function a little more realistic // (and harder to detect, incidentally) fn.prototype = {someMethod: function(){}}; - + // Again, instantiated objects shouldn't be matched ok(!jQuery.isPlainObject(new fn), "new fn"); // DOM Element ok(!jQuery.isPlainObject(document.createElement("div")), "DOM Element"); - + // Window ok(!jQuery.isPlainObject(window), "window"); @@ -298,7 +300,7 @@ test("isPlainObject", function() { document.body.removeChild( iframe ); start(); }; - + var doc = iframe.contentDocument || iframe.contentWindow.document; doc.open(); doc.write(""); @@ -659,7 +661,7 @@ test("jQuery.merge()", function() { // Fixed at [5998], #3641 same( parse([-2,-1], [0,1,2]), [-2,-1,0,1,2], "Second array including a zero (falsy)"); - + // After fixing #5527 same( parse([], [null, undefined]), [null, undefined], "Second array including null and undefined values"); same( parse({length:0}, [1,2]), {length:2, 0:1, 1:2}, "First array like"); @@ -694,7 +696,7 @@ test("jQuery.extend(Object, Object)", function() { equals( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" ); ok( jQuery.extend(true, {}, nestedarray).arr !== arr, "Deep extend of object must clone child array" ); - + // #5991 ok( jQuery.isArray( jQuery.extend(true, { arr: {} }, nestedarray).arr ), "Cloned array heve to be an Array" ); ok( jQuery.isPlainObject( jQuery.extend(true, { arr: arr }, { arr: {} }).arr ), "Cloned object heve to be an plain object" ); @@ -715,13 +717,13 @@ test("jQuery.extend(Object, Object)", function() { empty = {}; jQuery.extend(true, empty, optionsWithCustomObject); ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" ); - + // Makes the class a little more realistic myKlass.prototype = { someMethod: function(){} }; empty = {}; jQuery.extend(true, empty, optionsWithCustomObject); ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" ); - + var ret = jQuery.extend(true, { foo: 4 }, { foo: new Number(5) } ); ok( ret.foo == 5, "Wrapped numbers copy correctly" ); @@ -849,10 +851,10 @@ test("jQuery.makeArray", function(){ test("jQuery.isEmptyObject", function(){ expect(2); - + equals(true, jQuery.isEmptyObject({}), "isEmptyObject on empty object literal" ); equals(false, jQuery.isEmptyObject({a:1}), "isEmptyObject on non-empty object literal" ); - + // What about this ? // equals(true, jQuery.isEmptyObject(null), "isEmptyObject on null" ); }); @@ -878,23 +880,23 @@ test("jQuery.proxy", function(){ test("jQuery.parseJSON", function(){ expect(8); - + equals( jQuery.parseJSON(), null, "Nothing in, null out." ); equals( jQuery.parseJSON( null ), null, "Nothing in, null out." ); equals( jQuery.parseJSON( "" ), null, "Nothing in, null out." ); - + same( jQuery.parseJSON("{}"), {}, "Plain object parsing." ); same( jQuery.parseJSON('{"test":1}'), {"test":1}, "Plain object parsing." ); same( jQuery.parseJSON('\n{"test":1}'), {"test":1}, "Make sure leading whitespaces are handled." ); - + try { jQuery.parseJSON("{a:1}"); ok( false, "Test malformed JSON string." ); } catch( e ) { ok( true, "Test malformed JSON string." ); } - + try { jQuery.parseJSON("{'a':1}"); ok( false, "Test malformed JSON string." ); From 64ee5581afd6e9667ad45e75f082c95e2725efa6 Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Mon, 27 Dec 2010 13:30:05 -0600 Subject: [PATCH 6/7] When a native browser event is bubbling up the DOM, make sure that the correct isDefaultPrevented value is reflected by jQuery's Event object. Fixes #7793. --- src/event.js | 6 ++++++ test/unit/event.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/event.js b/src/event.js index fd470e718..c90473485 100644 --- a/src/event.js +++ b/src/event.js @@ -600,6 +600,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; diff --git a/test/unit/event.js b/test/unit/event.js index a647e5f3b..83f6096d7 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -295,6 +295,41 @@ test("live/delegate immediate propagation", function() { $p.undelegate( "click" ); }); +test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", 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) { + equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" ); + }); + 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(); From 5fd21fc02bda43d4e31bcf2d5b55b918a9190a7f Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Mon, 27 Dec 2010 13:43:52 -0600 Subject: [PATCH 7/7] Don't cache non-html strings in buildFragment to avoid possible collision with the names of Object methods like toString. Also makes the unit tests 0.5% to 8% faster. Fixes #6779. --- src/manipulation.js | 4 ++-- test/unit/manipulation.js | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/manipulation.js b/src/manipulation.js index 5f4b15dd9..96caa02d0 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -440,12 +440,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 or 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] ]; diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index da1635400..e273cf08a 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -1247,3 +1247,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( "
" ).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(); +});