| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943 | 
							- //------------------键盘处理类
 
- Namespace.register("U.K");
 
- //#region 全局变量区域
 
- //变量来存储_MAP的翻转版从上面
 
- U.K._REVERSE_MAP;
 
- //特殊键码的映射到其对应的键
 
- U.K._MAP = {
 
-     8: 'backspace',
 
-     9: 'tab',
 
-     13: 'enter',
 
-     16: 'shift',
 
-     17: 'ctrl',
 
-     18: 'alt',
 
-     20: 'capslock',
 
-     27: 'esc',
 
-     32: 'space',
 
-     33: 'pageup',
 
-     34: 'pagedown',
 
-     35: 'end',
 
-     36: 'home',
 
-     37: 'left',
 
-     38: 'up',
 
-     39: 'right',
 
-     40: 'down',
 
-     45: 'ins',
 
-     46: 'del',
 
-     91: 'meta',
 
-     93: 'meta',
 
-     224: 'meta'
 
- };
 
- //特殊字符,使他们能够支持映射
 
- U.K._KEYCODE_MAP = {
 
-     106: '*',
 
-     107: '+',
 
-     109: '-',
 
-     110: '.',
 
-     111: '/',
 
-     186: ';',
 
-     187: '=',
 
-     188: ',',
 
-     189: '-',
 
-     190: '.',
 
-     191: '/',
 
-     192: '`',
 
-     219: '[',
 
-     220: '\\',
 
-     221: ']',
 
-     222: '\''
 
- };
 
- //这是需要一个美国小键盘上的shift键的映射
 
- U.K._SHIFT_MAP = {
 
-     '~': '`',
 
-     '!': '1',
 
-     '@': '2',
 
-     '#': '3',
 
-     '$': '4',
 
-     '%': '5',
 
-     '^': '6',
 
-     '&': '7',
 
-     '*': '8',
 
-     '(': '9',
 
-     ')': '0',
 
-     '_': '-',
 
-     '+': '=',
 
-     ':': ';',
 
-     '\"': '\'',
 
-     '<': ',',
 
-     '>': '.',
 
-     '?': '/',
 
-     '|': '\\'
 
- };
 
- //这是你可以用它来绘制特殊字符串列表
 
- U.K._SPECIAL_ALIASES = {
 
-     'option': 'alt',
 
-     'command': 'meta',
 
-     'return': 'enter',
 
-     'escape': 'esc',
 
-     'plus': '+',
 
-     'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'
 
- };
 
- U.K.start = function () {
 
-     //遍历F键,F1至F19,并把它们添加到地图
 
-     for (var i = 1; i < 20; ++i) {
 
-         U.K._MAP[111 + i] = 'f' + i;
 
-     }
 
-     //数字键盘的数字添加
 
-     for (i = 0; i <= 9; ++i) {
 
-         U.K._MAP[i + 96] = i.toString();
 
-     }
 
- }
 
- //#endregion
 
- //#region 方法使用区域
 
- //取事件,并返回的键值
 
- U.K._characterFromEvent = function (e) {
 
-     //为按键事件,我们应该回到该字符是
 
-     if (e.type == 'keypress') {
 
-         var character = String.fromCharCode(e.which);
 
-         // 如果没有然后按下Shift键它是安全的假设
 
-         // 我们想要的字符是小写。这意味着,如果
 
-         // 你不小心有大写锁定,然后键绑定
 
-         // 将继续工作
 
-         //
 
-         // 可能是不希望的唯一副作用是,如果你
 
-         // 绑定类似'A',因为你要触发
 
-         // 事件被按下大写字母A时,大写锁定将不再
 
-         // 触发事件。尽管绑定了shift+a。
 
-         if (!e.shiftKey) {
 
-             character = character.toLowerCase();
 
-         }
 
-         return character;
 
-     }
 
-     // 非按键事件所需的专用地图
 
-     if (U.K._MAP[e.which]) {
 
-         return U.K._MAP[e.which];
 
-     }
 
-     if (U.K._KEYCODE_MAP[e.which]) {
 
-         return U.K._KEYCODE_MAP[e.which];
 
-     }
 
-     // 如果它不是在特殊的地图
 
-     // 与KEYDOWN和KeyUp事件的性质似乎总
 
-     // 进来作为一个大写字符无论您是按住Shift
 
-     //  或不。我们应该确保它始终是小写的比较
 
-     return String.fromCharCode(e.which).toLowerCase();
 
- }
 
