Merge branch 'hotfix/21.56.9' into master
[gitter.git] / public / js / views / controls / selectable-mixin.js
blob2664b5ef37340775af3eb8af407ccae6137a7404
1 'use strict';
2 var dataset = require('../../utils/dataset-shim');
4 module.exports = (function() {
5   function getContainer(self) {
6     if (self.$childViewContainer) return self.$childViewContainer;
7     return self.$el;
8   }
10   return {
11     events: {
12       keydown: 'selectKeydown',
13       'mouseover li:not(.divider):visible': 'selectMouseOver',
14       'click li': 'selectClicked'
15     },
16     selectMouseOver: function(e) {
17       var $c = getContainer(this);
18       var $items = $c.find('li:not(.divider):visible');
20       if (!$items.length) return;
22       var currentActive = $items.filter('.active');
23       var newActive = e.currentTarget;
25       if (currentActive[0] === newActive) return;
27       currentActive.removeClass('active');
28       newActive.classList.add('active');
29     },
30     selectKeydown: function(e) {
31       switch (e.keyCode) {
32         case 13:
33           this.simulateClick();
34           return;
35         case 38:
36           this.selectPrev();
37           break;
38         case 40:
39           this.selectNext();
40           break;
41         default:
42           return;
43       }
45       e.preventDefault();
46       e.stopPropagation();
47     },
48     selectPrev: function() {
49       this._moveSelect(-1);
50     },
51     selectNext: function() {
52       this._moveSelect(+1);
53     },
54     simulateClick: function() {
55       var $c = getContainer(this);
57       var first = $c.find('li:not(.divider):visible.active').first();
58       if (first.length) {
59         first.trigger('click');
60       } else {
61         this._moveSelect(0);
62         $c.find('li:not(.divider):visible.active')
63           .first()
64           .trigger('click');
65       }
66     },
67     selectActive: function() {
68       this.simulateClick();
69     },
70     selectClicked: function(e) {
71       if (!this.collection) return;
72       var selected = e.currentTarget;
73       var cid = dataset.get(selected, 'cid');
74       var model = this.collection.get(cid);
75       this.setSelected(model);
77       this.trigger('selectClicked');
79       if (!this.options.allowClickPropagation) {
80         e.preventDefault();
81         e.stopPropagation();
82       }
83     },
84     onAddChild: function(childView) {
85       if (this.selectedModel && childView.model.id && childView.model.id == this.selectedModel.id) {
86         childView.$el.addClass('selected');
87       }
88     },
89     setSelected: function(model) {
90       if (this.selectedModel) {
91         this.selectedModel.trigger('unselected');
93         var oldSelectedView = this.children.findByModel(this.selectedModel);
94         if (oldSelectedView) {
95           oldSelectedView.$el.removeClass('selected');
96         }
97       }
99       this.selectedModel = model;
101       if (model) {
102         model.trigger('selected');
103         var selectedView = this.children.findByModel(model);
104         selectedView.$el.addClass('selected');
105       }
106       this.triggerMethod('selected', model);
107     },
108     getActive: function() {
109       var $c = getContainer(this);
110       var $active = $c.find('li.active:not(.divider):visible');
112       var active = $active[0];
113       if (!active) return;
115       var cid = dataset.get(active, 'cid');
116       var model = this.collection.get(cid);
117       return model;
118     },
119     setActive: function(model) {
120       if (!model) return;
122       var activeView = this.children.findByModel(model);
123       if (!activeView) return;
125       /* Already active? */
126       if (activeView.$el.hasClass('active')) return;
128       var $c = getContainer(this);
129       $c.find('li.active:not(.divider):visible').removeClass('active');
131       activeView.$el.addClass('active');
132     },
133     _moveSelect: function(delta) {
134       var $c = getContainer(this);
136       var $items = $c.find('li:not(.divider):visible');
138       if (!$items.length) return;
140       var currentActive = $items.filter('.active');
141       var index = $items.index(currentActive);
142       if (!~index) {
143         index = 0;
144       } else {
145         index = index + delta;
146         if (index < 0) {
147           index = 0;
148         } else if (index >= $items.length) {
149           index = $items.length - 1;
150         }
151       }
153       if (index != currentActive) {
154         var newActive = $items.eq(index);
155         currentActive.removeClass('active');
156         newActive.addClass('active');
157         newActive.addClass('focus');
158       }
159     }
160   };
161 })();