bootstrap-multiselect_rails 0.9.4 → 0.9.5

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0408e8efe212dd67894af953f92040d999bfbcb0
4
+ data.tar.gz: d57f73b32a109390f97a4ee70fab3d5aa62d00c2
5
+ SHA512:
6
+ metadata.gz: de5dab8cd79b54ea807d862ed69ebe04510f4d55a31b933097ab8c098691d0fc5e51b42c9bde5874b1a2cdec1a4033b58b2c4f71a0d023d8ee4e49768fe093bf
7
+ data.tar.gz: 520049895048b42e58280de5819fab8421ae16d7fd8f06f2157bb40f8fc4903b99bea46aa772292917a12dd2d8e0f88a63195e34c7e18783941afb20d07ccbe8
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # bootstrap-multiselect_rails
2
2
 
3
- This gem packages the [bootstrap-multiselect](https://github.com/davidstutz/bootstrap-multiselect) library for the Rails 3.1+ asset pipeline.
3
+ [![Gem Version](https://badge.fury.io/rb/bootstrap-multiselect_rails.svg)](http://badge.fury.io/rb/bootstrap-multiselect_rails)
4
4
 
5
+ This gem packages the [bootstrap-multiselect](https://github.com/davidstutz/bootstrap-multiselect) library for the Rails 3.1+ asset pipeline.
5
6
 
6
7
  ## Installation
7
8
 
@@ -1,5 +1,5 @@
1
1
  module BootstrapMultiselect
2
2
  module Rails
3
- VERSION = '0.9.4'
3
+ VERSION = '0.9.5'
4
4
  end
5
5
  end
@@ -7,8 +7,17 @@
7
7
  * Dual licensed under the BSD-3-Clause and the Apache License, Version 2.0.
8
8
  */
9
9
  !function($) {
10
-
10
+
11
11
  "use strict";// jshint ;_;
12
+
13
+ if (Array.prototype.forEach === null || Array.prototype.forEach === undefined) {
14
+ Array.prototype.forEach = function (func) {
15
+ var index;
16
+ for (index = 0; index < this.length; ++index) {
17
+ func(this[index]);
18
+ }
19
+ };
20
+ }
12
21
 
13
22
  if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
14
23
  ko.bindingHandlers.multiselect = {
@@ -97,8 +106,8 @@
97
106
  // Build select all if enabled.
98
107
  this.buildContainer();
99
108
  this.buildButton();
100
- this.buildSelectAll();
101
109
  this.buildDropdown();
110
+ this.buildSelectAll();
102
111
  this.buildDropdownOptions();
103
112
  this.buildFilter();
104
113
 
@@ -216,10 +225,10 @@
216
225
  templates: {
217
226
  button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"></button>',
218
227
  ul: '<ul class="multiselect-container dropdown-menu"></ul>',
219
- filter: '<div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div>',
228
+ filter: '<li class="multiselect-item filter"><div class="input-group"><span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span><input class="form-control multiselect-search" type="text"></div></li>',
220
229
  li: '<li><a href="javascript:void(0);"><label></label></a></li>',
221
- divider: '<li class="divider"></li>',
222
- liGroup: '<li><label class="multiselect-group"></label></li>'
230
+ divider: '<li class="multiselect-item divider"></li>',
231
+ liGroup: '<li class="multiselect-item group"><label class="multiselect-group"></label></li>'
223
232
  }
224
233
  },
225
234
 
@@ -300,6 +309,10 @@
300
309
  // Support optgroups and options without a group simultaneously.
301
310
  var tag = $(element).prop('tagName')
302
311
  .toLowerCase();
312
+
313
+ if ($(element).prop('value') == this.options.selectAllValue) {
314
+ return;
315
+ }
303
316
 
304
317
  if (tag === 'optgroup') {
305
318
  this.createOptgroup(element);
@@ -345,56 +358,51 @@
345
358
  var $checkboxesNotThis = $('input', this.$container).not($target);
346
359
 
347
360
  if (isSelectAllOption) {
348
- var values = [];
349
-
350
- // Select the visible checkboxes except the "select-all" and possible divider.
351
- var availableInputs = $('li input[value!="' + this.options.selectAllValue + '"][data-role!="divider"]', this.$ul).filter(':visible');
352
- for (var i = 0, j = availableInputs.length; i < j; i++) {
353
- values.push(availableInputs[i].value);
354
- }
355
-
356
361
  if (checked) {
357
- this.select(values);
362
+ this.selectall();
358
363
  }
359
364
  else {
360
- this.deselect(values);
365
+ this.deselectall();
361
366
  }
362
367
  }
363
368
 
364
- if (checked) {
365
- $option.prop('selected', true);
366
-
367
- if (this.options.multiple) {
368
- // Simply select additional option.
369
+ if(!isSelectAllOption){
370
+ if (checked) {
369
371
  $option.prop('selected', true);
370
- }
371
- else {
372
- // Unselect all other options and corresponding checkboxes.
373
- if (this.options.selectedClass) {
374
- $($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
372
+
373
+ if (this.options.multiple) {
374
+ // Simply select additional option.
375
+ $option.prop('selected', true);
375
376
  }
377
+ else {
378
+ // Unselect all other options and corresponding checkboxes.
379
+ if (this.options.selectedClass) {
380
+ $($checkboxesNotThis).parents('li').removeClass(this.options.selectedClass);
381
+ }
376
382
 
377
- $($checkboxesNotThis).prop('checked', false);
378
- $optionsNotThis.prop('selected', false);
383
+ $($checkboxesNotThis).prop('checked', false);
384
+ $optionsNotThis.prop('selected', false);
379
385
 
380
- // It's a single selection, so close.
381
- this.$button.click();
382
- }
386
+ // It's a single selection, so close.
387
+ this.$button.click();
388
+ }
383
389
 
384
- if (this.options.selectedClass === "active") {
385
- $optionsNotThis.parents("a").css("outline", "");
390
+ if (this.options.selectedClass === "active") {
391
+ $optionsNotThis.parents("a").css("outline", "");
392
+ }
393
+ }
394
+ else {
395
+ // Unselect option.
396
+ $option.prop('selected', false);
386
397
  }
387
- }
388
- else {
389
- // Unselect option.
390
- $option.prop('selected', false);
391
398
  }
392
399
 
393
400
  this.$select.change();
394
- this.options.onChange($option, checked);
395
-
401
+
396
402
  this.updateButtonText();
397
403
  this.updateSelectAll();
404
+
405
+ this.options.onChange($option, checked);
398
406
 
399
407
  if(this.options.preventInputChangeEvent) {
400
408
  return false;
@@ -440,7 +448,7 @@
440
448
  });
441
449
 
442
450
  // Keyboard support.
443
- this.$container.on('keydown', $.proxy(function(event) {
451
+ this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {
444
452
  if ($('input[type="text"]', this.$container).is(':focus')) {
445
453
  return;
446
454
  }
@@ -451,7 +459,7 @@
451
459
  this.$button.click();
452
460
  }
453
461
  else {
454
- var $items = $(this.$container).find("li:not(.divider):visible a");
462
+ var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible");
455
463
 
456
464
  if (!$items.length) {
457
465
  return;
@@ -511,6 +519,7 @@
511
519
  $checkbox.val(value);
512
520
 
513
521
  if (value === this.options.selectAllValue) {
522
+ $li.addClass("multiselect-item multiselect-all");
514
523
  $checkbox.parent().parent()
515
524
  .addClass('multiselect-all');
516
525
  }
@@ -522,6 +531,8 @@
522
531
  if ($(element).is(':disabled')) {
523
532
  $checkbox.attr('disabled', 'disabled')
524
533
  .prop('disabled', true)
534
+ .parents('a')
535
+ .attr("tabindex", "-1")
525
536
  .parents('li')
526
537
  .addClass('disabled');
527
538
  }
@@ -570,20 +581,35 @@
570
581
 
571
582
  /**
572
583
  * Build the selct all.
573
- * Checks if a select all ahs already been created.
584
+ * Checks if a select all has already been created.
574
585
  */
575
586
  buildSelectAll: function() {
576
587
  var alreadyHasSelectAll = this.hasSelectAll();
577
588
 
578
589
  if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
579
- && $('option[data-role!="divider"]', this.$select).length > this.options.includeSelectAllIfMoreThan) {
590
+ && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {
580
591
 
581
592
  // Check whether to add a divider after the select all.
582
593
  if (this.options.includeSelectAllDivider) {
583
- this.$select.prepend('<option value="" disabled="disabled" data-role="divider">');
594
+ this.$ul.prepend($(this.options.templates.divider));
584
595
  }
585
-
586
- this.$select.prepend('<option value="' + this.options.selectAllValue + '">' + this.options.selectAllText + '</option>');
596
+
597
+ var $li = $(this.options.templates.li);
598
+ $('label', $li).addClass("checkbox");
599
+ $('label', $li).append('<input type="checkbox" name="' + this.options.checkboxName + '" />');
600
+
601
+ var $checkbox = $('input', $li);
602
+ $checkbox.val(this.options.selectAllValue);
603
+
604
+ $li.addClass("multiselect-item multiselect-all");
605
+ $checkbox.parent().parent()
606
+ .addClass('multiselect-all');
607
+
608
+ $('label', $li).append(" " + this.options.selectAllText);
609
+
610
+ this.$ul.prepend($li);
611
+
612
+ $checkbox.prop('checked', false);
587
613
  }
588
614
  },
589
615
 
@@ -641,16 +667,16 @@
641
667
  }
642
668
 
643
669
  if (showElement) {
644
- $(element).show();
670
+ $(element).show().removeClass("filter-hidden");
645
671
  }
646
672
  else {
647
- $(element).hide();
673
+ $(element).hide().addClass("filter-hidden");
648
674
  }
649
675
  }
650
676
  }, this));
651
677
  }
652
678
 
653
- // TODO: check whether select all option needs to be updated.
679
+ this.updateSelectAll();
654
680
  }, this), 300, this);
655
681
  }, this));
656
682
  }
@@ -725,6 +751,11 @@
725
751
  var $option = this.getOptionByValue(value);
726
752
  var $checkbox = this.getInputByValue(value);
727
753
 
754
+ if($option === void(0) || $checkbox === void(0))
755
+ {
756
+ continue;
757
+ }
758
+
728
759
  if (this.options.selectedClass) {
729
760
  $checkbox.parents('li')
730
761
  .addClass(this.options.selectedClass);
@@ -742,20 +773,9 @@
742
773
  *
743
774
  */
744
775
  clearSelection: function () {
745
-
746
- var selected = this.getSelected();
747
-
748
- if (selected.length) {
749
-
750
- var arry = [];
751
-
752
- for (var i = 0; i < selected.length; i = i + 1) {
753
- arry.push(selected[i].value);
754
- }
755
-
756
- this.deselect(arry);
757
- this.$select.change();
758
- }
776
+ this.deselectall(false);
777
+ this.updateButtonText();
778
+ this.updateSelectAll();
759
779
  },
760
780
 
761
781
  /**
@@ -775,6 +795,11 @@
775
795
  var $option = this.getOptionByValue(value);
776
796
  var $checkbox = this.getInputByValue(value);
777
797
 
798
+ if($option === void(0) || $checkbox === void(0))
799
+ {
800
+ continue;
801
+ }
802
+
778
803
  if (this.options.selectedClass) {
779
804
  $checkbox.parents('li')
780
805
  .removeClass(this.options.selectedClass);
@@ -786,6 +811,57 @@
786
811
 
787
812
  this.updateButtonText();
788
813
  },
814
+
815
+ /**
816
+ * Selects all enabled & visible options.
817
+ *
818
+ */
819
+ selectall: function () {
820
+ var allCheckboxes = $("li input[type='checkbox']:enabled", this.$ul),
821
+ visibleCheckboxes = allCheckboxes.filter(":visible"),
822
+ allCheckboxesCount = allCheckboxes.length,
823
+ visibleCheckboxesCount = visibleCheckboxes.length;
824
+
825
+ visibleCheckboxes.prop('checked', true);
826
+ $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").addClass(this.options.selectedClass);
827
+
828
+ if (allCheckboxesCount === visibleCheckboxesCount) {
829
+ $("option:enabled", this.$select).prop('selected', true);
830
+ }
831
+ else {
832
+ var values = visibleCheckboxes.map(function() { return $(this).val() }).get();
833
+ $("option:enabled", this.$select).filter(function(index){ return $.inArray($(this).val(), values) !== -1; }).prop('selected', true);
834
+ }
835
+ },
836
+
837
+ /**
838
+ * Deselects all options.
839
+ * If justVisible is true or not specified, only visible options are deselected.
840
+ *
841
+ * @param {Boolean} justVisible
842
+ */
843
+ deselectall: function (justVisible) {
844
+ var allCheckboxes = $("li input[type='checkbox']:enabled", this.$ul),
845
+ justVisible = typeof justVisible === 'undefined' ? true : justVisible,
846
+ visibleCheckboxes = void(0);
847
+
848
+ if(justVisible) {
849
+ var values = void(0);
850
+ visibleCheckboxes = allCheckboxes.filter(":visible");
851
+ visibleCheckboxes.prop('checked', false);
852
+
853
+ values = visibleCheckboxes.map(function() { return $(this).val() }).get();
854
+
855
+ $("option:enabled", this.$select).filter(function(index){ return $.inArray($(this).val(), values) !== -1; }).prop('selected', false);
856
+
857
+ $("li:not(.divider):not(.disabled)", this.$ul).filter(":visible").removeClass(this.options.selectedClass);
858
+
859
+ }else {
860
+ allCheckboxes.prop('checked', false);
861
+ $("option:enabled", this.$select).prop('selected', false);
862
+ $("li:not(.divider):not(.disabled)", this.$ul).removeClass(this.options.selectedClass);
863
+ }
864
+ },
789
865
 
790
866
  /**
791
867
  * Rebuild the plugin.
@@ -794,9 +870,6 @@
794
870
  rebuild: function() {
795
871
  this.$ul.html('');
796
872
 
797
- // Remove select all option in select.
798
- $('option[value="' + this.options.selectAllValue + '"]', this.$select).remove();
799
-
800
873
  // Important to distinguish between radios and checkboxes.
801
874
  this.options.multiple = this.$select.attr('multiple') === "multiple";
802
875
 
@@ -806,6 +879,10 @@
806
879
 
807
880
  this.updateButtonText();
808
881
  this.updateSelectAll();
882
+
883
+ if (this.options.dropRight) {
884
+ this.$ul.addClass('pull-right');
885
+ }
809
886
  },
810
887
 
811
888
  /**
@@ -815,10 +892,24 @@
815
892
  */
816
893
  dataprovider: function(dataprovider) {
817
894
  var optionDOM = "";
818
- dataprovider.forEach(function (option) {
819
- optionDOM += '<option value="' + option.value + '">' + option.label + '</option>';
820
- });
895
+ var groupCounter = 0;
896
+
897
+ $.each(dataprovider, function (option) {
898
+ if ($.isArray(option.children)) {
899
+ groupCounter++;
900
+ optionDOM += '<optgroup label="' + (option.title || 'Group ' + groupCounter) + '">';
821
901
 
902
+ option.children.forEach(function(subOption) {
903
+ optionDOM += '<option value="' + subOption.value + '">' + (subOption.label || subOption.value) + '</option>';
904
+ });
905
+
906
+ optionDOM += '</optgroup>';
907
+ }
908
+ else {
909
+ optionDOM += '<option value="' + option.value + '">' + (option.label || option.value) + '</option>';
910
+ }
911
+ });
912
+
822
913
  this.$select.html(optionDOM);
823
914
  this.rebuild();
824
915
  },
@@ -861,26 +952,32 @@
861
952
  },
862
953
 
863
954
  /**
864
- * Checks whether a select all option is present.
955
+ * Checks whether a select all checkbox is present.
865
956
  *
866
957
  * @returns {Boolean}
867
958
  */
868
959
  hasSelectAll: function() {
869
- return $('option[value="' + this.options.selectAllValue + '"]', this.$select).length > 0;
960
+ return $('li.' + this.options.selectAllValue, this.$ul).length > 0;
870
961
  },
871
962
 
872
963
  /**
873
- * Updates the select all option based on the currently selected options.
964
+ * Updates the select all checkbox based on the currently displayed and selected checkboxes.
874
965
  */
875
966
  updateSelectAll: function() {
876
967
  if (this.hasSelectAll()) {
877
- var selected = this.getSelected();
968
+ var allBoxes = $("li:not(.multiselect-item):not(.filter-hidden) input:enabled", this.$ul),
969
+ allBoxesLength = allBoxes.length,
970
+ checkedBoxesLength = allBoxes.filter(":checked").length,
971
+ selectAllLi = $("li." + this.options.selectAllValue, this.$ul),
972
+ selectAllInput = selectAllLi.find("input");
878
973
 
879
- if (selected.length === $('option:not([data-role=divider])', this.$select).length - 1) {
880
- this.select(this.options.selectAllValue);
974
+ if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
975
+ selectAllInput.prop("checked", true);
976
+ selectAllLi.addClass(this.options.selectedClass);
881
977
  }
882
978
  else {
883
- this.deselect(this.options.selectAllValue);
979
+ selectAllInput.prop("checked", false);
980
+ selectAllLi.removeClass(this.options.selectedClass);
884
981
  }
885
982
  }
886
983
  },
@@ -905,9 +1002,7 @@
905
1002
  * @returns {jQUery}
906
1003
  */
907
1004
  getSelected: function() {
908
- return $('option[value!="' + this.options.selectAllValue + '"]:selected', this.$select).filter(function() {
909
- return $(this).prop('selected');
910
- });
1005
+ return $('option', this.$select).filter(":selected");
911
1006
  },
912
1007
 
913
1008
  /**
metadata CHANGED
@@ -1,46 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootstrap-multiselect_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
5
- prerelease:
4
+ version: 0.9.5
6
5
  platform: ruby
7
6
  authors:
8
7
  - Trevor Strieber
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-04-28 00:00:00.000000000 Z
11
+ date: 2014-07-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.3'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.3'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  description: This gem packages the Bootstrap multiselect (JS & CSS) for Rails 3.1+
@@ -51,36 +46,34 @@ executables: []
51
46
  extensions: []
52
47
  extra_rdoc_files: []
53
48
  files:
49
+ - LICENSE.txt
50
+ - README.md
54
51
  - lib/bootstrap-multiselect_rails.rb
55
52
  - lib/bootstrap-multiselect_rails/version.rb
56
- - vendor/assets/stylesheets/bootstrap-multiselect.css
57
53
  - vendor/assets/javascripts/bootstrap-multiselect.js
58
- - LICENSE.txt
59
- - README.md
54
+ - vendor/assets/stylesheets/bootstrap-multiselect.css
60
55
  homepage: http://github.com/TrevorS/bootstrap-multiselect_rails
61
56
  licenses:
62
57
  - MIT
58
+ metadata: {}
63
59
  post_install_message:
64
60
  rdoc_options: []
65
61
  require_paths:
66
62
  - lib
67
63
  required_ruby_version: !ruby/object:Gem::Requirement
68
- none: false
69
64
  requirements:
70
- - - ! '>='
65
+ - - ">="
71
66
  - !ruby/object:Gem::Version
72
67
  version: '0'
73
68
  required_rubygems_version: !ruby/object:Gem::Requirement
74
- none: false
75
69
  requirements:
76
- - - ! '>='
70
+ - - ">="
77
71
  - !ruby/object:Gem::Version
78
72
  version: '0'
79
73
  requirements: []
80
74
  rubyforge_project:
81
- rubygems_version: 1.8.23
75
+ rubygems_version: 2.2.2
82
76
  signing_key:
83
- specification_version: 3
77
+ specification_version: 4
84
78
  summary: Bootstrap 2/3 multiselect's JS & CSS for Rails 3.1+ asset pipeline.
85
79
  test_files: []
86
- has_rdoc: