11/**
22 * bootstrap-multiselect.js 1.0.0
33 * https://github.com/davidstutz/bootstrap-multiselect
4- *
5- * Copyright 2012 David Stutz
6- *
4+ *
5+ * Copyright 2012 David Stutz
6+ *
77 * Licensed under the Apache License, Version 2.0 (the "License");
88 * you may not use this file except in compliance with the License.
99 * You may obtain a copy of the License at
1818 */
1919! function ( $ ) {
2020
21- "use strict" ; // jshint ;_;
22-
23- function Multiselect ( select , options ) {
24-
25- this . options = this . getOptions ( options ) ;
26- this . select = $ ( select ) ;
27- this . container = $ ( this . options . buttonContainer )
28- . append ( '<button type="button" style="width:' + this . options . buttonWidth + '" class="dropdown-toggle ' + this . options . buttonClass + '" data-toggle="dropdown">' + this . options . buttonText ( $ ( 'option:selected' , select ) ) + '</button>' )
29- . append ( '<ul class="dropdown-menu"></ul>' ) ;
30-
31- // Set max height of dropdown menu to activate auto scrollbar.
32- if ( this . options . maxHeight ) {
33- $ ( 'ul' , this . container ) . css ( {
34- 'max-height' : this . options . maxHeight + 'px' ,
35- 'overflow-y' : 'auto' ,
36- 'overflow-x' : 'hidden' ,
37- } ) ;
38- }
39-
40- // Manually add the multiple attribute, if its not already set.
41- if ( ! this . select . attr ( 'multiple' ) ) {
42- this . select . attr ( 'multiple' , true ) ;
43- }
44-
45- // Build the dropdown.
46- $ ( 'option' , this . select ) . each ( $ . proxy ( function ( index , element ) {
47- if ( $ ( element ) . is ( ':selected' ) ) {
48- $ ( element ) . attr ( 'selected' , 'selected' ) ;
49- $ ( element ) . prop ( 'selected' , 'selected' ) ;
50- }
51-
52- $ ( 'ul' , this . container ) . append ( '<li><a href="javascript:void(0);" style="padding:0;"><label style="margin:0;padding:3px 20px 3px 20px;width:100%;height:100%;cursor:pointer;"><input style="margin-bottom:5px;" type="checkbox" value="' + $ ( element ) . val ( ) + '" /> ' + $ ( element ) . text ( ) + '</label</a></li>' ) ;
53-
54- var selected = $ ( element ) . prop ( 'selected' ) || false ;
55- var checkbox = $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) ;
56-
57- checkbox . prop ( 'checked' , selected ) ;
58-
59- if ( selected ) {
60- checkbox . parents ( 'li' ) . addClass ( 'active' ) ;
61- }
62- } , this ) ) ;
63-
64- this . select . hide ( )
65- . after ( this . container ) ;
66-
67- // Bind the change event on the dropdown elements.
68- $ ( 'ul li input[type="checkbox"]' , this . container ) . on ( 'change' , $ . proxy ( function ( event ) {
69- var checked = $ ( event . target ) . prop ( 'checked' ) || false ;
70-
71- if ( checked ) {
72- $ ( event . target ) . parents ( 'li' ) . addClass ( 'active' ) ;
73- }
74- else {
75- $ ( event . target ) . parents ( 'li' ) . removeClass ( 'active' ) ;
76- }
77-
78- var option = $ ( 'option[value="' + $ ( event . target ) . val ( ) + '"]' , this . select ) ;
79-
80- if ( checked ) {
81- option . attr ( 'selected' , 'selected' ) ;
82- option . prop ( 'selected' , 'selected' ) ;
83- }
84- else {
85- option . removeAttr ( 'selected' ) ;
86- }
87- console . log ( option ) ;
88- var options = $ ( 'option:selected' , this . select ) ;
89- $ ( 'button' , this . container ) . html ( this . options . buttonText ( options ) ) ;
90-
91- this . options . onChange ( option , checked ) ;
92- } , this ) ) ;
93-
94- $ ( 'ul li a' , this . container ) . on ( 'click' , function ( event ) {
95- event . stopPropagation ( ) ;
96- } ) ;
97- } ;
98-
99- Multiselect . prototype = {
100-
101- defaults : {
102- // Default text function will either print 'None selected' in case no option is selected,
103- // or a list of the selected options up to a length of 3 selected options.
104- // If more than 3 options are selected, the number of selected options is printed.
105- buttonText : function ( options ) {
106- if ( options . length == 0 ) {
107- return 'None selected <b class="caret"></b>' ;
108- }
109- else if ( options . length > 3 ) {
110- return options . length + ' selected <b class="caret"></b>' ;
111- }
112- else {
113- var selected = '' ;
114- options . each ( function ( ) {
115- selected += $ ( this ) . text ( ) + ', ' ;
116- } ) ;
117- return selected . substr ( 0 , selected . length - 2 ) + ' <b class="caret"></b>' ;
118- }
119- } ,
120- // Is triggered on change of the selected options.
121- onChange : function ( ) {
122-
123- } ,
124- buttonClass : 'btn' ,
125- buttonWidth : 'auto' ,
126- buttonContainer : '<div class="btn-group" />' ,
127- // Maximum height of thet dropdown menu.
128- // If maximum height is exceeded a scrollbar will be displayed.
129- maxHeight : 400 ,
130- } ,
131-
132- constructor : Multiselect ,
133-
134- reset : function ( ) {
135-
136- } ,
137-
138- // Destroy - unbind - the plugin.
139- destroy : function ( ) {
140- this . container . remove ( ) ;
141- this . select . show ( ) ;
142- } ,
143-
144- // Refreshs the checked options based on the current state of the select.
145- refresh : function ( ) {
146- $ ( 'option' , this . select ) . each ( $ . proxy ( function ( index , element ) {
147- if ( $ ( element ) . is ( ':selected' ) ) {
148- $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . prop ( 'checked' , true ) ;
149- $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . parents ( 'li' ) . addClass ( 'active' ) ;
150- }
151- else {
152- $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . prop ( 'checked' , false ) ;
153- $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . parents ( 'li' ) . removeClass ( 'active' ) ;
154- }
155- } , this ) ) ;
156-
157- $ ( 'button' , this . container ) . html ( this . options . buttonText ( $ ( 'option:selected' , this . select ) ) ) ;
158- } ,
159-
160- // Get options by merging defaults and given options.
161- getOptions : function ( options ) {
162- return $ . extend ( { } , this . defaults , options ) ;
163- }
164- } ;
165-
166- $ . fn . multiselect = function ( option ) {
167- return this . each ( function ( ) {
168- var data = $ ( this ) . data ( 'multiselect' ) ,
169- options = typeof option == 'object' && option ;
170-
171- if ( ! data ) {
172- $ ( this ) . data ( 'multiselect' , ( data = new Multiselect ( this , options ) ) ) ;
173- }
174-
175- if ( typeof option == 'string' ) {
176- data [ option ] ( ) ;
177- }
178- } ) ;
179- }
180- } ( window . jQuery ) ;
21+ "use strict" ; // jshint ;_;
22+
23+ if ( ko && ko . bindingHandlers && ! ko . bindingHandlers . multiselect ) {
24+ ko . bindingHandlers . multiselect = {
25+ init : function ( element ) {
26+ var ms = $ ( element ) . data ( 'multiselect' ) ;
27+
28+ if ( ! ms )
29+ throw new Error ( "Bootstrap-multiselect's multiselect() has to be called on element before applying the Knockout View model!" ) ;
30+
31+ var prev = ms . options . onChange ;
32+
33+ ms . options . onChange = function ( option , checked ) {
34+ // We dont want to refresh the multiselect since it would delete / recreate all items
35+ $ ( element ) . data ( 'blockRefresh' , true ) ;
36+
37+ // Force the binding to be updated by triggering the change event on the select element
38+ $ ( element ) . trigger ( 'change' ) ;
39+
40+ // Call any defined change handler
41+ return prev ( option , checked ) ;
42+ }
43+ } ,
44+ update : function ( element ) {
45+ var blockRefresh = $ ( element ) . data ( 'blockRefresh' ) || false ;
46+ if ( ! blockRefresh ) { $ ( element ) . multiselect ( "refresh" ) ; }
47+ $ . data ( element , 'blockRefresh' , false ) ;
48+ }
49+ } ;
50+ }
51+
52+ function Multiselect ( select , options ) {
53+
54+ this . options = this . getOptions ( options ) ;
55+ this . select = $ ( select ) ;
56+ this . container = $ ( this . options . buttonContainer )
57+ . append ( '<button type="button" class="dropdown-toggle ' + this . options . buttonClass + '" data-toggle="dropdown">' + this . options . buttonText ( $ ( 'option:selected' , select ) ) + '</button>' )
58+ . append ( '<ul class="dropdown-menu"></ul>' ) ;
59+
60+ // Set max height of dropdown menu to activate auto scrollbar.
61+ if ( this . options . maxHeight ) {
62+ $ ( 'ul' , this . container ) . css ( {
63+ 'max-height' : this . options . maxHeight + 'px' ,
64+ 'overflow-y' : 'auto' ,
65+ 'overflow-x' : 'hidden' ,
66+ } ) ;
67+ }
68+
69+ // Manually add the multiple attribute, if its not already set.
70+ if ( ! this . select . attr ( 'multiple' ) ) {
71+ this . select . attr ( 'multiple' , true ) ;
72+ }
73+
74+ this . addOptions ( select , options ) ;
75+
76+ this . select
77+ . hide ( )
78+ . after ( this . container ) ;
79+ } ;
80+
81+ Multiselect . prototype = {
82+ addOptions : function ( select , options ) {
83+
84+
85+ // Build the dropdown.
86+ $ ( 'option' , this . select ) . each ( $ . proxy ( function ( index , element ) {
87+ if ( $ ( element ) . is ( ':selected' ) ) {
88+ $ ( element ) . attr ( 'selected' , 'selected' ) ;
89+ $ ( element ) . prop ( 'selected' , 'selected' ) ;
90+ }
91+
92+ $ ( 'ul' , this . container ) . append ( '<li><a href="javascript:void(0);" style="padding:0;"><label style="margin:0;padding:3px 20px 3px 20px;width:100%;height:100%;cursor:pointer;"><input style="margin-bottom:5px;" type="checkbox" value="' + $ ( element ) . val ( ) + '" /> ' + $ ( element ) . text ( ) + '</label</a></li>' ) ;
93+
94+ var selected = $ ( element ) . prop ( 'selected' ) || false ;
95+ var checkbox = $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) ;
96+
97+ checkbox . prop ( 'checked' , selected ) ;
98+
99+ if ( selected ) {
100+ checkbox . parents ( 'li' ) . addClass ( 'active' ) ;
101+ }
102+ } , this ) ) ;
103+
104+ // Bind the change event on the dropdown elements.
105+ $ ( 'ul li input[type="checkbox"]' , this . container ) . on ( 'change' , $ . proxy ( function ( event ) {
106+ var checked = $ ( event . target ) . prop ( 'checked' ) || false ;
107+
108+ if ( checked ) {
109+ $ ( event . target ) . parents ( 'li' ) . addClass ( 'active' ) ;
110+ }
111+ else {
112+ $ ( event . target ) . parents ( 'li' ) . removeClass ( 'active' ) ;
113+ }
114+
115+ var option = $ ( 'option[value="' + $ ( event . target ) . val ( ) + '"]' , this . select ) ;
116+
117+ if ( checked ) {
118+ option . attr ( 'selected' , 'selected' ) ;
119+ option . prop ( 'selected' , 'selected' ) ;
120+ }
121+ else {
122+ option . removeAttr ( 'selected' ) ;
123+ }
124+ console . log ( option ) ;
125+ var options = $ ( 'option:selected' , this . select ) ;
126+ $ ( 'button' , this . container ) . html ( this . options . buttonText ( options ) ) ;
127+
128+ this . options . onChange ( option , checked ) ;
129+ } , this ) ) ;
130+
131+ $ ( 'ul li a' , this . container ) . on ( 'click' , function ( event ) {
132+ event . stopPropagation ( ) ;
133+ } ) ;
134+ } ,
135+ defaults : {
136+ // Default text function will either print 'None selected' in case no option is selected,
137+ // or a list of the selected options up to a length of 3 selected options.
138+ // If more than 3 options are selected, the number of selected options is printed.
139+ buttonText : function ( options ) {
140+ if ( options . length == 0 ) {
141+ return 'None selected <b class="caret"></b>' ;
142+ }
143+ else if ( options . length > 3 ) {
144+ return options . length + ' selected <b class="caret"></b>' ;
145+ }
146+ else {
147+ var selected = '' ;
148+ options . each ( function ( ) {
149+ selected += $ ( this ) . text ( ) + ', ' ;
150+ } ) ;
151+ return selected . substr ( 0 , selected . length - 2 ) + ' <b class="caret"></b>' ;
152+ }
153+ } ,
154+ // Is triggered on change of the selected options.
155+ onChange : function ( ) {
156+
157+ } ,
158+ buttonClass : 'btn' ,
159+ buttonWidth : 'auto' ,
160+ buttonContainer : '<div class="btn-group" />' ,
161+ // Maximum height of thet dropdown menu.
162+ // If maximum height is exceeded a scrollbar will be displayed.
163+ maxHeight : 400 ,
164+ } ,
165+
166+ constructor : Multiselect ,
167+
168+ reset : function ( ) {
169+
170+ } ,
171+
172+ // Destroy - unbind - the plugin.
173+ destroy : function ( ) {
174+ this . container . remove ( ) ;
175+ this . select . show ( ) ;
176+ } ,
177+
178+ // Refreshs the checked options based on the current state of the select.
179+ refresh : function ( ) {
180+ $ ( 'ul' , this . container ) . html ( '' ) ;
181+ this . addOptions ( this . select , this . options ) ;
182+
183+ $ ( 'option' , this . select ) . each ( $ . proxy ( function ( index , element ) {
184+ if ( $ ( element ) . is ( ':selected' ) ) {
185+ $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . prop ( 'checked' , true ) ;
186+ $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . parents ( 'li' ) . addClass ( 'active' ) ;
187+ }
188+ else {
189+ $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . prop ( 'checked' , false ) ;
190+ $ ( 'ul li input[value="' + $ ( element ) . val ( ) + '"]' , this . container ) . parents ( 'li' ) . removeClass ( 'active' ) ;
191+ }
192+ } , this ) ) ;
193+
194+ $ ( 'button' , this . container ) . html ( this . options . buttonText ( $ ( 'option:selected' , this . select ) ) ) ;
195+ } ,
196+
197+ // Get options by merging defaults and given options.
198+ getOptions : function ( options ) {
199+ return $ . extend ( { } , this . defaults , options ) ;
200+ }
201+ } ;
202+
203+ $ . fn . multiselect = function ( option ) {
204+ return this . each ( function ( ) {
205+ var data = $ ( this ) . data ( 'multiselect' ) ,
206+ options = typeof option == 'object' && option ;
207+
208+ if ( ! data ) {
209+ $ ( this ) . data ( 'multiselect' , ( data = new Multiselect ( this , options ) ) ) ;
210+ }
211+
212+ if ( typeof option == 'string' ) {
213+ data [ option ] ( ) ;
214+ }
215+ } ) ;
216+ }
217+ } ( window . jQuery ) ;
0 commit comments