diff --git a/.gitmodules b/.gitmodules index 80ce2368..19c60418 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "src/sizzle"] path = src/sizzle - url = git://github.com/jeresig/sizzle.git + url = git://github.com/jquery/sizzle.git [submodule "test/qunit"] path = test/qunit url = git://github.com/jquery/qunit.git diff --git a/Makefile b/Makefile index 84816a19..cfd2a975 100644 --- a/Makefile +++ b/Makefile @@ -42,17 +42,15 @@ VER = sed "s/@VERSION/${JQ_VER}/" DATE=$(shell git log -1 --pretty=format:%ad) -all: jquery min lint +all: update_submodules core + +core: jquery min lint @@echo "jQuery build complete." ${DIST_DIR}: @@mkdir -p ${DIST_DIR} -init: - @@if [ -d .git ]; then git submodule update --init --recursive; fi - -jquery: init ${JQ} -jq: init ${JQ} +jquery: ${JQ} ${JQ}: ${MODULES} | ${DIST_DIR} @@echo "Building" ${JQ} @@ -75,9 +73,9 @@ lint: jquery echo "You must have NodeJS installed in order to test jQuery against JSLint."; \ fi -min: ${JQ_MIN} +min: jquery ${JQ_MIN} -${JQ_MIN}: jquery +${JQ_MIN}: ${JQ} @@if test ! -z ${JS_ENGINE}; then \ echo "Minifying jQuery" ${JQ_MIN}; \ ${COMPILER} ${JQ} > ${JQ_MIN}.tmp; \ @@ -99,6 +97,18 @@ distclean: clean @@echo "Removing submodules" @@rm -rf test/qunit src/sizzle +# change pointers for submodules and update them to what is specified in jQuery +# --merge doesn't work when doing an initial clone, thus test if we have non-existing +# submodules, then do an real update +update_submodules: + @@if [ -d .git ]; then \ + if git submodule status | grep -q -E '^-'; then \ + git submodule update --init --recursive; \ + else \ + git submodule update --init --recursive --merge; \ + fi; \ + fi; + # update the submodules to the latest at the most logical branch pull_submodules: @@git submodule foreach "git pull origin \$$(git branch --no-color --contains \$$(git rev-parse HEAD) | grep -v \( | head -1)" @@ -107,4 +117,4 @@ pull_submodules: pull: pull_submodules @@git pull ${REMOTE} ${BRANCH} -.PHONY: all jquery lint min init jq clean +.PHONY: all jquery lint min clean distclean update_submodules pull_submodules pull core diff --git a/src/css.js b/src/css.js index 8a982312..17ac136b 100644 --- a/src/css.js +++ b/src/css.js @@ -3,7 +3,8 @@ var ralpha = /alpha\([^)]*\)/i, ropacity = /opacity=([^)]*)/, rdashAlpha = /-([a-z])/ig, - rupper = /([A-Z])/g, + // fixed for IE9, see #8346 + rupper = /([A-Z]|^ms)/g, rnumpx = /^-?\d+(?:px)?$/i, rnum = /^-?\d/, @@ -240,6 +241,28 @@ if ( !jQuery.support.opacity ) { }; } +jQuery(function() { + // This hook cannot be added until DOM ready because the support test + // for it is not run until after DOM ready + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + var ret; + jQuery.swap( elem, { "display": "inline-block" }, function() { + if ( computed ) { + ret = curCSS( elem, "margin-right", "marginRight" ); + } else { + ret = elem.style.marginRight; + } + }); + return ret; + } + }; + } +}); + if ( document.defaultView && document.defaultView.getComputedStyle ) { getComputedStyle = function( elem, newName, name ) { var ret, defaultView, computedStyle; diff --git a/src/deferred.js b/src/deferred.js index f0d7c08c..90f9c808 100644 --- a/src/deferred.js +++ b/src/deferred.js @@ -144,7 +144,10 @@ jQuery.extend({ return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { - deferred.resolveWith( deferred, args ); + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); } }; } diff --git a/src/event.js b/src/event.js index f7e0a08c..bc2cf76e 100644 --- a/src/event.js +++ b/src/event.js @@ -70,10 +70,10 @@ jQuery.event = { } if ( !eventHandle ) { - elemData.handle = eventHandle = function() { + elemData.handle = eventHandle = function( e ) { // Handle the second event of a trigger and when // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; @@ -380,7 +380,7 @@ jQuery.event = { target[ "on" + targetType ] = null; } - jQuery.event.triggered = true; + jQuery.event.triggered = event.type; target[ targetType ](); } @@ -391,7 +391,7 @@ jQuery.event = { target[ "on" + targetType ] = old; } - jQuery.event.triggered = false; + jQuery.event.triggered = undefined; } } }, @@ -661,7 +661,7 @@ var withinElement = function( event ) { // Chrome does something similar, the parentNode property // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { + if ( parent && parent !== document && !parent.parentNode ) { return; } // Traverse up the tree @@ -868,19 +868,33 @@ function trigger( type, elem, args ) { // Create "bubbling" focus and blur events if ( document.addEventListener ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + jQuery.event.special[ fix ] = { setup: function() { - this.addEventListener( orig, handler, true ); + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } }, teardown: function() { - this.removeEventListener( orig, handler, true ); + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } } }; - function handler( e ) { - e = jQuery.event.fix( e ); + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); e.type = fix; - return jQuery.event.handle.call( this, e ); + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } } }); } diff --git a/src/offset.js b/src/offset.js index 1003c400..972278c8 100644 --- a/src/offset.js +++ b/src/offset.js @@ -151,7 +151,6 @@ jQuery.offset = { this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); body.removeChild( container ); - body = container = innerDiv = checkDiv = table = td = null; jQuery.offset.initialize = jQuery.noop; }, @@ -181,10 +180,10 @@ jQuery.offset = { curOffset = curElem.offset(), curCSSTop = jQuery.css( elem, "top" ), curCSSLeft = jQuery.css( elem, "left" ), - calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), + calculatePosition = ((position === "absolute" || position === "fixed") && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), props = {}, curPosition = {}, curTop, curLeft; - // need to be able to calculate position if either top or left is auto and position is absolute + // need to be able to calculate position if either top or left is auto and position is either absolute or fixed if ( calculatePosition ) { curPosition = curElem.position(); } diff --git a/src/sizzle b/src/sizzle index ef19279f..f12b9309 160000 --- a/src/sizzle +++ b/src/sizzle @@ -1 +1 @@ -Subproject commit ef19279f54ba49242c6461d47577c703f4f4e80e +Subproject commit f12b9309269ba7e705a99efe099f86ed1fe98d58 diff --git a/src/support.js b/src/support.js index 7470b33e..4c309562 100644 --- a/src/support.js +++ b/src/support.js @@ -67,7 +67,8 @@ boxModel: null, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, - reliableHiddenOffsets: true + reliableHiddenOffsets: true, + reliableMarginRight: true }; input.checked = true; @@ -85,15 +86,15 @@ script = document.createElement("script"), id = "script" + jQuery.now(); + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) try { script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); } catch(e) {} root.insertBefore( script, root.firstChild ); - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) if ( window[ id ] ) { _scriptEval = true; delete window[ id ]; @@ -102,8 +103,6 @@ } root.removeChild( script ); - // release memory in IE - root = script = id = null; } return _scriptEval; @@ -188,6 +187,17 @@ jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; div.innerHTML = ""; + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + div.style.width = "1px"; + div.style.marginRight = "0"; + jQuery.support.reliableMarginRight = ( parseInt(document.defaultView.getComputedStyle(div, null).marginRight, 10) || 0 ) === 0; + } + body.removeChild( div ).style.display = "none"; div = tds = null; }); @@ -211,8 +221,6 @@ el.setAttribute(eventName, "return;"); isSupported = typeof el[eventName] === "function"; } - el = null; - return isSupported; }; diff --git a/test/data/offset/bug_8316.html b/test/data/offset/bug_8316.html new file mode 100644 index 00000000..ce32a282 --- /dev/null +++ b/test/data/offset/bug_8316.html @@ -0,0 +1,30 @@ + + + + + bug_8316 + + + + + + + + + + + + + +

