angularstrap-rails 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,457 @@
1
+ !function($) {
2
+ var Selectpicker = function(element, options, e) {
3
+ if (e ) {
4
+ e.stopPropagation();
5
+ e.preventDefault();
6
+ }
7
+ this.$element = $(element);
8
+ this.$newElement = null;
9
+ this.button = null;
10
+
11
+ //Merge defaults, options and data-attributes to make our options
12
+ this.options = $.extend({}, $.fn.selectpicker.defaults, this.$element.data(), typeof options == 'object' && options);
13
+
14
+ //If we have no title yet, check the attribute 'title' (this is missed by jq as its not a data-attribute
15
+ if(this.options.title==null)
16
+ this.options.title = this.$element.attr('title');
17
+
18
+ //Expose public methods
19
+ this.val = Selectpicker.prototype.val;
20
+ this.render = Selectpicker.prototype.render;
21
+ this.refresh = Selectpicker.prototype.refresh;
22
+ this.selectAll = Selectpicker.prototype.selectAll;
23
+ this.deselectAll = Selectpicker.prototype.deselectAll;
24
+ this.init();
25
+ };
26
+
27
+ Selectpicker.prototype = {
28
+
29
+ constructor: Selectpicker,
30
+
31
+ init: function (e) {
32
+ if (!this.options.container) {
33
+ this.$element.hide();
34
+ } else {
35
+ this.$element.css('visibility','hidden');
36
+ };
37
+ this.multiple = this.$element.prop('multiple');
38
+ var classList = this.$element.attr('class') !== undefined ? this.$element.attr('class').split(/\s+/) : '';
39
+ var id = this.$element.attr('id');
40
+ this.$element.after( this.createView() );
41
+ this.$newElement = this.$element.next('.bootstrap-select');
42
+ if (this.options.container) {
43
+ this.selectPosition();
44
+ }
45
+ this.button = this.$newElement.find('> button');
46
+ if (id !== undefined) {
47
+ this.button.attr('id', id);
48
+ $('label[for="' + id + '"]').click( $.proxy(this, function(){ this.$newElement.find('button#'+id).focus(); }))
49
+ }
50
+ for (var i = 0; i < classList.length; i++) {
51
+ if(classList[i] != 'selectpicker') {
52
+ this.$newElement.addClass(classList[i]);
53
+ }
54
+ }
55
+ //If we are multiple, then add the show-tick class by default
56
+ if(this.multiple) {
57
+ this.$newElement.addClass('show-tick');
58
+ }
59
+ this.button.addClass(this.options.style);
60
+ this.checkDisabled();
61
+ this.checkTabIndex();
62
+ this.clickListener();
63
+
64
+ //Listen for updates to the DOM and re render...
65
+ this.$element.bind('DOMNodeInserted DOMNodeRemoved', $.proxy(this.refresh, this));
66
+
67
+ this.render();
68
+ this.setSize();
69
+ },
70
+
71
+ createDropdown: function() {
72
+ var drop =
73
+ "<div class='btn-group bootstrap-select'>" +
74
+ "<button class='btn dropdown-toggle clearfix' data-toggle='dropdown'>" +
75
+ "<span class='filter-option pull-left'></span>&nbsp;" +
76
+ "<span class='caret'></span>" +
77
+ "</button>" +
78
+ "<ul class='dropdown-menu' role='menu'>" +
79
+ "</ul>" +
80
+ "</div>";
81
+
82
+ return $(drop);
83
+ },
84
+
85
+
86
+ createView: function() {
87
+ var $drop = this.createDropdown();
88
+ var $li = this.createLi();
89
+ $drop.find('ul').append($li);
90
+ return $drop;
91
+ },
92
+
93
+ reloadLi: function() {
94
+ //Remove all children.
95
+ this.destroyLi();
96
+ //Re build
97
+ $li = this.createLi();
98
+ this.$newElement.find('ul').append( $li );
99
+ },
100
+
101
+ destroyLi:function() {
102
+ this.$newElement.find('li').remove();
103
+ },
104
+
105
+ createLi: function() {
106
+
107
+ var _this = this;
108
+ var _li = [];
109
+ var _liA = [];
110
+ var _liHtml = '';
111
+
112
+ this.$element.find('option').each(function(){
113
+ _li.push($(this).text());
114
+ });
115
+
116
+ this.$element.find('option').each(function(index) {
117
+ //Get the class and text for the option
118
+ var optionClass = $(this).attr("class") !== undefined ? $(this).attr("class") : '';
119
+ var text = $(this).text();
120
+ var subtext = $(this).data('subtext') !== undefined ? '<small class="muted">'+$(this).data('subtext')+'</small>' : '';
121
+
122
+ //Append any subtext to the main text.
123
+ text+=subtext;
124
+
125
+ if ($(this).parent().is('optgroup') && $(this).data('divider') != true) {
126
+ if ($(this).index() == 0) {
127
+ //Get the opt group label
128
+ var label = $(this).parent().attr('label');
129
+ var labelSubtext = $(this).parent().data('subtext') !== undefined ? '<small class="muted">'+$(this).parent().data('subtext')+'</small>' : '';
130
+ label += labelSubtext;
131
+
132
+ if ($(this)[0].index != 0) {
133
+ _liA.push(
134
+ '<div class="div-contain"><div class="divider"></div></div>'+
135
+ '<dt>'+label+'</dt>'+
136
+ _this.createA(text, "opt " + optionClass )
137
+ );
138
+ } else {
139
+ _liA.push(
140
+ '<dt>'+label+'</dt>'+
141
+ _this.createA(text, "opt " + optionClass ));
142
+ }
143
+ } else {
144
+ _liA.push( _this.createA(text, "opt " + optionClass ) );
145
+ }
146
+ } else if ($(this).data('divider') == true) {
147
+ _liA.push('<div class="div-contain"><div class="divider"></div></div>');
148
+ } else {
149
+ _liA.push( _this.createA(text, optionClass ) );
150
+ }
151
+ });
152
+
153
+ if (_li.length > 0) {
154
+ for (var i = 0; i < _li.length; i++) {
155
+ var $option = this.$element.find('option').eq(i);
156
+ _liHtml += "<li rel=" + i + ">" + _liA[i] + "</li>";
157
+ }
158
+ }
159
+
160
+ //If we dont have a selected item, and we dont have a title, select the first element so something is set in the button
161
+ if(this.$element.find('option:selected').length==0 && !_this.options.title) {
162
+ this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
163
+ }
164
+
165
+ return $(_liHtml);
166
+ },
167
+
168
+ createA:function(test, classes) {
169
+ return '<a tabindex="-1" href="#" class="'+classes+'">' +
170
+ '<span class="pull-left">' + test + '</span>' +
171
+ '<i class="icon-ok check-mark"></i>' +
172
+ '</a>';
173
+
174
+ },
175
+
176
+ render:function() {
177
+ var _this = this;
178
+
179
+ //Update the LI to match the SELECT
180
+ this.$element.find('option').each(function(index) {
181
+ _this.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled') );
182
+ _this.setSelected(index, $(this).is(':selected') );
183
+ });
184
+
185
+ var selectedItems = this.$element.find('option:selected').map(function(index,value) {
186
+ if($(this).attr('title')!=undefined) {
187
+ return $(this).attr('title');
188
+ } else {
189
+ return $(this).text();
190
+ }
191
+ }).toArray();
192
+
193
+ //Convert all the values into a comma delimited string
194
+ var title = selectedItems.join(", ");
195
+
196
+ //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..
197
+ if(_this.multiple && _this.options.selectedTextFormat.indexOf('count') > -1) {
198
+ var max = _this.options.selectedTextFormat.split(">");
199
+ if( (max.length>1 && selectedItems.length > max[1]) || (max.length==1 && selectedItems.length>=2)) {
200
+ title = selectedItems.length +' of ' + this.$element.find('option').length + ' selected';
201
+ }
202
+ }
203
+
204
+ //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
205
+ if(!title) {
206
+ title = _this.options.title != undefined ? _this.options.title : _this.options.noneSelectedText;
207
+ }
208
+
209
+ _this.$newElement.find('.filter-option').html( title );
210
+ },
211
+
212
+ setSize:function() {
213
+ var _this = this;
214
+ var menu = this.$newElement.find('.dropdown-menu');
215
+ var menuA = menu.find('li > a');
216
+ var liHeight = this.$newElement.addClass('open').find('.dropdown-menu li > a').outerHeight();
217
+ this.$newElement.removeClass('open');
218
+ var divHeight = menu.find('li .divider').outerHeight(true);
219
+ var selectOffset_top = this.$newElement.offset().top;
220
+ var selectHeight = this.$newElement.outerHeight();
221
+ var menuPadding = parseInt(menu.css('padding-top')) + parseInt(menu.css('padding-bottom')) + parseInt(menu.css('border-top-width')) + parseInt(menu.css('border-bottom-width'));
222
+ if (this.options.size == 'auto') {
223
+ function getSize() {
224
+ var selectOffset_top_scroll = selectOffset_top - $(window).scrollTop();
225
+ var windowHeight = window.innerHeight;
226
+ var menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2;
227
+ var selectOffset_bot = windowHeight - selectOffset_top_scroll - selectHeight - menuExtras;
228
+ menuHeight = selectOffset_bot;
229
+ if (_this.$newElement.hasClass('dropup')) {
230
+ menuHeight = selectOffset_top_scroll - menuExtras;
231
+ }
232
+ if ((menu.find('li').length + menu.find('dt').length) > 3) {
233
+ minHeight = liHeight*3 + menuExtras - 2;
234
+ } else {
235
+ minHeight = 0;
236
+ }
237
+ menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'auto', 'min-height' : minHeight + 'px'});
238
+ }
239
+ getSize();
240
+ $(window).resize(getSize);
241
+ $(window).scroll(getSize);
242
+ } else if (this.options.size && this.options.size != 'auto' && menu.find('li').length > this.options.size) {
243
+ var optIndex = menu.find("li > *").filter(':not(.div-contain)').slice(0,this.options.size).last().parent().index();
244
+ var divLength = menu.find("li").slice(0,optIndex + 1).find('.div-contain').length;
245
+ menuHeight = liHeight*this.options.size + divLength*divHeight + menuPadding;
246
+ menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'auto'});
247
+ }
248
+
249
+ //Set width of select
250
+ if (this.options.width == 'auto') {
251
+ this.$newElement.find('.dropdown-menu').css('min-width','0');
252
+ var ulWidth = this.$newElement.find('.dropdown-menu').css('width');
253
+ this.$newElement.css('width',ulWidth);
254
+ if (this.options.container) {
255
+ this.$element.css('width',ulWidth);
256
+ }
257
+ } else if (this.options.width && this.options.width != 'auto') {
258
+ this.$newElement.css('width',this.options.width);
259
+ if (this.options.container) {
260
+ this.$element.css('width',this.options.width);
261
+ }
262
+ }
263
+ },
264
+
265
+ selectPosition:function() {
266
+ var selectElementTop = this.$element.offset().top;
267
+ var selectElementLeft = this.$element.offset().left;
268
+ this.$newElement.appendTo(this.options.container);
269
+ this.$newElement.css({'position':'absolute', 'top':selectElementTop+'px', 'left':selectElementLeft+'px'});
270
+ },
271
+
272
+ refresh:function() {
273
+ this.reloadLi();
274
+ this.render();
275
+ this.setSize();
276
+ this.checkDisabled();
277
+ if (this.options.container) {
278
+ this.selectPosition();
279
+ }
280
+ },
281
+
282
+ setSelected:function(index, selected) {
283
+ if(selected) {
284
+ this.$newElement.find('li').eq(index).addClass('selected');
285
+ } else {
286
+ this.$newElement.find('li').eq(index).removeClass('selected');
287
+ }
288
+ },
289
+
290
+ setDisabled:function(index, disabled) {
291
+ if(disabled) {
292
+ this.$newElement.find('li').eq(index).addClass('disabled');
293
+ } else {
294
+ this.$newElement.find('li').eq(index).removeClass('disabled');
295
+ }
296
+ },
297
+
298
+ checkDisabled: function() {
299
+ if (this.$element.is(':disabled')) {
300
+ this.button.addClass('disabled');
301
+ this.button.click(function(e) {
302
+ e.preventDefault();
303
+ });
304
+ this.button.on('focusin', function() {
305
+ $(this).blur();
306
+ });
307
+ } else if (!this.$element.is(':disabled') && this.button.hasClass('disabled')) {
308
+ this.button.removeClass('disabled');
309
+ this.button.click(function() {
310
+ return true;
311
+ });
312
+ }
313
+ },
314
+
315
+ checkTabIndex: function() {
316
+ if (this.$element.is('[tabindex]')) {
317
+ var tabindex = this.$element.attr("tabindex");
318
+ this.button.attr('tabindex', tabindex);
319
+ }
320
+ },
321
+
322
+ clickListener: function() {
323
+ var _this = this;
324
+
325
+ $('body').on('touchstart.dropdown', '.dropdown-menu', function (e) { e.stopPropagation(); });
326
+
327
+ this.$newElement.on('click', 'li a', function(e){
328
+ var clickedIndex = $(this).parent().index(),
329
+ $this = $(this).parent(),
330
+ $select = $this.parents('.bootstrap-select'),
331
+ prevValue = _this.$element.val();
332
+
333
+ //Dont close on multi choice menu
334
+ if(_this.multiple) {
335
+ e.stopPropagation();
336
+ }
337
+
338
+ e.preventDefault();
339
+
340
+ //Dont run if we have been disabled
341
+ if (_this.$element.not(':disabled') && !$(this).parent().hasClass('disabled')){
342
+ //Deselect all others if not multi select box
343
+ if (!_this.multiple) {
344
+ _this.$element.find('option').removeAttr('selected');
345
+ _this.$element.find('option').eq(clickedIndex).prop('selected', true).attr('selected', 'selected');
346
+ }
347
+ //Else toggle the one we have chosen if we are multi selet.
348
+ else {
349
+ var selected = _this.$element.find('option').eq(clickedIndex).prop('selected');
350
+
351
+ if(selected) {
352
+ _this.$element.find('option').eq(clickedIndex).removeAttr('selected');
353
+ } else {
354
+ _this.$element.find('option').eq(clickedIndex).prop('selected', true).attr('selected', 'selected');
355
+ }
356
+ }
357
+
358
+
359
+ $select.find('.filter-option').html($this.text());
360
+ $select.find('button').focus();
361
+
362
+ // Trigger select 'change'
363
+ if (prevValue != _this.$element.val()) {
364
+ _this.$element.trigger('change');
365
+ }
366
+
367
+ _this.render();
368
+ }
369
+
370
+ });
371
+
372
+ this.$newElement.on('click', 'li.disabled a, li dt, li .div-contain', function(e) {
373
+ e.preventDefault();
374
+ e.stopPropagation();
375
+ $select = $(this).parent().parents('.bootstrap-select');
376
+ $select.find('button').focus();
377
+ });
378
+
379
+ this.$element.on('change', function(e) {
380
+ _this.render();
381
+ });
382
+ },
383
+
384
+ val:function(value) {
385
+
386
+ if(value!=undefined) {
387
+ this.$element.val( value );
388
+
389
+ this.$element.trigger('change');
390
+ return this.$element;
391
+ } else {
392
+ return this.$element.val();
393
+ }
394
+ },
395
+
396
+ selectAll:function() {
397
+ this.$element.find('option').prop('selected', true).attr('selected', 'selected');
398
+ this.render();
399
+ },
400
+
401
+ deselectAll:function() {
402
+ this.$element.find('option').prop('selected', false).removeAttr('selected');
403
+ this.render();
404
+ },
405
+
406
+ };
407
+
408
+ $.fn.selectpicker = function(option, event) {
409
+ //get the args of the outer function..
410
+ var args = arguments;
411
+ var value;
412
+ var chain = this.each(function () {
413
+ if ($(this).is('select')) {
414
+ var $this = $(this),
415
+ data = $this.data('selectpicker'),
416
+ options = typeof option == 'object' && option;
417
+
418
+ if (!data) {
419
+ $this.data('selectpicker', (data = new Selectpicker(this, options, event)));
420
+ } else if(options){
421
+ for(var i in options) {
422
+ data.options[i]=options[i];
423
+ }
424
+ }
425
+
426
+ if (typeof option == 'string') {
427
+ //Copy the value of option, as once we shift the arguments
428
+ //it also shifts the value of option.
429
+ property = option;
430
+ if(data[property] instanceof Function) {
431
+ [].shift.apply(args);
432
+ value = data[property].apply(data, args);
433
+ } else {
434
+ value = data.options[property];
435
+ }
436
+ }
437
+ }
438
+ });
439
+
440
+ if(value!=undefined) {
441
+ return value;
442
+ } else {
443
+ return chain;
444
+ }
445
+ };
446
+
447
+ $.fn.selectpicker.defaults = {
448
+ style: null,
449
+ size: 'auto',
450
+ title: null,
451
+ selectedTextFormat : 'values',
452
+ noneSelectedText : 'Nothing selected',
453
+ width: null,
454
+ container: false
455
+ }
456
+
457
+ }(window.jQuery);