fae-rails 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,532 @@
1
+ /*
2
+ * MultiSelect v0.9.11
3
+ * Copyright (c) 2012 Louis Cuny
4
+ *
5
+ * This program is free software. It comes without any warranty, to
6
+ * the extent permitted by applicable law. You can redistribute it
7
+ * and/or modify it under the terms of the Do What The Fuck You Want
8
+ * To Public License, Version 2, as published by Sam Hocevar. See
9
+ * http://sam.zoy.org/wtfpl/COPYING for more details.
10
+ */
11
+
12
+ !function ($) {
13
+
14
+ "use strict";
15
+
16
+
17
+ /* MULTISELECT CLASS DEFINITION
18
+ * ====================== */
19
+
20
+ var MultiSelect = function (element, options) {
21
+ this.options = options;
22
+ this.$element = $(element);
23
+ this.$container = $('<div/>', { 'class': "ms-container" });
24
+ this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });
25
+ this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });
26
+ this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
27
+ this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
28
+ this.scrollTo = 0;
29
+ this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';
30
+ };
31
+
32
+ MultiSelect.prototype = {
33
+ constructor: MultiSelect,
34
+
35
+ init: function(){
36
+ var that = this,
37
+ ms = this.$element;
38
+
39
+ if (ms.next('.ms-container').length === 0){
40
+ ms.css({ position: 'absolute', left: '-9999px' });
41
+ ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
42
+ this.$container.attr('id', 'ms-'+ms.attr('id'));
43
+ this.$container.addClass(that.options.cssClass);
44
+ ms.find('option').each(function(){
45
+ that.generateLisFromOption(this);
46
+ });
47
+
48
+ this.$selectionUl.find('.ms-optgroup-label').hide();
49
+
50
+ if (that.options.selectableHeader){
51
+ that.$selectableContainer.append(that.options.selectableHeader);
52
+ }
53
+ that.$selectableContainer.append(that.$selectableUl);
54
+ if (that.options.selectableFooter){
55
+ that.$selectableContainer.append(that.options.selectableFooter);
56
+ }
57
+
58
+ if (that.options.selectionHeader){
59
+ that.$selectionContainer.append(that.options.selectionHeader);
60
+ }
61
+ that.$selectionContainer.append(that.$selectionUl);
62
+ if (that.options.selectionFooter){
63
+ that.$selectionContainer.append(that.options.selectionFooter);
64
+ }
65
+
66
+ that.$container.append(that.$selectableContainer);
67
+ that.$container.append(that.$selectionContainer);
68
+ ms.after(that.$container);
69
+
70
+ that.activeMouse(that.$selectableUl);
71
+ that.activeKeyboard(that.$selectableUl);
72
+
73
+ var action = that.options.dblClick ? 'dblclick' : 'click';
74
+
75
+ that.$selectableUl.on(action, '.ms-elem-selectable', function(){
76
+ that.select($(this).data('ms-value'));
77
+ });
78
+ that.$selectionUl.on(action, '.ms-elem-selection', function(){
79
+ that.deselect($(this).data('ms-value'));
80
+ });
81
+
82
+ that.activeMouse(that.$selectionUl);
83
+ that.activeKeyboard(that.$selectionUl);
84
+
85
+ ms.on('focus', function(){
86
+ that.$selectableUl.focus();
87
+ })
88
+ }
89
+
90
+ var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();
91
+ that.select(selectedValues, 'init');
92
+
93
+ if (typeof that.options.afterInit === 'function') {
94
+ that.options.afterInit.call(this, this.$container);
95
+ }
96
+ },
97
+
98
+ 'generateLisFromOption' : function(option, index, $container){
99
+ var that = this,
100
+ ms = that.$element,
101
+ attributes = "",
102
+ $option = $(option);
103
+
104
+ for (var cpt = 0; cpt < option.attributes.length; cpt++){
105
+ var attr = option.attributes[cpt];
106
+
107
+ if(attr.name !== 'value' && attr.name !== 'disabled'){
108
+ attributes += attr.name+'="'+attr.value+'" ';
109
+ }
110
+ }
111
+ var selectableLi = $('<li '+attributes+'><span>'+that.escapeHTML($option.text())+'</span></li>'),
112
+ selectedLi = selectableLi.clone(),
113
+ value = $option.val(),
114
+ elementId = that.sanitize(value);
115
+
116
+ selectableLi
117
+ .data('ms-value', value)
118
+ .addClass('ms-elem-selectable')
119
+ .attr('id', elementId+'-selectable');
120
+
121
+ selectedLi
122
+ .data('ms-value', value)
123
+ .addClass('ms-elem-selection')
124
+ .attr('id', elementId+'-selection')
125
+ .hide();
126
+
127
+ if ($option.prop('disabled') || ms.prop('disabled')){
128
+ selectedLi.addClass(that.options.disabledClass);
129
+ selectableLi.addClass(that.options.disabledClass);
130
+ }
131
+
132
+ var $optgroup = $option.parent('optgroup');
133
+
134
+ if ($optgroup.length > 0){
135
+ var optgroupLabel = $optgroup.attr('label'),
136
+ optgroupId = that.sanitize(optgroupLabel),
137
+ $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
138
+ $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
139
+
140
+ if ($selectableOptgroup.length === 0){
141
+ var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',
142
+ optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';
143
+
144
+ $selectableOptgroup = $(optgroupContainerTpl);
145
+ $selectionOptgroup = $(optgroupContainerTpl);
146
+ $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);
147
+ $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);
148
+ $selectableOptgroup.append($(optgroupTpl));
149
+ $selectionOptgroup.append($(optgroupTpl));
150
+ if (that.options.selectableOptgroup){
151
+ $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){
152
+ var values = $optgroup.children(':not(:selected, :disabled)').map(function(){ return $(this).val() }).get();
153
+ that.select(values);
154
+ });
155
+ $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){
156
+ var values = $optgroup.children(':selected:not(:disabled)').map(function(){ return $(this).val() }).get();
157
+ that.deselect(values);
158
+ });
159
+ }
160
+ that.$selectableUl.append($selectableOptgroup);
161
+ that.$selectionUl.append($selectionOptgroup);
162
+ }
163
+ index = index == undefined ? $selectableOptgroup.find('ul').children().length : index + 1;
164
+ selectableLi.insertAt(index, $selectableOptgroup.children());
165
+ selectedLi.insertAt(index, $selectionOptgroup.children());
166
+ } else {
167
+ index = index == undefined ? that.$selectableUl.children().length : index;
168
+
169
+ selectableLi.insertAt(index, that.$selectableUl);
170
+ selectedLi.insertAt(index, that.$selectionUl);
171
+ }
172
+ },
173
+
174
+ 'addOption' : function(options){
175
+ var that = this;
176
+
177
+ if (options.value) options = [options];
178
+ $.each(options, function(index, option){
179
+ if (option.value && that.$element.find("option[value='"+option.value+"']").length === 0){
180
+ var $option = $('<option value="'+option.value+'">'+option.text+'</option>'),
181
+ index = parseInt((typeof option.index === 'undefined' ? that.$element.children().length : option.index)),
182
+ $container = option.nested == undefined ? that.$element : $("optgroup[label='"+option.nested+"']")
183
+
184
+ $option.insertAt(index, $container);
185
+ that.generateLisFromOption($option.get(0), index, option.nested);
186
+ }
187
+ })
188
+ },
189
+
190
+ 'escapeHTML' : function(text){
191
+ return $("<div>").text(text).html();
192
+ },
193
+
194
+ 'activeKeyboard' : function($list){
195
+ var that = this;
196
+
197
+ $list.on('focus', function(){
198
+ $(this).addClass('ms-focus');
199
+ })
200
+ .on('blur', function(){
201
+ $(this).removeClass('ms-focus');
202
+ })
203
+ .on('keydown', function(e){
204
+ switch (e.which) {
205
+ case 40:
206
+ case 38:
207
+ e.preventDefault();
208
+ e.stopPropagation();
209
+ that.moveHighlight($(this), (e.which === 38) ? -1 : 1);
210
+ return;
211
+ case 37:
212
+ case 39:
213
+ e.preventDefault();
214
+ e.stopPropagation();
215
+ that.switchList($list);
216
+ return;
217
+ case 9:
218
+ if(that.$element.is('[tabindex]')){
219
+ e.preventDefault();
220
+ var tabindex = parseInt(that.$element.attr('tabindex'), 10);
221
+ tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1;
222
+ $('[tabindex="'+(tabindex)+'"]').focus();
223
+ return;
224
+ }else{
225
+ if(e.shiftKey){
226
+ that.$element.trigger('focus');
227
+ }
228
+ }
229
+ }
230
+ if($.inArray(e.which, that.options.keySelect) > -1){
231
+ e.preventDefault();
232
+ e.stopPropagation();
233
+ that.selectHighlighted($list);
234
+ return;
235
+ }
236
+ });
237
+ },
238
+
239
+ 'moveHighlight': function($list, direction){
240
+ var $elems = $list.find(this.elemsSelector),
241
+ $currElem = $elems.filter('.ms-hover'),
242
+ $nextElem = null,
243
+ elemHeight = $elems.first().outerHeight(),
244
+ containerHeight = $list.height(),
245
+ containerSelector = '#'+this.$container.prop('id');
246
+
247
+ $elems.removeClass('ms-hover');
248
+ if (direction === 1){ // DOWN
249
+
250
+ $nextElem = $currElem.nextAll(this.elemsSelector).first();
251
+ if ($nextElem.length === 0){
252
+ var $optgroupUl = $currElem.parent();
253
+
254
+ if ($optgroupUl.hasClass('ms-optgroup')){
255
+ var $optgroupLi = $optgroupUl.parent(),
256
+ $nextOptgroupLi = $optgroupLi.next(':visible');
257
+
258
+ if ($nextOptgroupLi.length > 0){
259
+ $nextElem = $nextOptgroupLi.find(this.elemsSelector).first();
260
+ } else {
261
+ $nextElem = $elems.first();
262
+ }
263
+ } else {
264
+ $nextElem = $elems.first();
265
+ }
266
+ }
267
+ } else if (direction === -1){ // UP
268
+
269
+ $nextElem = $currElem.prevAll(this.elemsSelector).first();
270
+ if ($nextElem.length === 0){
271
+ var $optgroupUl = $currElem.parent();
272
+
273
+ if ($optgroupUl.hasClass('ms-optgroup')){
274
+ var $optgroupLi = $optgroupUl.parent(),
275
+ $prevOptgroupLi = $optgroupLi.prev(':visible');
276
+
277
+ if ($prevOptgroupLi.length > 0){
278
+ $nextElem = $prevOptgroupLi.find(this.elemsSelector).last();
279
+ } else {
280
+ $nextElem = $elems.last();
281
+ }
282
+ } else {
283
+ $nextElem = $elems.last();
284
+ }
285
+ }
286
+ }
287
+ if ($nextElem.length > 0){
288
+ $nextElem.addClass('ms-hover');
289
+ var scrollTo = $list.scrollTop() + $nextElem.position().top -
290
+ containerHeight / 2 + elemHeight / 2;
291
+
292
+ $list.scrollTop(scrollTo);
293
+ }
294
+ },
295
+
296
+ 'selectHighlighted' : function($list){
297
+ var $elems = $list.find(this.elemsSelector),
298
+ $highlightedElem = $elems.filter('.ms-hover').first();
299
+
300
+ if ($highlightedElem.length > 0){
301
+ if ($list.parent().hasClass('ms-selectable')){
302
+ this.select($highlightedElem.data('ms-value'));
303
+ } else {
304
+ this.deselect($highlightedElem.data('ms-value'));
305
+ }
306
+ $elems.removeClass('ms-hover');
307
+ }
308
+ },
309
+
310
+ 'switchList' : function($list){
311
+ $list.blur();
312
+ this.$container.find(this.elemsSelector).removeClass('ms-hover');
313
+ if ($list.parent().hasClass('ms-selectable')){
314
+ this.$selectionUl.focus();
315
+ } else {
316
+ this.$selectableUl.focus();
317
+ }
318
+ },
319
+
320
+ 'activeMouse' : function($list){
321
+ var that = this;
322
+
323
+ $('body').on('mouseenter', that.elemsSelector, function(){
324
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');
325
+ $(this).addClass('ms-hover');
326
+ });
327
+
328
+ $('body').on('mouseleave', that.elemsSelector, function () {
329
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');;
330
+ });
331
+ },
332
+
333
+ 'refresh' : function() {
334
+ this.destroy();
335
+ this.$element.multiSelect(this.options);
336
+ },
337
+
338
+ 'destroy' : function(){
339
+ $("#ms-"+this.$element.attr("id")).remove();
340
+ this.$element.css('position', '').css('left', '')
341
+ this.$element.removeData('multiselect');
342
+ },
343
+
344
+ 'select' : function(value, method){
345
+ if (typeof value === 'string'){ value = [value]; }
346
+
347
+ var that = this,
348
+ ms = this.$element,
349
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
350
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
351
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
352
+ options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
353
+
354
+ if (method === 'init'){
355
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
356
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection');
357
+ }
358
+
359
+ if (selectables.length > 0){
360
+ selectables.addClass('ms-selected').hide();
361
+ selections.addClass('ms-selected').show();
362
+
363
+ options.prop('selected', true);
364
+
365
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
366
+
367
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
368
+ if (selectableOptgroups.length > 0){
369
+ selectableOptgroups.each(function(){
370
+ var selectablesLi = $(this).find('.ms-elem-selectable');
371
+ if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){
372
+ $(this).find('.ms-optgroup-label').hide();
373
+ }
374
+ });
375
+
376
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
377
+ selectionOptgroups.each(function(){
378
+ var selectionsLi = $(this).find('.ms-elem-selection');
379
+ if (selectionsLi.filter('.ms-selected').length > 0){
380
+ $(this).find('.ms-optgroup-label').show();
381
+ }
382
+ });
383
+ } else {
384
+ if (that.options.keepOrder && method !== 'init'){
385
+ var selectionLiLast = that.$selectionUl.find('.ms-selected');
386
+ if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {
387
+ selections.insertAfter(selectionLiLast.last());
388
+ }
389
+ }
390
+ }
391
+ if (method !== 'init'){
392
+ ms.trigger('change');
393
+ if (typeof that.options.afterSelect === 'function') {
394
+ that.options.afterSelect.call(this, value);
395
+ }
396
+ }
397
+ }
398
+ },
399
+
400
+ 'deselect' : function(value){
401
+ if (typeof value === 'string'){ value = [value]; }
402
+
403
+ var that = this,
404
+ ms = this.$element,
405
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
406
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
407
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'),
408
+ options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
409
+
410
+ if (selections.length > 0){
411
+ selectables.removeClass('ms-selected').show();
412
+ selections.removeClass('ms-selected').hide();
413
+ options.prop('selected', false);
414
+
415
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
416
+
417
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
418
+ if (selectableOptgroups.length > 0){
419
+ selectableOptgroups.each(function(){
420
+ var selectablesLi = $(this).find('.ms-elem-selectable');
421
+ if (selectablesLi.filter(':not(.ms-selected)').length > 0){
422
+ $(this).find('.ms-optgroup-label').show();
423
+ }
424
+ });
425
+
426
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
427
+ selectionOptgroups.each(function(){
428
+ var selectionsLi = $(this).find('.ms-elem-selection');
429
+ if (selectionsLi.filter('.ms-selected').length === 0){
430
+ $(this).find('.ms-optgroup-label').hide();
431
+ }
432
+ });
433
+ }
434
+ ms.trigger('change');
435
+ if (typeof that.options.afterDeselect === 'function') {
436
+ that.options.afterDeselect.call(this, value);
437
+ }
438
+ }
439
+ },
440
+
441
+ 'select_all' : function(){
442
+ var ms = this.$element,
443
+ values = ms.val();
444
+
445
+ ms.find('option:not(":disabled")').prop('selected', true);
446
+ this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();
447
+ this.$selectionUl.find('.ms-optgroup-label').show();
448
+ this.$selectableUl.find('.ms-optgroup-label').hide();
449
+ this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();
450
+ this.$selectionUl.focus();
451
+ ms.trigger('change');
452
+ if (typeof this.options.afterSelect === 'function') {
453
+ var selectedValues = $.grep(ms.val(), function(item){
454
+ return $.inArray(item, values) < 0;
455
+ });
456
+ this.options.afterSelect.call(this, selectedValues);
457
+ }
458
+ },
459
+
460
+ 'deselect_all' : function(){
461
+ var ms = this.$element,
462
+ values = ms.val();
463
+
464
+ ms.find('option').prop('selected', false);
465
+ this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
466
+ this.$selectionUl.find('.ms-optgroup-label').hide();
467
+ this.$selectableUl.find('.ms-optgroup-label').show();
468
+ this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
469
+ this.$selectableUl.focus();
470
+ ms.trigger('change');
471
+ if (typeof this.options.afterDeselect === 'function') {
472
+ this.options.afterDeselect.call(this, values);
473
+ }
474
+ },
475
+
476
+ sanitize: function(value){
477
+ var hash = 0, i, character;
478
+ if (value.length == 0) return hash;
479
+ var ls = 0;
480
+ for (i = 0, ls = value.length; i < ls; i++) {
481
+ character = value.charCodeAt(i);
482
+ hash = ((hash<<5)-hash)+character;
483
+ hash |= 0; // Convert to 32bit integer
484
+ }
485
+ return hash;
486
+ }
487
+ };
488
+
489
+ /* MULTISELECT PLUGIN DEFINITION
490
+ * ======================= */
491
+
492
+ $.fn.multiSelect = function () {
493
+ var option = arguments[0],
494
+ args = arguments;
495
+
496
+ return this.each(function () {
497
+ var $this = $(this),
498
+ data = $this.data('multiselect'),
499
+ options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);
500
+
501
+ if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }
502
+
503
+ if (typeof option === 'string'){
504
+ data[option](args[1]);
505
+ } else {
506
+ data.init();
507
+ }
508
+ });
509
+ };
510
+
511
+ $.fn.multiSelect.defaults = {
512
+ keySelect: [32],
513
+ selectableOptgroup: false,
514
+ disabledClass : 'disabled',
515
+ dblClick : false,
516
+ keepOrder: false,
517
+ cssClass: ''
518
+ };
519
+
520
+ $.fn.multiSelect.Constructor = MultiSelect;
521
+
522
+ $.fn.insertAt = function(index, $parent) {
523
+ return this.each(function() {
524
+ if (index === 0) {
525
+ $parent.prepend(this);
526
+ } else {
527
+ $parent.children().eq(index - 1).after(this);
528
+ }
529
+ });
530
+ }
531
+
532
+ }(window.jQuery);