define("dojo/touch", ["./_base/kernel", "./aspect", "./dom", "./on", "./has", "./mouse", "./ready", "./_base/window"], function(dojo, aspect, dom, on, has, mouse, ready, 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; } var touchmove, hoveredNode; if(hasTouch){ ready(function(){ // Keep track of currently hovered node hoveredNode = win.body(); // currently hovered node win.doc.addEventListener("touchstart", function(evt){ // 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){ 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); } }); }; } function _handle(type){ // type: String // press | move | release | cancel return function(node, listener){//called by on(), see dojo.on return on(node, type, listener); }; } //device neutral events - touch.press|move|release|cancel/over/out var touch = { press: _handle(hasTouch ? "touchstart": "mousedown"), move: hasTouch ? touchmove :_handle("mousemove"), release: _handle(hasTouch ? "touchend": "mouseup"), cancel: hasTouch ? _handle("touchcancel") : mouse.leave, over: _handle(hasTouch ? "dojotouchover": "mouseover"), out: _handle(hasTouch ? "dojotouchout": "mouseout"), enter: mouse._eventHandler(hasTouch ? "dojotouchover" : "mouseover"), leave: mouse._eventHandler(hasTouch ? "dojotouchout" : "mouseout") }; /*===== 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; });