keyboard.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // XXX Pressing `?` should display a list of all shortcuts available.
  2. //
  3. // XXX There is no reason to define these shortcuts globally, they should be
  4. // attached to a template (most of them will go in the `board` template).
  5. Mousetrap.bind('w', function() {
  6. Sidebar.toogle();
  7. });
  8. Mousetrap.bind('q', function() {
  9. var currentBoardId = Session.get('currentBoard');
  10. var currentUserId = Meteor.userId();
  11. if (currentBoardId && currentUserId) {
  12. Filter.members.toogle(currentUserId);
  13. }
  14. });
  15. Mousetrap.bind('x', function() {
  16. if (Filter.isActive()) {
  17. Filter.reset();
  18. }
  19. });
  20. Mousetrap.bind(['down', 'up'], function(evt, key) {
  21. if (! Session.get('currentCard')) {
  22. return;
  23. }
  24. var nextFunc = (key === 'down' ? 'next' : 'prev');
  25. var nextCard = $('.js-minicard.is-selected')[nextFunc]('.js-minicard').get(0);
  26. if (nextCard) {
  27. var nextCardId = Blaze.getData(nextCard)._id;
  28. Utils.goCardId(nextCardId);
  29. }
  30. });
  31. // Pressing `Escape` should close the last opened “element” and only the last
  32. // one. Components can register themselves using a label a condition, and an
  33. // action. This is used by Popup or inlinedForm for instance. When we press
  34. // escape we execute the action which have a condition is valid and his the the
  35. // highest in the label hierarchy.
  36. EscapeActions = {
  37. _actions: [],
  38. // Executed in order
  39. hierarchy: [
  40. 'textcomplete',
  41. 'popup',
  42. 'inlinedForm',
  43. 'multiselection-disable',
  44. 'sidebarView',
  45. 'detailsPane',
  46. 'multiselection-reset'
  47. ],
  48. register: function(label, action, condition) {
  49. if (_.isUndefined(condition))
  50. condition = function() { return true; };
  51. // XXX Rewrite this with ES6: .push({ priority, condition, action })
  52. var priority = this.hierarchy.indexOf(label);
  53. if (priority === -1) {
  54. throw Error('You must define the label in the EscapeActions hierarchy');
  55. }
  56. this._actions.push({
  57. priority: priority,
  58. condition: condition,
  59. action: action
  60. });
  61. // XXX Rewrite this with ES6: => function
  62. this._actions = _.sortBy(this._actions, function(a) { return a.priority; });
  63. },
  64. executeLowest: function() {
  65. var topActiveAction = _.find(this._actions, function(a) {
  66. return !! a.condition();
  67. });
  68. return topActiveAction && topActiveAction.action();
  69. },
  70. executeLowerThan: function(label) {
  71. var maxPriority, currentAction;
  72. if (! label)
  73. maxPriority = Infinity;
  74. else
  75. maxPriority = this.hierarchy.indexOf(label);
  76. for (var i = 0; i < this._actions.length; i++) {
  77. currentAction = this._actions[i];
  78. if (currentAction.priority > maxPriority)
  79. return;
  80. if (!! currentAction.condition())
  81. currentAction.action();
  82. }
  83. },
  84. executeAll: function() {
  85. return this.executeLowerThan();
  86. }
  87. };
  88. Mousetrap.bind('esc', function() {
  89. EscapeActions.executeLowest();
  90. });