| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /* ***** BEGIN LICENSE BLOCK *****
- * Distributed under the BSD license:
- *
- * Copyright (c) 2010, Ajax.org B.V.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Ajax.org B.V. nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ***** END LICENSE BLOCK ***** */
- define(function(require, exports, module) {
- "use strict";
- var keys = require("./keys");
- var useragent = require("./useragent");
- var pressedKeys = null;
- var ts = 0;
- exports.addListener = function(elem, type, callback) {
- if (elem.addEventListener) {
- return elem.addEventListener(type, callback, false);
- }
- if (elem.attachEvent) {
- var wrapper = function() {
- callback.call(elem, window.event);
- };
- callback._wrapper = wrapper;
- elem.attachEvent("on" + type, wrapper);
- }
- };
- exports.removeListener = function(elem, type, callback) {
- if (elem.removeEventListener) {
- return elem.removeEventListener(type, callback, false);
- }
- if (elem.detachEvent) {
- elem.detachEvent("on" + type, callback._wrapper || callback);
- }
- };
- /*
- * Prevents propagation and clobbers the default action of the passed event
- */
- exports.stopEvent = function(e) {
- exports.stopPropagation(e);
- exports.preventDefault(e);
- return false;
- };
- exports.stopPropagation = function(e) {
- if (e.stopPropagation)
- e.stopPropagation();
- else
- e.cancelBubble = true;
- };
- exports.preventDefault = function(e) {
- if (e.preventDefault)
- e.preventDefault();
- else
- e.returnValue = false;
- };
- /*
- * @return {Number} 0 for left button, 1 for middle button, 2 for right button
- */
- exports.getButton = function(e) {
- if (e.type == "dblclick")
- return 0;
- if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey)))
- return 2;
- // DOM Event
- if (e.preventDefault) {
- return e.button;
- }
- // old IE
- else {
- return {1:0, 2:2, 4:1}[e.button];
- }
- };
- exports.capture = function(el, eventHandler, releaseCaptureHandler) {
- function onMouseUp(e) {
- eventHandler && eventHandler(e);
- releaseCaptureHandler && releaseCaptureHandler(e);
- exports.removeListener(document, "mousemove", eventHandler, true);
- exports.removeListener(document, "mouseup", onMouseUp, true);
- exports.removeListener(document, "dragstart", onMouseUp, true);
- }
- exports.addListener(document, "mousemove", eventHandler, true);
- exports.addListener(document, "mouseup", onMouseUp, true);
- exports.addListener(document, "dragstart", onMouseUp, true);
-
- return onMouseUp;
- };
- exports.addTouchMoveListener = function (el, callback) {
- if ("ontouchmove" in el) {
- var startx, starty;
- exports.addListener(el, "touchstart", function (e) {
- var touchObj = e.changedTouches[0];
- startx = touchObj.clientX;
- starty = touchObj.clientY;
- });
- exports.addListener(el, "touchmove", function (e) {
- var factor = 1,
- touchObj = e.changedTouches[0];
- e.wheelX = -(touchObj.clientX - startx) / factor;
- e.wheelY = -(touchObj.clientY - starty) / factor;
- startx = touchObj.clientX;
- starty = touchObj.clientY;
- callback(e);
- });
- }
- };
- exports.addMouseWheelListener = function(el, callback) {
- if ("onmousewheel" in el) {
- exports.addListener(el, "mousewheel", function(e) {
- var factor = 8;
- if (e.wheelDeltaX !== undefined) {
- e.wheelX = -e.wheelDeltaX / factor;
- e.wheelY = -e.wheelDeltaY / factor;
- } else {
- e.wheelX = 0;
- e.wheelY = -e.wheelDelta / factor;
- }
- callback(e);
- });
- } else if ("onwheel" in el) {
- exports.addListener(el, "wheel", function(e) {
- var factor = 0.35;
- switch (e.deltaMode) {
- case e.DOM_DELTA_PIXEL:
- e.wheelX = e.deltaX * factor || 0;
- e.wheelY = e.deltaY * factor || 0;
- break;
- case e.DOM_DELTA_LINE:
- case e.DOM_DELTA_PAGE:
- e.wheelX = (e.deltaX || 0) * 5;
- e.wheelY = (e.deltaY || 0) * 5;
- break;
- }
-
- callback(e);
- });
- } else {
- exports.addListener(el, "DOMMouseScroll", function(e) {
- if (e.axis && e.axis == e.HORIZONTAL_AXIS) {
- e.wheelX = (e.detail || 0) * 5;
- e.wheelY = 0;
- } else {
- e.wheelX = 0;
- e.wheelY = (e.detail || 0) * 5;
- }
- callback(e);
- });
- }
- };
- exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) {
- var clicks = 0;
- var startX, startY, timer;
- var eventNames = {
- 2: "dblclick",
- 3: "tripleclick",
- 4: "quadclick"
- };
- exports.addListener(el, "mousedown", function(e) {
- if (exports.getButton(e) !== 0) {
- clicks = 0;
- } else if (e.detail > 1) {
- clicks++;
- if (clicks > 4)
- clicks = 1;
- } else {
- clicks = 1;
- }
- if (useragent.isIE) {
- var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5;
- if (!timer || isNewClick)
- clicks = 1;
- if (timer)
- clearTimeout(timer);
- timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
- if (clicks == 1) {
- startX = e.clientX;
- startY = e.clientY;
- }
- }
-
- e._clicks = clicks;
- eventHandler[callbackName]("mousedown", e);
- if (clicks > 4)
- clicks = 0;
- else if (clicks > 1)
- return eventHandler[callbackName](eventNames[clicks], e);
- });
- if (useragent.isOldIE) {
- exports.addListener(el, "dblclick", function(e) {
- clicks = 2;
- if (timer)
- clearTimeout(timer);
- timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600);
- eventHandler[callbackName]("mousedown", e);
- eventHandler[callbackName](eventNames[clicks], e);
- });
- }
- };
- var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window)
- ? function(e) {
- return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
- }
- : function(e) {
- return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
- };
- exports.getModifierString = function(e) {
- return keys.KEY_MODS[getModifierHash(e)];
- };
- function normalizeCommandKeys(callback, e, keyCode) {
- var hashId = getModifierHash(e);
- if (!useragent.isMac && pressedKeys) {
- if (pressedKeys.OSKey)
- hashId |= 8;
- if (pressedKeys.altGr) {
- if ((3 & hashId) != 3)
- pressedKeys.altGr = 0;
- else
- return;
- }
- if (keyCode === 18 || keyCode === 17) {
- var location = "location" in e ? e.location : e.keyLocation;
- if (keyCode === 17 && location === 1) {
- if (pressedKeys[keyCode] == 1)
- ts = e.timeStamp;
- } else if (keyCode === 18 && hashId === 3 && location === 2) {
- var dt = e.timeStamp - ts;
- if (dt < 50)
- pressedKeys.altGr = true;
- }
- }
- }
-
- if (keyCode in keys.MODIFIER_KEYS) {
- keyCode = -1;
- }
- // keyCode of right command is 93 on mac and 92 on windows.
- // keyCode of left command key is 91
- if (hashId & 8 && (keyCode >= 91 && keyCode <= 93)) {
- keyCode = -1;
- }
-
- if (!hashId && keyCode === 13) {
- var location = "location" in e ? e.location : e.keyLocation;
- if (location === 3) {
- callback(e, hashId, -keyCode);
- if (e.defaultPrevented)
- return;
- }
- }
-
- if (useragent.isChromeOS && hashId & 8) {
- callback(e, hashId, keyCode);
- if (e.defaultPrevented)
- return;
- else
- hashId &= ~8;
- }
- // If there is no hashId and the keyCode is not a function key, then
- // we don't call the callback as we don't handle a command key here
- // (it's a normal key/character input).
- if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {
- return false;
- }
-
- return callback(e, hashId, keyCode);
- }
- exports.addCommandKeyListener = function(el, callback) {
- var addListener = exports.addListener;
- if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) {
- // Old versions of Gecko aka. Firefox < 4.0 didn't repeat the keydown
- // event if the user pressed the key for a longer time. Instead, the
- // keydown event was fired once and later on only the keypress event.
- // To emulate the 'right' keydown behavior, the keyCode of the initial
- // keyDown event is stored and in the following keypress events the
- // stores keyCode is used to emulate a keyDown event.
- var lastKeyDownKeyCode = null;
- addListener(el, "keydown", function(e) {
- lastKeyDownKeyCode = e.keyCode;
- });
- addListener(el, "keypress", function(e) {
- return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);
- });
- } else {
- var lastDefaultPrevented = null;
- addListener(el, "keydown", function(e) {
- var keyCode = e.keyCode;
- pressedKeys[keyCode] = (pressedKeys[keyCode] || 0) + 1;
- if (keyCode == 91 || keyCode == 92) {
- pressedKeys.OSKey = true;
- } else if (pressedKeys.OSKey) {
- if (e.timeStamp - pressedKeys.lastT > 200 && pressedKeys.count == 1)
- resetPressedKeys();
- }
- if (pressedKeys[keyCode] == 1)
- pressedKeys.count++;
- // console.log(e.timeStamp - pressedKeys.lastT)
- pressedKeys.lastT = e.timeStamp;
- var result = normalizeCommandKeys(callback, e, keyCode);
- lastDefaultPrevented = e.defaultPrevented;
- return result;
- });
- addListener(el, "keypress", function(e) {
- if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) {
- exports.stopEvent(e);
- lastDefaultPrevented = null;
- }
- });
- addListener(el, "keyup", function(e) {
- var keyCode = e.keyCode;
- if (!pressedKeys[keyCode]) {
- // console.log("resetting", 1)
- resetPressedKeys();
- } else {
- pressedKeys.count = Math.max(pressedKeys.count - 1, 0);
- }
- if (keyCode == 91 || keyCode == 92) {
- pressedKeys.OSKey = false;
- }
- pressedKeys[keyCode] = null;
- });
- if (!pressedKeys) {
- resetPressedKeys();
- addListener(window, "focus", resetPressedKeys);
- }
- }
- };
- function resetPressedKeys() {
- // console.log("resetting")
- pressedKeys = Object.create(null);
- pressedKeys.count = 0;
- pressedKeys.lastT = 0;
- }
- if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
- var postMessageId = 1;
- exports.nextTick = function(callback, win) {
- win = win || window;
- var messageName = "zero-timeout-message-" + postMessageId;
- exports.addListener(win, "message", function listener(e) {
- if (e.data == messageName) {
- exports.stopPropagation(e);
- exports.removeListener(win, "message", listener);
- callback();
- }
- });
- win.postMessage(messageName, "*");
- };
- }
- exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame
- || window.mozRequestAnimationFrame
- || window.webkitRequestAnimationFrame
- || window.msRequestAnimationFrame
- || window.oRequestAnimationFrame);
- if (exports.nextFrame)
- exports.nextFrame = exports.nextFrame.bind(window);
- else
- exports.nextFrame = function(callback) {
- setTimeout(callback, 17);
- };
- });
|