- /**
 
- * 检查,如果两个数组相等,
 
- *
 
- * @param {Array} modifiers1
 
- * @param {Array} modifiers2
 
- * @returns {boolean}
 
- */
 
- U.K._modifiersMatch = function (modifiers1, modifiers2) {
 
-     return modifiers1.sort().join(',') === modifiers2.sort().join(',');
 
- }
 
- /**
 
- * 需要一个关键事件,并计算出的修饰符是什么
 
- *
 
- * @param {Event} e
 
- * @returns {Array}
 
- */
 
- U.K._eventModifiers = function (e) {
 
-     var modifiers = [];
 
-     if (e.shiftKey) {
 
-         modifiers.push('shift');
 
-     }
 
-     if (e.altKey) {
 
-         modifiers.push('alt');
 
-     }
 
-     if (e.ctrlKey) {
 
-         modifiers.push('ctrl');
 
-     }
 
-     if (e.metaKey) {
 
-         modifiers.push('meta');
 
-     }
 
-     return modifiers;
 
- }
 
- /**
 
- * 确定指定的键码是一个修改键或不
 
- *
 
- * @param {string} key
 
- * @returns {boolean}
 
- */
 
- U.K._isModifier = function (key) {
 
-     return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';
 
- }
 
- /**
 
- * 颠倒了地图查找,这样我们可以寻找特定键
 
- *看看有什么可以和不能使用的按键
 
- *
 
- * @return {Object}
 
- */
 
- U.K._getReverseMap = function () {
 
-     if (!_REVERSE_MAP) {
 
-         _REVERSE_MAP = {};
 
-         for (var key in U.K._MAP) {
 
-             //从这里拉出数字小键盘按键的事业宜
 
-             //能够从字符检测的按键
 
-             if (key > 95 && key < 112) {
 
-                 continue;
 
-             }
 
-             if (U.K._MAP.hasOwnProperty(key)) {
 
-                 _REVERSE_MAP[U.K._MAP[key]] = key;
 
-             }
 
-         }
 
-     }
 
-     return _REVERSE_MAP;
 
- }
 
- /**
 
- * 挑选基础上,组合键最佳动作
 
- *
 
- * @param {string} key - character for key
 
- * @param {Array} modifiers
 
- * @param {string=} action passed in
 
- */
 
- U.K._pickBestAction = function (key, modifiers, action) {
 
-     //如果没有动作,拿起我们应该尽量挑选一个
 
-     //我们认为将工作最适合这一关键
 
-     if (!action) {
 
-         action = U.K._getReverseMap()[key] ? 'keydown' : 'keypress';
 
-     }
 
-     //与预期的按键组合键不起作用,
 
-     //切换到KEYDOWN
 
-     if (action == 'keypress' && modifiers.length) {
 
-         action = 'keydown';
 
-     }
 
-     return action;
 
- }
 
- /**
 
- * *从一个字符串组合键转换到一个数组
 
- *
 
- * @param  {string} 的组合,如 "command+shift+l"
 
- * @return {Array}
 
- */
 
- U.K._keysFromString = function (combination) {
 
-     if (combination === '+') {
 
-         return ['+'];
 
-     }
 
-     combination = combination.replace(/\+{2}/g, '+plus');
 
-     return combination.split('+');
 
- }
 
- /**
 
- * Gets 获取信息的特定的组合键
 
- *
 
- * @param  {string} combination key combination ("command+s" or "a" or "*")
 
- * @param  {string=} action
 
- * @returns {Object}
 
- */
 
- U.K._getKeyInfo = function (combination, action) {
 
-     var keys;
 
-     var key;
 
-     var i;
 
-     var modifiers = [];
 
-     // 从这种模式带钥匙,弄清实际
 
-     // 模式是所有
 
-     keys = U.K._keysFromString(combination);
 
-     for (i = 0; i < keys.length; ++i) {
 
-         key = keys[i];
 
-         // normalize key names
 
-         if (U.K._SPECIAL_ALIASES[key]) {
 
-             key = U.K._SPECIAL_ALIASES[key];
 
-         }
 
-         //如果这不是一个按键事件那么我们应该
 
-         //聪明地使用shift键
 
-         //这只会为我们工作不过键盘
 
-         if (action && action != 'keypress' && U.K._SHIFT_MAP[key]) {
 
-             key = U.K._SHIFT_MAP[key];
 
-             modifiers.push('shift');
 
-         }
 
-         //如果该键是一个修改,然后将其添加到修改器列表
 
-         if (U.K._isModifier(key)) {
 
-             modifiers.push(key);
 
-         }
 
-     }
 
-     //根据密钥的组合是什么
 
-     //我们会尽力挑选最好的事件它
 
-     action = U.K._pickBestAction(key, modifiers, action);
 
-     return {
 
-         key: key,
 
-         modifiers: modifiers,
 
-         action: action
 
-     };
 
- }
 
