Skip to content
Browse files

Merge branch 'master' into changepage-prevent

  • Loading branch information...
2 parents 6aa8c8f + d0fe757 commit 04623c21cf7cc5959a958362e5392cdeba3e9b42 @jblas jblas committed Sep 7, 2011
View
2 js/jquery.mobile.core.js
@@ -36,7 +36,7 @@
defaultPageTransition: "slide",
// Minimum scroll distance that will be remembered when returning to a page
- minScrollBack: screen.height / 2,
+ minScrollBack: 250,
// Set default dialog transition - 'none' for no transitions
defaultDialogTransition: "pop",
View
16 js/jquery.mobile.event.js
@@ -78,16 +78,19 @@ $.event.special.tap = {
return false;
}
- var touching = true,
- origTarget = event.target,
+ var origTarget = event.target,
origEvent = event.originalEvent,
timer;
+ function clearTapTimer() {
+ clearTimeout( timer );
+ }
+
function clearTapHandlers() {
- touching = false;
- clearTimeout(timer);
+ clearTapTimer();
$this.unbind( "vclick", clickHandler )
+ .unbind( "vmouseup", clearTapTimer )
.unbind( "vmousecancel", clearTapHandlers );
}
@@ -102,12 +105,11 @@ $.event.special.tap = {
}
$this.bind( "vmousecancel", clearTapHandlers )
+ .bind( "vmouseup", clearTapTimer )
.bind( "vclick", clickHandler );
timer = setTimeout(function() {
- if ( touching ) {
- triggerCustomEvent( thisObject, "taphold", event );
- }
+ triggerCustomEvent( thisObject, "taphold", $.Event( "taphold" ) );
}, 750 );
});
}
View
4 js/jquery.mobile.forms.select.custom.js
@@ -103,7 +103,7 @@
.delegate( ".ui-li>a", "focusout", function() {
$( this ).attr( "tabindex", "-1" );
})
- .delegate( "li:not(.ui-disabled, .ui-li-divider)", "vclick", function( event ) {
+ .delegate( "li:not(.ui-disabled, .ui-li-divider)", "click", function( event ) {
// index of option tag to be selected
var oldIndex = self.select[ 0 ].selectedIndex,
@@ -174,7 +174,7 @@
// If enter or space is pressed, trigger click
case 13:
case 32:
- target.trigger( "vclick" );
+ target.trigger( "click" );
return false;
break;
View
9 js/jquery.mobile.forms.slider.js
@@ -140,16 +140,9 @@ $.widget( "mobile.slider", $.mobile.widget, {
if ( !self.userModified ) {
//tap occurred, but value didn't change. flip it!
+ handle.addClass( "ui-slider-handle-snapping" );
self.refresh( !self.beforeStart ? 1 : 0 );
}
- var curval = val();
- var snapped = Math.round( curval / ( max - min ) * 100 );
- handle
- .addClass( "ui-slider-handle-snapping" )
- .css( "left", snapped + "%" )
- .animationComplete( function() {
- handle.removeClass( "ui-slider-handle-snapping" );
- });
}
return false;
}
View
2 js/jquery.mobile.media.classes.js
@@ -77,7 +77,7 @@ $( document ).bind( "mobileinit.htmlclass", function() {
var ev = $.support.orientation;
- $window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
+ $window.bind( "orientationchange.htmlclass throttledresize.htmlclass", function( event ) {
// add orientation class to HTML element on flip/resize.
if ( event.orientation ) {
View
82 js/jquery.mobile.navigation.js
@@ -354,20 +354,13 @@
//direct focus to the page title, or otherwise first focusable element
function reFocus( page ) {
- var lastClicked = page.jqmData( "lastClicked" );
+ var pageTitle = page.find( ".ui-title:eq(0)" );
- if( lastClicked && lastClicked.length ) {
- lastClicked.focus();
+ if( pageTitle.length ) {
+ pageTitle.focus();
}
- else {
- var pageTitle = page.find( ".ui-title:eq(0)" );
-
- if( pageTitle.length ) {
- pageTitle.focus();
- }
- else{
- page.find( focusable ).eq( 0 ).focus();
- }
+ else{
+ page.focus();
}
}
@@ -385,32 +378,46 @@
$.mobile.changePage.apply( null, pageTransitionQueue.pop() );
}
}
+
+ // Save the last scroll distance per page, before it is hidden
+ var getLastScroll = (function( lastScrollEnabled ){
+ return function(){
+ if( !lastScrollEnabled ){
+ lastScrollEnabled = true;
+ return;
+ }
+
+ lastScrollEnabled = false;
+
+ var active = $.mobile.urlHistory.getActive();
+
+ if( active ){
+ var lastScroll = $( window ).scrollTop();
+
+ // Set active page's lastScroll prop.
+ // If the Y location we're scrolling to is less than minScrollBack, let it go.
+ active.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;
+ }
+ };
+ })( true );
+
+ // to get last scroll, we need to get scrolltop before the page change
+ // using beforechangepage or popstate/hashchange (whichever comes first)
+ $( document ).bind( "beforechangepage", getLastScroll );
+ $( window ).bind( $.support.pushState ? "popstate" : "hashchange", getLastScroll );
//function for transitioning between two existing pages
function transitionPages( toPage, fromPage, transition, reverse ) {
//get current scroll distance
- var currScroll = $.support.scrollTop ? $window.scrollTop() : true,
- toScroll = toPage.data( "lastScroll" ) || $.mobile.defaultHomeScroll,
+ var active = $.mobile.urlHistory.getActive(),
+ toScroll = active.lastScroll || $.mobile.defaultHomeScroll,
screenHeight = getScreenHeight();
- //if scrolled down, scroll to top
- if( currScroll ){
- window.scrollTo( 0, $.mobile.defaultHomeScroll );
- }
-
- //if the Y location we're scrolling to is less than 10px, let it go for sake of smoothness
- if( toScroll < $.mobile.minScrollBack ){
- toScroll = 0;
- }
+ // Scroll to top
+ window.scrollTo( 0, $.mobile.defaultHomeScroll );
if( fromPage ) {
- //set as data for returning to that spot
- fromPage
- .height( screenHeight + currScroll )
- .jqmData( "lastScroll", currScroll )
- .jqmData( "lastClicked", $activeClickedLink );
-
//trigger before show/hide events
fromPage.data( "page" )._trigger( "beforehide", null, { nextPage: toPage } );
}
@@ -430,15 +437,12 @@
promise.done(function() {
//reset toPage height bac
toPage.height( "" );
-
- //jump to top or prev scroll, sometimes on iOS the page has not rendered yet.
- if( toScroll ){
- $.mobile.silentScroll( toScroll );
- $( document ).one( "silentscroll", function() { reFocus( toPage ); } );
- }
- else{
- reFocus( toPage );
- }
+
+ // Send focus to the newly shown page
+ reFocus( toPage );
+
+ // Jump to top or prev scroll, sometimes on iOS the page has not rendered yet.
+ $.mobile.silentScroll( toScroll );
//trigger show/hide events
if( fromPage ) {
@@ -463,6 +467,8 @@
return pageMin;
}
+
+ $.mobile.getScreenHeight = getScreenHeight;
//simply set the active page's minimum height to screen height, depending on orientation
function resetActivePageHeight(){
View
4 js/jquery.mobile.page.js
@@ -17,7 +17,9 @@ $.widget( "mobile.page", $.mobile.widget, {
this._trigger( "beforecreate" );
- this.element.addClass( "ui-page ui-body-" + this.options.theme );
+ this.element
+ .attr( "tabindex", "0" )
+ .addClass( "ui-page ui-body-" + this.options.theme );
}
});
View
23 js/jquery.mobile.vmouse.js
@@ -164,27 +164,35 @@ function clearResetTimer() {
}
function triggerVirtualEvent( eventType, event, flags ) {
- var defaultPrevented = false,
- ve;
+ var ve;
if ( ( flags && flags[ eventType ] ) ||
( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
ve = createVirtualEvent( event, eventType );
$( event.target).trigger( ve );
-
- defaultPrevented = ve.isDefaultPrevented();
}
- return defaultPrevented;
+ return ve;
}
function mouseEventCallback( event ) {
var touchID = $.data(event.target, touchTargetPropertyName);
if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){
- triggerVirtualEvent( "v" + event.type, event );
+ var ve = triggerVirtualEvent( "v" + event.type, event );
+ if ( ve ) {
+ if ( ve.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ if ( ve.isPropagationStopped() ) {
+ event.stopPropagation();
+ }
+ if ( ve.isImmediatePropagationStopped() ) {
+ event.stopImmediatePropagation();
+ }
+ }
}
}
@@ -264,7 +272,8 @@ function handleTouchEnd( event ) {
triggerVirtualEvent( "vmouseup", event, flags );
if ( !didScroll ) {
- if ( triggerVirtualEvent( "vclick", event, flags ) ) {
+ var ve = triggerVirtualEvent( "vclick", event, flags );
+ if ( ve && ve.isDefaultPrevented() ) {
// The target of the mouse events that follow the touchend
// event don't necessarily match the target used during the
// touch. This means we need to rely on coordinates for blocking
View
169 tests/unit/event/event_core.js
@@ -14,21 +14,19 @@
setup: function(){
// ensure bindings are removed
- $.each(events, function(i, name){
- $.each([$("#qunit-fixture"),
- $($.event.special.scrollstart),
- $($.event.special.tap),
- $($.event.special.tap),
- $($.event.special.swipe)], function(j, obj){
- obj.unbind(name);
- });
+ $.each(events + "vmouseup vmousedown".split(" "), function(i, name){
+ $("#qunit-fixture").unbind();
});
//NOTE unmock
Math.abs = absFn;
$.Event.prototype.originalEvent = originalEventFn;
$.Event.prototype.preventDefault = preventDefaultFn;
+ // make sure the event objects respond to touches to simulate
+ // the collections existence in non touch enabled test browsers
+ $.Event.prototype.touches = [{pageX: 1, pageY: 1 }];
+
$($.mobile.pageContainer).unbind( "throttledresize" );
}
});
@@ -43,7 +41,7 @@
$.testHelper.reloadLib(libName);
$.each(events, function( i, name ) {
- ok($.fn[name] !== undefined, name + "is not undefined");
+ ok($.fn[name] !== undefined, name + " is not undefined");
});
});
});
@@ -88,40 +86,40 @@
expect( 1 );
$.event.special.scrollstart.enabled = false;
- $($.event.special.scrollstart).bind("scrollstart", function(){
+ $( "#qunit-fixture" ).bind("scrollstart", function(){
ok(false, "scrollstart fired");
});
- $($.event.special.scrollstart).bind("touchmove", function(){
+ $( "#qunit-fixture" ).bind("touchmove", function(){
ok(true, "touchmove fired");
start();
});
- $($.event.special.scrollstart).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchmove");
});
asyncTest( "scrollstart setup binds a function that triggers scroll start when enabled", function(){
$.event.special.scrollstart.enabled = true;
- $($.event.special.scrollstart).bind("scrollstart", function(){
+ $( "#qunit-fixture" ).bind("scrollstart", function(){
ok(true, "scrollstart fired");
start();
});
- $($.event.special.scrollstart).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchmove");
});
asyncTest( "scrollstart setup binds a function that triggers scroll stop after 50 ms", function(){
var triggered = false;
$.event.special.scrollstart.enabled = true;
- $($.event.special.scrollstart).bind("scrollstop", function(){
+ $( "#qunit-fixture" ).bind("scrollstop", function(){
triggered = true;
});
ok(!triggered, "not triggered");
- $($.event.special.scrollstart).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchmove");
setTimeout(function(){
ok(triggered, "triggered");
@@ -144,11 +142,11 @@
forceTouchSupport();
- $($.event.special.tap).bind("taphold", function(){
+ $( "#qunit-fixture" ).bind("taphold", function(){
taphold = true;
});
- $($.event.special.tap).trigger("vmousedown");
+ $( "#qunit-fixture" ).trigger("vmousedown");
setTimeout(function(){
ok(taphold);
@@ -172,17 +170,17 @@
mockAbs(100);
//NOTE record taphold event
- $($.event.special.tap).bind("taphold", function(){
+ $( "#qunit-fixture" ).bind("taphold", function(){
ok(false, "taphold fired");
taphold = true;
});
//NOTE start the touch events
- $($.event.special.tap).trigger("vmousedown");
+ $( "#qunit-fixture" ).trigger("vmousedown");
//NOTE fire touchmove to push back taphold
setTimeout(function(){
- $($.event.special.tap).trigger("vmousecancel");
+ $( "#qunit-fixture" ).trigger("vmousecancel");
}, 100);
//NOTE verify that the taphold hasn't been fired
@@ -203,11 +201,11 @@
forceTouchSupport();
//NOTE record the tap event
- $($.event.special.tap).bind("tap", checkTap);
+ $( "#qunit-fixture" ).bind("tap", checkTap);
- $($.event.special.tap).trigger("vmousedown");
- $($.event.special.tap).trigger("vmouseup");
- $($.event.special.tap).trigger("vclick");
+ $( "#qunit-fixture" ).trigger("vmousedown");
+ $( "#qunit-fixture" ).trigger("vmouseup");
+ $( "#qunit-fixture" ).trigger("vclick");
setTimeout(function(){
start();
@@ -220,7 +218,7 @@
forceTouchSupport();
//NOTE record tap event
- $($.event.special.tap).bind("tap", function(){
+ $( "#qunit-fixture" ).bind("tap", function(){
ok(false, "tap fired");
tap = true;
});
@@ -229,12 +227,12 @@
mockAbs(100);
//NOTE start and move right away
- $($.event.special.tap).trigger("touchstart");
- $($.event.special.tap).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchstart");
+ $( "#qunit-fixture" ).trigger("touchmove");
//NOTE end touch sequence after 20 ms
setTimeout(function(){
- $($.event.special.tap).trigger("touchend");
+ $( "#qunit-fixture" ).trigger("touchend");
}, 20);
setTimeout(function(){
@@ -243,12 +241,101 @@
}, 40);
});
+ asyncTest( "tap event propagates up DOM tree", function(){
+ var tap = 0,
+ $qf = $( "#qunit-fixture" ),
+ $doc = $( document ),
+ docTapCB = function(){
+ same(++tap, 2, "document tap callback called once after #qunit-fixture callback");
+ };
+
+ $qf.bind( "tap", function() {
+ same(++tap, 1, "#qunit-fixture tap callback called once");
+ });
+
+ $doc.bind( "tap", docTapCB );
+
+ $qf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered twice, once for
+ // #qunit-fixture, and a second time for document.
+ same( tap, 2, "final tap callback count is 2" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
+ asyncTest( "stopPropagation() prevents tap from propagating up DOM tree", function(){
+ var tap = 0,
+ $qf = $( "#qunit-fixture" ),
+ $doc = $( document ),
+ docTapCB = function(){
+ ok(false, "tap should NOT be triggered on document");
+ };
+
+ $qf.bind( "tap", function(e) {
+ same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
+ e.stopPropagation();
+ })
+ .bind( "tap", function(e) {
+ same(++tap, 2, "tap callback 2 triggered once on #qunit-fixture");
+ });
+
+ $doc.bind( "tap", docTapCB);
+
+ $qf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered twice.
+ same( tap, 2, "final tap count is 2" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
+ asyncTest( "stopImmediatePropagation() prevents tap propagation and execution of 2nd handler", function(){
+ var tap = 0,
+ $cf = $( "#qunit-fixture" );
+ $doc = $( document ),
+ docTapCB = function(){
+ ok(false, "tap should NOT be triggered on document");
+ };
+
+ // Bind 2 tap callbacks on qunit-fixture. Only the first
+ // one should ever be called.
+ $cf.bind( "tap", function(e) {
+ same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
+ e.stopImmediatePropagation();
+ })
+ .bind( "tap", function(e) {
+ ok(false, "tap callback 2 should NOT be triggered on #qunit-fixture");
+ });
+
+ $doc.bind( "tap", docTapCB);
+
+ $cf.trigger( "vmousedown" )
+ .trigger( "vmouseup" )
+ .trigger( "vclick" );
+
+ // tap binding should be triggered once.
+ same( tap, 1, "final tap count is 1" );
+
+ $doc.unbind( "tap", docTapCB );
+
+ start();
+ });
+
var swipeTimedTest = function(opts){
var swipe = false;
forceTouchSupport();
- $($.event.special.swipe).bind('swipe', function(){
+ $( "#qunit-fixture" ).bind('swipe', function(){
swipe = true;
});
@@ -257,15 +344,15 @@
touches: false
};
- $($.event.special.swipe).trigger("touchstart");
+ $( "#qunit-fixture" ).trigger("touchstart");
//NOTE make sure the coordinates are calculated within range
// to be registered as a swipe
mockAbs(opts.coordChange);
setTimeout(function(){
- $($.event.special.swipe).trigger("touchmove");
- $($.event.special.swipe).trigger("touchend");
+ $( "#qunit-fixture" ).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchend");
}, opts.timeout + 100);
setTimeout(function(){
@@ -298,7 +385,7 @@
forceTouchSupport();
// ensure the swipe custome event is setup
- $($.event.special.swipe).bind('swipe', function(){});
+ $( "#qunit-fixture" ).bind('swipe', function(){});
//NOTE bypass the trigger source check
$.Event.prototype.originalEvent = {
@@ -312,8 +399,8 @@
mockAbs(11);
- $($.event.special.swipe).trigger("touchstart");
- $($.event.special.swipe).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchstart");
+ $( "#qunit-fixture" ).trigger("touchmove");
});
asyncTest( "move handler returns when touchstart has been fired since touchstop", function(){
@@ -327,12 +414,12 @@
forceTouchSupport();
// ensure the swipe custome event is setup
- $($.event.special.swipe).bind('swipe', function(){});
+ $( "#qunit-fixture" ).bind('swipe', function(){});
- $($.event.special.swipe).trigger("touchstart");
- $($.event.special.swipe).trigger("touchend");
+ $( "#qunit-fixture" ).trigger("touchstart");
+ $( "#qunit-fixture" ).trigger("touchend");
- $($.event.special.swipe).bind("touchmove", function(){
+ $( "#qunit-fixture" ).bind("touchmove", function(){
ok(true, "touchmove bound functions are fired");
start();
});
@@ -341,7 +428,7 @@
ok(false, "shouldn't compare coordinates");
};
- $($.event.special.swipe).trigger("touchmove");
+ $( "#qunit-fixture" ).trigger("touchmove");
});
var nativeSupportTest = function(opts){
View
32 tests/unit/navigation/navigation_core.js
@@ -110,6 +110,38 @@
start();
}]);
});
+
+ asyncTest( "page last scroll distance is remembered while navigating to and from pages", function(){
+ $.testHelper.pageSequence([
+ navigateTestRoot,
+
+ function(){
+ $( "body" ).height( $( window ).height() + 500 );
+ },
+
+ function(){
+ $.mobile.changePage( "external.html" );
+ },
+
+ function(){
+ window.scrollTo( 0, 300 );
+ },
+
+ navigateTestRoot,
+
+ function(){
+ $.mobile.changePage( "external.html" );
+ },
+
+ function(){
+ same( $(window).scrollTop(), 300 );
+ $( "body" ).height( "" );
+ start();
+ }
+
+ ]);
+
+ });
asyncTest( "forms with data attribute ajax set to false will not call changePage", function(){
var called = false;
View
2 themes/default/jquery.mobile.forms.slider.css
@@ -16,7 +16,7 @@ a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; }
div.ui-slider-switch { height: 32px; overflow: hidden; margin-left: 0; }
div.ui-slider-inneroffset { margin-left: 50%; position: absolute; top: 1px; height: 100%; width: 50%; }
-div.ui-slider-handle-snapping { -webkit-transition: left 100ms linear; }
+a.ui-slider-handle-snapping { -webkit-transition: left 100ms linear; }
div.ui-slider-labelbg { position: absolute; top:0; margin: 0; border-width: 0; }
div.ui-slider-switch div.ui-slider-labelbg-a { width: 60%; height: 100%; left: 0; }
div.ui-slider-switch div.ui-slider-labelbg-b { width: 60%; height: 100%; right: 0; }

0 comments on commit 04623c2

Please sign in to comment.
Something went wrong with that request. Please try again.