weaver 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/data/weaver/css/animate.css +36 -4
  3. data/data/weaver/css/bootstrap.css +31 -74
  4. data/data/weaver/css/bootstrap.css.map +1 -1
  5. data/data/weaver/css/bootstrap.min.css +4 -3
  6. data/data/weaver/css/bootstrap.min.css.map +1 -0
  7. data/data/weaver/css/plugins/bootstrap-markdown/bootstrap-markdown.min.css +1 -0
  8. data/data/weaver/css/plugins/bootstrap-tagsinput/bootstrap-tagsinput.css +55 -0
  9. data/data/weaver/css/plugins/bootstrapSocial/bootstrap-social.css +147 -0
  10. data/data/weaver/css/plugins/bootstrapTour/bootstrap-tour.min.css +22 -0
  11. data/data/weaver/css/plugins/c3/c3.min.css +1 -0
  12. data/data/weaver/css/plugins/chosen/bootstrap-chosen.css +332 -0
  13. data/data/weaver/css/plugins/codemirror/codemirror.css +1 -0
  14. data/data/weaver/css/plugins/dataTables/datatables.min.css +17 -0
  15. data/data/weaver/css/plugins/dropzone/basic.css +32 -148
  16. data/data/weaver/css/plugins/dropzone/dropzone.css +363 -385
  17. data/data/weaver/css/plugins/dualListbox/bootstrap-duallistbox.min.css +10 -0
  18. data/data/weaver/css/plugins/fullcalendar/fullcalendar.css +663 -379
  19. data/data/weaver/css/plugins/fullcalendar/fullcalendar.print.css +11 -5
  20. data/data/weaver/css/plugins/jQueryUI/jquery-ui.css +1177 -0
  21. data/data/weaver/css/plugins/ladda/ladda-themeless.min.css +7 -0
  22. data/data/weaver/css/plugins/ladda/ladda.min.css +9 -0
  23. data/data/weaver/css/plugins/summernote/font/summernote.eot +0 -0
  24. data/data/weaver/css/plugins/summernote/font/summernote.ttf +0 -0
  25. data/data/weaver/css/plugins/summernote/font/summernote.woff +0 -0
  26. data/data/weaver/css/plugins/summernote/summernote.css +1 -446
  27. data/data/weaver/css/plugins/textSpinners/spinners.css +204 -0
  28. data/data/weaver/css/plugins/touchspin/jquery.bootstrap-touchspin.min.css +10 -0
  29. data/data/weaver/css/style.css +687 -220
  30. data/data/weaver/font-awesome/css/font-awesome.css +547 -11
  31. data/data/weaver/font-awesome/css/font-awesome.min.css +2 -2
  32. data/data/weaver/font-awesome/fonts/FontAwesome.otf +0 -0
  33. data/data/weaver/font-awesome/fonts/fontawesome-webfont.eot +0 -0
  34. data/data/weaver/font-awesome/fonts/fontawesome-webfont.svg +2668 -562
  35. data/data/weaver/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
  36. data/data/weaver/font-awesome/fonts/fontawesome-webfont.woff +0 -0
  37. data/data/weaver/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
  38. data/data/weaver/font-awesome/less/bordered-pulled.less +9 -0
  39. data/data/weaver/font-awesome/less/core.less +1 -2
  40. data/data/weaver/font-awesome/less/font-awesome.less +2 -1
  41. data/data/weaver/font-awesome/less/icons.less +195 -2
  42. data/data/weaver/font-awesome/less/mixins.less +37 -4
  43. data/data/weaver/font-awesome/less/path.less +1 -1
  44. data/data/weaver/font-awesome/less/screen-reader.less +5 -0
  45. data/data/weaver/font-awesome/less/variables.less +198 -4
  46. data/data/weaver/font-awesome/scss/_bordered-pulled.scss +9 -0
  47. data/data/weaver/font-awesome/scss/_core.scss +1 -2
  48. data/data/weaver/font-awesome/scss/_icons.scss +195 -2
  49. data/data/weaver/font-awesome/scss/_mixins.scss +37 -4
  50. data/data/weaver/font-awesome/scss/_screen-reader.scss +5 -0
  51. data/data/weaver/font-awesome/scss/_variables.scss +198 -4
  52. data/data/weaver/font-awesome/scss/font-awesome.scss +2 -1
  53. data/data/weaver/js/api/typehead_collection.json +3 -0
  54. data/data/weaver/js/bootstrap.js +66 -52
  55. data/data/weaver/js/bootstrap.min.js +4 -4
  56. data/data/weaver/js/demo/chartjs-demo.js +68 -157
  57. data/data/weaver/js/jquery-3.1.1.min.js +4 -0
  58. data/data/weaver/js/plugins/bootstrap-markdown/bootstrap-markdown.js +1386 -0
  59. data/data/weaver/js/plugins/bootstrap-markdown/markdown.js +1616 -0
  60. data/data/weaver/js/plugins/bootstrap-tagsinput/bootstrap-tagsinput.js +646 -0
  61. data/data/weaver/js/plugins/bootstrapTour/bootstrap-tour.min.js +22 -0
  62. data/data/weaver/js/plugins/c3/c3.min.js +5 -0
  63. data/data/weaver/js/plugins/chartJs/Chart.min.js +8 -5
  64. data/data/weaver/js/plugins/clipboard/clipboard.min.js +7 -0
  65. data/data/weaver/js/plugins/d3/LICENSE +27 -0
  66. data/data/weaver/js/plugins/d3/d3.min.js +5 -0
  67. data/data/weaver/js/plugins/dataTables/datatables.min.js +308 -0
  68. data/data/weaver/js/plugins/datamaps/datamaps.all.min.js +3 -0
  69. data/data/weaver/js/plugins/dotdotdot/jquery.dotdotdot.min.js +13 -0
  70. data/data/weaver/js/plugins/dropzone/dropzone.js +1575 -1649
  71. data/data/weaver/js/plugins/dualListbox/jquery.bootstrap-duallistbox.js +761 -0
  72. data/data/weaver/js/plugins/fullcalendar/fullcalendar.min.js +7 -6
  73. data/data/weaver/js/plugins/i18next/i18next.min.js +7 -0
  74. data/data/weaver/js/plugins/jquery-ui/LICENSE.txt +43 -0
  75. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_444444_256x240.png +0 -0
  76. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_555555_256x240.png +0 -0
  77. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_777620_256x240.png +0 -0
  78. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_777777_256x240.png +0 -0
  79. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_cc0000_256x240.png +0 -0
  80. data/data/weaver/js/plugins/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
  81. data/data/weaver/js/plugins/jquery-ui/jquery-ui.min.css +6 -3
  82. data/data/weaver/js/plugins/jquery-ui/jquery-ui.min.js +12 -11
  83. data/data/weaver/js/plugins/jvectormap/jquery-jvectormap-world-mill-en.js +481 -1
  84. data/data/weaver/js/plugins/ladda/ladda.jquery.min.js +8 -0
  85. data/data/weaver/js/plugins/ladda/ladda.min.js +8 -0
  86. data/data/weaver/js/plugins/ladda/spin.min.js +1 -0
  87. data/data/weaver/js/plugins/masonary/masonry.pkgd.min.js +2 -2
  88. data/data/weaver/js/plugins/nouslider/jquery.nouislider.min.js +2 -33
  89. data/data/weaver/js/plugins/pace/pace.min.js +2 -2
  90. data/data/weaver/js/plugins/pdfjs/pdf.js +10905 -0
  91. data/data/weaver/js/plugins/pdfjs/pdf.worker.js +43194 -0
  92. data/data/weaver/js/plugins/pwstrength/pwstrength-bootstrap.min.js +4 -0
  93. data/data/weaver/js/plugins/pwstrength/zxcvbn.js +28 -0
  94. data/data/weaver/js/plugins/steps/jquery.steps.min.js +6 -0
  95. data/data/weaver/js/plugins/summernote/summernote.min.js +4 -2
  96. data/data/weaver/js/plugins/switchery/switchery.js +1 -1
  97. data/data/weaver/js/plugins/topojson/LICENSE +26 -0
  98. data/data/weaver/js/plugins/topojson/topojson.js +534 -0
  99. data/data/weaver/js/plugins/touchpunch/jquery.ui.touch-punch.min.js +11 -0
  100. data/data/weaver/js/plugins/touchspin/jquery.bootstrap-touchspin.min.js +9 -0
  101. data/data/weaver/js/plugins/typehead/bootstrap3-typeahead.min.js +1 -0
  102. data/data/weaver/js/plugins/validate/jquery.validate.min.js +3 -3
  103. data/data/weaver/js/{inspinia.js → weaver.js} +34 -38
  104. data/lib/weaver.rb +1 -1
  105. data/lib/weaver/version.rb +1 -1
  106. metadata +58 -4
@@ -0,0 +1,761 @@
1
+ /*
2
+ * Bootstrap Duallistbox - v3.0.5
3
+ * A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
4
+ * http://www.virtuosoft.eu/code/bootstrap-duallistbox/
5
+ *
6
+ * Made by István Ujj-Mészáros
7
+ * Under Apache License v2.0 License
8
+ */
9
+ ;(function ($, window, document, undefined) {
10
+ // Create the defaults once
11
+ var pluginName = 'bootstrapDualListbox',
12
+ defaults = {
13
+ bootstrap2Compatible: false,
14
+ filterTextClear: 'show all',
15
+ filterPlaceHolder: 'Filter',
16
+ moveSelectedLabel: 'Move selected',
17
+ moveAllLabel: 'Move all',
18
+ removeSelectedLabel: 'Remove selected',
19
+ removeAllLabel: 'Remove all',
20
+ moveOnSelect: true, // true/false (forced true on androids, see the comment later)
21
+ preserveSelectionOnMove: false, // 'all' / 'moved' / false
22
+ selectedListLabel: false, // 'string', false
23
+ nonSelectedListLabel: false, // 'string', false
24
+ helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false
25
+ selectorMinimalHeight: 100,
26
+ showFilterInputs: true, // whether to show filter inputs
27
+ nonSelectedFilter: '', // string, filter the non selected options
28
+ selectedFilter: '', // string, filter the selected options
29
+ infoText: 'Showing all {0}', // text when all options are visible / false for no info text
30
+ infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
31
+ infoTextEmpty: 'Empty list', // when there are no options present in the list
32
+ filterOnValues: false, // filter by selector's values, boolean
33
+ sortByInputOrder: false
34
+ },
35
+ // Selections are invisible on android if the containing select is styled with CSS
36
+ // http://code.google.com/p/android/issues/detail?id=16922
37
+ isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
38
+
39
+ // The actual plugin constructor
40
+ function BootstrapDualListbox(element, options) {
41
+ this.element = $(element);
42
+ // jQuery has an extend method which merges the contents of two or
43
+ // more objects, storing the result in the first object. The first object
44
+ // is generally empty as we don't want to alter the default options for
45
+ // future instances of the plugin
46
+ this.settings = $.extend({}, defaults, options);
47
+ this._defaults = defaults;
48
+ this._name = pluginName;
49
+ this.init();
50
+ }
51
+
52
+ function triggerChangeEvent(dualListbox) {
53
+ dualListbox.element.trigger('change');
54
+ }
55
+
56
+ function updateSelectionStates(dualListbox) {
57
+ dualListbox.element.find('option').each(function(index, item) {
58
+ var $item = $(item);
59
+ if (typeof($item.data('original-index')) === 'undefined') {
60
+ $item.data('original-index', dualListbox.elementCount++);
61
+ }
62
+ if (typeof($item.data('_selected')) === 'undefined') {
63
+ $item.data('_selected', false);
64
+ }
65
+ });
66
+ }
67
+
68
+ function changeSelectionState(dualListbox, original_index, selected) {
69
+ dualListbox.element.find('option').each(function(index, item) {
70
+ var $item = $(item);
71
+ if ($item.data('original-index') === original_index) {
72
+ $item.prop('selected', selected);
73
+ if(selected){
74
+ $item.attr('data-sortindex', dualListbox.sortIndex);
75
+ dualListbox.sortIndex++;
76
+ } else {
77
+ $item.removeAttr('data-sortindex');
78
+ }
79
+ }
80
+ });
81
+ }
82
+
83
+ function formatString(s, args) {
84
+ return s.replace(/\{(\d+)\}/g, function(match, number) {
85
+ return typeof args[number] !== 'undefined' ? args[number] : match;
86
+ });
87
+ }
88
+
89
+ function refreshInfo(dualListbox) {
90
+ if (!dualListbox.settings.infoText) {
91
+ return;
92
+ }
93
+
94
+ var visible1 = dualListbox.elements.select1.find('option').length,
95
+ visible2 = dualListbox.elements.select2.find('option').length,
96
+ all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
97
+ all2 = dualListbox.selectedElements,
98
+ content = '';
99
+
100
+ if (all1 === 0) {
101
+ content = dualListbox.settings.infoTextEmpty;
102
+ } else if (visible1 === all1) {
103
+ content = formatString(dualListbox.settings.infoText, [visible1, all1]);
104
+ } else {
105
+ content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
106
+ }
107
+
108
+ dualListbox.elements.info1.html(content);
109
+ dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
110
+
111
+ if (all2 === 0) {
112
+ content = dualListbox.settings.infoTextEmpty;
113
+ } else if (visible2 === all2) {
114
+ content = formatString(dualListbox.settings.infoText, [visible2, all2]);
115
+ } else {
116
+ content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
117
+ }
118
+
119
+ dualListbox.elements.info2.html(content);
120
+ dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
121
+ }
122
+
123
+ function refreshSelects(dualListbox) {
124
+ dualListbox.selectedElements = 0;
125
+
126
+ dualListbox.elements.select1.empty();
127
+ dualListbox.elements.select2.empty();
128
+
129
+ dualListbox.element.find('option').each(function(index, item) {
130
+ var $item = $(item);
131
+ if ($item.prop('selected')) {
132
+ dualListbox.selectedElements++;
133
+ dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
134
+ } else {
135
+ dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
136
+ }
137
+ });
138
+
139
+ if (dualListbox.settings.showFilterInputs) {
140
+ filter(dualListbox, 1);
141
+ filter(dualListbox, 2);
142
+ }
143
+ refreshInfo(dualListbox);
144
+ }
145
+
146
+ function filter(dualListbox, selectIndex) {
147
+ if (!dualListbox.settings.showFilterInputs) {
148
+ return;
149
+ }
150
+
151
+ saveSelections(dualListbox, selectIndex);
152
+
153
+ dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
154
+ var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
155
+ allOptions = dualListbox.element.find('option'),
156
+ options = dualListbox.element;
157
+
158
+ if (selectIndex === 1) {
159
+ options = allOptions.not(':selected');
160
+ } else {
161
+ options = options.find('option:selected');
162
+ }
163
+
164
+ options.each(function(index, item) {
165
+ var $item = $(item),
166
+ isFiltered = true;
167
+ if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
168
+ isFiltered = false;
169
+ dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
170
+ }
171
+ allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
172
+ });
173
+
174
+ refreshInfo(dualListbox);
175
+ }
176
+
177
+ function saveSelections(dualListbox, selectIndex) {
178
+ var options = dualListbox.element.find('option');
179
+ dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
180
+ var $item = $(item);
181
+ options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
182
+ });
183
+ }
184
+
185
+ function sortOptionsByInputOrder(select){
186
+ var selectopt = select.children('option');
187
+
188
+ selectopt.sort(function(a,b){
189
+ var an = parseInt(a.getAttribute('data-sortindex')),
190
+ bn = parseInt(b.getAttribute('data-sortindex'));
191
+
192
+ if(an > bn) {
193
+ return 1;
194
+ }
195
+ if(an < bn) {
196
+ return -1;
197
+ }
198
+ return 0;
199
+ });
200
+
201
+ selectopt.detach().appendTo(select);
202
+ }
203
+
204
+ function sortOptions(select) {
205
+ select.find('option').sort(function(a, b) {
206
+ return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
207
+ }).appendTo(select);
208
+ }
209
+
210
+ function clearSelections(dualListbox) {
211
+ dualListbox.elements.select1.find('option').each(function() {
212
+ dualListbox.element.find('option').data('_selected', false);
213
+ });
214
+ }
215
+
216
+ function move(dualListbox) {
217
+ if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
218
+ saveSelections(dualListbox, 1);
219
+ saveSelections(dualListbox, 2);
220
+ } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
221
+ saveSelections(dualListbox, 1);
222
+ }
223
+
224
+ dualListbox.elements.select1.find('option:selected').each(function(index, item) {
225
+ var $item = $(item);
226
+ if (!$item.data('filtered1')) {
227
+ changeSelectionState(dualListbox, $item.data('original-index'), true);
228
+ }
229
+ });
230
+
231
+ refreshSelects(dualListbox);
232
+ triggerChangeEvent(dualListbox);
233
+ if(dualListbox.settings.sortByInputOrder){
234
+ sortOptionsByInputOrder(dualListbox.elements.select2);
235
+ } else {
236
+ sortOptions(dualListbox.elements.select2);
237
+ }
238
+ }
239
+
240
+ function remove(dualListbox) {
241
+ if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
242
+ saveSelections(dualListbox, 1);
243
+ saveSelections(dualListbox, 2);
244
+ } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
245
+ saveSelections(dualListbox, 2);
246
+ }
247
+
248
+ dualListbox.elements.select2.find('option:selected').each(function(index, item) {
249
+ var $item = $(item);
250
+ if (!$item.data('filtered2')) {
251
+ changeSelectionState(dualListbox, $item.data('original-index'), false);
252
+ }
253
+ });
254
+
255
+ refreshSelects(dualListbox);
256
+ triggerChangeEvent(dualListbox);
257
+ sortOptions(dualListbox.elements.select1);
258
+ }
259
+
260
+ function moveAll(dualListbox) {
261
+ if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
262
+ saveSelections(dualListbox, 1);
263
+ saveSelections(dualListbox, 2);
264
+ } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
265
+ saveSelections(dualListbox, 1);
266
+ }
267
+
268
+ dualListbox.element.find('option').each(function(index, item) {
269
+ var $item = $(item);
270
+ if (!$item.data('filtered1')) {
271
+ $item.prop('selected', true);
272
+ $item.attr('data-sortindex', dualListbox.sortIndex);
273
+ dualListbox.sortIndex++;
274
+ }
275
+ });
276
+
277
+ refreshSelects(dualListbox);
278
+ triggerChangeEvent(dualListbox);
279
+ }
280
+
281
+ function removeAll(dualListbox) {
282
+ if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
283
+ saveSelections(dualListbox, 1);
284
+ saveSelections(dualListbox, 2);
285
+ } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
286
+ saveSelections(dualListbox, 2);
287
+ }
288
+
289
+ dualListbox.element.find('option').each(function(index, item) {
290
+ var $item = $(item);
291
+ if (!$item.data('filtered2')) {
292
+ $item.prop('selected', false);
293
+ $item.removeAttr('data-sortindex');
294
+ }
295
+ });
296
+
297
+ refreshSelects(dualListbox);
298
+ triggerChangeEvent(dualListbox);
299
+ }
300
+
301
+ function bindEvents(dualListbox) {
302
+ dualListbox.elements.form.submit(function(e) {
303
+ if (dualListbox.elements.filterInput1.is(':focus')) {
304
+ e.preventDefault();
305
+ dualListbox.elements.filterInput1.focusout();
306
+ } else if (dualListbox.elements.filterInput2.is(':focus')) {
307
+ e.preventDefault();
308
+ dualListbox.elements.filterInput2.focusout();
309
+ }
310
+ });
311
+
312
+ dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
313
+ dualListbox.refresh(mustClearSelections);
314
+ });
315
+
316
+ dualListbox.elements.filterClear1.on('click', function() {
317
+ dualListbox.setNonSelectedFilter('', true);
318
+ });
319
+
320
+ dualListbox.elements.filterClear2.on('click', function() {
321
+ dualListbox.setSelectedFilter('', true);
322
+ });
323
+
324
+ dualListbox.elements.moveButton.on('click', function() {
325
+ move(dualListbox);
326
+ });
327
+
328
+ dualListbox.elements.moveAllButton.on('click', function() {
329
+ moveAll(dualListbox);
330
+ });
331
+
332
+ dualListbox.elements.removeButton.on('click', function() {
333
+ remove(dualListbox);
334
+ });
335
+
336
+ dualListbox.elements.removeAllButton.on('click', function() {
337
+ removeAll(dualListbox);
338
+ });
339
+
340
+ dualListbox.elements.filterInput1.on('change keyup', function() {
341
+ filter(dualListbox, 1);
342
+ });
343
+
344
+ dualListbox.elements.filterInput2.on('change keyup', function() {
345
+ filter(dualListbox, 2);
346
+ });
347
+ }
348
+
349
+ BootstrapDualListbox.prototype = {
350
+ init: function () {
351
+ // Add the custom HTML template
352
+ this.container = $('' +
353
+ '<div class="bootstrap-duallistbox-container">' +
354
+ ' <div class="box1">' +
355
+ ' <label></label>' +
356
+ ' <span class="info-container">' +
357
+ ' <span class="info"></span>' +
358
+ ' <button type="button" class="btn clear1 pull-right"></button>' +
359
+ ' </span>' +
360
+ ' <input class="filter" type="text">' +
361
+ ' <div class="btn-group buttons">' +
362
+ ' <button type="button" class="btn moveall">' +
363
+ ' <i></i>' +
364
+ ' <i></i>' +
365
+ ' </button>' +
366
+ ' <button type="button" class="btn move">' +
367
+ ' <i></i>' +
368
+ ' </button>' +
369
+ ' </div>' +
370
+ ' <select multiple="multiple"></select>' +
371
+ ' </div>' +
372
+ ' <div class="box2">' +
373
+ ' <label></label>' +
374
+ ' <span class="info-container">' +
375
+ ' <span class="info"></span>' +
376
+ ' <button type="button" class="btn clear2 pull-right"></button>' +
377
+ ' </span>' +
378
+ ' <input class="filter" type="text">' +
379
+ ' <div class="btn-group buttons">' +
380
+ ' <button type="button" class="btn remove">' +
381
+ ' <i></i>' +
382
+ ' </button>' +
383
+ ' <button type="button" class="btn removeall">' +
384
+ ' <i></i>' +
385
+ ' <i></i>' +
386
+ ' </button>' +
387
+ ' </div>' +
388
+ ' <select multiple="multiple"></select>' +
389
+ ' </div>' +
390
+ '</div>')
391
+ .insertBefore(this.element);
392
+
393
+ // Cache the inner elements
394
+ this.elements = {
395
+ originalSelect: this.element,
396
+ box1: $('.box1', this.container),
397
+ box2: $('.box2', this.container),
398
+ filterInput1: $('.box1 .filter', this.container),
399
+ filterInput2: $('.box2 .filter', this.container),
400
+ filterClear1: $('.box1 .clear1', this.container),
401
+ filterClear2: $('.box2 .clear2', this.container),
402
+ label1: $('.box1 > label', this.container),
403
+ label2: $('.box2 > label', this.container),
404
+ info1: $('.box1 .info', this.container),
405
+ info2: $('.box2 .info', this.container),
406
+ select1: $('.box1 select', this.container),
407
+ select2: $('.box2 select', this.container),
408
+ moveButton: $('.box1 .move', this.container),
409
+ removeButton: $('.box2 .remove', this.container),
410
+ moveAllButton: $('.box1 .moveall', this.container),
411
+ removeAllButton: $('.box2 .removeall', this.container),
412
+ form: $($('.box1 .filter', this.container)[0].form)
413
+ };
414
+
415
+ // Set select IDs
416
+ this.originalSelectName = this.element.attr('name') || '';
417
+ var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
418
+ select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
419
+ this.elements.select1.attr('id', select1Id);
420
+ this.elements.select2.attr('id', select2Id);
421
+ this.elements.label1.attr('for', select1Id);
422
+ this.elements.label2.attr('for', select2Id);
423
+
424
+ // Apply all settings
425
+ this.selectedElements = 0;
426
+ this.sortIndex = 0;
427
+ this.elementCount = 0;
428
+ this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
429
+ this.setFilterTextClear(this.settings.filterTextClear);
430
+ this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
431
+ this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
432
+ this.setMoveAllLabel(this.settings.moveAllLabel);
433
+ this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
434
+ this.setRemoveAllLabel(this.settings.removeAllLabel);
435
+ this.setMoveOnSelect(this.settings.moveOnSelect);
436
+ this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
437
+ this.setSelectedListLabel(this.settings.selectedListLabel);
438
+ this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
439
+ this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
440
+ this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
441
+
442
+ updateSelectionStates(this);
443
+
444
+ this.setShowFilterInputs(this.settings.showFilterInputs);
445
+ this.setNonSelectedFilter(this.settings.nonSelectedFilter);
446
+ this.setSelectedFilter(this.settings.selectedFilter);
447
+ this.setInfoText(this.settings.infoText);
448
+ this.setInfoTextFiltered(this.settings.infoTextFiltered);
449
+ this.setInfoTextEmpty(this.settings.infoTextEmpty);
450
+ this.setFilterOnValues(this.settings.filterOnValues);
451
+ this.setSortByInputOrder(this.settings.sortByInputOrder);
452
+
453
+ // Hide the original select
454
+ this.element.hide();
455
+
456
+ bindEvents(this);
457
+ refreshSelects(this);
458
+
459
+ return this.element;
460
+ },
461
+ setBootstrap2Compatible: function(value, refresh) {
462
+ this.settings.bootstrap2Compatible = value;
463
+ if (value) {
464
+ this.container.removeClass('row').addClass('row-fluid bs2compatible');
465
+ this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
466
+ this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');
467
+ this.container.find('input, select').removeClass('form-control');
468
+ this.container.find('.btn').removeClass('btn-default');
469
+ this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');
470
+ this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');
471
+ } else {
472
+ this.container.removeClass('row-fluid bs2compatible').addClass('row');
473
+ this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
474
+ this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');
475
+ this.container.find('input, select').addClass('form-control');
476
+ this.container.find('.btn').addClass('btn-default');
477
+ this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');
478
+ this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');
479
+ }
480
+ if (refresh) {
481
+ refreshSelects(this);
482
+ }
483
+ return this.element;
484
+ },
485
+ setFilterTextClear: function(value, refresh) {
486
+ this.settings.filterTextClear = value;
487
+ this.elements.filterClear1.html(value);
488
+ this.elements.filterClear2.html(value);
489
+ if (refresh) {
490
+ refreshSelects(this);
491
+ }
492
+ return this.element;
493
+ },
494
+ setFilterPlaceHolder: function(value, refresh) {
495
+ this.settings.filterPlaceHolder = value;
496
+ this.elements.filterInput1.attr('placeholder', value);
497
+ this.elements.filterInput2.attr('placeholder', value);
498
+ if (refresh) {
499
+ refreshSelects(this);
500
+ }
501
+ return this.element;
502
+ },
503
+ setMoveSelectedLabel: function(value, refresh) {
504
+ this.settings.moveSelectedLabel = value;
505
+ this.elements.moveButton.attr('title', value);
506
+ if (refresh) {
507
+ refreshSelects(this);
508
+ }
509
+ return this.element;
510
+ },
511
+ setMoveAllLabel: function(value, refresh) {
512
+ this.settings.moveAllLabel = value;
513
+ this.elements.moveAllButton.attr('title', value);
514
+ if (refresh) {
515
+ refreshSelects(this);
516
+ }
517
+ return this.element;
518
+ },
519
+ setRemoveSelectedLabel: function(value, refresh) {
520
+ this.settings.removeSelectedLabel = value;
521
+ this.elements.removeButton.attr('title', value);
522
+ if (refresh) {
523
+ refreshSelects(this);
524
+ }
525
+ return this.element;
526
+ },
527
+ setRemoveAllLabel: function(value, refresh) {
528
+ this.settings.removeAllLabel = value;
529
+ this.elements.removeAllButton.attr('title', value);
530
+ if (refresh) {
531
+ refreshSelects(this);
532
+ }
533
+ return this.element;
534
+ },
535
+ setMoveOnSelect: function(value, refresh) {
536
+ if (isBuggyAndroid) {
537
+ value = true;
538
+ }
539
+ this.settings.moveOnSelect = value;
540
+ if (this.settings.moveOnSelect) {
541
+ this.container.addClass('moveonselect');
542
+ var self = this;
543
+ this.elements.select1.on('change', function() {
544
+ move(self);
545
+ });
546
+ this.elements.select2.on('change', function() {
547
+ remove(self);
548
+ });
549
+ } else {
550
+ this.container.removeClass('moveonselect');
551
+ this.elements.select1.off('change');
552
+ this.elements.select2.off('change');
553
+ }
554
+ if (refresh) {
555
+ refreshSelects(this);
556
+ }
557
+ return this.element;
558
+ },
559
+ setPreserveSelectionOnMove: function(value, refresh) {
560
+ // We are forcing to move on select and disabling preserveSelectionOnMove on Android
561
+ if (isBuggyAndroid) {
562
+ value = false;
563
+ }
564
+ this.settings.preserveSelectionOnMove = value;
565
+ if (refresh) {
566
+ refreshSelects(this);
567
+ }
568
+ return this.element;
569
+ },
570
+ setSelectedListLabel: function(value, refresh) {
571
+ this.settings.selectedListLabel = value;
572
+ if (value) {
573
+ this.elements.label2.show().html(value);
574
+ } else {
575
+ this.elements.label2.hide().html(value);
576
+ }
577
+ if (refresh) {
578
+ refreshSelects(this);
579
+ }
580
+ return this.element;
581
+ },
582
+ setNonSelectedListLabel: function(value, refresh) {
583
+ this.settings.nonSelectedListLabel = value;
584
+ if (value) {
585
+ this.elements.label1.show().html(value);
586
+ } else {
587
+ this.elements.label1.hide().html(value);
588
+ }
589
+ if (refresh) {
590
+ refreshSelects(this);
591
+ }
592
+ return this.element;
593
+ },
594
+ setHelperSelectNamePostfix: function(value, refresh) {
595
+ this.settings.helperSelectNamePostfix = value;
596
+ if (value) {
597
+ this.elements.select1.attr('name', this.originalSelectName + value + '1');
598
+ this.elements.select2.attr('name', this.originalSelectName + value + '2');
599
+ } else {
600
+ this.elements.select1.removeAttr('name');
601
+ this.elements.select2.removeAttr('name');
602
+ }
603
+ if (refresh) {
604
+ refreshSelects(this);
605
+ }
606
+ return this.element;
607
+ },
608
+ setSelectOrMinimalHeight: function(value, refresh) {
609
+ this.settings.selectorMinimalHeight = value;
610
+ var height = this.element.height();
611
+ if (this.element.height() < value) {
612
+ height = value;
613
+ }
614
+ this.elements.select1.height(height);
615
+ this.elements.select2.height(height);
616
+ if (refresh) {
617
+ refreshSelects(this);
618
+ }
619
+ return this.element;
620
+ },
621
+ setShowFilterInputs: function(value, refresh) {
622
+ if (!value) {
623
+ this.setNonSelectedFilter('');
624
+ this.setSelectedFilter('');
625
+ refreshSelects(this);
626
+ this.elements.filterInput1.hide();
627
+ this.elements.filterInput2.hide();
628
+ } else {
629
+ this.elements.filterInput1.show();
630
+ this.elements.filterInput2.show();
631
+ }
632
+ this.settings.showFilterInputs = value;
633
+ if (refresh) {
634
+ refreshSelects(this);
635
+ }
636
+ return this.element;
637
+ },
638
+ setNonSelectedFilter: function(value, refresh) {
639
+ if (this.settings.showFilterInputs) {
640
+ this.settings.nonSelectedFilter = value;
641
+ this.elements.filterInput1.val(value);
642
+ if (refresh) {
643
+ refreshSelects(this);
644
+ }
645
+ return this.element;
646
+ }
647
+ },
648
+ setSelectedFilter: function(value, refresh) {
649
+ if (this.settings.showFilterInputs) {
650
+ this.settings.selectedFilter = value;
651
+ this.elements.filterInput2.val(value);
652
+ if (refresh) {
653
+ refreshSelects(this);
654
+ }
655
+ return this.element;
656
+ }
657
+ },
658
+ setInfoText: function(value, refresh) {
659
+ this.settings.infoText = value;
660
+ if (refresh) {
661
+ refreshSelects(this);
662
+ }
663
+ return this.element;
664
+ },
665
+ setInfoTextFiltered: function(value, refresh) {
666
+ this.settings.infoTextFiltered = value;
667
+ if (refresh) {
668
+ refreshSelects(this);
669
+ }
670
+ return this.element;
671
+ },
672
+ setInfoTextEmpty: function(value, refresh) {
673
+ this.settings.infoTextEmpty = value;
674
+ if (refresh) {
675
+ refreshSelects(this);
676
+ }
677
+ return this.element;
678
+ },
679
+ setFilterOnValues: function(value, refresh) {
680
+ this.settings.filterOnValues = value;
681
+ if (refresh) {
682
+ refreshSelects(this);
683
+ }
684
+ return this.element;
685
+ },
686
+ setSortByInputOrder: function(value, refresh){
687
+ this.settings.sortByInputOrder = value;
688
+ if (refresh) {
689
+ refreshSelects(this);
690
+ }
691
+ return this.element;
692
+ },
693
+ getContainer: function() {
694
+ return this.container;
695
+ },
696
+ refresh: function(mustClearSelections) {
697
+ updateSelectionStates(this);
698
+
699
+ if (!mustClearSelections) {
700
+ saveSelections(this, 1);
701
+ saveSelections(this, 2);
702
+ } else {
703
+ clearSelections(this);
704
+ }
705
+
706
+ refreshSelects(this);
707
+ },
708
+ destroy: function() {
709
+ this.container.remove();
710
+ this.element.show();
711
+ $.data(this, 'plugin_' + pluginName, null);
712
+ return this.element;
713
+ }
714
+ };
715
+
716
+ // A really lightweight plugin wrapper around the constructor,
717
+ // preventing against multiple instantiations
718
+ $.fn[ pluginName ] = function (options) {
719
+ var args = arguments;
720
+
721
+ // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
722
+ if (options === undefined || typeof options === 'object') {
723
+ return this.each(function () {
724
+ // If this is not a select
725
+ if (!$(this).is('select')) {
726
+ $(this).find('select').each(function(index, item) {
727
+ // For each nested select, instantiate the Dual List Box
728
+ $(item).bootstrapDualListbox(options);
729
+ });
730
+ } else if (!$.data(this, 'plugin_' + pluginName)) {
731
+ // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
732
+
733
+ // if it has no instance, create a new one, pass options to our plugin constructor,
734
+ // and store the plugin instance in the elements jQuery data object.
735
+ $.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
736
+ }
737
+ });
738
+ // If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
739
+ // treat this as a call to a public method.
740
+ } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
741
+
742
+ // Cache the method call to make it possible to return a value
743
+ var returns;
744
+
745
+ this.each(function () {
746
+ var instance = $.data(this, 'plugin_' + pluginName);
747
+ // Tests that there's already a plugin-instance and checks that the requested public method exists
748
+ if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
749
+ // Call the method of our plugin instance, and pass it the supplied arguments.
750
+ returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
751
+ }
752
+ });
753
+
754
+ // If the earlier cached method gives a value back return the value,
755
+ // otherwise return this to preserve chainability.
756
+ return returns !== undefined ? returns : this;
757
+ }
758
+
759
+ };
760
+
761
+ })(jQuery, window, document);