- //判断监听来源
 
- U.K._belongsTo = function (element, ancestor) {
 
-     if (element === null || element === document) {
 
-         return false;
 
-     }
 
-     if (element === ancestor) {
 
-         return true;
 
-     }
 
-     return U.K._getReverseMap(element.parentNode, ancestor);
 
- }
 
- //#endregion
 
- //#region 对外接口区域
 
- //对外公布函数
 
- U.K.Mousetrap = function (targetElement) {
 
-     var self = this;
 
-     targetElement = targetElement || document;
 
-     if (!(self instanceof U.K.Mousetrap)) {
 
-         return new U.K.Mousetrap(targetElement);
 
-     }
 
-     /**
 
-     * 元素附加关键事件
 
-     *
 
-     * @type {Element}
 
-     */
 
-     self.target = targetElement;
 
-     /**
 
-     * 通过Mousetrap.bind所有的回调设置列表()
 
-     *
 
-     * @type {Object}
 
-     */
 
-     self._callbacks = {};
 
-     /**
 
-     * 字符串组合的直接映射到用于触发回调()
 
-     *
 
-     * @type {Object}
 
-     */
 
-     self._directMap = {};
 
-     /**
 
-     * 跟踪什么级别的每个序列是因为多个
 
-     *序列可以开始时具有相同的序列
 
-     *
 
-     * @type {Object}
 
-     */
 
-     var _sequenceLevels = {};
 
-     /**
 
-     * 变量来存储方法setTimeout
 
-     *
 
-     * @type {null|number}
 
-     */
 
-     var _resetTimer;
 
-     /**
 
-     * 临时的状态,我们会忽略下一个KEYUP
 
-     *
 
-     * @type {boolean|string}
 
-     */
 
-     var _ignoreNextKeyup = false;
 
-     /**
 
-     * 临时的状态,我们会忽略下一个按键
 
-     *
 
-     * @type {boolean}
 
-     */
 
-     var _ignoreNextKeypress = false;
 
-     /**
 
-     * 是我们目前的序列里面?
 
-     * acticon(“KEYUP”或“的keydown”或“keypress”)或flase的类型
 
-     *
 
-     * @type {boolean|string}
 
-     */
 
-     var _nextExpectedAction = false;
 
-     /**
 
-     * 重置所有序列柜台,除了传递的那些
 
-     *
 
-     * @param {Object} doNotReset
 
-     * @returns void
 
-     */
 
-     function _resetSequences(doNotReset) {
 
-         doNotReset = doNotReset || {};
 
-         var activeSequences = false,
 
-         key;
 
-         for (key in _sequenceLevels) {
 
-             if (doNotReset[key]) {
 
-                 activeSequences = true;
 
-                 continue;
 
-             }
 
-             _sequenceLevels[key] = 0;
 
-         }
 
-         if (!activeSequences) {
 
-             _nextExpectedAction = false;
 
-         }
 
-     }
 
-     /**
 
-     * *查找匹配基础上的keyCode,所有的callback,modifiers,action
 
-     *
 
-     * @param {string} character
 
-     * @param {Array} modifiers
 
-     * @param {Event|Object} e
 
-     * @param {string=} sequenceName - name of the sequence we are looking for
 
-     * @param {string=} combination
 
-     * @param {number=} level
 
-     * @returns {Array}
 
-     */
 
-     function _getMatches(character, modifiers, e, sequenceName, combination, level) {
 
-         var i;
 
-         var callback;
 
-         var matches = [];
 
-         var action = e.type;
 
-         // 如果没有与此相关的键码的事件
 
-         if (!self._callbacks[character]) {
 
-             return [];
 
-         }
 
-         // 如果修改键快到了自身,我们应该允许它
 
-         if (action == 'keyup' && U.K._isModifier(character)) {
 
-             modifiers = [character];
 
-         }
 
-         // 通过被按下该键所有的回调循环
 
-         //,看看其中是否匹配
 
-         for (i = 0; i < self._callbacks[character].length; ++i) {
 
-             callback = self._callbacks[character][i];
 
-             //如果一个序列名未指定,但是这是一个序列的
 
-             //错误的水平,那么移动到下一个match
 
-             if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {
 
-                 continue;
 
-             }
 
-             // //如果我们正在寻找的action不符合我们的action
 
-             //那么我们就应该继续执行
 
-             if (action != callback.action) {
 
-                 continue;
 
-             }
 
-             //如果这是一个keypress event和meta和control key
 
-             //没有按下这意味着我们只需要看
 
-             //字符,否则检查改性剂以及
 
-             //
 
-             // Chrome浏览器不会触发一个keypress如果meta or control is down
 
-             // Safari会触发一个 keypress 如果 meta or meta+shift is down
 
-             // Firefox会触发一个keypress 如果 meta or control is down
 
-             if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || U.K._modifiersMatch(modifiers, callback.modifiers)) {
 
-                 //当你绑定的组合或序列的第二次它
 
-                 //应该覆盖的第一个。如果sequenceName或
 
-                 //组合在这个指定的调用它做到了这一点
 
-                 //
 
-                 //@todo使删除它自己的方法?
 
-                 var deleteCombo = !sequenceName && callback.combo == combination;
 
-                 var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;
 
-                 if (deleteCombo || deleteSequence) {
 
-                     self._callbacks[character].splice(i, 1);
 
-                 }
 
-                 matches.push(callback);
 
-             }
 
-         }
 
-         return matches;
 
-     }
 
-     /**
 
-     * 实际调用回调函数
 
-     *
 
-     *
 
-     *
 
-     *如果您的回调函数返回false,这将使用jQuery的
 
-     * convention - 防止违约和对事件停止传播史
 
-     *
 
-     * @param {Function} callback
 
-     * @param {Event} e
 
-     * @returns void
 
-     */
 
-     function _fireCallback(callback, e, combo, sequence) {
 
-         // //如果此事件不应该发生到此为止
 
-         if (self.stopCallback(e, e.target || e.srcElement, combo, sequence)) {
 
-             return;
 
-         }
 
-         if (callback(e, combo) === false) {
 
-             U.M.StopDefault(e);
 
-             U.M.StopBubble(e);
 
-         }
 
-     }
 
-     /**
 
-     * 处理一个字符键事件
 
-     *
 
-     * @param {string} character
 
-     * @param {Array} modifiers
 
-     * @param {Event} e
 
-     * @returns void
 
-     */
 
-     self._handleKey = function (character, modifiers, e) {
 
-         var callbacks = _getMatches(character, modifiers, e);
 
-         var i;
 
-         var doNotReset = {};
 
-         var maxLevel = 0;
 
-         var processedSequenceCallback = false;
 
-         // 计算maxLevel的序列,所以我们只能执行时间最长的回调序列
 
-         for (i = 0; i < callbacks.length; ++i) {
 
-             if (callbacks[i].seq) {
 
-                 maxLevel = Math.max(maxLevel, callbacks[i].level);
 
-             }
 
-         }
 
-         //通过匹配回调回路这一关键事件
 
-         for (i = 0; i < callbacks.length; ++i) {
 
-             // 触发有序回调
 
-             // 这是因为例如,如果您有多个序列
 
-             // 结合诸如“G i”和“G t”,他们都需要触发
 
-             // 回调匹配摹原因,否则你永远只能
 
-             // 匹配到第一个
 
-             if (callbacks[i].seq) {
 
-                 //只触发回调的maxLevel防止
 
-                 //
 
-                 //
 
-                 //例如 “a option b' 应该不会造成'option b' 触发
 
-                 //即使'option b'为其它序列的一部分
 
-                 //
 
-                 //这里不匹配任何序列都将被丢弃
 
-                 //下面的_resetSequences通话
 
-                 if (callbacks[i].level != maxLevel) {
 
-                     continue;
 
-                 }
 
-                 processedSequenceCallback = true;
 
-                 // //保留其中的序列是匹配为以后列表
 
-                 doNotReset[callbacks[i].seq] = 1;
 
-                 _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
 
-                 continue;
 
-             }
 
-             // 如果没有序列相匹配,但我们还在这里
 
-             // 这意味着这是一个普通的匹配,所以我们应该触发了
 
-             if (!processedSequenceCallback) {
 
-                 _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
 
-             }
 
-         }
 
-         // if the key you pressed matches the type of sequence without
 
-         // being a modifier (ie "keyup" or "keypress") then we should
 
-         // reset all sequences that were not matched by this event
 
-         //
 
-         // this is so, for example, if you have the sequence "h a t" and you
 
-         // type "h e a r t" it does not match.  in this case the "e" will
 
-         // cause the sequence to reset
 
-         //
 
-         // modifier keys are ignored because you can have a sequence
 
-         // that contains modifiers such as "enter ctrl+space" and in most
 
-         // cases the modifier key will be pressed before the next key
 
-         //
 
-         // also if you have a sequence such as "ctrl+b a" then pressing the
 
-         // "b" key will trigger a "keypress" and a "keydown"
 
-         //
 
-         // the "keydown" is expected when there is a modifier, but the
 
-         // "keypress" ends up matching the _nextExpectedAction since it occurs
 
-         // after and that causes the sequence to reset
 
-         //
 
-         // we ignore keypresses in a sequence that directly follow a keydown
 
-         // for the same character
 
-         //如果你按下键序列无类型相匹配
 
-         //是一个修改(即“KEYUP”或“按键”),那么,我们应该
 
-         //重新设置那些没有此事件相匹配的所有序列
 
-         //
 
-         //是这样,例如,如果你有序列“哈t”和你
 
-         //型“听到T”不匹配。在这种情况下,将“e”的意愿
 
-         //导致序列复位
 
-         //
 
-         //修饰键被忽略,因为你可以有一个序列
 
-         //包含修饰,如“输入Ctrl +空格”,并在最
 
-         //情况下,修改键将在下键之前按下
 
-         //
 
-         //此外,如果你有一个序列,例如“CTRL + B A”,然后按
 
-         //“b”的键将触发一个“按键”和一个“的keydown”
 
-         //
 
-         //在“的keydown”时,有一个改性剂预期,但
 
-         //“按键”结束了,因为它发生_nextExpectedAction匹配
 
-         //之后和使该序列重新设置
 
-         //
 
-         //我们忽略了一个顺序按键直接遵循的keydown
 
-         //对于相同的字符
 
-         var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;
 
-         if (e.type == _nextExpectedAction && !U.K._isModifier(character) && !ignoreThisKeypress) {
 
-             _resetSequences(doNotReset);
 
-         }
 
-         _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';
 
-     };
 
-     /**
 
-     *处理一个keydown事件
 
-     *
 
-     * @param {Event} e
 
-     * @returns void
 
-     */
 
-     function _handleKeyEvent(e) {
 
-         // 为正常化的关键事件e.which
 
-         if (typeof e.which !== 'number') {
 
-             e.which = e.keyCode;
 
-         }
 
-         var character = U.K._characterFromEvent(e);
 
-         //没有字符发现后停止
 
-         if (!character) {
 
-             return;
 
-         }
 
-         //需要使用===用于字符检查,因为该字符可以是0
 
-         if (e.type == 'keyup' && _ignoreNextKeyup === character) {
 
-             _ignoreNextKeyup = false;
 
-             return;
 
-         }
 
-         self.handleKey(character, U.K._eventModifiers(e), e);
 
-     }
 
-     /**
 
-     * 称为设置1秒超时指定的顺序
 
-     *
 
-     *这是为了让序列中的每个按键后,你长为1秒
 
-     *按下一个键,你必须重新开始之前
 
-     *
 
-     * @returns void
 
-     */
 
-     function _resetSequenceTimer() {
 
-         clearTimeout(_resetTimer);
 
-         _resetTimer = setTimeout(_resetSequences, 1000);
 
-     }
 
-     /**
 
-     * 绑定一个键序列事件
 
-     *
 
-     * @param {string} combo - combo specified in bind call
 
-     * @param {Array} keys
 
-     * @param {Function} callback
 
-     * @param {string=} action
 
-     * @returns void
 
-     */
 
