UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

464 lines (430 loc) 16.3 kB
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,user-scalable=no"/> <title>Dojo Touch Testing</title> <style type="text/css"> #test { width: 300px; height: 150px; border: 1px solid #7FB0DB; background-color: #7FB0DB; touch-action: none; -ms-touch-action: none; } #innertest { border: 1px solid white; width: 100px; height: 75px; background-color: white; } #test2 { /* for testing touch.move */ width: 200px; height: 50px; border: 1px solid yellow; background-color: yellow; touch-action: none; -ms-touch-action: none; } #test3 { width: 300px; height: 150px; border: 1px solid red; background-color: red; touch-action: none; -ms-touch-action: none; } #innertest3 { border: 1px solid white; width: 250px; height: 75px; background-color: white; touch-action: none; -ms-touch-action: none; } #current, #log { width: 50%; height: 200px; float: left; } #dohDiv { display: none; background-color:#800300; color: wheat; } </style> <script type="text/javascript" src="../dojo.js" data-dojo-config="async: true"></script> <script> require([ "dojo/_base/array", "dojo/dom", "dojo/_base/lang", "dojo/on", "dojo/has", "doh/runner", "dojo/dom-geometry", "dojo/dom-style", "dojo/domReady", "dojo/touch" ], function(array, dom, lang, on, has, doh, domGeom, domStyle, domReady, touch){ var action = function(comment, e){ // summary: // Callback to display into when events fire // Detailed log of the most recent event: dom.byId("current").innerHTML = "Most recent non touch.move event:"; var info = "[Touch Event]: " + e.type + " on " + comment + "<br/> ------ Event Properties: ------<br/>"; for(var i in e){ if(i == "touches" || i == "targetTouches" || i == "changedTouches"){ info += i + ": " + e[i].length + "<br/>"; }else{ if(typeof e[i] != "function"){ info += " " + i + ": " + e[i] + "<br/>"; } } } dom.byId("current").innerHTML += info + "<br/>"; // This is a log of all events, most recent first: dom.byId("log").innerHTML = comment + "{type:" + e.type + ", target:" + (e.target.id||e.target.tagName) + "}<br/>" + dom.byId("log").innerHTML; e.preventDefault(); }; var node = dom.byId("test"), innerNode = dom.byId("innertest"); //1. should work well on PC and touch devices array.forEach(["test", "innertest"], function(name){ for(var event in touch){ if(event != "move"){ on(dom.byId(name), touch[event], lang.hitch(null, action, "on("+name+", touch."+event+")-->")); } } }); on(dom.byId("test2"), touch.move, function(e){ dom.byId("log").innerHTML = "on(touch2, touch.move)--> {type:" + e.type + ", target:" + (e.target.id||e.target.tagName) + ", pageX = " + e.pageX + ", pageY = " + e.pageY + "}<br/>" + dom.byId("log").innerHTML; // this should stop scrolling e.preventDefault(); // stopPropagation() should work too e.stopPropagation(); }); function logClickEvent(e) { // synthetic click has _dojo_click = true dom.byId("log").innerHTML = " - _dojo_click [" + e._dojo_click + "]<br/>" + dom.byId("log").innerHTML; // display mouse event attributes // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mouseevents var info = "", mouseEventAttrNames = ["screenX", "screenY", "clientX", "clientY", "ctrlKey", "altKey", "shiftKey", "metaKey", "button"]; for (var attrIdx = 0, name; attrIdx < mouseEventAttrNames.length && (name = mouseEventAttrNames[attrIdx]); attrIdx++) { info += " - " + name + " [" + e[name] + "]<br/>"; } dom.byId("log").innerHTML = info + dom.byId("log").innerHTML; } dom.byId("test3").dojoClick = true; on(dom.byId("test3"), "click", function(e){ logClickEvent(e); if(has("touch")){ // click should be a synthetic click dom.byId("log").innerHTML = (e._dojo_click ? "Synthetic click received in test3" : "ERROR: native click received in test3") + "<br/>" + dom.byId("log").innerHTML; }else{ // click should be a native click dom.byId("log").innerHTML = (e._dojo_click ? "ERROR: Synthetic click received in test3 (non touch device)" : "Native click received in test3 (non touch device)") + "<br/>" + dom.byId("log").innerHTML; } }); dom.byId("innertest3").dojoClick = false; on(dom.byId("innertest3"), "click", function(e){ logClickEvent(e); // click should be a native click dom.byId("log").innerHTML = (e._dojo_click ? "ERROR: Synthetic click received in innertest3" : "Native click received in innertest3") + "<br/>" + dom.byId("log").innerHTML;; e.stopPropagation(); }); // //2. should work well across touch devices // on(node, "touchstart", action); // on(node, "touchmove", action); // on(node, "touchend", action); // on(node, "touchcancel", action); // on(node, "orientationchange", action); /** * Fires an event. All coordinates are defaulted to zero. * @param target the target element. * @param eventType touchstart, touchmove or touchend, or mouse or MSPointer equivalents. */ function emit(target, eventType, options){ var targetPos = domGeom.position(target); options = lang.mixin({ pageX: targetPos.x + targetPos.w / 2, pageY: targetPos.y + targetPos.h / 2 }, options || {}); if(document.createEvent && target.dispatchEvent){ var touch = { identifier: (new Date()).getTime(), target: target, screenX: 0, screenY: 0, clientX: 0, clientY: 0, pageX: 0, pageY: 0 }; lang.mixin(touch, options || {}); var mouseEvent = document.createEvent("MouseEvent"); mouseEvent.initMouseEvent( eventType, true, true, target.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, document.body // relatedTarget, for mouseout events ); if(/touch/.test(eventType)){ mouseEvent['touches'] = [touch]; mouseEvent['targetTouches'] = [touch]; mouseEvent['changedTouches'] = [touch]; } target.dispatchEvent(mouseEvent); }else{ options.bubbles = true; options.cancelable = true; on.emit(target, eventType, options); } } // if we declare "dojo/domReady!" touch.js will register its handler *after* the test execution // so here we explicitly call domReady. domReady(function(){ var dohDiv = dom.byId('dohDiv'); domStyle.set(dohDiv, {display: 'block'}); // Function to register tests on mouse events, touch events, or Microsoft's pointer-ish events function register(testName, downEvent, moveEvent, upEvent, cancelEvent){ doh.register(testName, [ function press(){ var executed, target; on.once(dohDiv, touch.press, function(e){ //console.log(e.type); executed = true; target = e.target; }); emit(dohDiv, downEvent); doh.t(executed, 'dojo.touch.press fired'); doh.is(dohDiv, target, "target"); }, function move(){ var executed, target; on.once(dohDiv, touch.move, function(e){ //console.log(e.type); executed = true; target = e.target; }); emit(dohDiv, moveEvent); doh.t(executed, 'dojo.touch.move fired'); doh.is(dohDiv, target, "target"); }, function release(){ var executed, target; on.once(dohDiv, touch.release, function(e){ //console.log(e.type); executed = true; target = e.target; }); emit(dohDiv, upEvent, {screenX: 0, screenY: 50}); doh.t(executed, 'dojo.touch.release fired'); doh.is(dohDiv, target, "target"); }, function cancel(){ var executed, target; on.once(dohDiv, touch.cancel, function(e){ executed = true; target = e.target; }); emit(dohDiv, cancelEvent, { relatedTarget: document.body, // needed for mouseout event screenX: 0, screenY: 50, pageX: 0, pageY: 0 }); doh.t(executed, 'dojo.touch.cancel fired'); doh.is(dohDiv, target, "target"); }, function movePreventDefault(){ /** * checks that calling preventDefault() on dojo "touch.move" event * prevents default behavior on the underlying native event * Ref. #17220 * window * | => (1) listen and prevent default on dojo "touch.move" event * | => (2) listen and check default behavior status on native "touchmove" event * | * +--dohDiv => (3) dispatch native "touchmove" event **/ var prevented = false; // (1) register dojo "touch.move" listener on.once(dohDiv, touch.move, function(e){ e.preventDefault(); //console.log("prevent default on event " + e.type); }); // (2) register listener for native event (touchmove, mousemove, or MSPointerMove) // Call addEventListener() except on IE6-8 where that's not supported function listener(e){ prevented = e.defaultPrevented; //console.log("native listener, prevented = " + prevented); } if(window.addEventListener){ window.addEventListener(moveEvent, listener); }else{ // IE6-8 code path on.once(document.body, moveEvent, listener); } // (3) dispatch native touchmove/mousemove/MSPointerMove event emit(dohDiv, moveEvent); doh.t(prevented, 'prevented'); if(window.addEventListener){ window.removeEventListener(moveEvent, listener); } } ]); } // Setup tests relevant for this platform if(has("pointer-events")){ register('Pointer events', 'pointerdown', 'pointermove', 'pointerup', 'pointercancel'); }else if(has("MSPointer")){ register('MSPointer events', 'MSPointerDown', 'MSPointerMove', 'MSPointerUp', 'MSPointerCancel'); }else{ // Mouse is always supported, even on devices with touch capability. // Test mouse first because once we start emitting touch events, dojo/touch ignores mouse events // for 1000ms. register('mouse events', 'mousedown', 'mousemove', 'mouseup', 'mouseout'); if(has("touch-events")){ register('touch events', 'touchstart', 'touchmove', 'touchend', 'touchcancel'); var domEltWithDisabledSyntheticClick = dom.byId("innertest3"); var box = domEltWithDisabledSyntheticClick.getBoundingClientRect(); // position in viewport coordinates var coordInsideEltWithDisabledSyntheticClick = {x: box.right - box.left, y:box.bottom - box.top}; var domElt = dom.byId("innertest"); domElt.dojoClick = "useTarget"; var outsideElt = dom.byId("dohDiv"); box = domElt.getBoundingClientRect(); // position in viewport coordinates var coordInsideElt = {x: box.right - box.left, y:box.bottom - box.top}; var coordOutsideElt = {x: box.right + 100, y:box.bottom + 100}; doh.register("dojoClick.useTarget", [{ name: "Click inside", timeout: 1000, runTest: function(){ /** * check that synthetic click is fired as expected when dojoClick value is set * to "useTarget" on a dom element and touchstart/touchend are on that element, * even if a touchmove happens outside the element. * Note that synthetic click is fired ONLY on touch enabled devices (touch or MSPointer). */ var clicked = false; // register the click handler function listener(e){ clicked = true; } domElt.addEventListener("click", listener); // emit "touchstart" then "up" event inside the element emit(domElt, "touchstart", {screenX: coordInsideElt.x, screenY: coordInsideElt.y}); emit(outsideElt, "touchmove",{screenX: coordOutsideElt.x, screenY: coordOutsideElt.y}); emit(domElt, "touchend", {screenX: coordInsideElt.x, screenY: coordInsideElt.y}); var deferred = new doh.Deferred(); // without deferred the click handler is called after the doh method ends. setTimeout(deferred.getTestCallback(function(){ doh.t(clicked, 'synthetic click fired'); }), 0); return deferred; } },{ name: "Click outside", timeout: 1000, runTest: function(){ /** * check that synthetic click is NOT fired when dojoClick value is set * to "useTarget" on a dom element and touch is released outside the element. * Note that synthetic click is fired ONLY on touch enabled devices (touch or MSPointer). */ var clicked = false; // register the click handler function listener(e){ alert("click fired ??"); clicked = true; } domElt.addEventListener("click", listener); // emit "touchstart" inside, then "touchend" event outside the element emit(domElt, "touchstart", {screenX: coordInsideElt.x, screenY: coordInsideElt.y}); emit(outsideElt, "touchmove", {screenX: coordOutsideElt.x, screenY: coordOutsideElt.y}); emit(outsideElt, "touchend", {screenX: coordOutsideElt.x, screenY: coordOutsideElt.y}); var deferred = new doh.Deferred(); // without deferred the click handler is called after the doh method ends. setTimeout(deferred.getTestCallback(function(){ doh.t(!clicked, 'synthetic click fired'); }), 0); return deferred; } },{ name: "Synthetic click disabled", timeout: 1000, runTest: function(){ /** * check that synthetic click is NOT fired when dojoClick value is set * to falsy on a dom element and touch is released inside the element. * Note that synthetic click is fired ONLY on touch enabled devices (touch or MSPointer). */ var clicked = false; // register the click handler function listener(e){ alert("click fired ??"); clicked = true; } domEltWithDisabledSyntheticClick.addEventListener("click", listener); // emit "touchstart" and "touchend" events inside the element emit(domEltWithDisabledSyntheticClick, "touchstart", {screenX: coordInsideEltWithDisabledSyntheticClick.x, screenY: coordInsideEltWithDisabledSyntheticClick.y}); emit(domEltWithDisabledSyntheticClick, "touchend", {screenX: coordInsideEltWithDisabledSyntheticClick.x, screenY: coordInsideEltWithDisabledSyntheticClick.y}); var deferred = new doh.Deferred(); // without deferred the click handler is called after the doh method ends. setTimeout(deferred.getTestCallback(function(){ doh.t(!clicked, 'synthetic click fired'); }), 0); return deferred; } } ]); } } doh.run(); }); }); </script> </head> <body> <div id="test"> test <div id="innertest"> inner test </div> </div> <div id="test2"> touch.move </div> <div id="test3"> On touch devices, synthetic clicks are enabled in this area. <div id="innertest3"> On touch devices, synthetic clicks disabled in this area. </div> </div> <div id="dohDiv">doh</div> <div id="current"></div> <div id="log"></div> <br style="clear:both"/> </body> </html>