Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Выполнение комбинаций клавиш с помощью jQuery/JavaScript

Автор вопроса: Oscar GodsonОтветов: 4

Мне любопытно, как я, со следующим кодом плагина jQuery, который я пишу внизу этого вопроса, мог реализовать комбинации клавиш. Как это работает до сих пор, это позволяет пользователю создавать ключевые команды, просто выполняя обычный синтаксис, подобный jQuery, и предоставлять событие для ключевой команды, например так:

$(window).jkey('a',function(){
   alert('you pressed the a key!');
});

or

$(window).jkey('b c d',function(){
   alert('you pressed either the b, c, or d key!');
});

и, наконец, то, что я хочу, это способность делать, но не могу понять:

$(window).jkey('alt+n',function(){
   alert('you pressed alt+n!');
});

Я знаю, как это сделать вне плагина (при нажатии клавиши установите переменную false, а при нажатии клавиши установите переменную true и проверьте, истинна ли переменная, когда вы нажимаете другую клавишу), но я не знаю, как это сделать, когда вы не знаете, какие клавиши будут нажаты и сколько. Как добавить эту поддержку? Я хочу иметь возможность разрешить им делать что-то вроде alt+shift+a или a+s+d+f, если они захотят. Я просто не могу понять, как это реализовать. Любые идеи?

Я собираюсь выпустить это как плагин с открытым исходным кодом, и я хотел бы дать тому, кто дает мне право, работает, ответить на некоторые кредиты в сообщении в блоге и в коде, который он сам. Заранее спасибо!

(function($) {
  $.fn.jkey = function(keyCombo,callback) {
    if(keyCombo.indexOf(' ') > -1){ //If multiple keys are selected
        var keySplit = keyCombo.split(' ');
    }
    else{ //Else just store this single key
        var keySplit = [keyCombo];
    }
    for(x in keySplit){ //For each key in the array...

        if(keySplit[x].indexOf('+') > -1){
            //Key selection by user is a key combo... what now?
        }
        else{
            //Otherwise, it's just a normal, single key command
        }

        switch(keySplit[x]){
            case 'a':
                keySplit[x] = 65;
                break;
            case 'b':
                keySplit[x] = 66;
                break;
            case 'c':
                keySplit[x] = 67;
                break;
            //And so on for all the rest of the keys
        }
    }
    return this.each(function() {
        $this = $(this);
        $this.keydown(function(e){
            if($.inArray(e.keyCode, keySplit) > -1){ //If the key the user pressed is matched with any key the developer set a key code with...
                if(typeof callback == 'function'){ //and they provided a callback function
                    callback(); //trigger call back and...
                    e.preventDefault(); //cancel the normal
                }
            }
        });
    });
  }
})(jQuery);

javascriptpluginsjquerykeyboard-shortcutsjkey

Ответы

Ответ 1 · рейтинг 2 · sebnitu

Вот что я придумал. По сути, я создал объект JSON, в котором хранятся все коды клавиш. Затем я заменяю все предоставленные ключи кодами. Если клавиши используют "+" для создания комбинации клавиш, я затем создаю из нее массив кодов.

Затем мы создаем еще один массив, в котором хранятся все нажатые клавиши (keyDown добавляет элемент, keyUp удаляет его). На keyDown мы проверяем, является ли это одной клавишей или комбинацией. Если это комбинация, мы проверяем ее по всем текущим активным нажатиям клавиш. Если они все совпадают, мы выполняем обратный вызов.

Это будет работать с любым количеством комбинаций клавиш. Единственный раз, когда я видел, что он не работает, это когда вы используете "оповещение ()" для отображения сообщения о комбинации клавиш, потому что он больше не будет удалять элементы из активного массива нажатия клавиш.