-     function _bindSequence(combo, keys, callback, action) {
 
-         // 通过增加一个序列水平记录这个组合开始
 
-         // 和level设定为0
 
-         _sequenceLevels[combo] = 0;
 
-         /**
 
-         * *回调,以增加该序列的序列水平和复位
 
-         * 处于活动状态的所有其他序列
 
-         *
 
-         * @param {string} nextAction
 
-         * @returns {Function}
 
-         */
 
-         function _increaseSequence(nextAction) {
 
-             return function () {
 
-                 _nextExpectedAction = nextAction;
 
-                 ++_sequenceLevels[combo];
 
-                 _resetSequenceTimer();
 
-             };
 
-         }
 
-         /**
 
-         * 包装指定的回调另一个函数内,以便
 
-         *尽快此序列完成后重置所有序列计数器
 
-         *
 
-         * @param {Event} e
 
-         * @returns void
 
-         */
 
-         function _callbackAndReset(e) {
 
-             _fireCallback(callback, e, combo);
 
-             //我们应该忽略下一个关键了,如果动作键不放
 
-             //或按键。这是如此,如果你完成一个序列
 
-             //松开按键的最后一个关键不会触发KEYUP
 
-             if (action !== 'keyup') {
 
-                 _ignoreNextKeyup = U.K._characterFromEvent(e);
 
-             }
 
-             //怪异的竞争条件,如果一个序列与该键结束
 
-             //另一序列始于
 
-             setTimeout(_resetSequences, 10);
 
-         }
 
-         //通过按键一次,并结合适当的回调循环
 
-         //功能。任何关键领导到最后,就应
 
-         //增加的顺序。决赛之后,应该重置所有序列
 
-         //
 
-         //如果在原来的绑定调用指定的操作那么就会
 
-         //在整个使用。否则,我们将通过动作的
 
-         //下一个关键应该匹配。这允许顺序
 
-         //混搭按键和KEYDOWN事件,这取决于
 
-         //的是更好地适合于提供的密钥
 
-         for (var i = 0; i < keys.length; ++i) {
 
-             var isFinal = i + 1 === keys.length;
 
-             var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || U.K._getKeyInfo(keys[i + 1]).action);
 
-             _bindSingle(keys[i], wrappedCallback, action, combo, i);
 
-         }
 
-     }
 
-     /**
 
-     * 绑定一个键盘组合
 
-     *
 
-     * @param {string} combination
 
-     * @param {Function} callback
 
-     * @param {string=} action
 
-     * @param {string=} sequenceName - name of sequence if part of sequence
 
-     * @param {number=} level - what part of the sequence the command is
 
-     * @returns void
 
-     */
 
-     function _bindSingle(combination, callback, action, sequenceName, level) {
 
-         //  //存储与Mousetrap.trigger使用直接映射参考
 
-         self._directMap[combination + ':' + action] = callback;
 
-         // 使连续务必多个空格成为一个空格
 
-         combination = combination.replace(/\s+/g, ' ');
 
-         var sequence = combination.split(' ');
 
-         var info;
 
-         //如果该模式是键的序列然后通过此方法运行
 
-         //重新处理每个模式一键在同一时间
 
-         if (sequence.length > 1) {
 
-             _bindSequence(combination, sequence, callback, action);
 
-             return;
 
-         }
 
-         info = U.K._getKeyInfo(combination, action);
 
-         //确保初始化数组,如果这是第一次
 
-         //回调增加了对这一关键
 
-         self._callbacks[info.key] = self._callbacks[info.key] || [];
 
-         //删除现有的比赛,如果有一个
 
-         _getMatches(info.key, info.modifiers, { type: info.action }, sequenceName, combination, level);
 
-         //后面添加此调用数组
 
-         //如果它是一个序列把它在开始时
 
-         //如果不把它在最后
 
-         //
 
-         //这是重要的,因为这些方式处理预期
 
-         //序列的人是第一位的
 
-         self._callbacks[info.key][sequenceName ? 'unshift' : 'push']({
 
-             callback: callback,
 
-             modifiers: info.modifiers,
 
-             action: info.action,
 
-             seq: sequenceName,
 
-             level: level,
 
-             combo: combination
 
-         });
 
-     }
 
-     /**
 
-     * 结合多种组合到同一个回调
 
-     *
 
-     * @param {Array} combinations
 
-     * @param {Function} callback
 
-     * @param {string|undefined} action
 
-     * @returns void
 
-     */
 
-     self._bindMultiple = function (combinations, callback, action) {
 
-         for (var i = 0; i < combinations.length; ++i) {
 
-             _bindSingle(combinations[i], callback, action);
 
-         }
 
-     };
 
-     // start!
 
-     U.M.AddEvent(targetElement, 'keypress', _handleKeyEvent);
 
-     U.M.AddEvent(targetElement, 'keydown', _handleKeyEvent);
 
