@atlassian/aui
Version:
Atlassian User Interface Framework
194 lines (169 loc) • 7.28 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define([], factory);
} else if (typeof exports !== "undefined") {
factory();
} else {
var mod = {
exports: {}
};
factory();
global.jqueryHotkeys = mod.exports;
}
})(this, function () {
"use strict";
/*
* Modified by Atlassian to allow chaining of keys
*
* jQuery Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* http://github.com/tzuryby/hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
(function (jQuery) {
jQuery.hotkeys = {
version: "0.8",
specialKeys: {
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
91: "meta",
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111: "/",
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll",
188: ",", 190: ".", 191: "/", 224: "meta", 219: '[', 221: ']'
},
// These only work under Mac Gecko when using keypress (see http://unixpapa.com/js/key.html).
keypressKeys: ["<", ">", "?"],
shiftNums: {
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ":", "'": "\"", ",": "<",
".": ">", "/": "?", "\\": "|"
}
};
jQuery.each(jQuery.hotkeys.keypressKeys, function (_, key) {
jQuery.hotkeys.shiftNums[key] = key;
});
function TimedNumber(timer) {
this.num = 0;
this.timer = timer > 0 ? timer : false;
}
TimedNumber.prototype.val = function () {
return this.num;
};
TimedNumber.prototype.inc = function () {
if (this.timer) {
clearTimeout(this.timeout);
this.timeout = setTimeout(jQuery.proxy(TimedNumber.prototype.reset, this), this.timer);
}
this.num++;
};
TimedNumber.prototype.reset = function () {
if (this.timer) {
clearTimeout(this.timeout);
}
this.num = 0;
};
function keyHandler(handleObj) {
// Only care when a possible input has been specified
if (!(jQuery.isPlainObject(handleObj.data) || jQuery.isArray(handleObj.data) || typeof handleObj.data === "string")) {
return;
}
var origHandler = handleObj.handler,
options = {
timer: 700,
combo: []
};
(function (data) {
if (typeof data === 'string') {
options.combo = [data];
} else if (jQuery.isArray(data)) {
options.combo = data;
} else {
jQuery.extend(options, data);
}
options.combo = jQuery.map(options.combo, function (key) {
return key.toLowerCase();
});
})(handleObj.data);
handleObj.index = new TimedNumber(options.timer);
handleObj.handler = function (event) {
// Don't fire in text-accepting inputs that we didn't directly bind to
// important to note that jQuery.fn.prop is only available on jquery 1.6+
if (this !== event.target && (/textarea|select|input/i.test(event.target.nodeName) || jQuery(event.target).prop('contenteditable') === 'true')) {
return;
}
// Keypress represents characters, not special keys
var special = event.type !== 'keypress' ? jQuery.hotkeys.specialKeys[event.which] : null,
character = String.fromCharCode(event.which).toLowerCase(),
key,
modif = "",
possible = {};
// check combinations (alt|ctrl|shift+anything)
if (event.altKey && special !== "alt") {
modif += "alt+";
}
if (event.ctrlKey && special !== "ctrl") {
modif += "ctrl+";
}
// TODO: Need to make sure this works consistently across platforms
if (event.metaKey && !event.ctrlKey && special !== "meta") {
modif += "meta+";
}
if (event.shiftKey && special !== "shift") {
modif += "shift+";
}
// Under Chrome and Safari, meta's keycode == '['s charcode
// Even if they did type this key combo we could not use it because it is browser back in Chrome/Safari on OS X
if (event.metaKey && character === '[') {
character = null;
}
if (special) {
possible[modif + special] = true;
}
if (character) {
possible[modif + character] = true;
}
// "$" can be specified as "shift+4" or "$"
if (/shift+/.test(modif)) {
possible[modif.replace('shift+', '') + jQuery.hotkeys.shiftNums[special || character]] = true;
}
var index = handleObj.index,
combo = options.combo;
if (pressed(combo[index.val()], possible)) {
if (index.val() === combo.length - 1) {
index.reset();
return origHandler.apply(this, arguments);
} else {
index.inc();
}
} else {
index.reset();
// For mutli-key combinations, we might have restarted the key sequence.
if (pressed(combo[0], possible)) {
index.inc();
}
}
};
}
function pressed(key, possible) {
var keys = key.split(' ');
for (var i = 0, len = keys.length; i < len; i++) {
if (possible[keys[i]]) {
return true;
}
}
return false;
}
jQuery.each(["keydown", "keyup", "keypress"], function () {
jQuery.event.special[this] = { add: keyHandler };
});
})(jQuery);
});
//# sourceMappingURL=jquery.hotkeys.js.map