bootstrap-multiselect_rails 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: