weaver 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);