-     U.M.AddEvent(targetElement, 'keyup', _handleKeyEvent);
 
- }
 
- U.K.Mousetrap = function () { };
 
- /**
 
- *  / **
 
- *绑定的事件捕鼠器
 
- *
 
- *可以是单一的键,以+分离键的组合,
 
- *键的阵列,或由空格分隔键序列
 
- *
 
- *请务必先列出的组合键,以确保
 
- *正确的密钥最终得到的约束(在模式的最后一个键)
 
- *
 
- * @param {string|Array} keys
 
- * @param {Function} callback
 
- * @param {string=} action - 'keypress', 'keydown', or 'keyup'
 
- * @returns void
 
- */
 
- U.K.Mousetrap.prototype.bind = function (keys, callback, action) {
 
-     var self = this;
 
-     keys = keys instanceof Array ? keys : [keys];
 
-     self._bindMultiple.call(self, keys, callback, action);
 
-     return self;
 
- };
 
- /**
 
- **
 
- *解除绑定的事件捕鼠器
 
- *
 
- *在解除绑定设置指定组合键的回调函数
 
- *到一个空的功能,并在删除相应的键
 
- * _directMap字典。
 
- *
 
- * TODO:其实从_callbacks词典中删除这个代替
 
- 结合一个空函数*
 
- *
 
- *在keycombo +操作必须是完全一样
 
- *它在绑定方法定义
 
- *
 
- * @param {string|Array} keys
 
- * @param {string} action
 
- * @returns void
 
- */
 
- U.K.Mousetrap.prototype.unbind = function (keys, action) {
 
-     var self = this;
 
-     return self.bind.call(self, keys, function () { }, action);
 
- };
 
- /**
 
- *  *触发器已被绑定的事件
 
- *
 
- * @param {string} keys
 
- * @param {string=} action
 
- * @returns void
 
- */
 
- U.K.Mousetrap.prototype.trigger = function (keys, action) {
 
-     var self = this;
 
-     if (self._directMap[keys + ':' + action]) {
 
-         self._directMap[keys + ':' + action]({}, keys);
 
-     }
 
-     return self;
 
- };
 
- /**
 
- * *重置库恢复到初始状态。这是非常有用的
 
- *如果您想清除出当前的键盘快捷键和绑定
 
- *新的 - 例如,如果您切换到另一页
 
- * @returns void
 
- */
 
- U.K.Mousetrap.prototype.reset = function () {
 
-     var self = this;
 
-     self._callbacks = {};
 
-     self._directMap = {};
 
-     return self;
 
- };
 
- /**
 
- *  *我们应该发射了回调之前停止该事件
 
- *
 
- * @param {Event} e
 
- * @param {Element} element
 
- * @return {boolean}
 
- */
 
- U.K.Mousetrap.prototype.stopCallback = function (e, element) {
 
-     var self = this;
 
-     // if the element has the class "mousetrap" then no need to stop
 
-     if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
 
-         return false;
 
-     }
 
-     if (U.K._getReverseMap(element, self.target)) {
 
-         return false;
 
-     }
 
-     // stop for input, select, and textarea
 
-     return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;
 
- };
 
- /**
 
- * 公开暴露_handleKey,因此它可以通过扩展覆盖
 
- */
 
- U.K.Mousetrap.prototype.handleKey = function () {
 
-     var self = this;
 
-     return self._handleKey.apply(self, arguments);
 
- };
 
- /**
 
- * 允许自定义键映射
 
- */
 
- U.K.Mousetrap.addKeycodes = function (object) {
 
-     for (var key in object) {
 
-         if (object.hasOwnProperty(key)) {
 
-             U.K._MAP[key] = object[key];
 
-         }
 
-     }
 
-     _REVERSE_MAP = null;
 
- };
 
- /**
 
- * *初始化全球捕鼠器功能
 
- *
 
- *需要使用此方法来允许在全球捕鼠器职能工作
 
- *现在的捕鼠器是一个构造函数。
 
- */
 
- U.K.Mousetrap.init = function () {
 
-     var documentMousetrap = Mousetrap(document);
 
-     for (var method in documentMousetrap) {
 
-         if (method.charAt(0) !== '_') {
 
-             Mousetrap[method] = (function (method) {
 
-                 return function () {
 
-                     return documentMousetrap[method].apply(documentMousetrap, arguments);
 
-                 };
 
-             } (method));
 
-         }
 
-     }
 
- };
 
- //#endregion
 
 
  |