key-combo.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. function KeyCombo(keyComboStr) {
  2. this.sourceStr = keyComboStr;
  3. this.subCombos = KeyCombo.parseComboStr(keyComboStr);
  4. this.keyNames = this.subCombos.reduce(function(memo, nextSubCombo) {
  5. return memo.concat(nextSubCombo);
  6. });
  7. }
  8. // TODO: Add support for key combo sequences
  9. KeyCombo.sequenceDeliminator = '>>';
  10. KeyCombo.comboDeliminator = '>';
  11. KeyCombo.keyDeliminator = '+';
  12. KeyCombo.parseComboStr = function(keyComboStr) {
  13. var subComboStrs = KeyCombo._splitStr(keyComboStr, KeyCombo.comboDeliminator);
  14. var combo = [];
  15. for (var i = 0 ; i < subComboStrs.length; i += 1) {
  16. combo.push(KeyCombo._splitStr(subComboStrs[i], KeyCombo.keyDeliminator));
  17. }
  18. return combo;
  19. };
  20. KeyCombo.prototype.check = function(pressedKeyNames) {
  21. var startingKeyNameIndex = 0;
  22. for (var i = 0; i < this.subCombos.length; i += 1) {
  23. startingKeyNameIndex = this._checkSubCombo(
  24. this.subCombos[i],
  25. startingKeyNameIndex,
  26. pressedKeyNames
  27. );
  28. if (startingKeyNameIndex === -1) { return false; }
  29. }
  30. return true;
  31. };
  32. KeyCombo.prototype.isEqual = function(otherKeyCombo) {
  33. if (
  34. !otherKeyCombo ||
  35. typeof otherKeyCombo !== 'string' &&
  36. typeof otherKeyCombo !== 'object'
  37. ) { return false; }
  38. if (typeof otherKeyCombo === 'string') {
  39. otherKeyCombo = new KeyCombo(otherKeyCombo);
  40. }
  41. if (this.subCombos.length !== otherKeyCombo.subCombos.length) {
  42. return false;
  43. }
  44. for (var i = 0; i < this.subCombos.length; i += 1) {
  45. if (this.subCombos[i].length !== otherKeyCombo.subCombos[i].length) {
  46. return false;
  47. }
  48. }
  49. for (var i = 0; i < this.subCombos.length; i += 1) {
  50. var subCombo = this.subCombos[i];
  51. var otherSubCombo = otherKeyCombo.subCombos[i].slice(0);
  52. for (var j = 0; j < subCombo.length; j += 1) {
  53. var keyName = subCombo[j];
  54. var index = otherSubCombo.indexOf(keyName);
  55. if (index > -1) {
  56. otherSubCombo.splice(index, 1);
  57. }
  58. }
  59. if (otherSubCombo.length !== 0) {
  60. return false;
  61. }
  62. }
  63. return true;
  64. };
  65. KeyCombo._splitStr = function(str, deliminator) {
  66. var s = str;
  67. var d = deliminator;
  68. var c = '';
  69. var ca = [];
  70. for (var ci = 0; ci < s.length; ci += 1) {
  71. if (ci > 0 && s[ci] === d && s[ci - 1] !== '\\') {
  72. ca.push(c.trim());
  73. c = '';
  74. ci += 1;
  75. }
  76. c += s[ci];
  77. }
  78. if (c) { ca.push(c.trim()); }
  79. return ca;
  80. };
  81. KeyCombo.prototype._checkSubCombo = function(subCombo, startingKeyNameIndex, pressedKeyNames) {
  82. subCombo = subCombo.slice(0);
  83. pressedKeyNames = pressedKeyNames.slice(startingKeyNameIndex);
  84. var endIndex = startingKeyNameIndex;
  85. for (var i = 0; i < subCombo.length; i += 1) {
  86. var keyName = subCombo[i];
  87. if (keyName[0] === '\\') {
  88. var escapedKeyName = keyName.slice(1);
  89. if (
  90. escapedKeyName === KeyCombo.comboDeliminator ||
  91. escapedKeyName === KeyCombo.keyDeliminator
  92. ) {
  93. keyName = escapedKeyName;
  94. }
  95. }
  96. var index = pressedKeyNames.indexOf(keyName);
  97. if (index > -1) {
  98. subCombo.splice(i, 1);
  99. i -= 1;
  100. if (index > endIndex) {
  101. endIndex = index;
  102. }
  103. if (subCombo.length === 0) {
  104. return endIndex;
  105. }
  106. }
  107. }
  108. return -1;
  109. };
  110. module.exports = KeyCombo;