multiSelection.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. var getCardsBetween = function(idA, idB) {
  2. var pluckId = function(doc) {
  3. return doc._id;
  4. };
  5. var getListsStrictlyBetween = function(id1, id2) {
  6. return Lists.find({
  7. $and: [
  8. { sort: { $gt: Lists.findOne(id1).sort } },
  9. { sort: { $lt: Lists.findOne(id2).sort } }
  10. ],
  11. archived: false
  12. }).map(pluckId);
  13. };
  14. var cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], function(c) {
  15. return c.sort;
  16. });
  17. var selector;
  18. if (cards[0].listId === cards[1].listId) {
  19. selector = {
  20. listId: cards[0].listId,
  21. sort: {
  22. $gte: cards[0].sort,
  23. $lte: cards[1].sort
  24. },
  25. archived: false
  26. };
  27. } else {
  28. selector = {
  29. $or: [{
  30. listId: cards[0].listId,
  31. sort: { $lte: cards[0].sort }
  32. }, {
  33. listId: {
  34. $in: getListsStrictlyBetween(cards[0].listId, cards[1].listId)
  35. }
  36. }, {
  37. listId: cards[1].listId,
  38. sort: { $gte: cards[1].sort }
  39. }],
  40. archived: false
  41. };
  42. }
  43. return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
  44. };
  45. MultiSelection = {
  46. sidebarView: 'multiselection',
  47. _selectedCards: new ReactiveVar([]),
  48. _isActive: new ReactiveVar(false),
  49. startRangeCardId: null,
  50. reset: function() {
  51. this._selectedCards.set([]);
  52. },
  53. getMongoSelector: function() {
  54. return Filter.mongoSelector({
  55. _id: { $in: this._selectedCards.get() }
  56. });
  57. },
  58. isActive: function() {
  59. return this._isActive.get();
  60. },
  61. count: function() {
  62. return Cards.find(this.getMongoSelector()).count();
  63. },
  64. isEmpty: function() {
  65. return this.count() === 0;
  66. },
  67. activate: function() {
  68. if (! this.isActive()) {
  69. EscapeActions.executeUpTo('detailsPane');
  70. this._isActive.set(true);
  71. Tracker.flush();
  72. }
  73. Sidebar.setView(this.sidebarView);
  74. },
  75. disable: function() {
  76. if (this.isActive()) {
  77. this._isActive.set(false);
  78. if (Sidebar && Sidebar.getView() === this.sidebarView) {
  79. Sidebar.setView();
  80. }
  81. this.reset();
  82. }
  83. },
  84. add: function(cardIds) {
  85. return this.toogle(cardIds, { add: true, remove: false });
  86. },
  87. remove: function(cardIds) {
  88. return this.toogle(cardIds, { add: false, remove: true });
  89. },
  90. toogleRange: function(cardId) {
  91. var selectedCards = this._selectedCards.get();
  92. var startRange;
  93. this.reset();
  94. if (! this.isActive() || selectedCards.length === 0) {
  95. this.toogle(cardId);
  96. } else {
  97. startRange = selectedCards[selectedCards.length - 1];
  98. this.toogle(getCardsBetween(startRange, cardId));
  99. }
  100. },
  101. toogle: function(cardIds, options) {
  102. var self = this;
  103. cardIds = _.isString(cardIds) ? [cardIds] : cardIds;
  104. options = _.extend({
  105. add: true,
  106. remove: true
  107. }, options || {});
  108. if (! self.isActive()) {
  109. self.reset();
  110. self.activate();
  111. }
  112. var selectedCards = self._selectedCards.get();
  113. _.each(cardIds, function(cardId) {
  114. var indexOfCard = selectedCards.indexOf(cardId);
  115. if (options.remove && indexOfCard > -1)
  116. selectedCards.splice(indexOfCard, 1);
  117. else if (options.add)
  118. selectedCards.push(cardId);
  119. });
  120. self._selectedCards.set(selectedCards);
  121. },
  122. isSelected: function(cardId) {
  123. return this._selectedCards.get().indexOf(cardId) > -1;
  124. }
  125. };
  126. Blaze.registerHelper('MultiSelection', MultiSelection);
  127. EscapeActions.register('multiselection',
  128. function() { MultiSelection.disable(); },
  129. function() { return MultiSelection.isActive(); }, {
  130. noClickEscapeOn: '.js-minicard,.js-board-sidebar-content'
  131. }
  132. );