Some foo text

+
+ + diff --git a/test/unit/css.js b/test/unit/css.js index 555f1357..8ae8fcb3 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -333,3 +333,15 @@ test("internal ref to elem.runtimeStyle (bug #7608)", function () { ok( result, "elem.runtimeStyle does not throw exception" ); }); + +test("marginRight computed style (bug #3333)", function() { + expect(1); + + var $div = jQuery("#foo"); + $div.css({ + width: "1px", + marginRight: 0 + }); + + equals($div.css("marginRight"), "0px"); +}); diff --git a/test/unit/event.js b/test/unit/event.js index b7b26046..1e40e0f3 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -683,6 +683,20 @@ test("hover()", function() { equals( times, 4, "hover handlers fired" ); }); +test("mouseover triggers mouseenter", function() { + expect(1); + + var count = 0, + elem = jQuery(""); + elem.mouseenter(function () { + count++; + }); + elem.trigger('mouseover'); + equals(count, 1, "make sure mouseover triggers a mouseenter" ); + + elem.remove(); +}); + test("trigger() shortcuts", function() { expect(6); @@ -1966,6 +1980,31 @@ test("window resize", function() { ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." ); }); +test("focusin bubbles", function() { + expect(4); + + var input = jQuery( '' ).prependTo( "body" ), + order = 0; + + 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" ); + }); + + // DOM focus method + input[0].focus(); + // jQuery trigger, which calls DOM focus + order = 0; + input[0].blur(); + input.trigger( "focus" ); + + input.remove(); + jQuery( "body" ).unbind( "focusin.focusinBubblesTest" ); +}); + /* test("jQuery(function($) {})", function() { stop(); diff --git a/test/unit/offset.js b/test/unit/offset.js index 329d69f9..b7f72a0c 100644 --- a/test/unit/offset.js +++ b/test/unit/offset.js @@ -422,6 +422,21 @@ test("offsetParent", function(){ equals( div[1], jQuery("#nothiddendiv")[0], "The div is the offsetParent." ); }); +testoffset("bug_8316", function( jQuery ){ + expect(2); + + var tests = [ + { id:'#elem', top: 100, left: 100 } + ]; + + jQuery.each(tests, function(){ + var el = jQuery(this.id); + el.offset({ top: this.top, left: this.left}); + equals(Math.round(el.offset().top), this.top); + equals(Math.round(el.offset().left), this.left); + }); +}); + function testoffset(name, fn) { test(name, function() { @@ -447,7 +462,7 @@ function testoffset(name, fn) { function loadFixture() { var src = './data/offset/' + name + '.html?' + parseInt( Math.random()*1000, 10 ), iframe = jQuery('