GPQAPP

Форк
0
/
jquery.bootstrap-duallistbox.js 
893 строки · 32.5 Кб
1
/*
2
 *  Bootstrap Duallistbox - v4.0.2
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(factory) {
10
  if (typeof define === 'function' && define.amd) {
11
    define(['jquery'], factory);
12
  } else if (typeof module === 'object' && module.exports) {
13
    module.exports = function(root, jQuery) {
14
      if (jQuery === undefined) {
15
        if (typeof window !== 'undefined') {
16
          jQuery = require('jquery');
17
        }
18
        else {
19
          jQuery = require('jquery')(root);
20
        }
21
      }
22
      factory(jQuery);
23
      return jQuery;
24
    };
25
  } else {
26
    factory(jQuery);
27
  }
28
}(function($) {
29
  // Create the defaults once
30
  var pluginName = 'bootstrapDualListbox',
31
    defaults = {
32
      filterTextClear: 'show all',
33
      filterPlaceHolder: 'Filter',
34
      moveSelectedLabel: 'Move selected',
35
      moveAllLabel: 'Move all',
36
      removeSelectedLabel: 'Remove selected',
37
      removeAllLabel: 'Remove all',
38
      moveOnSelect: true,                                                                 // true/false (forced true on androids, see the comment later)
39
      moveOnDoubleClick: true,                                                            // true/false (forced false on androids, cause moveOnSelect is forced to true)
40
      preserveSelectionOnMove: false,                                                     // 'all' / 'moved' / false
41
      selectedListLabel: false,                                                           // 'string', false
42
      nonSelectedListLabel: false,                                                        // 'string', false
43
      helperSelectNamePostfix: '_helper',                                                 // 'string_of_postfix' / false
44
      selectorMinimalHeight: 100,
45
      showFilterInputs: true,                                                             // whether to show filter inputs
46
      nonSelectedFilter: '',                                                              // string, filter the non selected options
47
      selectedFilter: '',                                                                 // string, filter the selected options
48
      infoText: 'Showing all {0}',                                                        // text when all options are visible / false for no info text
49
      infoTextFiltered: '<span class="badge badge-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
50
      infoTextEmpty: 'Empty list',                                                        // when there are no options present in the list
51
      filterOnValues: false,                                                              // filter by selector's values, boolean
52
      sortByInputOrder: false,
53
      eventMoveOverride: false,                                                           // boolean, allows user to unbind default event behaviour and run their own instead
54
      eventMoveAllOverride: false,                                                        // boolean, allows user to unbind default event behaviour and run their own instead
55
      eventRemoveOverride: false,                                                         // boolean, allows user to unbind default event behaviour and run their own instead
56
      eventRemoveAllOverride: false,                                                      // boolean, allows user to unbind default event behaviour and run their own instead
57
      btnClass: 'btn-outline-secondary',                                                  // sets the button style class for all the buttons
58
      btnMoveText: '&gt;',                                                                // string, sets the text for the "Move" button
59
      btnRemoveText: '&lt;',                                                              // string, sets the text for the "Remove" button
60
      btnMoveAllText: '&gt;&gt;',                                                         // string, sets the text for the "Move All" button
61
      btnRemoveAllText: '&lt;&lt;'                                                        // string, sets the text for the "Remove All" button
62
    },
63
    // Selections are invisible on android if the containing select is styled with CSS
64
    // http://code.google.com/p/android/issues/detail?id=16922
65
    isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
66

67
  // The actual plugin constructor
68
  function BootstrapDualListbox(element, options) {
69
    this.element = $(element);
70
    // jQuery has an extend method which merges the contents of two or
71
    // more objects, storing the result in the first object. The first object
72
    // is generally empty as we don't want to alter the default options for
73
    // future instances of the plugin
74
    this.settings = $.extend({}, defaults, options);
75
    this._defaults = defaults;
76
    this._name = pluginName;
77
    this.init();
78
  }
79

80
  function triggerChangeEvent(dualListbox) {
81
    dualListbox.element.trigger('change');
82
  }
83

84
  function updateSelectionStates(dualListbox) {
85
    dualListbox.element.find('option').each(function(index, item) {
86
      var $item = $(item);
87
      if (typeof($item.data('original-index')) === 'undefined') {
88
        $item.data('original-index', dualListbox.elementCount++);
89
      }
90
      if (typeof($item.data('_selected')) === 'undefined') {
91
        $item.data('_selected', false);
92
      }
93
    });
94
  }
95

96
  function changeSelectionState(dualListbox, original_index, selected) {
97
    dualListbox.element.find('option').each(function(index, item) {
98
      var $item = $(item);
99
      if ($item.data('original-index') === original_index) {
100
        $item.prop('selected', selected);
101
        if(selected){
102
          $item.attr('data-sortindex', dualListbox.sortIndex);
103
          dualListbox.sortIndex++;
104
        } else {
105
          $item.removeAttr('data-sortindex');
106
        }
107
      }
108
    });
109
  }
110

111
  function formatString(s, args) {
112
    console.log(s, args);
113
    return s.replace(/{(\d+)}/g, function(match, number) {
114
      return typeof args[number] !== 'undefined' ? args[number] : match;
115
    });
116
  }
117

118
  function refreshInfo(dualListbox) {
119
    if (!dualListbox.settings.infoText) {
120
      return;
121
    }
122

123
    var visible1 = dualListbox.elements.select1.find('option').length,
124
      visible2 = dualListbox.elements.select2.find('option').length,
125
      all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
126
      all2 = dualListbox.selectedElements,
127
      content = '';
128

129
    if (all1 === 0) {
130
      content = dualListbox.settings.infoTextEmpty;
131
    } else if (visible1 === all1) {
132
      content = formatString(dualListbox.settings.infoText, [visible1, all1]);
133
    } else {
134
      content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
135
    }
136

137
    dualListbox.elements.info1.html(content);
138
    dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
139

140
    if (all2 === 0) {
141
      content = dualListbox.settings.infoTextEmpty;
142
    } else if (visible2 === all2) {
143
      content = formatString(dualListbox.settings.infoText, [visible2, all2]);
144
    } else {
145
      content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
146
    }
147

148
    dualListbox.elements.info2.html(content);
149
    dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
150
  }
151

152
  function refreshSelects(dualListbox) {
153
    dualListbox.selectedElements = 0;
154

155
    dualListbox.elements.select1.empty();
156
    dualListbox.elements.select2.empty();
157

158
    dualListbox.element.find('option').each(function(index, item) {
159
      var $item = $(item);
160
      if ($item.prop('selected')) {
161
        dualListbox.selectedElements++;
162
        dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
163
      } else {
164
        dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
165
      }
166
    });
167

168
    if (dualListbox.settings.showFilterInputs) {
169
      filter(dualListbox, 1);
170
      filter(dualListbox, 2);
171
    }
172
    refreshInfo(dualListbox);
173
  }
174

175
  function filter(dualListbox, selectIndex) {
176
    if (!dualListbox.settings.showFilterInputs) {
177
      return;
178
    }
179

180
    saveSelections(dualListbox, selectIndex);
181

182
    dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
183
    var regex,
184
      allOptions = dualListbox.element.find('option'),
185
      options = dualListbox.element;
186

187
    if (selectIndex === 1) {
188
      options = allOptions.not(':selected');
189
    } else  {
190
      options = options.find('option:selected');
191
    }
192

193
    try {
194
      regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi');
195
    }
196
    catch(e) {
197
      // a regex to match nothing
198
      regex = new RegExp('/a^/', 'gi');
199
    }
200

201
    options.each(function(index, item) {
202
      var $item = $(item),
203
        isFiltered = true;
204
      if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
205
        isFiltered = false;
206
        dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
207
      }
208
      allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
209
    });
210

211
    refreshInfo(dualListbox);
212
  }
213

214
  function saveSelections(dualListbox, selectIndex) {
215
    var options = dualListbox.element.find('option');
216
    dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
217
      var $item = $(item);
218
      options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
219
    });
220
  }
221

222
  function sortOptionsByInputOrder(select){
223
    var selectopt = select.children('option');
224

225
    selectopt.sort(function(a,b){
226
      var an = parseInt(a.getAttribute('data-sortindex')),
227
          bn = parseInt(b.getAttribute('data-sortindex'));
228

229
          if(an > bn) {
230
             return 1;
231
          }
232
          if(an < bn) {
233
            return -1;
234
          }
235
          return 0;
236
    });
237

238
    selectopt.detach().appendTo(select);
239
  }
240

241
  function sortOptions(select, dualListbox) {
242
    select.find('option').sort(function(a, b) {
243
      return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
244
    }).appendTo(select);
245

246
    // workaround for chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1072475
247
    refreshSelects(dualListbox);
248
  }
249

250
  function clearSelections(dualListbox) {
251
    dualListbox.elements.select1.find('option').each(function() {
252
      dualListbox.element.find('option').data('_selected', false);
253
    });
254
  }
255

256
  function move(dualListbox) {
257
    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
258
      saveSelections(dualListbox, 1);
259
      saveSelections(dualListbox, 2);
260
    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
261
      saveSelections(dualListbox, 1);
262
    }
263

264
    dualListbox.elements.select1.find('option:selected').each(function(index, item) {
265
      var $item = $(item);
266
      if (!$item.data('filtered1')) {
267
        changeSelectionState(dualListbox, $item.data('original-index'), true);
268
      }
269
    });
270

271
    refreshSelects(dualListbox);
272
    triggerChangeEvent(dualListbox);
273
    if(dualListbox.settings.sortByInputOrder){
274
        sortOptionsByInputOrder(dualListbox.elements.select2);
275
    } else {
276
        sortOptions(dualListbox.elements.select2, dualListbox);
277
    }
278
  }
279

280
  function remove(dualListbox) {
281
    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
282
      saveSelections(dualListbox, 1);
283
      saveSelections(dualListbox, 2);
284
    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
285
      saveSelections(dualListbox, 2);
286
    }
287

288
    dualListbox.elements.select2.find('option:selected').each(function(index, item) {
289
      var $item = $(item);
290
      if (!$item.data('filtered2')) {
291
        changeSelectionState(dualListbox, $item.data('original-index'), false);
292
      }
293
    });
294

295
    refreshSelects(dualListbox);
296
    triggerChangeEvent(dualListbox);
297
    sortOptions(dualListbox.elements.select1, dualListbox);
298
    if(dualListbox.settings.sortByInputOrder){
299
        sortOptionsByInputOrder(dualListbox.elements.select2);
300
    }
301
  }
302

303
  function moveAll(dualListbox) {
304
    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
305
      saveSelections(dualListbox, 1);
306
      saveSelections(dualListbox, 2);
307
    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
308
      saveSelections(dualListbox, 1);
309
    }
310

311
    dualListbox.element.find('option').each(function(index, item) {
312
      var $item = $(item);
313
      if (!$item.data('filtered1')) {
314
        $item.prop('selected', true);
315
        $item.attr('data-sortindex', dualListbox.sortIndex);
316
        dualListbox.sortIndex++;
317
      }
318
    });
319

320
    refreshSelects(dualListbox);
321
    triggerChangeEvent(dualListbox);
322
  }
323

324
  function removeAll(dualListbox) {
325
    if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
326
      saveSelections(dualListbox, 1);
327
      saveSelections(dualListbox, 2);
328
    } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
329
      saveSelections(dualListbox, 2);
330
    }
331

332
    dualListbox.element.find('option').each(function(index, item) {
333
      var $item = $(item);
334
      if (!$item.data('filtered2')) {
335
        $item.prop('selected', false);
336
        $item.removeAttr('data-sortindex');
337
      }
338
    });
339

340
    refreshSelects(dualListbox);
341
    triggerChangeEvent(dualListbox);
342
  }
343

344
  function bindEvents(dualListbox) {
345
    dualListbox.elements.form.submit(function(e) {
346
      if (dualListbox.elements.filterInput1.is(':focus')) {
347
        e.preventDefault();
348
        dualListbox.elements.filterInput1.focusout();
349
      } else if (dualListbox.elements.filterInput2.is(':focus')) {
350
        e.preventDefault();
351
        dualListbox.elements.filterInput2.focusout();
352
      }
353
    });
354

355
    dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
356
      dualListbox.refresh(mustClearSelections);
357
    });
358

359
    dualListbox.elements.filterClear1.on('click', function() {
360
      dualListbox.setNonSelectedFilter('', true);
361
    });
362

363
    dualListbox.elements.filterClear2.on('click', function() {
364
      dualListbox.setSelectedFilter('', true);
365
    });
366

367
    if (dualListbox.settings.eventMoveOverride === false) {
368
      dualListbox.elements.moveButton.on('click', function() {
369
        move(dualListbox);
370
      });
371
    }
372

373
    if (dualListbox.settings.eventMoveAllOverride === false) {
374
      dualListbox.elements.moveAllButton.on('click', function() {
375
        moveAll(dualListbox);
376
      });
377
    }
378

379
    if (dualListbox.settings.eventRemoveOverride === false) {
380
      dualListbox.elements.removeButton.on('click', function() {
381
        remove(dualListbox);
382
      });
383
    }
384

385
    if (dualListbox.settings.eventRemoveAllOverride === false) {
386
      dualListbox.elements.removeAllButton.on('click', function() {
387
        removeAll(dualListbox);
388
      });
389
    }
390

391
    dualListbox.elements.filterInput1.on('change keyup', function() {
392
      filter(dualListbox, 1);
393
    });
394

395
    dualListbox.elements.filterInput2.on('change keyup', function() {
396
      filter(dualListbox, 2);
397
    });
398
  }
399

400
  BootstrapDualListbox.prototype = {
401
    init: function () {
402
      // Add the custom HTML template
403
      this.container = $('' +
404
        '<div class="bootstrap-duallistbox-container row">' +
405
        ' <div class="box1 col-md-6">' +
406
        '   <label></label>' +
407
        '   <span class="info-container">' +
408
        '     <span class="info"></span>' +
409
        '     <button type="button" class="btn btn-sm clear1" style="float:right!important;"></button>' +
410
        '   </span>' +
411
        '   <input class="form-control filter" type="text">' +
412
        '   <div class="btn-group buttons">' +
413
        '     <button type="button" class="btn moveall"></button>' +
414
        '     <button type="button" class="btn move"></button>' +
415
        '   </div>' +
416
        '   <select multiple="multiple"></select>' +
417
        ' </div>' +
418
        ' <div class="box2 col-md-6">' +
419
        '   <label></label>' +
420
        '   <span class="info-container">' +
421
        '     <span class="info"></span>' +
422
        '     <button type="button" class="btn btn-sm clear2" style="float:right!important;"></button>' +
423
        '   </span>' +
424
        '   <input class="form-control filter" type="text">' +
425
        '   <div class="btn-group buttons">' +
426
        '     <button type="button" class="btn remove"></button>' +
427
        '     <button type="button" class="btn removeall"></button>' +
428
        '   </div>' +
429
        '   <select multiple="multiple"></select>' +
430
        ' </div>' +
431
        '</div>')
432
        .insertBefore(this.element);
433

434
      // Cache the inner elements
435
      this.elements = {
436
        originalSelect: this.element,
437
        box1: $('.box1', this.container),
438
        box2: $('.box2', this.container),
439
        filterInput1: $('.box1 .filter', this.container),
440
        filterInput2: $('.box2 .filter', this.container),
441
        filterClear1: $('.box1 .clear1', this.container),
442
        filterClear2: $('.box2 .clear2', this.container),
443
        label1: $('.box1 > label', this.container),
444
        label2: $('.box2 > label', this.container),
445
        info1: $('.box1 .info', this.container),
446
        info2: $('.box2 .info', this.container),
447
        select1: $('.box1 select', this.container),
448
        select2: $('.box2 select', this.container),
449
        moveButton: $('.box1 .move', this.container),
450
        removeButton: $('.box2 .remove', this.container),
451
        moveAllButton: $('.box1 .moveall', this.container),
452
        removeAllButton: $('.box2 .removeall', this.container),
453
        form: $($('.box1 .filter', this.container)[0].form)
454
      };
455

456
      // Set select IDs
457
      this.originalSelectName = this.element.attr('name') || '';
458
      var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
459
        select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
460
      this.elements.select1.attr('id', select1Id);
461
      this.elements.select2.attr('id', select2Id);
462
      this.elements.label1.attr('for', select1Id);
463
      this.elements.label2.attr('for', select2Id);
464

465
      // Apply all settings
466
      this.selectedElements = 0;
467
      this.sortIndex = 0;
468
      this.elementCount = 0;
469
      this.setFilterTextClear(this.settings.filterTextClear);
470
      this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
471
      this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
472
      this.setMoveAllLabel(this.settings.moveAllLabel);
473
      this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
474
      this.setRemoveAllLabel(this.settings.removeAllLabel);
475
      this.setMoveOnSelect(this.settings.moveOnSelect);
476
      this.setMoveOnDoubleClick(this.settings.moveOnDoubleClick);
477
      this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
478
      this.setSelectedListLabel(this.settings.selectedListLabel);
479
      this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
480
      this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
481
      this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
482

483
      updateSelectionStates(this);
484

485
      this.setShowFilterInputs(this.settings.showFilterInputs);
486
      this.setNonSelectedFilter(this.settings.nonSelectedFilter);
487
      this.setSelectedFilter(this.settings.selectedFilter);
488
      this.setInfoText(this.settings.infoText);
489
      this.setInfoTextFiltered(this.settings.infoTextFiltered);
490
      this.setInfoTextEmpty(this.settings.infoTextEmpty);
491
      this.setFilterOnValues(this.settings.filterOnValues);
492
      this.setSortByInputOrder(this.settings.sortByInputOrder);
493
      this.setEventMoveOverride(this.settings.eventMoveOverride);
494
      this.setEventMoveAllOverride(this.settings.eventMoveAllOverride);
495
      this.setEventRemoveOverride(this.settings.eventRemoveOverride);
496
      this.setEventRemoveAllOverride(this.settings.eventRemoveAllOverride);
497
      this.setBtnClass(this.settings.btnClass);
498
      this.setBtnMoveText(this.settings.btnMoveText);
499
      this.setBtnRemoveText(this.settings.btnRemoveText);
500
      this.setBtnMoveAllText(this.settings.btnMoveAllText);
501
      this.setBtnRemoveAllText(this.settings.btnRemoveAllText);
502

503
      // Hide the original select
504
      this.element.hide();
505

506
      bindEvents(this);
507
      refreshSelects(this);
508

509
      return this.element;
510
    },
511
    setFilterTextClear: function(value, refresh) {
512
      this.settings.filterTextClear = value;
513
      this.elements.filterClear1.html(value);
514
      this.elements.filterClear2.html(value);
515
      if (refresh) {
516
        refreshSelects(this);
517
      }
518
      return this.element;
519
    },
520
    setFilterPlaceHolder: function(value, refresh) {
521
      this.settings.filterPlaceHolder = value;
522
      this.elements.filterInput1.attr('placeholder', value);
523
      this.elements.filterInput2.attr('placeholder', value);
524
      if (refresh) {
525
        refreshSelects(this);
526
      }
527
      return this.element;
528
    },
529
    setMoveSelectedLabel: function(value, refresh) {
530
      this.settings.moveSelectedLabel = value;
531
      this.elements.moveButton.attr('title', value);
532
      if (refresh) {
533
        refreshSelects(this);
534
      }
535
      return this.element;
536
    },
537
    setMoveAllLabel: function(value, refresh) {
538
      this.settings.moveAllLabel = value;
539
      this.elements.moveAllButton.attr('title', value);
540
      if (refresh) {
541
        refreshSelects(this);
542
      }
543
      return this.element;
544
    },
545
    setRemoveSelectedLabel: function(value, refresh) {
546
      this.settings.removeSelectedLabel = value;
547
      this.elements.removeButton.attr('title', value);
548
      if (refresh) {
549
        refreshSelects(this);
550
      }
551
      return this.element;
552
    },
553
    setRemoveAllLabel: function(value, refresh) {
554
      this.settings.removeAllLabel = value;
555
      this.elements.removeAllButton.attr('title', value);
556
      if (refresh) {
557
        refreshSelects(this);
558
      }
559
      return this.element;
560
    },
561
    setMoveOnSelect: function(value, refresh) {
562
      if (isBuggyAndroid) {
563
        value = true;
564
      }
565
      this.settings.moveOnSelect = value;
566
      if (this.settings.moveOnSelect) {
567
        this.container.addClass('moveonselect');
568
        var self = this;
569
        this.elements.select1.on('change', function() {
570
          move(self);
571
        });
572
        this.elements.select2.on('change', function() {
573
          remove(self);
574
        });
575
        this.elements.moveButton.detach();
576
        this.elements.removeButton.detach();
577
      } else {
578
        this.container.removeClass('moveonselect');
579
        this.elements.select1.off('change');
580
        this.elements.select2.off('change');
581
        this.elements.moveButton.insertAfter(this.elements.moveAllButton);
582
        this.elements.removeButton.insertBefore(this.elements.removeAllButton);
583
      }
584
      if (refresh) {
585
        refreshSelects(this);
586
      }
587
      return this.element;
588
    },
589
    setMoveOnDoubleClick: function(value, refresh) {
590
      if (isBuggyAndroid) {
591
        value = false;
592
      }
593
      this.settings.moveOnDoubleClick = value;
594
      if (this.settings.moveOnDoubleClick) {
595
        this.container.addClass('moveondoubleclick');
596
        var self = this;
597
        this.elements.select1.on('dblclick', function() {
598
          move(self);
599
        });
600
        this.elements.select2.on('dblclick', function() {
601
          remove(self);
602
        });
603
      } else {
604
        this.container.removeClass('moveondoubleclick');
605
        this.elements.select1.off('dblclick');
606
        this.elements.select2.off('dblclick');
607
      }
608
      if (refresh) {
609
        refreshSelects(this);
610
      }
611
      return this.element;
612
    },
613
    setPreserveSelectionOnMove: function(value, refresh) {
614
      // We are forcing to move on select and disabling preserveSelectionOnMove on Android
615
      if (isBuggyAndroid) {
616
        value = false;
617
      }
618
      this.settings.preserveSelectionOnMove = value;
619
      if (refresh) {
620
        refreshSelects(this);
621
      }
622
      return this.element;
623
    },
624
    setSelectedListLabel: function(value, refresh) {
625
      this.settings.selectedListLabel = value;
626
      if (value) {
627
        this.elements.label2.show().html(value);
628
      } else {
629
        this.elements.label2.hide().html(value);
630
      }
631
      if (refresh) {
632
        refreshSelects(this);
633
      }
634
      return this.element;
635
    },
636
    setNonSelectedListLabel: function(value, refresh) {
637
      this.settings.nonSelectedListLabel = value;
638
      if (value) {
639
        this.elements.label1.show().html(value);
640
      } else {
641
        this.elements.label1.hide().html(value);
642
      }
643
      if (refresh) {
644
        refreshSelects(this);
645
      }
646
      return this.element;
647
    },
648
    setHelperSelectNamePostfix: function(value, refresh) {
649
      this.settings.helperSelectNamePostfix = value;
650
      if (value) {
651
        this.elements.select1.attr('name', this.originalSelectName + value + '1');
652
        this.elements.select2.attr('name', this.originalSelectName + value + '2');
653
      } else {
654
        this.elements.select1.removeAttr('name');
655
        this.elements.select2.removeAttr('name');
656
      }
657
      if (refresh) {
658
        refreshSelects(this);
659
      }
660
      return this.element;
661
    },
662
    setSelectOrMinimalHeight: function(value, refresh) {
663
      this.settings.selectorMinimalHeight = value;
664
      var height = this.element.height();
665
      if (this.element.height() < value) {
666
        height = value;
667
      }
668
      this.elements.select1.height(height);
669
      this.elements.select2.height(height);
670
      if (refresh) {
671
        refreshSelects(this);
672
      }
673
      return this.element;
674
    },
675
    setShowFilterInputs: function(value, refresh) {
676
      if (!value) {
677
        this.setNonSelectedFilter('');
678
        this.setSelectedFilter('');
679
        refreshSelects(this);
680
        this.elements.filterInput1.hide();
681
        this.elements.filterInput2.hide();
682
      } else {
683
        this.elements.filterInput1.show();
684
        this.elements.filterInput2.show();
685
      }
686
      this.settings.showFilterInputs = value;
687
      if (refresh) {
688
        refreshSelects(this);
689
      }
690
      return this.element;
691
    },
692
    setNonSelectedFilter: function(value, refresh) {
693
      if (this.settings.showFilterInputs) {
694
        this.settings.nonSelectedFilter = value;
695
        this.elements.filterInput1.val(value);
696
        if (refresh) {
697
          refreshSelects(this);
698
        }
699
        return this.element;
700
      }
701
    },
702
    setSelectedFilter: function(value, refresh) {
703
      if (this.settings.showFilterInputs) {
704
        this.settings.selectedFilter = value;
705
        this.elements.filterInput2.val(value);
706
        if (refresh) {
707
          refreshSelects(this);
708
        }
709
        return this.element;
710
      }
711
    },
712
    setInfoText: function(value, refresh) {
713
      this.settings.infoText = value;
714
      if (value) {
715
        this.elements.info1.show();
716
        this.elements.info2.show();
717
      } else {
718
        this.elements.info1.hide();
719
        this.elements.info2.hide();
720
      }
721
      if (refresh) {
722
        refreshSelects(this);
723
      }
724
      return this.element;
725
    },
726
    setInfoTextFiltered: function(value, refresh) {
727
      this.settings.infoTextFiltered = value;
728
      if (refresh) {
729
        refreshSelects(this);
730
      }
731
      return this.element;
732
    },
733
    setInfoTextEmpty: function(value, refresh) {
734
      this.settings.infoTextEmpty = value;
735
      if (refresh) {
736
        refreshSelects(this);
737
      }
738
      return this.element;
739
    },
740
    setFilterOnValues: function(value, refresh) {
741
      this.settings.filterOnValues = value;
742
      if (refresh) {
743
        refreshSelects(this);
744
      }
745
      return this.element;
746
    },
747
    setSortByInputOrder: function(value, refresh){
748
        this.settings.sortByInputOrder = value;
749
        if (refresh) {
750
          refreshSelects(this);
751
        }
752
        return this.element;
753
    },
754
    setEventMoveOverride: function(value, refresh) {
755
        this.settings.eventMoveOverride = value;
756
        if (refresh) {
757
          refreshSelects(this);
758
        }
759
        return this.element;
760
    },
761
    setEventMoveAllOverride: function(value, refresh) {
762
        this.settings.eventMoveAllOverride = value;
763
        if (refresh) {
764
          refreshSelects(this);
765
        }
766
        return this.element;
767
    },
768
    setEventRemoveOverride: function(value, refresh) {
769
        this.settings.eventRemoveOverride = value;
770
        if (refresh) {
771
          refreshSelects(this);
772
        }
773
        return this.element;
774
    },
775
    setEventRemoveAllOverride: function(value, refresh) {
776
        this.settings.eventRemoveAllOverride = value;
777
        if (refresh) {
778
          refreshSelects(this);
779
        }
780
        return this.element;
781
    },
782
    setBtnClass: function(value, refresh) {
783
      this.settings.btnClass = value;
784
      this.elements.moveButton.attr('class', 'btn move').addClass(value);
785
      this.elements.removeButton.attr('class', 'btn remove').addClass(value);
786
      this.elements.moveAllButton.attr('class', 'btn moveall').addClass(value);
787
      this.elements.removeAllButton.attr('class', 'btn removeall').addClass(value);
788
      if (refresh) {
789
        refreshSelects(this);
790
      }
791
      return this.element;
792
    },
793
    setBtnMoveText: function(value, refresh) {
794
      this.settings.btnMoveText = value;
795
      this.elements.moveButton.html(value);
796
      if (refresh) {
797
        refreshSelects(this);
798
      }
799
      return this.element;
800
    },
801
    setBtnRemoveText: function(value, refresh) {
802
      this.settings.btnMoveText = value;
803
      this.elements.removeButton.html(value);
804
      if (refresh) {
805
        refreshSelects(this);
806
      }
807
      return this.element;
808
    },
809
    setBtnMoveAllText: function(value, refresh) {
810
      this.settings.btnMoveText = value;
811
      this.elements.moveAllButton.html(value);
812
      if (refresh) {
813
        refreshSelects(this);
814
      }
815
      return this.element;
816
    },
817
    setBtnRemoveAllText: function(value, refresh) {
818
      this.settings.btnMoveText = value;
819
      this.elements.removeAllButton.html(value);
820
      if (refresh) {
821
        refreshSelects(this);
822
      }
823
      return this.element;
824
    },
825
    getContainer: function() {
826
      return this.container;
827
    },
828
    refresh: function(mustClearSelections) {
829
      updateSelectionStates(this);
830

831
      if (!mustClearSelections) {
832
        saveSelections(this, 1);
833
        saveSelections(this, 2);
834
      } else {
835
        clearSelections(this);
836
      }
837

838
      refreshSelects(this);
839
    },
840
    destroy: function() {
841
      this.container.remove();
842
      this.element.show();
843
      $.data(this, 'plugin_' + pluginName, null);
844
      return this.element;
845
    }
846
  };
847

848
  // A really lightweight plugin wrapper around the constructor,
849
  // preventing against multiple instantiations
850
  $.fn[ pluginName ] = function (options) {
851
    var args = arguments;
852

853
    // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
854
    if (options === undefined || typeof options === 'object') {
855
      return this.each(function () {
856
        // If this is not a select
857
        if (!$(this).is('select')) {
858
          $(this).find('select').each(function(index, item) {
859
            // For each nested select, instantiate the Dual List Box
860
            $(item).bootstrapDualListbox(options);
861
          });
862
        } else if (!$.data(this, 'plugin_' + pluginName)) {
863
          // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
864

865
          // if it has no instance, create a new one, pass options to our plugin constructor,
866
          // and store the plugin instance in the elements jQuery data object.
867
          $.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
868
        }
869
      });
870
      // If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
871
      // treat this as a call to a public method.
872
    } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
873

874
      // Cache the method call to make it possible to return a value
875
      var returns;
876

877
      this.each(function () {
878
        var instance = $.data(this, 'plugin_' + pluginName);
879
        // Tests that there's already a plugin-instance and checks that the requested public method exists
880
        if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
881
          // Call the method of our plugin instance, and pass it the supplied arguments.
882
          returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
883
        }
884
      });
885

886
      // If the earlier cached method gives a value back return the value,
887
      // otherwise return this to preserve chainability.
888
      return returns !== undefined ? returns : this;
889
    }
890

891
  };
892

893
}));
894

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.