(function($) {
  $.fn.jkey = function(keyCombo,callback) {

    // Save the key codes to JSON object
    var keyCodes = {
      'a'   : 65,
      'b'   : 66,
      'c'   : 67,
      'alt' : 18
    };

    var x = '';
    var y = '';

    if(keyCombo.indexOf(' ') > -1){ //If multiple keys are selected
        var keySplit = keyCombo.split(' ');
    }
    else{ //Else just store this single key
        var keySplit = [keyCombo];
    }

    for(x in keySplit){ //For each key in the array...

      if(keySplit[x].indexOf('+') > -1){
        //Key selection by user is a key combo
        // Create a combo array and split the key combo
        var combo = Array();
        var comboSplit = keySplit[x].split('+');

        // Save the key codes for each element in the key combo
        for(y in comboSplit){
          combo[y] = keyCodes[ comboSplit[y] ];
        }

        keySplit[x] = combo;

      } else {
        //Otherwise, it's just a normal, single key command
        keySplit[x] = keyCodes[ keySplit[x] ];
      }

    }

    return this.each(function() {
        $this = $(this);

        // Create active keys array
        // This array will store all the keys that are currently being pressed
        var activeKeys = Array();

        $this.keydown(function(e){

          // Save the current key press
          activeKeys[ e.keyCode ] = e.keyCode;

          if($.inArray(e.keyCode, keySplit) > -1){ // If the key the user pressed is matched with any key the developer set a key code with...

            if(typeof callback == 'function'){ //and they provided a callback function
              callback(); //trigger call back and...
              e.preventDefault(); //cancel the normal
            }

          } else { // Else, the key did  not match which means it's either a key combo or just dosn't exist

            // Check if the individual items in the key combo match what was pressed
            for(x in keySplit){
              if($.inArray(e.keyCode, keySplit[x]) > -1){

                // Initiate the active variable
                var active = 'unchecked';

                // All the individual keys in the combo with the keys that are currently being pressed
                for(y in keySplit[x]) {
                  if(active != false) {
                    if($.inArray(keySplit[x][y], activeKeys) > -1){
                      active = true;
                    } else {
                      active = false;
                    }
                  }
                }

                // If all the keys in the combo are being pressed, active will equal true
                if(active === true){
                  if(typeof callback == 'function'){ //and they provided a callback function
                    callback(); //trigger call back and...
                    e.preventDefault(); //cancel the normal
                  }
                }
              }
            }

          } // end of if in array

        }).keyup(function(e) {
          // Remove the current key press
          activeKeys[ e.keyCode ] = '';
        });

    });

  }
})(jQuery);

Ответ 2 · рейтинг 5 · Josh Stodola

Используйте нажатие клавиши вместо keyup/keydown, потому что последние два неточно передают код клавиши (ссылка, см. последний абзац). В этом случае вы можете ссылаться на логические свойства altKey ctrlKey и shiftKey объекта события...

$(document).keypress(function(e) {
  var key = String.fromCharCode(e.which);
  var alt = e.altKey;
  var ctrl = e.ctrlKey
  var shift = e.shiftKey;
  alert("Key:" + key + "\nAlt:" + alt + "\nCtrl:" + ctrl + "\nShift:" + shift);
});

Кроме того, вы можете использовать String.fromCharCode для преобразования кода клавиши в реальную букву.

Вы не можете захватить несколько клавиш, кроме комбинаций с Ctrl, Alt и Shift. Вы просто не можете сделать это в одном мероприятии. Так что выбросьте идею a+s+d+f в окно.

Примечание. Очевидно, что браузер использует определенные комбинации клавиш. Например, Alt + F обычно вызывает меню "Файл" в Windows. Ctrl + N обычно запускает новое окно/вкладку. не пытайтесь переопределить любую из этих комбинаций.

Вот демонстрация для вашего удовольствия.

Ответ 3 · Infotekka

Это просто выстрел в темноту, но, возможно, он поможет вам встать на правильный путь.

Если возможно, чтобы эта функция распознавала шестнадцатеричное значение для введенного вами ключа вместо буквального ключа (например, 0x6E для буквы "n"), вы могли бы получить, что "alt+n" переводится в шестнадцатеричном виде, и иметь функция ищет это значение.

Ответ 4 · рейтинг -1 · Suan

Если вы ищете что-то, что позволит пользователю легко вводить и определять комбинации клавиш с помощью простого поля ввода, я написал плагин, который сделает это за вас: http://suan.github.com/jquery-keycombinator/

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы