From 1230c6678b29f1c0c3129f70fa7e9729733c6def Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Thu, 17 Jun 2021 14:41:01 +0100 Subject: [PATCH] issue/3178 Fixed jquery.mobile touch event subsystem --- src/core/libraries/jquery.mobile.custom.js | 966 ------------------ .../libraries/jquery.mobile.custom.min.js | 10 + src/core/required/adapt/js/scriptLoader.js | 6 +- 3 files changed, 14 insertions(+), 968 deletions(-) delete mode 100644 src/core/libraries/jquery.mobile.custom.js create mode 100644 src/core/libraries/jquery.mobile.custom.min.js diff --git a/src/core/libraries/jquery.mobile.custom.js b/src/core/libraries/jquery.mobile.custom.js deleted file mode 100644 index 204eb8203..000000000 --- a/src/core/libraries/jquery.mobile.custom.js +++ /dev/null @@ -1,966 +0,0 @@ -// This is a custom build which contains touch/swipe events support only. -// -// To create this build do the following: -// 1. Go to http://jquerymobile.com/download-builder/ -// 2. Select "Touch" under "Events" -// 3. click "Build My Download" - -/* -* jQuery Mobile v1.5.0-alpha.1 -* http://jquerymobile.com -* -* Copyright jQuery Foundation, Inc. and other contributors -* Released under the MIT license. -* http://jquery.org/license -* -*/ - -(function ( root, doc, factory ) { - if ( typeof define === "function" && define.amd ) { - // AMD. Register as an anonymous module. - define( [ "jquery" ], function ( $ ) { - factory( $, root, doc ); - return $.mobile; - }); - } else { - // Browser globals - factory( root.jQuery, root, doc ); - } -}( this, document, function ( jQuery, window, document, undefined ) {/*! - * jQuery Mobile Virtual Mouse @VERSION - * http://jquerymobile.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - -//>>label: Virtual Mouse (vmouse) Bindings -//>>group: Core -//>>description: Normalizes touch/mouse events. -//>>docs: http://api.jquerymobile.com/?s=vmouse - -// This plugin is an experiment for abstracting away the touch and mouse -// events so that developers don't have to worry about which method of input -// the device their document is loaded on supports. -// -// The idea here is to allow the developer to register listeners for the -// basic mouse events, such as mousedown, mousemove, mouseup, and click, -// and the plugin will take care of registering the correct listeners -// behind the scenes to invoke the listener at the fastest possible time -// for that device, while still retaining the order of event firing in -// the traditional mouse environment, should multiple handlers be registered -// on the same element for different events. -// -// The current version exposes the following virtual events to jQuery bind methods: -// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel" - -( function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( 'vmouse',[ "jquery" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -} )( function( $ ) { - -var dataPropertyName = "virtualMouseBindings", - touchTargetPropertyName = "virtualTouchID", - touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ), - virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ), - generalProps = ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + - "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), - mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [], - mouseEventProps = generalProps.concat( mouseHookProps ), - activeDocHandlers = {}, - resetTimerID = 0, - startX = 0, - startY = 0, - didScroll = false, - clickBlockList = [], - blockMouseTriggers = false, - blockTouchTriggers = false, - eventCaptureSupported = "addEventListener" in document, - $document = $( document ), - nextTouchID = 1, - lastTouchID = 0, threshold, - i; - -$.vmouse = { - moveDistanceThreshold: 10, - clickDistanceThreshold: 10, - resetTimerDuration: 1500, - maximumTimeBetweenTouches: 100 -}; - -function getNativeEvent( event ) { - - while ( event && typeof event.originalEvent !== "undefined" ) { - event = event.originalEvent; - } - return event; -} - -function createVirtualEvent( event, eventType ) { - - var t = event.type, - oe, props, ne, prop, ct, touch, i, j, len; - - event = $.Event( event ); - event.type = eventType; - - oe = event.originalEvent; - props = generalProps; - - // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280 - // https://github.com/jquery/jquery-mobile/issues/3280 - if ( t.search( /^(mouse|click)/ ) > -1 ) { - props = mouseEventProps; - } - - // copy original event properties over to the new event - // this would happen if we could call $.event.fix instead of $.Event - // but we don't have a way to force an event to be fixed multiple times - if ( oe ) { - for ( i = props.length; i; ) { - prop = props[ --i ]; - event[ prop ] = oe[ prop ]; - } - } - - // make sure that if the mouse and click virtual events are generated - // without a .which one is defined - if ( t.search( /mouse(down|up)|click/ ) > -1 && !event.which ) { - event.which = 1; - } - - if ( t.search( /^touch/ ) !== -1 ) { - ne = getNativeEvent( oe ); - t = ne.touches; - ct = ne.changedTouches; - touch = ( t && t.length ) ? t[ 0 ] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined ); - - if ( touch ) { - for ( j = 0, len = touchEventProps.length; j < len; j++ ) { - prop = touchEventProps[ j ]; - event[ prop ] = touch[ prop ]; - } - } - } - - return event; -} - -function getVirtualBindingFlags( element ) { - - var flags = {}, - b, k; - - while ( element ) { - - b = $.data( element, dataPropertyName ); - - for ( k in b ) { - if ( b[ k ] ) { - flags[ k ] = flags.hasVirtualBinding = true; - } - } - element = element.parentNode; - } - return flags; -} - -function getClosestElementWithVirtualBinding( element, eventType ) { - var b; - while ( element ) { - - b = $.data( element, dataPropertyName ); - - if ( b && ( !eventType || b[ eventType ] ) ) { - return element; - } - element = element.parentNode; - } - return null; -} - -function enableTouchBindings() { - blockTouchTriggers = false; -} - -function disableTouchBindings() { - blockTouchTriggers = true; -} - -function enableMouseBindings() { - lastTouchID = 0; - clickBlockList.length = 0; - blockMouseTriggers = false; - - // When mouse bindings are enabled, our - // touch bindings are disabled. - disableTouchBindings(); -} - -function disableMouseBindings() { - // When mouse bindings are disabled, our - // touch bindings are enabled. - enableTouchBindings(); -} - -function clearResetTimer() { - if ( resetTimerID ) { - clearTimeout( resetTimerID ); - resetTimerID = 0; - } -} - -function startResetTimer() { - clearResetTimer(); - resetTimerID = setTimeout( function() { - resetTimerID = 0; - enableMouseBindings(); - }, $.vmouse.resetTimerDuration ); -} - -function triggerVirtualEvent( eventType, event, flags ) { - var ve; - - if ( ( flags && flags[ eventType ] ) || - ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) { - - ve = createVirtualEvent( event, eventType ); - - $( event.target ).trigger( ve ); - } - - return ve; -} - -function mouseEventCallback( event ) { - var touchID = $.data( event.target, touchTargetPropertyName ), - ve; - - // It is unexpected if a click event is received before a touchend - // or touchmove event, however this is a known behavior in Mobile - // Safari when Mobile VoiceOver (as of iOS 8) is enabled and the user - // double taps to activate a link element. In these cases if a touch - // event is not received within the maximum time between touches, - // re-enable mouse bindings and call the mouse event handler again. - if ( event.type === "click" && $.data( event.target, "lastTouchType" ) === "touchstart" ) { - setTimeout( function() { - if ( $.data( event.target, "lastTouchType" ) === "touchstart" ) { - enableMouseBindings(); - delete $.data( event.target ).lastTouchType; - mouseEventCallback( event ); - } - }, $.vmouse.maximumTimeBetweenTouches ); - } - - if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) { - ve = triggerVirtualEvent( "v" + event.type, event ); - if ( ve ) { - if ( ve.isDefaultPrevented() ) { - event.preventDefault(); - } - if ( ve.isPropagationStopped() ) { - event.stopPropagation(); - } - if ( ve.isImmediatePropagationStopped() ) { - event.stopImmediatePropagation(); - } - } - } -} - -function handleTouchStart( event ) { - - var touches = getNativeEvent( event ).touches, - target, flags, t; - - if ( touches && touches.length === 1 ) { - - target = event.target; - flags = getVirtualBindingFlags( target ); - - $.data( event.target, "lastTouchType", event.type ); - - if ( flags.hasVirtualBinding ) { - - lastTouchID = nextTouchID++; - $.data( target, touchTargetPropertyName, lastTouchID ); - - clearResetTimer(); - - disableMouseBindings(); - didScroll = false; - - t = getNativeEvent( event ).touches[ 0 ]; - startX = t.pageX; - startY = t.pageY; - - triggerVirtualEvent( "vmouseover", event, flags ); - triggerVirtualEvent( "vmousedown", event, flags ); - } - } -} - -function handleScroll( event ) { - if ( blockTouchTriggers ) { - return; - } - - if ( !didScroll ) { - triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) ); - } - - $.data( event.target, "lastTouchType", event.type ); - - didScroll = true; - startResetTimer(); -} - -function handleTouchMove( event ) { - if ( blockTouchTriggers ) { - return; - } - - var t = getNativeEvent( event ).touches[ 0 ], - didCancel = didScroll, - moveThreshold = $.vmouse.moveDistanceThreshold, - flags = getVirtualBindingFlags( event.target ); - - $.data( event.target, "lastTouchType", event.type ); - - didScroll = didScroll || - ( Math.abs( t.pageX - startX ) > moveThreshold || - Math.abs( t.pageY - startY ) > moveThreshold ); - - if ( didScroll && !didCancel ) { - triggerVirtualEvent( "vmousecancel", event, flags ); - } - - triggerVirtualEvent( "vmousemove", event, flags ); - startResetTimer(); -} - -function handleTouchEnd( event ) { - if ( blockTouchTriggers || $.data( event.target, "lastTouchType" ) === undefined ) { - return; - } - - disableTouchBindings(); - delete $.data( event.target ).lastTouchType; - - var flags = getVirtualBindingFlags( event.target ), - ve, t; - triggerVirtualEvent( "vmouseup", event, flags ); - - if ( !didScroll ) { - 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 - // any click that is generated. - t = getNativeEvent( event ).changedTouches[ 0 ]; - clickBlockList.push( { - touchID: lastTouchID, - x: t.clientX, - y: t.clientY - } ); - - // Prevent any mouse events that follow from triggering - // virtual event notifications. - blockMouseTriggers = true; - } - } - triggerVirtualEvent( "vmouseout", event, flags ); - didScroll = false; - - startResetTimer(); -} - -function hasVirtualBindings( ele ) { - var bindings = $.data( ele, dataPropertyName ), - k; - - if ( bindings ) { - for ( k in bindings ) { - if ( bindings[ k ] ) { - return true; - } - } - } - return false; -} - -function dummyMouseHandler() { -} - -function getSpecialEventObject( eventType ) { - var realType = eventType.substr( 1 ); - - return { - setup: function( /* data, namespace */ ) { - // If this is the first virtual mouse binding for this element, - // add a bindings object to its data. - - if ( !hasVirtualBindings( this ) ) { - $.data( this, dataPropertyName, {} ); - } - - // If setup is called, we know it is the first binding for this - // eventType, so initialize the count for the eventType to zero. - var bindings = $.data( this, dataPropertyName ); - bindings[ eventType ] = true; - - // If this is the first virtual mouse event for this type, - // register a global handler on the document. - - activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1; - - if ( activeDocHandlers[ eventType ] === 1 ) { - $document.bind( realType, mouseEventCallback ); - } - - // Some browsers, like Opera Mini, won't dispatch mouse/click events - // for elements unless they actually have handlers registered on them. - // To get around this, we register dummy handlers on the elements. - - $( this ).bind( realType, dummyMouseHandler ); - - // For now, if event capture is not supported, we rely on mouse handlers. - if ( eventCaptureSupported ) { - // If this is the first virtual mouse binding for the document, - // register our touchstart handler on the document. - - activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0 ) + 1; - - if ( activeDocHandlers[ "touchstart" ] === 1 ) { - $document.bind( "touchstart", handleTouchStart ) - .bind( "touchend", handleTouchEnd ) - - // On touch platforms, touching the screen and then dragging your finger - // causes the window content to scroll after some distance threshold is - // exceeded. On these platforms, a scroll prevents a click event from being - // dispatched, and on some platforms, even the touchend is suppressed. To - // mimic the suppression of the click event, we need to watch for a scroll - // event. Unfortunately, some platforms like iOS don't dispatch scroll - // events until *AFTER* the user lifts their finger (touchend). This means - // we need to watch both scroll and touchmove events to figure out whether - // or not a scroll happenens before the touchend event is fired. - - .bind( "touchmove", handleTouchMove ) - .bind( "scroll", handleScroll ); - } - } - }, - - teardown: function( /* data, namespace */ ) { - // If this is the last virtual binding for this eventType, - // remove its global handler from the document. - - --activeDocHandlers[eventType]; - - if ( !activeDocHandlers[ eventType ] ) { - $document.unbind( realType, mouseEventCallback ); - } - - if ( eventCaptureSupported ) { - // If this is the last virtual mouse binding in existence, - // remove our document touchstart listener. - - --activeDocHandlers["touchstart"]; - - if ( !activeDocHandlers[ "touchstart" ] ) { - $document.unbind( "touchstart", handleTouchStart ) - .unbind( "touchmove", handleTouchMove ) - .unbind( "touchend", handleTouchEnd ) - .unbind( "scroll", handleScroll ); - } - } - - var $this = $( this ), - bindings = $.data( this, dataPropertyName ); - - // teardown may be called when an element was - // removed from the DOM. If this is the case, - // jQuery core may have already stripped the element - // of any data bindings so we need to check it before - // using it. - if ( bindings ) { - bindings[ eventType ] = false; - } - - // Unregister the dummy event handler. - - $this.unbind( realType, dummyMouseHandler ); - - // If this is the last virtual mouse binding on the - // element, remove the binding data from the element. - - if ( !hasVirtualBindings( this ) ) { - $this.removeData( dataPropertyName ); - } - } - }; -} - -// Expose our custom events to the jQuery bind/unbind mechanism. - -for ( i = 0; i < virtualEventNames.length; i++ ) { - $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] ); -} - -// Add a capture click handler to block clicks. -// Note that we require event capture support for this so if the device -// doesn't support it, we punt for now and rely solely on mouse events. -if ( eventCaptureSupported ) { - document.addEventListener( "click", function( e ) { - var cnt = clickBlockList.length, - target = e.target, - x, y, ele, i, o, touchID; - - if ( cnt ) { - x = e.clientX; - y = e.clientY; - threshold = $.vmouse.clickDistanceThreshold; - - // The idea here is to run through the clickBlockList to see if - // the current click event is in the proximity of one of our - // vclick events that had preventDefault() called on it. If we find - // one, then we block the click. - // - // Why do we have to rely on proximity? - // - // Because the target of the touch event that triggered the vclick - // can be different from the target of the click event synthesized - // by the browser. The target of a mouse/click event that is synthesized - // from a touch event seems to be implementation specific. For example, - // some browsers will fire mouse/click events for a link that is near - // a touch event, even though the target of the touchstart/touchend event - // says the user touched outside the link. Also, it seems that with most - // browsers, the target of the mouse/click event is not calculated until the - // time it is dispatched, so if you replace an element that you touched - // with another element, the target of the mouse/click will be the new - // element underneath that point. - // - // Aside from proximity, we also check to see if the target and any - // of its ancestors were the ones that blocked a click. This is necessary - // because of the strange mouse/click target calculation done in the - // Android 2.1 browser, where if you click on an element, and there is a - // mouse/click handler on one of its ancestors, the target will be the - // innermost child of the touched element, even if that child is no where - // near the point of touch. - - ele = target; - - while ( ele ) { - for ( i = 0; i < cnt; i++ ) { - o = clickBlockList[ i ]; - touchID = 0; - - if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) || - $.data( ele, touchTargetPropertyName ) === o.touchID ) { - // XXX: We may want to consider removing matches from the block list - // instead of waiting for the reset timer to fire. - e.preventDefault(); - e.stopPropagation(); - return; - } - } - ele = ele.parentNode; - } - } - }, true ); -} -} ); - -/*! - * jQuery Mobile Namespace @VERSION - * http://jquerymobile.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - -//>>label: Namespace -//>>group: Core -//>>description: The mobile namespace on the jQuery object - -( function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( 'ns',[ "jquery" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -} )( function( $ ) { - -$.mobile = { version: "@VERSION" }; - -return $.mobile; -} ); - -/*! - * jQuery Mobile Touch Support Test @VERSION - * http://jquerymobile.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - -//>>label: Touch support test -//>>group: Core -//>>description: Touch feature test - -( function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( 'support/touch',[ - "jquery", - "../ns" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -} )( function( $ ) { - -var support = { - touch: "ontouchend" in document -}; - -$.mobile.support = $.mobile.support || {}; -$.extend( $.support, support ); -$.extend( $.mobile.support, support ); - -return $.support; -} ); - -/*! - * jQuery Mobile Touch Events @VERSION - * http://jquerymobile.com - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license. - * http://jquery.org/license - */ - -//>>label: Touch -//>>group: Events -//>>description: Touch events including: touchstart, touchmove, touchend, tap, taphold, swipe, swipeleft, swiperight - -( function( factory ) { - if ( typeof define === "function" && define.amd ) { - - // AMD. Register as an anonymous module. - define( 'events/touch',[ - "jquery", - "../vmouse", - "../support/touch" ], factory ); - } else { - - // Browser globals - factory( jQuery ); - } -} )( function( $ ) { -var $document = $( document ), - supportTouch = $.mobile.support.touch, - touchStartEvent = supportTouch ? "touchstart" : "mousedown", - touchStopEvent = supportTouch ? "touchend" : "mouseup", - touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; - -// setup new event shortcuts -$.each( ( "touchstart touchmove touchend " + -"tap taphold " + -"swipe swipeleft swiperight" ).split( " " ), function( i, name ) { - - $.fn[ name ] = function( fn ) { - return fn ? this.bind( name, fn ) : this.trigger( name ); - }; - - // jQuery < 1.8 - if ( $.attrFn ) { - $.attrFn[ name ] = true; - } -} ); - -function triggerCustomEvent( obj, eventType, event, bubble ) { - var originalType = event.type; - event.type = eventType; - if ( bubble ) { - $.event.trigger( event, undefined, obj ); - } else { - $.event.dispatch.call( obj, event ); - } - event.type = originalType; -} - -// also handles taphold -$.event.special.tap = { - tapholdThreshold: 750, - emitTapOnTaphold: true, - setup: function() { - var thisObject = this, - $this = $( thisObject ), - isTaphold = false; - - $this.bind( "vmousedown", function( event ) { - isTaphold = false; - if ( event.which && event.which !== 1 ) { - return true; - } - - var origTarget = event.target, - timer, clickHandler; - - function clearTapTimer() { - if ( timer ) { - $this.bind( "vclick", clickHandler ); - clearTimeout( timer ); - } - } - - function clearTapHandlers() { - clearTapTimer(); - - $this.unbind( "vclick", clickHandler ) - .unbind( "vmouseup", clearTapTimer ); - $document.unbind( "vmousecancel", clearTapHandlers ); - } - - clickHandler = function( event ) { - clearTapHandlers(); - - // ONLY trigger a 'tap' event if the start target is - // the same as the stop target. - if ( !isTaphold && origTarget === event.target ) { - triggerCustomEvent( thisObject, "tap", event ); - } else if ( isTaphold ) { - event.preventDefault(); - } - }; - - $this.bind( "vmouseup", clearTapTimer ); - - $document.bind( "vmousecancel", clearTapHandlers ); - - timer = setTimeout( function() { - if ( !$.event.special.tap.emitTapOnTaphold ) { - isTaphold = true; - } - timer = 0; - triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) ); - }, $.event.special.tap.tapholdThreshold ); - } ); - }, - teardown: function() { - $( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" ); - $document.unbind( "vmousecancel" ); - } -}; - -// Also handles swipeleft, swiperight -$.event.special.swipe = { - - // More than this horizontal displacement, and we will suppress scrolling. - scrollSupressionThreshold: 30, - - // More time than this, and it isn't a swipe. - durationThreshold: 1000, - - // Swipe horizontal displacement must be more than this. - horizontalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, - - // Swipe vertical displacement must be less than this. - verticalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, - - getLocation: function( event ) { - var winPageX = window.pageXOffset, - winPageY = window.pageYOffset, - x = event.clientX, - y = event.clientY; - - if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || - event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { - - // iOS4 clientX/clientY have the value that should have been - // in pageX/pageY. While pageX/page/ have the value 0 - x = x - winPageX; - y = y - winPageY; - } else if ( y < ( event.pageY - winPageY ) || x < ( event.pageX - winPageX ) ) { - - // Some Android browsers have totally bogus values for clientX/Y - // when scrolling/zooming a page. Detectable since clientX/clientY - // should never be smaller than pageX/pageY minus page scroll - x = event.pageX - winPageX; - y = event.pageY - winPageY; - } - - return { - x: x, - y: y - }; - }, - - start: function( event ) { - var data = event.originalEvent.touches ? - event.originalEvent.touches[ 0 ] : event, - location = $.event.special.swipe.getLocation( data ); - return { - time: ( new Date() ).getTime(), - coords: [ location.x, location.y ], - origin: $( event.target ) - }; - }, - - stop: function( event ) { - var data = event.originalEvent.touches ? - event.originalEvent.touches[ 0 ] : event, - location = $.event.special.swipe.getLocation( data ); - return { - time: ( new Date() ).getTime(), - coords: [ location.x, location.y ] - }; - }, - - handleSwipe: function( start, stop, thisObject, origTarget ) { - if ( stop.time - start.time < $.event.special.swipe.durationThreshold && - Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && - Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { - var direction = start.coords[ 0 ] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; - - triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop } ), true ); - triggerCustomEvent( thisObject, direction, $.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); - return true; - } - return false; - - }, - - // This serves as a flag to ensure that at most one swipe event event is - // in work at any given time - eventInProgress: false, - - setup: function() { - var events, - thisObject = this, - $this = $( thisObject ), - context = {}; - - // Retrieve the events data for this element and add the swipe context - events = $.data( this, "mobile-events" ); - if ( !events ) { - events = { length: 0 }; - $.data( this, "mobile-events", events ); - } - events.length++; - events.swipe = context; - - context.start = function( event ) { - - // Bail if we're already working on a swipe event - if ( $.event.special.swipe.eventInProgress ) { - return; - } - $.event.special.swipe.eventInProgress = true; - - var stop, - start = $.event.special.swipe.start( event ), - origTarget = event.target, - emitted = false; - - context.move = function( event ) { - if ( !start || event.isDefaultPrevented() ) { - return; - } - - stop = $.event.special.swipe.stop( event ); - if ( !emitted ) { - emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); - if ( emitted ) { - - // Reset the context to make way for the next swipe event - $.event.special.swipe.eventInProgress = false; - } - } - // prevent scrolling - if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { - event.preventDefault(); - } - }; - - context.stop = function() { - emitted = true; - - // Reset the context to make way for the next swipe event - $.event.special.swipe.eventInProgress = false; - $document.off( touchMoveEvent, context.move ); - context.move = null; - }; - - $document.on( touchMoveEvent, context.move ) - .one( touchStopEvent, context.stop ); - }; - $this.on( touchStartEvent, context.start ); - }, - - teardown: function() { - var events, context; - - events = $.data( this, "mobile-events" ); - if ( events ) { - context = events.swipe; - delete events.swipe; - events.length--; - if ( events.length === 0 ) { - $.removeData( this, "mobile-events" ); - } - } - - if ( context ) { - if ( context.start ) { - $( this ).off( touchStartEvent, context.start ); - } - if ( context.move ) { - $document.off( touchMoveEvent, context.move ); - } - if ( context.stop ) { - $document.off( touchStopEvent, context.stop ); - } - } - } -}; -$.each( { - taphold: "tap", - swipeleft: "swipe.left", - swiperight: "swipe.right" -}, function( event, sourceEvent ) { - - $.event.special[ event ] = { - setup: function() { - $( this ).bind( sourceEvent, $.noop ); - }, - teardown: function() { - $( this ).unbind( sourceEvent ); - } - }; -} ); - -return $.event.special; -} ); - - - -})); diff --git a/src/core/libraries/jquery.mobile.custom.min.js b/src/core/libraries/jquery.mobile.custom.min.js new file mode 100644 index 000000000..a3f1a8725 --- /dev/null +++ b/src/core/libraries/jquery.mobile.custom.min.js @@ -0,0 +1,10 @@ +// This is a custom build which contains touch/swipe events support only. +// +// To create this build do the following: +// 1. Go to http://jquerymobile.com/download-builder/ +// 2. Select "Touch" under "Events" +// 3. click "Build My Download" + +/*! jQuery Mobile v1.5.0-rc1 | Copyright jQuery Foundation, Inc. | jquery.org/license */ + +!function(e,t,n){"function"==typeof define&&define.amd?define(["jquery"],function(o){return n(o,e,t),o.mobile}):n(e.jQuery,e,t)}(this,document,function(e,t,n,o){!function(t){"function"==typeof define&&define.amd?define("vmouse",["jquery"],t):t(e)}(function(e){function t(e){for(;e&&void 0!==e.originalEvent;)e=e.originalEvent;return e}function i(n,i){var a,s,r,u,c,p,l,h,d,v=n.type;if(n=e.Event(n),n.type=i,a=n.originalEvent,s=Y,v.search(/^(mouse|click)/)>-1&&(s=x),a)for(l=s.length;l;)u=s[--l],n[u]=a[u];if(v.search(/mouse(down|up)|click/)>-1&&!n.which&&(n.which=1),-1!==v.search(/^touch/)&&(r=t(a),v=r.touches,c=r.changedTouches,p=v&&v.length?v[0]:c&&c.length?c[0]:o))for(h=0,d=k.length;hs||Math.abs(o.pageY-q)>s,B&&!i&&d("vmousecancel",n,r),d("vmousemove",n,r),h()}}function w(n){if(!K&&e.data(n.target,"lastTouchType")!==o){u(),delete e.data(n.target).lastTouchType;var i,s,r=a(n.target);d("vmouseup",n,r),B||(i=d("vclick",n,r))&&i.isDefaultPrevented()&&(s=t(n).changedTouches[0],L.push({touchID:z,x:s.clientX,y:s.clientY}),O=!0),d("vmouseout",n,r),B=!1,h()}}function T(t){var n,o=e.data(t,P);if(o)for(n in o)if(o[n])return!0;return!1}function b(){}var y,D,P="virtualMouseBindings",E="virtualTouchID",k="clientX clientY pageX pageY screenX screenY".split(" "),X="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),Y="altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),M=e.event.mouseHooks?e.event.mouseHooks.props:[],x=Y.concat(M),I={},S=0,j=0,q=0,B=!1,L=[],O=!1,K=!1,N="addEventListener"in n,R=e(n),V=1,z=0;for(e.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500,maximumTimeBetweenTouches:100},D=0;D=2?15:30,verticalDistanceThreshold:t.devicePixelRatio>=2?15:30,getLocation:function(e){var n=t.pageXOffset,o=t.pageYOffset,i=e.clientX,a=e.clientY;return 0===e.pageY&&Math.floor(a)>Math.floor(e.pageY)||0===e.pageX&&Math.floor(i)>Math.floor(e.pageX)?(i-=n,a-=o):(ae.event.special.swipe.horizontalDistanceThreshold&&Math.abs(t.coords[1]-n.coords[1])n.coords[0]?"swipeleft":"swiperight";return i(o,"swipe",e.Event("swipe",{target:a,swipestart:t,swipestop:n}),!0),i(o,s,e.Event(s,{target:a,swipestart:t,swipestop:n}),!0),!0}return!1},eventInProgress:!1,setup:function(){var t,n=this,o=e(n),i={};t=e.data(this,"mobile-events"),t||(t={length:0},e.data(this,"mobile-events",t)),t.length++,t.swipe=i,i.start=function(t){if(!e.event.special.swipe.eventInProgress){e.event.special.swipe.eventInProgress=!0;var o,s=e.event.special.swipe.start(t),r=t.target,p=!1;i.move=function(t){s&&!t.isDefaultPrevented()&&(o=e.event.special.swipe.stop(t),p||(p=e.event.special.swipe.handleSwipe(s,o,n,r))&&(e.event.special.swipe.eventInProgress=!1),Math.abs(s.coords[0]-o.coords[0])>e.event.special.swipe.scrollSupressionThreshold&&t.preventDefault())},i.stop=function(){p=!0,e.event.special.swipe.eventInProgress=!1,a.off(c,i.move),i.move=null},a.on(c,i.move).one(u,i.stop)}},o.on(r,i.start)},teardown:function(){var t,n;t=e.data(this,"mobile-events"),t&&(n=t.swipe,delete t.swipe,0===--t.length&&e.removeData(this,"mobile-events")),n&&(n.start&&e(this).off(r,n.start),n.move&&a.off(c,n.move),n.stop&&a.off(u,n.stop))}},e.each({taphold:"tap",swipeleft:"swipe.left",swiperight:"swipe.right"},function(t,n){e.event.special[t]={setup:function(){e(this).bind(n,e.noop)},teardown:function(){e(this).unbind(n)}}}),e.event.special})}); diff --git a/src/core/required/adapt/js/scriptLoader.js b/src/core/required/adapt/js/scriptLoader.js index 427eeeaae..e67bc96ff 100644 --- a/src/core/required/adapt/js/scriptLoader.js +++ b/src/core/required/adapt/js/scriptLoader.js @@ -80,7 +80,7 @@ scrollTo: 'libraries/scrollTo.min', bowser: 'libraries/bowser', 'enum': 'libraries/enum', - jqueryMobile: 'libraries/jquery.mobile.custom', + jqueryMobile: 'libraries/jquery.mobile.custom.min', react: isProduction ? 'libraries/react.production.min' : 'libraries/react.development', 'react-dom': isProduction ? 'libraries/react-dom.production.min' : 'libraries/react-dom.development', 'object.assign': 'libraries/object.assign', @@ -145,7 +145,9 @@ function loadGlobals(Handlebars, _) { window._ = _; window.Handlebars = Handlebars; - loadTemplates(); + require([ + 'events/touch' + ], loadTemplates); } // 8. Load templates