define("dojo/touch", ["./_base/kernel", "./aspect", "./dom", "./on", "./has", "./mouse", "./domReady", "./_base/window"], function(dojo, aspect, dom, on, has, mouse, domReady, win){ // module: // dojo/touch var hasTouch = has("touch"); // TODO: get iOS version from dojo/sniff after #15827 is fixed var ios4 = false; if(has("ios")){ var ua = navigator.userAgent; var v = ua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1"; var os = parseFloat(v.replace(/_/, '.').replace(/_/g, '')); ios4 = os < 5; } // Time of most recent touchstart or touchmove event var lastTouch; function dualEvent(mouseType, touchType){ // Returns synthetic event that listens for both the specified mouse event and specified touch event. // But ignore fake mouse events that were generated due to the user touching the screen. if(hasTouch){ return function(node, listener){ var handle1 = on(node, touchType, listener), handle2 = on(node, mouseType, function(evt){ if(!lastTouch || (new Date()).getTime() > lastTouch + 1000){ listener.call(this, evt); } }); return { remove: function(){ handle1.remove(); handle2.remove(); } }; }; }else{ // Avoid creating listeners for touch events on performance sensitive older browsers like IE6 return function(node, listener){ return on(node, mouseType, listener); } } } var touchmove, hoveredNode; if(hasTouch){ domReady(function(){ // Keep track of currently hovered node hoveredNode = win.body(); // currently hovered node win.doc.addEventListener("touchstart", function(evt){ lastTouch = (new Date()).getTime(); // Precede touchstart event with touch.over event. DnD depends on this. // Use addEventListener(cb, true) to run cb before any touchstart handlers on node run, // and to ensure this code runs even if the listener on the node does event.stop(). var oldNode = hoveredNode; hoveredNode = evt.target; on.emit(oldNode, "dojotouchout", { target: oldNode, relatedTarget: hoveredNode, bubbles: true }); on.emit(hoveredNode, "dojotouchover", { target: hoveredNode, relatedTarget: oldNode, bubbles: true }); }, true); // Fire synthetic touchover and touchout events on nodes since the browser won't do it natively. on(win.doc, "touchmove", function(evt){ lastTouch = (new Date()).getTime(); var newNode = win.doc.elementFromPoint( evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords evt.pageY - (ios4 ? 0 : win.global.pageYOffset) ); if(newNode && hoveredNode !== newNode){ // touch out on the old node on.emit(hoveredNode, "dojotouchout", { target: hoveredNode, relatedTarget: newNode, bubbles: true }); // touchover on the new node on.emit(newNode, "dojotouchover", { target: newNode, relatedTarget: hoveredNode, bubbles: true }); hoveredNode = newNode; } }); }); // Define synthetic touch.move event that unlike the native touchmove, fires for the node the finger is // currently dragging over rather than the node where the touch started. touchmove = function(node, listener){ return on(win.doc, "touchmove", function(evt){ if(node === win.doc || dom.isDescendant(hoveredNode, node)){ evt.target = hoveredNode; listener.call(this, evt); } }); }; } //device neutral events - touch.press|move|release|cancel/over/out var touch = { press: dualEvent("mousedown", "touchstart"), move: dualEvent("mousemove", touchmove), release: dualEvent("mouseup", "touchend"), cancel: dualEvent(mouse.leave, "touchcancel"), over: dualEvent("mouseover", "dojotouchover"), out: dualEvent("mouseout", "dojotouchout"), enter: mouse._eventHandler(dualEvent("mouseover","dojotouchover")), leave: mouse._eventHandler(dualEvent("mouseout", "dojotouchout")) }; /*===== touch = { // summary: // This module provides unified touch event handlers by exporting // press, move, release and cancel which can also run well on desktop. // Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html // // example: // Used with dojo.on // | define(["dojo/on", "dojo/touch"], function(on, touch){ // | on(node, touch.press, function(e){}); // | on(node, touch.move, function(e){}); // | on(node, touch.release, function(e){}); // | on(node, touch.cancel, function(e){}); // example: // Used with touch.* directly // | touch.press(node, function(e){}); // | touch.move(node, function(e){}); // | touch.release(node, function(e){}); // | touch.cancel(node, function(e){}); press: function(node, listener){ // summary: // Register a listener to 'touchstart'|'mousedown' for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, move: function(node, listener){ // summary: // Register a listener to 'touchmove'|'mousemove' for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, release: function(node, listener){ // summary: // Register a listener to 'touchend'|'mouseup' for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, cancel: function(node, listener){ // summary: // Register a listener to 'touchcancel'|'mouseleave' for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, over: function(node, listener){ // summary: // Register a listener to 'mouseover' or touch equivalent for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, out: function(node, listener){ // summary: // Register a listener to 'mouseout' or touch equivalent for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, enter: function(node, listener){ // summary: // Register a listener to mouse.enter or touch equivalent for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() }, leave: function(node, listener){ // summary: // Register a listener to mouse.leave or touch equivalent for the given node // node: Dom // Target node to listen to // listener: Function // Callback function // returns: // A handle which will be used to remove the listener by handle.remove() } }; =====*/ 1 && (dojo.touch = touch); return touch; });