jumbo-jekyll-theme 5.7.0 → 5.7.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/_config.yml +42 -1
  3. data/_includes/blog/disqus_comments.html +1 -2
  4. data/_includes/blog/post_sidebar.html +3 -10
  5. data/_includes/components/breadcrumb.html +0 -3
  6. data/_includes/components/github_edit.html +21 -48
  7. data/_includes/components/head.html +2 -1
  8. data/_includes/components/schema.html +1 -43
  9. data/_includes/footer/footer.html +3 -0
  10. data/_includes/js_bundles/app.html +0 -1
  11. data/_includes/js_bundles/vendor.html +0 -1
  12. data/_includes/nav/nav.html +1 -1
  13. data/_includes/social_media_icons.html +10 -14
  14. data/_layouts/base.html +0 -1
  15. metadata +2 -39
  16. data/_data/settings.yml +0 -97
  17. data/_data/sidebar-nav.yml +0 -23
  18. data/_data/sticky-tab-bar.yml +0 -29
  19. data/_data/tags.yml +0 -11
  20. data/_includes/blog/post_tags.html +0 -9
  21. data/assets/css/main-blog.scss +0 -15
  22. data/assets/css/main-error.scss +0 -14
  23. data/assets/css/main-search.scss +0 -14
  24. data/assets/images/placeholder.png +0 -0
  25. data/assets/js/app/scroll-to-anchors.js +0 -11
  26. data/assets/js/app/sticky-tab-bar.js +0 -68
  27. data/assets/js/app/tables.js +0 -35
  28. data/assets/js/vendor/bootstrap-multiselect.js +0 -1776
  29. data/assets/js/vendor/cognito.js +0 -11
  30. data/assets/js/vendor/disqus-loader.js +0 -87
  31. data/assets/js/vendor/fess-ss.min.js +0 -24
  32. data/assets/js/vendor/jquery.doubleScroll.js +0 -128
  33. data/assets/js/vendor/jquery.rss.js +0 -333
  34. data/assets/js/vendor/jquery.slim.js +0 -8842
  35. data/assets/js/vendor/jquery.validate.js +0 -1601
  36. data/assets/js/vendor/loadCSS.js +0 -35
  37. data/assets/js/vendor/picturefill.js +0 -1471
  38. data/assets/js/vendor/shuffle.js +0 -2004
@@ -1,23 +0,0 @@
1
- pages:
2
- -
3
- list:
4
- -
5
- title: "Container Left Sidebar"
6
- url: /jekyll/layouts/container-left-sidebar/
7
- -
8
- title: "Container Right Sidebar"
9
- url: "/jekyll/layouts/container-right-sidebar/"
10
- -
11
- title: "Container Breadcrumb Left Sidebar"
12
- url: "/jekyll/layouts/container-breadcrumb-left-sidebar/"
13
- -
14
- title: "Container Breadcrumb Right Sidebar"
15
- url: "/jekyll/layouts/container-breadcrumb-right-sidebar/"
16
- # custom-include: custom
17
- # Custom includes can be used using the above setting. Simply add the name of the
18
- # jekyll _include file (without .html exetension) to the above setting and that will be used instead.
19
- urls: [
20
- /jekyll/layouts/container-breadcrumb-left-sidebar/,
21
- /jekyll/layouts/container-breadcrumb-right-sidebar/,
22
- /jekyll/layouts/container-left-sidebar/,
23
- /jekyll/layouts/container-right-sidebar/]
@@ -1,29 +0,0 @@
1
- pages:
2
- -
3
- list:
4
- -
5
- title: "Home"
6
- url: /
7
- -
8
- title: "About"
9
- url: "/about/"
10
- -
11
- title: "FAQ"
12
- url: "/faq/"
13
- -
14
- title: "Jekyll"
15
- url: "/jekyll/"
16
-
17
- urls: [
18
- /,
19
- /about/,
20
- /faq/,
21
- /jekyll/]
22
- -
23
- list:
24
- -
25
- title: "Container Breadcrumb"
26
- url: /jekyll/layouts/container-breadcrumb/
27
-
28
- urls: [
29
- /jekyll/layouts/container-breadcrumb/]
@@ -1,11 +0,0 @@
1
- items:
2
- - name: Productivity
3
- slug: productivity
4
- - name: News
5
- slug: news
6
- - name: Blog
7
- slug: blog
8
- - name: Case Study
9
- slug: case-study
10
- - name: Update
11
- slug: update
@@ -1,9 +0,0 @@
1
- {% if site.data.settings.blog.tags_enabled %}
2
- {% if post.tags %}
3
- <h3>Tags</h3>
4
- {% assign tags = post.tags %}
5
- {% for tag in tags %}
6
- <a class="btn btn-blog btn-xs post_tag" href="/blog/tag#{{tag | slugify }}">{{tag}}</a>
7
- {% endfor %}
8
- {% endif %}
9
- {% endif %}
@@ -1,15 +0,0 @@
1
- ---
2
- ---
3
- @charset "UTF-8";
4
- //Bootstrap Overrides
5
- @import "bootstrap/functions";
6
- @import "bootstrap/variables";
7
- @import "bootstrap/mixins";
8
-
9
- @import "app/overrides";
10
- //Boostrap Includes
11
- @import 'bootstrap/bootstrap';
12
- // Linaro Jekyll Theme Includes
13
- @import 'core';
14
- // Additional Core Includes
15
- @import 'blog';
@@ -1,14 +0,0 @@
1
- ---
2
- ---
3
- @charset "UTF-8";
4
- @import "bootstrap/functions";
5
- @import "bootstrap/variables";
6
- @import "bootstrap/mixins";
7
- // App Overrides - Sass variables
8
- @import "app/overrides";
9
- //Boostrap Includes
10
- @import 'bootstrap/bootstrap';
11
- // Core Theme
12
- @import 'core';
13
- //Additional Core includes
14
- @import "core/error";
@@ -1,14 +0,0 @@
1
- ---
2
- ---
3
- @charset "UTF-8";
4
- @import "bootstrap/functions";
5
- @import "bootstrap/variables";
6
- @import "bootstrap/mixins";
7
- //Bootstrap Overrides
8
- @import "app/overrides";
9
- //Boostrap Includes
10
- @import 'bootstrap/bootstrap';
11
- // Linaro Jekyll Theme Includes
12
- @import "core";
13
- // App Includes
14
- @import "app/search";
@@ -1,11 +0,0 @@
1
- // Animated scroll to anchors and offset
2
- var $root = $("html, body");
3
- $('#content-container a[href^="#"]').click(function() {
4
- $root.animate(
5
- {
6
- scrollTop: $($.attr(this, "href")).offset().top - 200
7
- },
8
- 500
9
- );
10
- return false;
11
- });
@@ -1,68 +0,0 @@
1
- $(document).ready(function() {
2
- // Check to see if the tabbed nav bar is in use.
3
- if ($("#tabbed-nav-bar").length > 0) {
4
- // Set the sub nav text
5
- var text = $("#tabbed-nav-bar ul.nav-tabs li.active a").text();
6
- $("#sub-navigation-header").text(text);
7
- console.log(text);
8
- // Menu selector
9
- var menu = $("#tabbed-nav-bar");
10
- // Get sub nav offset from the page top
11
- var origOffsetY = menu.offset().top;
12
- if ($("#universal-nav").length > 0) {
13
- origOffsetY = origOffsetY - 20;
14
- }
15
- // Instantiate Bootstrap 3 Affix plugin
16
- $("#tabbed-nav-bar").affix({
17
- offset: {
18
- top: origOffsetY
19
- }
20
- });
21
- // Event listeners
22
- $("#tabbed-nav-bar").on("affixed.bs.affix", function() {
23
- affixed();
24
- });
25
- $("#tabbed-nav-bar").on("affixed-top.bs.affix ", function() {
26
- affixTop();
27
- });
28
- function scroll() {
29
- if ($("#tabbed-nav-bar.affix-top").length > 0) {
30
- affixTop();
31
- }
32
- if ($("#tabbed-nav-bar.affix").length > 0) {
33
- affixed();
34
- }
35
- }
36
- function affixTop() {
37
- $("#tabbed-nav-bar").addClass("non-sticky-nav");
38
- $("#tabbed-nav-bar").removeClass("sticky-nav");
39
- $("nav#main-navigation").show();
40
- if ($(window).width() < 1000) {
41
- $("#tabbed-nav-bar ul.nav-tabs").addClass("nav-stacked");
42
- $("#sub-navigation-header").show();
43
- } else {
44
- $("#tabbed-nav-bar ul.nav-tabs").removeClass("nav-stacked");
45
- $("#sub-navigation-header").hide();
46
- }
47
- }
48
- function affixed() {
49
- // Set thge sticky-nav clas
50
- $("#tabbed-nav-bar").removeClass("non-sticky-nav");
51
- $("#tabbed-nav-bar").addClass("sticky-nav");
52
- // Hide the main navigation bar
53
- $("nav#main-navigation").hide();
54
- if ($(window).width() < 768) {
55
- $("#tabbed-nav-bar ul.nav-tabs").addClass("nav-stacked");
56
- $("#sub-navigation-header").show();
57
- } else {
58
- $("#tabbed-nav-bar ul.nav-tabs").removeClass("nav-stacked");
59
- $("#sub-navigation-header").hide();
60
- }
61
- }
62
- scroll();
63
- $(window).scroll(function() {
64
- scroll();
65
- });
66
- $(window).resize(scroll);
67
- }
68
- });
@@ -1,35 +0,0 @@
1
- var numShown = 5; // Initial rows shown & index
2
- var numMore = 5; // Increment
3
-
4
- var $table = $('table.hidden_rows').find('tbody'); // tbody containing all the rows
5
- var numRows = $table.find('tr').length; // Total # rows
6
-
7
- $(function () {
8
- // Hide rows and add clickable div
9
- $table.find('tr:gt(' + (numShown - 1) + ')').hide().end()
10
- .after('<tbody id="more"><tr><td colspan="' +
11
- $table.find('tr:first td').length + '"><div>Show <span>' +
12
- numMore + '</span> More</div</tbody></td></tr>');
13
-
14
- $('#more').click(function() {
15
- numShown = numShown + numMore;
16
- // no more "show more" if done
17
- if (numShown >= numRows) {
18
- $('#more').remove();
19
- }
20
- // change rows remaining if less than increment
21
- if (numRows - numShown < numMore) {
22
- $('#more span').html(numRows - numShown);
23
- }
24
- $table.find('tr:lt(' + numShown + ')').show();
25
- });
26
- $('#all').click(function() {
27
- numShown = numRows;
28
- // no more "show more" if done
29
- if (numShown >= numRows) {
30
- $('#all').remove();
31
- }
32
- $table.find('tr:lt(' + numShown + ')').show();
33
- });
34
-
35
- });
@@ -1,1776 +0,0 @@
1
- /**
2
- * Bootstrap Multiselect (http://davidstutz.de/bootstrap-multiselect/)
3
- *
4
- * Apache License, Version 2.0:
5
- * Copyright (c) 2012 - 2018 David Stutz
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
- * use this file except in compliance with the License. You may obtain a
9
- * copy of the License at http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
- * License for the specific language governing permissions and limitations
15
- * under the License.
16
- *
17
- * BSD 3-Clause License:
18
- * Copyright (c) 2012 - 2018 David Stutz
19
- * All rights reserved.
20
- *
21
- * Redistribution and use in source and binary forms, with or without
22
- * modification, are permitted provided that the following conditions are met:
23
- * - Redistributions of source code must retain the above copyright notice,
24
- * this list of conditions and the following disclaimer.
25
- * - Redistributions in binary form must reproduce the above copyright notice,
26
- * this list of conditions and the following disclaimer in the documentation
27
- * and/or other materials provided with the distribution.
28
- * - Neither the name of David Stutz nor the names of its contributors may be
29
- * used to endorse or promote products derived from this software without
30
- * specific prior written permission.
31
- *
32
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
39
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
41
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
42
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
- */
44
- (function (root, factory) {
45
- // check to see if 'knockout' AMD module is specified if using requirejs
46
- if (typeof define === 'function' && define.amd &&
47
- typeof require === 'function' && typeof require.specified === 'function' && require.specified('knockout')) {
48
-
49
- // AMD. Register as an anonymous module.
50
- define(['jquery', 'knockout'], factory);
51
- } else {
52
- // Browser globals
53
- factory(root.jQuery, root.ko);
54
- }
55
- })(this, function ($, ko) {
56
- "use strict";// jshint ;_;
57
-
58
- if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
59
- ko.bindingHandlers.multiselect = {
60
- after: ['options', 'value', 'selectedOptions', 'enable', 'disable'],
61
-
62
- init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
63
- var $element = $(element);
64
- var config = ko.toJS(valueAccessor());
65
-
66
- $element.multiselect(config);
67
-
68
- if (allBindings.has('options')) {
69
- var options = allBindings.get('options');
70
- if (ko.isObservable(options)) {
71
- ko.computed({
72
- read: function() {
73
- options();
74
- setTimeout(function() {
75
- var ms = $element.data('multiselect');
76
- if (ms)
77
- ms.updateOriginalOptions();//Not sure how beneficial this is.
78
- $element.multiselect('rebuild');
79
- }, 1);
80
- },
81
- disposeWhenNodeIsRemoved: element
82
- });
83
- }
84
- }
85
-
86
- //value and selectedOptions are two-way, so these will be triggered even by our own actions.
87
- //It needs some way to tell if they are triggered because of us or because of outside change.
88
- //It doesn't loop but it's a waste of processing.
89
- if (allBindings.has('value')) {
90
- var value = allBindings.get('value');
91
- if (ko.isObservable(value)) {
92
- ko.computed({
93
- read: function() {
94
- value();
95
- setTimeout(function() {
96
- $element.multiselect('refresh');
97
- }, 1);
98
- },
99
- disposeWhenNodeIsRemoved: element
100
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
101
- }
102
- }
103
-
104
- //Switched from arrayChange subscription to general subscription using 'refresh'.
105
- //Not sure performance is any better using 'select' and 'deselect'.
106
- if (allBindings.has('selectedOptions')) {
107
- var selectedOptions = allBindings.get('selectedOptions');
108
- if (ko.isObservable(selectedOptions)) {
109
- ko.computed({
110
- read: function() {
111
- selectedOptions();
112
- setTimeout(function() {
113
- $element.multiselect('refresh');
114
- }, 1);
115
- },
116
- disposeWhenNodeIsRemoved: element
117
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
118
- }
119
- }
120
-
121
- var setEnabled = function (enable) {
122
- setTimeout(function () {
123
- if (enable)
124
- $element.multiselect('enable');
125
- else
126
- $element.multiselect('disable');
127
- });
128
- };
129
-
130
- if (allBindings.has('enable')) {
131
- var enable = allBindings.get('enable');
132
- if (ko.isObservable(enable)) {
133
- ko.computed({
134
- read: function () {
135
- setEnabled(enable());
136
- },
137
- disposeWhenNodeIsRemoved: element
138
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
139
- } else {
140
- setEnabled(enable);
141
- }
142
- }
143
-
144
- if (allBindings.has('disable')) {
145
- var disable = allBindings.get('disable');
146
- if (ko.isObservable(disable)) {
147
- ko.computed({
148
- read: function () {
149
- setEnabled(!disable());
150
- },
151
- disposeWhenNodeIsRemoved: element
152
- }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
153
- } else {
154
- setEnabled(!disable);
155
- }
156
- }
157
-
158
- ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
159
- $element.multiselect('destroy');
160
- });
161
- },
162
-
163
- update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
164
- var $element = $(element);
165
- var config = ko.toJS(valueAccessor());
166
-
167
- $element.multiselect('setOptions', config);
168
- $element.multiselect('rebuild');
169
- }
170
- };
171
- }
172
-
173
- function forEach(array, callback) {
174
- for (var index = 0; index < array.length; ++index) {
175
- callback(array[index], index);
176
- }
177
- }
178
-
179
- /**
180
- * Constructor to create a new multiselect using the given select.
181
- *
182
- * @param {jQuery} select
183
- * @param {Object} options
184
- * @returns {Multiselect}
185
- */
186
- function Multiselect(select, options) {
187
-
188
- this.$select = $(select);
189
- this.options = this.mergeOptions($.extend({}, options, this.$select.data()));
190
-
191
- // Placeholder via data attributes
192
- if (this.$select.attr("data-placeholder")) {
193
- this.options.nonSelectedText = this.$select.data("placeholder");
194
- }
195
-
196
- // Initialization.
197
- // We have to clone to create a new reference.
198
- this.originalOptions = this.$select.clone()[0].options;
199
- this.query = '';
200
- this.searchTimeout = null;
201
- this.lastToggledInput = null;
202
-
203
- this.options.multiple = this.$select.attr('multiple') === "multiple";
204
- this.options.onChange = $.proxy(this.options.onChange, this);
205
- this.options.onSelectAll = $.proxy(this.options.onSelectAll, this);
206
- this.options.onDeselectAll = $.proxy(this.options.onDeselectAll, this);
207
- this.options.onDropdownShow = $.proxy(this.options.onDropdownShow, this);
208
- this.options.onDropdownHide = $.proxy(this.options.onDropdownHide, this);
209
- this.options.onDropdownShown = $.proxy(this.options.onDropdownShown, this);
210
- this.options.onDropdownHidden = $.proxy(this.options.onDropdownHidden, this);
211
- this.options.onInitialized = $.proxy(this.options.onInitialized, this);
212
- this.options.onFiltering = $.proxy(this.options.onFiltering, this);
213
-
214
- // Build select all if enabled.
215
- this.buildContainer();
216
- this.buildButton();
217
- this.buildDropdown();
218
- this.buildReset();
219
- this.buildSelectAll();
220
- this.buildDropdownOptions();
221
- this.buildFilter();
222
-
223
- this.updateButtonText();
224
- this.updateSelectAll(true);
225
-
226
- if (this.options.enableClickableOptGroups && this.options.multiple) {
227
- this.updateOptGroups();
228
- }
229
-
230
- this.options.wasDisabled = this.$select.prop('disabled');
231
- if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
232
- this.disable();
233
- }
234
-
235
- this.$select.wrap('<span class="multiselect-native-select" />').after(this.$container);
236
- this.options.onInitialized(this.$select, this.$container);
237
- }
238
-
239
- Multiselect.prototype = {
240
-
241
- defaults: {
242
- /**
243
- * Default text function will either print 'None selected' in case no
244
- * option is selected or a list of the selected options up to a length
245
- * of 3 selected options.
246
- *
247
- * @param {jQuery} options
248
- * @param {jQuery} select
249
- * @returns {String}
250
- */
251
- buttonText: function(options, select) {
252
- if (this.disabledText.length > 0
253
- && (select.prop('disabled') || (options.length == 0 && this.disableIfEmpty))) {
254
-
255
- return this.disabledText;
256
- }
257
- else if (options.length === 0) {
258
- return this.nonSelectedText;
259
- }
260
- else if (this.allSelectedText
261
- && options.length === $('option', $(select)).length
262
- && $('option', $(select)).length !== 1
263
- && this.multiple) {
264
-
265
- if (this.selectAllNumber) {
266
- return this.allSelectedText + ' (' + options.length + ')';
267
- }
268
- else {
269
- return this.allSelectedText;
270
- }
271
- }
272
- else if (this.numberDisplayed != 0 && options.length > this.numberDisplayed) {
273
- return options.length + ' ' + this.nSelectedText;
274
- }
275
- else {
276
- var selected = '';
277
- var delimiter = this.delimiterText;
278
-
279
- options.each(function() {
280
- var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
281
- selected += label + delimiter;
282
- });
283
-
284
- return selected.substr(0, selected.length - this.delimiterText.length);
285
- }
286
- },
287
- /**
288
- * Updates the title of the button similar to the buttonText function.
289
- *
290
- * @param {jQuery} options
291
- * @param {jQuery} select
292
- * @returns {@exp;selected@call;substr}
293
- */
294
- buttonTitle: function(options, select) {
295
- if (options.length === 0) {
296
- return this.nonSelectedText;
297
- }
298
- else {
299
- var selected = '';
300
- var delimiter = this.delimiterText;
301
-
302
- options.each(function () {
303
- var label = ($(this).attr('label') !== undefined) ? $(this).attr('label') : $(this).text();
304
- selected += label + delimiter;
305
- });
306
- return selected.substr(0, selected.length - this.delimiterText.length);
307
- }
308
- },
309
- checkboxName: function(option) {
310
- return false; // no checkbox name
311
- },
312
- /**
313
- * Create a label.
314
- *
315
- * @param {jQuery} element
316
- * @returns {String}
317
- */
318
- optionLabel: function(element){
319
- return $(element).attr('label') || $(element).text();
320
- },
321
- /**
322
- * Create a class.
323
- *
324
- * @param {jQuery} element
325
- * @returns {String}
326
- */
327
- optionClass: function(element) {
328
- return $(element).attr('class') || '';
329
- },
330
- /**
331
- * Triggered on change of the multiselect.
332
- *
333
- * Not triggered when selecting/deselecting options manually.
334
- *
335
- * @param {jQuery} option
336
- * @param {Boolean} checked
337
- */
338
- onChange : function(option, checked) {
339
-
340
- },
341
- /**
342
- * Triggered when the dropdown is shown.
343
- *
344
- * @param {jQuery} event
345
- */
346
- onDropdownShow: function(event) {
347
-
348
- },
349
- /**
350
- * Triggered when the dropdown is hidden.
351
- *
352
- * @param {jQuery} event
353
- */
354
- onDropdownHide: function(event) {
355
-
356
- },
357
- /**
358
- * Triggered after the dropdown is shown.
359
- *
360
- * @param {jQuery} event
361
- */
362
- onDropdownShown: function(event) {
363
-
364
- },
365
- /**
366
- * Triggered after the dropdown is hidden.
367
- *
368
- * @param {jQuery} event
369
- */
370
- onDropdownHidden: function(event) {
371
-
372
- },
373
- /**
374
- * Triggered on select all.
375
- */
376
- onSelectAll: function() {
377
-
378
- },
379
- /**
380
- * Triggered on deselect all.
381
- */
382
- onDeselectAll: function() {
383
-
384
- },
385
- /**
386
- * Triggered after initializing.
387
- *
388
- * @param {jQuery} $select
389
- * @param {jQuery} $container
390
- */
391
- onInitialized: function($select, $container) {
392
-
393
- },
394
- /**
395
- * Triggered on filtering.
396
- *
397
- * @param {jQuery} $filter
398
- */
399
- onFiltering: function($filter) {
400
-
401
- },
402
- enableHTML: false,
403
- buttonClass: 'btn btn-default',
404
- inheritClass: false,
405
- buttonWidth: 'auto',
406
- buttonContainer: '<div class="btn-group" />',
407
- dropRight: false,
408
- dropUp: false,
409
- selectedClass: 'active',
410
- // Maximum height of the dropdown menu.
411
- // If maximum height is exceeded a scrollbar will be displayed.
412
- maxHeight: false,
413
- includeSelectAllOption: false,
414
- includeSelectAllIfMoreThan: 0,
415
- selectAllText: ' Select all',
416
- selectAllValue: 'multiselect-all',
417
- selectAllName: false,
418
- selectAllNumber: true,
419
- selectAllJustVisible: true,
420
- enableFiltering: false,
421
- enableCaseInsensitiveFiltering: false,
422
- enableFullValueFiltering: false,
423
- enableClickableOptGroups: false,
424
- enableCollapsibleOptGroups: false,
425
- collapseOptGroupsByDefault: false,
426
- filterPlaceholder: 'Search',
427
- // possible options: 'text', 'value', 'both'
428
- filterBehavior: 'text',
429
- includeFilterClearBtn: true,
430
- preventInputChangeEvent: false,
431
- nonSelectedText: 'None selected',
432
- nSelectedText: 'selected',
433
- allSelectedText: 'All selected',
434
- numberDisplayed: 3,
435
- disableIfEmpty: false,
436
- disabledText: '',
437
- delimiterText: ', ',
438
- includeResetOption: false,
439
- includeResetDivider: false,
440
- resetText: 'Reset',
441
- templates: {
442
- button: '<button type="button" class="multiselect dropdown-toggle" data-toggle="dropdown"><span class="multiselect-selected-text"></span> <b class="caret"></b></button>',
443
- ul: '<ul class="multiselect-container dropdown-menu"></ul>',
444
- filter: '<li class="multiselect-item multiselect-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>',
445
- filterClearBtn: '<span class="input-group-btn"><button class="btn btn-default multiselect-clear-filter" type="button"><i class="glyphicon glyphicon-remove-circle"></i></button></span>',
446
- li: '<li><a tabindex="0"><label></label></a></li>',
447
- divider: '<li class="multiselect-item divider"></li>',
448
- liGroup: '<li class="multiselect-item multiselect-group"><label></label></li>',
449
- resetButton: '<li class="multiselect-reset text-center"><div class="input-group"><a class="btn btn-default btn-block"></a></div></li>'
450
- }
451
- },
452
-
453
- constructor: Multiselect,
454
-
455
- /**
456
- * Builds the container of the multiselect.
457
- */
458
- buildContainer: function() {
459
- this.$container = $(this.options.buttonContainer);
460
- this.$container.on('show.bs.dropdown', this.options.onDropdownShow);
461
- this.$container.on('hide.bs.dropdown', this.options.onDropdownHide);
462
- this.$container.on('shown.bs.dropdown', this.options.onDropdownShown);
463
- this.$container.on('hidden.bs.dropdown', this.options.onDropdownHidden);
464
- },
465
-
466
- /**
467
- * Builds the button of the multiselect.
468
- */
469
- buildButton: function() {
470
- this.$button = $(this.options.templates.button).addClass(this.options.buttonClass);
471
- if (this.$select.attr('class') && this.options.inheritClass) {
472
- this.$button.addClass(this.$select.attr('class'));
473
- }
474
- // Adopt active state.
475
- if (this.$select.prop('disabled')) {
476
- this.disable();
477
- }
478
- else {
479
- this.enable();
480
- }
481
-
482
- // Manually add button width if set.
483
- if (this.options.buttonWidth && this.options.buttonWidth !== 'auto') {
484
- this.$button.css({
485
- 'width' : '100%', //this.options.buttonWidth,
486
- 'overflow' : 'hidden',
487
- 'text-overflow' : 'ellipsis'
488
- });
489
- this.$container.css({
490
- 'width': this.options.buttonWidth
491
- });
492
- }
493
-
494
- // Keep the tab index from the select.
495
- var tabindex = this.$select.attr('tabindex');
496
- if (tabindex) {
497
- this.$button.attr('tabindex', tabindex);
498
- }
499
-
500
- this.$container.prepend(this.$button);
501
- },
502
-
503
- /**
504
- * Builds the ul representing the dropdown menu.
505
- */
506
- buildDropdown: function() {
507
-
508
- // Build ul.
509
- this.$ul = $(this.options.templates.ul);
510
-
511
- if (this.options.dropRight) {
512
- this.$ul.addClass('pull-right');
513
- }
514
-
515
- // Set max height of dropdown menu to activate auto scrollbar.
516
- if (this.options.maxHeight) {
517
- // TODO: Add a class for this option to move the css declarations.
518
- this.$ul.css({
519
- 'max-height': this.options.maxHeight + 'px',
520
- 'overflow-y': 'auto',
521
- 'overflow-x': 'hidden'
522
- });
523
- }
524
-
525
- if (this.options.dropUp) {
526
-
527
- var height = Math.min(this.options.maxHeight, $('option[data-role!="divider"]', this.$select).length*26 + $('option[data-role="divider"]', this.$select).length*19 + (this.options.includeSelectAllOption ? 26 : 0) + (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering ? 44 : 0));
528
- var moveCalc = height + 34;
529
-
530
- this.$ul.css({
531
- 'max-height': height + 'px',
532
- 'overflow-y': 'auto',
533
- 'overflow-x': 'hidden',
534
- 'margin-top': "-" + moveCalc + 'px'
535
- });
536
- }
537
-
538
- this.$container.append(this.$ul);
539
- },
540
-
541
- /**
542
- * Build the dropdown options and binds all necessary events.
543
- *
544
- * Uses createDivider and createOptionValue to create the necessary options.
545
- */
546
- buildDropdownOptions: function() {
547
-
548
- this.$select.children().each($.proxy(function(index, element) {
549
-
550
- var $element = $(element);
551
- // Support optgroups and options without a group simultaneously.
552
- var tag = $element.prop('tagName')
553
- .toLowerCase();
554
-
555
- if ($element.prop('value') === this.options.selectAllValue) {
556
- return;
557
- }
558
-
559
- if (tag === 'optgroup') {
560
- this.createOptgroup(element);
561
- }
562
- else if (tag === 'option') {
563
-
564
- if ($element.data('role') === 'divider') {
565
- this.createDivider();
566
- }
567
- else {
568
- this.createOptionValue(element);
569
- }
570
-
571
- }
572
-
573
- // Other illegal tags will be ignored.
574
- }, this));
575
-
576
- // Bind the change event on the dropdown elements.
577
- $(this.$ul).off('change', 'li:not(.multiselect-group) input[type="checkbox"], li:not(.multiselect-group) input[type="radio"]');
578
- $(this.$ul).on('change', 'li:not(.multiselect-group) input[type="checkbox"], li:not(.multiselect-group) input[type="radio"]', $.proxy(function(event) {
579
- var $target = $(event.target);
580
-
581
- var checked = $target.prop('checked') || false;
582
- var isSelectAllOption = $target.val() === this.options.selectAllValue;
583
-
584
- // Apply or unapply the configured selected class.
585
- if (this.options.selectedClass) {
586
- if (checked) {
587
- $target.closest('li')
588
- .addClass(this.options.selectedClass);
589
- }
590
- else {
591
- $target.closest('li')
592
- .removeClass(this.options.selectedClass);
593
- }
594
- }
595
-
596
- // Get the corresponding option.
597
- var value = $target.val();
598
- var $option = this.getOptionByValue(value);
599
-
600
- var $optionsNotThis = $('option', this.$select).not($option);
601
- var $checkboxesNotThis = $('input', this.$container).not($target);
602
-
603
- if (isSelectAllOption) {
604
-
605
- if (checked) {
606
- this.selectAll(this.options.selectAllJustVisible, true);
607
- }
608
- else {
609
- this.deselectAll(this.options.selectAllJustVisible, true);
610
- }
611
- }
612
- else {
613
- if (checked) {
614
- $option.prop('selected', true);
615
-
616
- if (this.options.multiple) {
617
- // Simply select additional option.
618
- $option.prop('selected', true);
619
- }
620
- else {
621
- // Unselect all other options and corresponding checkboxes.
622
- if (this.options.selectedClass) {
623
- $($checkboxesNotThis).closest('li').removeClass(this.options.selectedClass);
624
- }
625
-
626
- $($checkboxesNotThis).prop('checked', false);
627
- $optionsNotThis.prop('selected', false);
628
-
629
- // It's a single selection, so close.
630
- this.$button.click();
631
- }
632
-
633
- if (this.options.selectedClass === "active") {
634
- $optionsNotThis.closest("a").css("outline", "");
635
- }
636
- }
637
- else {
638
- // Unselect option.
639
- $option.prop('selected', false);
640
- }
641
-
642
- // To prevent select all from firing onChange: #575
643
- this.options.onChange($option, checked);
644
-
645
- // Do not update select all or optgroups on select all change!
646
- this.updateSelectAll();
647
-
648
- if (this.options.enableClickableOptGroups && this.options.multiple) {
649
- this.updateOptGroups();
650
- }
651
- }
652
-
653
- this.$select.change();
654
- this.updateButtonText();
655
-
656
- if(this.options.preventInputChangeEvent) {
657
- return false;
658
- }
659
- }, this));
660
-
661
- $('li a', this.$ul).on('mousedown', function(e) {
662
- if (e.shiftKey) {
663
- // Prevent selecting text by Shift+click
664
- return false;
665
- }
666
- });
667
-
668
- $(this.$ul).on('touchstart click', 'li a', $.proxy(function(event) {
669
- event.stopPropagation();
670
-
671
- var $target = $(event.target);
672
-
673
- if (event.shiftKey && this.options.multiple) {
674
- if($target.is("label")){ // Handles checkbox selection manually (see https://github.com/davidstutz/bootstrap-multiselect/issues/431)
675
- event.preventDefault();
676
- $target = $target.find("input");
677
- $target.prop("checked", !$target.prop("checked"));
678
- }
679
- var checked = $target.prop('checked') || false;
680
-
681
- if (this.lastToggledInput !== null && this.lastToggledInput !== $target) { // Make sure we actually have a range
682
- var from = this.$ul.find("li:visible").index($target.parents("li"));
683
- var to = this.$ul.find("li:visible").index(this.lastToggledInput.parents("li"));
684
-
685
- if (from > to) { // Swap the indices
686
- var tmp = to;
687
- to = from;
688
- from = tmp;
689
- }
690
-
691
- // Make sure we grab all elements since slice excludes the last index
692
- ++to;
693
-
694
- // Change the checkboxes and underlying options
695
- var range = this.$ul.find("li").not(".multiselect-filter-hidden").slice(from, to).find("input");
696
-
697
- range.prop('checked', checked);
698
-
699
- if (this.options.selectedClass) {
700
- range.closest('li')
701
- .toggleClass(this.options.selectedClass, checked);
702
- }
703
-
704
- for (var i = 0, j = range.length; i < j; i++) {
705
- var $checkbox = $(range[i]);
706
-
707
- var $option = this.getOptionByValue($checkbox.val());
708
-
709
- $option.prop('selected', checked);
710
- }
711
- }
712
-
713
- // Trigger the select "change" event
714
- $target.trigger("change");
715
- }
716
-
717
- // Remembers last clicked option
718
- if($target.is("input") && !$target.closest("li").is(".multiselect-item")){
719
- this.lastToggledInput = $target;
720
- }
721
-
722
- $target.blur();
723
- }, this));
724
-
725
- // Keyboard support.
726
- this.$container.off('keydown.multiselect').on('keydown.multiselect', $.proxy(function(event) {
727
- if ($('input[type="text"]', this.$container).is(':focus')) {
728
- return;
729
- }
730
-
731
- if (event.keyCode === 9 && this.$container.hasClass('open')) {
732
- this.$button.click();
733
- }
734
- else {
735
- var $items = $(this.$container).find("li:not(.divider):not(.disabled) a").filter(":visible");
736
-
737
- if (!$items.length) {
738
- return;
739
- }
740
-
741
- var index = $items.index($items.filter(':focus'));
742
-
743
- // Navigation up.
744
- if (event.keyCode === 38 && index > 0) {
745
- index--;
746
- }
747
- // Navigate down.
748
- else if (event.keyCode === 40 && index < $items.length - 1) {
749
- index++;
750
- }
751
- else if (!~index) {
752
- index = 0;
753
- }
754
-
755
- var $current = $items.eq(index);
756
- $current.focus();
757
-
758
- if (event.keyCode === 32 || event.keyCode === 13) {
759
- var $checkbox = $current.find('input');
760
-
761
- $checkbox.prop("checked", !$checkbox.prop("checked"));
762
- $checkbox.change();
763
- }
764
-
765
- event.stopPropagation();
766
- event.preventDefault();
767
- }
768
- }, this));
769
-
770
- if (this.options.enableClickableOptGroups && this.options.multiple) {
771
- $("li.multiselect-group input", this.$ul).on("change", $.proxy(function(event) {
772
- event.stopPropagation();
773
-
774
- var $target = $(event.target);
775
- var checked = $target.prop('checked') || false;
776
-
777
- var $li = $(event.target).closest('li');
778
- var $group = $li.nextUntil("li.multiselect-group")
779
- .not('.multiselect-filter-hidden')
780
- .not('.disabled');
781
-
782
- var $inputs = $group.find("input");
783
-
784
- var values = [];
785
- var $options = [];
786
-
787
- if (this.options.selectedClass) {
788
- if (checked) {
789
- $li.addClass(this.options.selectedClass);
790
- }
791
- else {
792
- $li.removeClass(this.options.selectedClass);
793
- }
794
- }
795
-
796
- $.each($inputs, $.proxy(function(index, input) {
797
- var value = $(input).val();
798
- var $option = this.getOptionByValue(value);
799
-
800
- if (checked) {
801
- $(input).prop('checked', true);
802
- $(input).closest('li')
803
- .addClass(this.options.selectedClass);
804
-
805
- $option.prop('selected', true);
806
- }
807
- else {
808
- $(input).prop('checked', false);
809
- $(input).closest('li')
810
- .removeClass(this.options.selectedClass);
811
-
812
- $option.prop('selected', false);
813
- }
814
-
815
- $options.push(this.getOptionByValue(value));
816
- }, this))
817
-
818
- // Cannot use select or deselect here because it would call updateOptGroups again.
819
-
820
- this.options.onChange($options, checked);
821
-
822
- this.$select.change();
823
- this.updateButtonText();
824
- this.updateSelectAll();
825
- }, this));
826
- }
827
-
828
- if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
829
- $("li.multiselect-group .caret-container", this.$ul).on("click", $.proxy(function(event) {
830
- var $li = $(event.target).closest('li');
831
- var $inputs = $li.nextUntil("li.multiselect-group")
832
- .not('.multiselect-filter-hidden');
833
-
834
- var visible = true;
835
- $inputs.each(function() {
836
- visible = visible && !$(this).hasClass('multiselect-collapsible-hidden');
837
- });
838
-
839
- if (visible) {
840
- $inputs.hide()
841
- .addClass('multiselect-collapsible-hidden');
842
- }
843
- else {
844
- $inputs.show()
845
- .removeClass('multiselect-collapsible-hidden');
846
- }
847
- }, this));
848
-
849
- $("li.multiselect-all", this.$ul).css('background', '#f3f3f3').css('border-bottom', '1px solid #eaeaea');
850
- $("li.multiselect-all > a > label.checkbox", this.$ul).css('padding', '3px 20px 3px 35px');
851
- $("li.multiselect-group > a > input", this.$ul).css('margin', '4px 0px 5px -20px');
852
- }
853
- },
854
-
855
- /**
856
- * Create an option using the given select option.
857
- *
858
- * @param {jQuery} element
859
- */
860
- createOptionValue: function(element) {
861
- var $element = $(element);
862
- if ($element.is(':selected')) {
863
- $element.prop('selected', true);
864
- }
865
-
866
- // Support the label attribute on options.
867
- var label = this.options.optionLabel(element);
868
- var classes = this.options.optionClass(element);
869
- var value = $element.val();
870
- var inputType = this.options.multiple ? "checkbox" : "radio";
871
-
872
- var $li = $(this.options.templates.li);
873
- var $label = $('label', $li);
874
- $label.addClass(inputType);
875
- $label.attr("title", label);
876
- $li.addClass(classes);
877
-
878
- // Hide all children items when collapseOptGroupsByDefault is true
879
- if (this.options.collapseOptGroupsByDefault && $(element).parent().prop("tagName").toLowerCase() === "optgroup") {
880
- $li.addClass("multiselect-collapsible-hidden");
881
- $li.hide();
882
- }
883
-
884
- if (this.options.enableHTML) {
885
- $label.html(" " + label);
886
- }
887
- else {
888
- $label.text(" " + label);
889
- }
890
-
891
- var $checkbox = $('<input/>').attr('type', inputType);
892
-
893
- var name = this.options.checkboxName($element);
894
- if (name) {
895
- $checkbox.attr('name', name);
896
- }
897
-
898
- $label.prepend($checkbox);
899
-
900
- var selected = $element.prop('selected') || false;
901
- $checkbox.val(value);
902
-
903
- if (value === this.options.selectAllValue) {
904
- $li.addClass("multiselect-item multiselect-all");
905
- $checkbox.parent().parent()
906
- .addClass('multiselect-all');
907
- }
908
-
909
- $label.attr('title', $element.attr('title'));
910
-
911
- this.$ul.append($li);
912
-
913
- if ($element.is(':disabled')) {
914
- $checkbox.attr('disabled', 'disabled')
915
- .prop('disabled', true)
916
- .closest('a')
917
- .attr("tabindex", "-1")
918
- .closest('li')
919
- .addClass('disabled');
920
- }
921
-
922
- $checkbox.prop('checked', selected);
923
-
924
- if (selected && this.options.selectedClass) {
925
- $checkbox.closest('li')
926
- .addClass(this.options.selectedClass);
927
- }
928
- },
929
-
930
- /**
931
- * Creates a divider using the given select option.
932
- *
933
- * @param {jQuery} element
934
- */
935
- createDivider: function(element) {
936
- var $divider = $(this.options.templates.divider);
937
- this.$ul.append($divider);
938
- },
939
-
940
- /**
941
- * Creates an optgroup.
942
- *
943
- * @param {jQuery} group
944
- */
945
- createOptgroup: function(group) {
946
- var label = $(group).attr("label");
947
- var value = $(group).attr("value");
948
- var $li = $('<li class="multiselect-item multiselect-group"><a href="javascript:void(0);"><label><b></b></label></a></li>');
949
-
950
- var classes = this.options.optionClass(group);
951
- $li.addClass(classes);
952
-
953
- if (this.options.enableHTML) {
954
- $('label b', $li).html(" " + label);
955
- }
956
- else {
957
- $('label b', $li).text(" " + label);
958
- }
959
-
960
- if (this.options.enableCollapsibleOptGroups && this.options.multiple) {
961
- $('a', $li).append('<span class="caret-container"><b class="caret"></b></span>');
962
- }
963
-
964
- if (this.options.enableClickableOptGroups && this.options.multiple) {
965
- $('a label', $li).prepend('<input type="checkbox" value="' + value + '"/>');
966
- }
967
-
968
- if ($(group).is(':disabled')) {
969
- $li.addClass('disabled');
970
- }
971
-
972
- this.$ul.append($li);
973
-
974
- $("option", group).each($.proxy(function($, group) {
975
- this.createOptionValue(group);
976
- }, this))
977
- },
978
-
979
- /**
980
- * Build the reset.
981
- *
982
- */
983
- buildReset: function() {
984
- if (this.options.includeResetOption) {
985
-
986
- // Check whether to add a divider after the reset.
987
- if (this.options.includeResetDivider) {
988
- this.$ul.prepend($(this.options.templates.divider));
989
- }
990
-
991
- var $resetButton = $(this.options.templates.resetButton);
992
-
993
- if (this.options.enableHTML) {
994
- $('a', $resetButton).html(this.options.resetText);
995
- }
996
- else {
997
- $('a', $resetButton).text(this.options.resetText);
998
- }
999
-
1000
- $('a', $resetButton).click($.proxy(function(){
1001
- this.clearSelection();
1002
- }, this));
1003
-
1004
- this.$ul.prepend($resetButton);
1005
- }
1006
- },
1007
-
1008
- /**
1009
- * Build the select all.
1010
- *
1011
- * Checks if a select all has already been created.
1012
- */
1013
- buildSelectAll: function() {
1014
- if (typeof this.options.selectAllValue === 'number') {
1015
- this.options.selectAllValue = this.options.selectAllValue.toString();
1016
- }
1017
-
1018
- var alreadyHasSelectAll = this.hasSelectAll();
1019
-
1020
- if (!alreadyHasSelectAll && this.options.includeSelectAllOption && this.options.multiple
1021
- && $('option', this.$select).length > this.options.includeSelectAllIfMoreThan) {
1022
-
1023
- // Check whether to add a divider after the select all.
1024
- if (this.options.includeSelectAllDivider) {
1025
- this.$ul.prepend($(this.options.templates.divider));
1026
- }
1027
-
1028
- var $li = $(this.options.templates.li);
1029
- $('label', $li).addClass("checkbox");
1030
-
1031
- if (this.options.enableHTML) {
1032
- $('label', $li).html(" " + this.options.selectAllText);
1033
- }
1034
- else {
1035
- $('label', $li).text(" " + this.options.selectAllText);
1036
- }
1037
-
1038
- if (this.options.selectAllName) {
1039
- $('label', $li).prepend('<input type="checkbox" name="' + this.options.selectAllName + '" />');
1040
- }
1041
- else {
1042
- $('label', $li).prepend('<input type="checkbox" />');
1043
- }
1044
-
1045
- var $checkbox = $('input', $li);
1046
- $checkbox.val(this.options.selectAllValue);
1047
-
1048
- $li.addClass("multiselect-item multiselect-all");
1049
- $checkbox.parent().parent()
1050
- .addClass('multiselect-all');
1051
-
1052
- this.$ul.prepend($li);
1053
-
1054
- $checkbox.prop('checked', false);
1055
- }
1056
- },
1057
-
1058
- /**
1059
- * Builds the filter.
1060
- */
1061
- buildFilter: function() {
1062
-
1063
- // Build filter if filtering OR case insensitive filtering is enabled and the number of options exceeds (or equals) enableFilterLength.
1064
- if (this.options.enableFiltering || this.options.enableCaseInsensitiveFiltering) {
1065
- var enableFilterLength = Math.max(this.options.enableFiltering, this.options.enableCaseInsensitiveFiltering);
1066
-
1067
- if (this.$select.find('option').length >= enableFilterLength) {
1068
-
1069
- this.$filter = $(this.options.templates.filter);
1070
- $('input', this.$filter).attr('placeholder', this.options.filterPlaceholder);
1071
-
1072
- // Adds optional filter clear button
1073
- if(this.options.includeFilterClearBtn) {
1074
- var clearBtn = $(this.options.templates.filterClearBtn);
1075
- clearBtn.on('click', $.proxy(function(event){
1076
- clearTimeout(this.searchTimeout);
1077
-
1078
- this.query = '';
1079
- this.$filter.find('.multiselect-search').val('');
1080
- $('li', this.$ul).show().removeClass('multiselect-filter-hidden');
1081
-
1082
- this.updateSelectAll();
1083
-
1084
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1085
- this.updateOptGroups();
1086
- }
1087
-
1088
- }, this));
1089
- this.$filter.find('.input-group').append(clearBtn);
1090
- }
1091
-
1092
- this.$ul.prepend(this.$filter);
1093
-
1094
- this.$filter.val(this.query).on('click', function(event) {
1095
- event.stopPropagation();
1096
- }).on('input keydown', $.proxy(function(event) {
1097
- // Cancel enter key default behaviour
1098
- if (event.which === 13) {
1099
- event.preventDefault();
1100
- }
1101
-
1102
- // This is useful to catch "keydown" events after the browser has updated the control.
1103
- clearTimeout(this.searchTimeout);
1104
-
1105
- this.searchTimeout = this.asyncFunction($.proxy(function() {
1106
-
1107
- if (this.query !== event.target.value) {
1108
- this.query = event.target.value;
1109
-
1110
- var currentGroup, currentGroupVisible;
1111
- $.each($('li', this.$ul), $.proxy(function(index, element) {
1112
- var value = $('input', element).length > 0 ? $('input', element).val() : "";
1113
- var text = $('label', element).text();
1114
-
1115
- var filterCandidate = '';
1116
- if ((this.options.filterBehavior === 'text')) {
1117
- filterCandidate = text;
1118
- }
1119
- else if ((this.options.filterBehavior === 'value')) {
1120
- filterCandidate = value;
1121
- }
1122
- else if (this.options.filterBehavior === 'both') {
1123
- filterCandidate = text + '\n' + value;
1124
- }
1125
-
1126
- if (value !== this.options.selectAllValue && text) {
1127
-
1128
- // By default lets assume that element is not
1129
- // interesting for this search.
1130
- var showElement = false;
1131
-
1132
- if (this.options.enableCaseInsensitiveFiltering) {
1133
- filterCandidate = filterCandidate.toLowerCase();
1134
- this.query = this.query.toLowerCase();
1135
- }
1136
-
1137
- if (this.options.enableFullValueFiltering && this.options.filterBehavior !== 'both') {
1138
- var valueToMatch = filterCandidate.trim().substring(0, this.query.length);
1139
- if (this.query.indexOf(valueToMatch) > -1) {
1140
- showElement = true;
1141
- }
1142
- }
1143
- else if (filterCandidate.indexOf(this.query) > -1) {
1144
- showElement = true;
1145
- }
1146
-
1147
- // Toggle current element (group or group item) according to showElement boolean.
1148
- if(!showElement){
1149
- $(element).css('display', 'none');
1150
- $(element).addClass('multiselect-filter-hidden');
1151
- }
1152
- if(showElement){
1153
- $(element).css('display', 'block');
1154
- $(element).removeClass('multiselect-filter-hidden');
1155
- }
1156
-
1157
- // Differentiate groups and group items.
1158
- if ($(element).hasClass('multiselect-group')) {
1159
- // Remember group status.
1160
- currentGroup = element;
1161
- currentGroupVisible = showElement;
1162
- }
1163
- else {
1164
- // Show group name when at least one of its items is visible.
1165
- if (showElement) {
1166
- $(currentGroup).show()
1167
- .removeClass('multiselect-filter-hidden');
1168
- }
1169
-
1170
- // Show all group items when group name satisfies filter.
1171
- if (!showElement && currentGroupVisible) {
1172
- $(element).show()
1173
- .removeClass('multiselect-filter-hidden');
1174
- }
1175
- }
1176
- }
1177
- }, this));
1178
- }
1179
-
1180
- this.updateSelectAll();
1181
-
1182
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1183
- this.updateOptGroups();
1184
- }
1185
-
1186
- this.options.onFiltering(event.target);
1187
-
1188
- }, this), 300, this);
1189
- }, this));
1190
- }
1191
- }
1192
- },
1193
-
1194
- /**
1195
- * Unbinds the whole plugin.
1196
- */
1197
- destroy: function() {
1198
- this.$container.remove();
1199
- this.$select.show();
1200
-
1201
- // reset original state
1202
- this.$select.prop('disabled', this.options.wasDisabled);
1203
-
1204
- this.$select.data('multiselect', null);
1205
- },
1206
-
1207
- /**
1208
- * Refreshs the multiselect based on the selected options of the select.
1209
- */
1210
- refresh: function () {
1211
- var inputs = {};
1212
- $('li input', this.$ul).each(function() {
1213
- inputs[$(this).val()] = $(this);
1214
- });
1215
-
1216
- $('option', this.$select).each($.proxy(function (index, element) {
1217
- var $elem = $(element);
1218
- var $input = inputs[$(element).val()];
1219
-
1220
- if ($elem.is(':selected')) {
1221
- $input.prop('checked', true);
1222
-
1223
- if (this.options.selectedClass) {
1224
- $input.closest('li')
1225
- .addClass(this.options.selectedClass);
1226
- }
1227
- }
1228
- else {
1229
- $input.prop('checked', false);
1230
-
1231
- if (this.options.selectedClass) {
1232
- $input.closest('li')
1233
- .removeClass(this.options.selectedClass);
1234
- }
1235
- }
1236
-
1237
- if ($elem.is(":disabled")) {
1238
- $input.attr('disabled', 'disabled')
1239
- .prop('disabled', true)
1240
- .closest('li')
1241
- .addClass('disabled');
1242
- }
1243
- else {
1244
- $input.prop('disabled', false)
1245
- .closest('li')
1246
- .removeClass('disabled');
1247
- }
1248
- }, this));
1249
-
1250
- this.updateButtonText();
1251
- this.updateSelectAll();
1252
-
1253
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1254
- this.updateOptGroups();
1255
- }
1256
- },
1257
-
1258
- /**
1259
- * Select all options of the given values.
1260
- *
1261
- * If triggerOnChange is set to true, the on change event is triggered if
1262
- * and only if one value is passed.
1263
- *
1264
- * @param {Array} selectValues
1265
- * @param {Boolean} triggerOnChange
1266
- */
1267
- select: function(selectValues, triggerOnChange) {
1268
- if(!$.isArray(selectValues)) {
1269
- selectValues = [selectValues];
1270
- }
1271
-
1272
- for (var i = 0; i < selectValues.length; i++) {
1273
- var value = selectValues[i];
1274
-
1275
- if (value === null || value === undefined) {
1276
- continue;
1277
- }
1278
-
1279
- var $option = this.getOptionByValue(value);
1280
- var $checkbox = this.getInputByValue(value);
1281
-
1282
- if($option === undefined || $checkbox === undefined) {
1283
- continue;
1284
- }
1285
-
1286
- if (!this.options.multiple) {
1287
- this.deselectAll(false);
1288
- }
1289
-
1290
- if (this.options.selectedClass) {
1291
- $checkbox.closest('li')
1292
- .addClass(this.options.selectedClass);
1293
- }
1294
-
1295
- $checkbox.prop('checked', true);
1296
- $option.prop('selected', true);
1297
-
1298
- if (triggerOnChange) {
1299
- this.options.onChange($option, true);
1300
- }
1301
- }
1302
-
1303
- this.updateButtonText();
1304
- this.updateSelectAll();
1305
-
1306
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1307
- this.updateOptGroups();
1308
- }
1309
- },
1310
-
1311
- /**
1312
- * Clears all selected items.
1313
- */
1314
- clearSelection: function () {
1315
- this.deselectAll(false);
1316
- this.updateButtonText();
1317
- this.updateSelectAll();
1318
-
1319
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1320
- this.updateOptGroups();
1321
- }
1322
- },
1323
-
1324
- /**
1325
- * Deselects all options of the given values.
1326
- *
1327
- * If triggerOnChange is set to true, the on change event is triggered, if
1328
- * and only if one value is passed.
1329
- *
1330
- * @param {Array} deselectValues
1331
- * @param {Boolean} triggerOnChange
1332
- */
1333
- deselect: function(deselectValues, triggerOnChange) {
1334
- if(!$.isArray(deselectValues)) {
1335
- deselectValues = [deselectValues];
1336
- }
1337
-
1338
- for (var i = 0; i < deselectValues.length; i++) {
1339
- var value = deselectValues[i];
1340
-
1341
- if (value === null || value === undefined) {
1342
- continue;
1343
- }
1344
-
1345
- var $option = this.getOptionByValue(value);
1346
- var $checkbox = this.getInputByValue(value);
1347
-
1348
- if($option === undefined || $checkbox === undefined) {
1349
- continue;
1350
- }
1351
-
1352
- if (this.options.selectedClass) {
1353
- $checkbox.closest('li')
1354
- .removeClass(this.options.selectedClass);
1355
- }
1356
-
1357
- $checkbox.prop('checked', false);
1358
- $option.prop('selected', false);
1359
-
1360
- if (triggerOnChange) {
1361
- this.options.onChange($option, false);
1362
- }
1363
- }
1364
-
1365
- this.updateButtonText();
1366
- this.updateSelectAll();
1367
-
1368
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1369
- this.updateOptGroups();
1370
- }
1371
- },
1372
-
1373
- /**
1374
- * Selects all enabled & visible options.
1375
- *
1376
- * If justVisible is true or not specified, only visible options are selected.
1377
- *
1378
- * @param {Boolean} justVisible
1379
- * @param {Boolean} triggerOnSelectAll
1380
- */
1381
- selectAll: function (justVisible, triggerOnSelectAll) {
1382
-
1383
- var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
1384
- var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
1385
- var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
1386
-
1387
- if(justVisible) {
1388
- $('input:enabled' , visibleLis).prop('checked', true);
1389
- visibleLis.addClass(this.options.selectedClass);
1390
-
1391
- $('input:enabled' , visibleLis).each($.proxy(function(index, element) {
1392
- var value = $(element).val();
1393
- var option = this.getOptionByValue(value);
1394
- $(option).prop('selected', true);
1395
- }, this));
1396
- }
1397
- else {
1398
- $('input:enabled' , allLis).prop('checked', true);
1399
- allLis.addClass(this.options.selectedClass);
1400
-
1401
- $('input:enabled' , allLis).each($.proxy(function(index, element) {
1402
- var value = $(element).val();
1403
- var option = this.getOptionByValue(value);
1404
- $(option).prop('selected', true);
1405
- }, this));
1406
- }
1407
-
1408
- $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', true);
1409
-
1410
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1411
- this.updateOptGroups();
1412
- }
1413
-
1414
- if (triggerOnSelectAll) {
1415
- this.options.onSelectAll();
1416
- }
1417
- },
1418
-
1419
- /**
1420
- * Deselects all options.
1421
- *
1422
- * If justVisible is true or not specified, only visible options are deselected.
1423
- *
1424
- * @param {Boolean} justVisible
1425
- */
1426
- deselectAll: function (justVisible, triggerOnDeselectAll) {
1427
-
1428
- var justVisible = typeof justVisible === 'undefined' ? true : justVisible;
1429
- var allLis = $("li:not(.divider):not(.disabled):not(.multiselect-group)", this.$ul);
1430
- var visibleLis = $("li:not(.divider):not(.disabled):not(.multiselect-group):not(.multiselect-filter-hidden):not(.multiselect-collapisble-hidden)", this.$ul).filter(':visible');
1431
-
1432
- if(justVisible) {
1433
- $('input[type="checkbox"]:enabled' , visibleLis).prop('checked', false);
1434
- visibleLis.removeClass(this.options.selectedClass);
1435
-
1436
- $('input[type="checkbox"]:enabled' , visibleLis).each($.proxy(function(index, element) {
1437
- var value = $(element).val();
1438
- var option = this.getOptionByValue(value);
1439
- $(option).prop('selected', false);
1440
- }, this));
1441
- }
1442
- else {
1443
- $('input[type="checkbox"]:enabled' , allLis).prop('checked', false);
1444
- allLis.removeClass(this.options.selectedClass);
1445
-
1446
- $('input[type="checkbox"]:enabled' , allLis).each($.proxy(function(index, element) {
1447
- var value = $(element).val();
1448
- var option = this.getOptionByValue(value);
1449
- $(option).prop('selected', false);
1450
- }, this));
1451
- }
1452
-
1453
- $('li input[value="' + this.options.selectAllValue + '"]', this.$ul).prop('checked', false);
1454
-
1455
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1456
- this.updateOptGroups();
1457
- }
1458
-
1459
- if (triggerOnDeselectAll) {
1460
- this.options.onDeselectAll();
1461
- }
1462
- },
1463
-
1464
- /**
1465
- * Rebuild the plugin.
1466
- *
1467
- * Rebuilds the dropdown, the filter and the select all option.
1468
- */
1469
- rebuild: function() {
1470
- this.$ul.html('');
1471
-
1472
- // Important to distinguish between radios and checkboxes.
1473
- this.options.multiple = this.$select.attr('multiple') === "multiple";
1474
-
1475
- this.buildSelectAll();
1476
- this.buildDropdownOptions();
1477
- this.buildFilter();
1478
-
1479
- this.updateButtonText();
1480
- this.updateSelectAll(true);
1481
-
1482
- if (this.options.enableClickableOptGroups && this.options.multiple) {
1483
- this.updateOptGroups();
1484
- }
1485
-
1486
- if (this.options.disableIfEmpty && $('option', this.$select).length <= 0) {
1487
- this.disable();
1488
- }
1489
- else {
1490
- this.enable();
1491
- }
1492
-
1493
- if (this.options.dropRight) {
1494
- this.$ul.addClass('pull-right');
1495
- }
1496
- },
1497
-
1498
- /**
1499
- * The provided data will be used to build the dropdown.
1500
- */
1501
- dataprovider: function(dataprovider) {
1502
-
1503
- var groupCounter = 0;
1504
- var $select = this.$select.empty();
1505
-
1506
- $.each(dataprovider, function (index, option) {
1507
- var $tag;
1508
-
1509
- if ($.isArray(option.children)) { // create optiongroup tag
1510
- groupCounter++;
1511
-
1512
- $tag = $('<optgroup/>').attr({
1513
- label: option.label || 'Group ' + groupCounter,
1514
- disabled: !!option.disabled,
1515
- value: option.value
1516
- });
1517
-
1518
- forEach(option.children, function(subOption) { // add children option tags
1519
- var attributes = {
1520
- value: subOption.value,
1521
- label: subOption.label || subOption.value,
1522
- title: subOption.title,
1523
- selected: !!subOption.selected,
1524
- disabled: !!subOption.disabled
1525
- };
1526
-
1527
- //Loop through attributes object and add key-value for each attribute
1528
- for (var key in subOption.attributes) {
1529
- attributes['data-' + key] = subOption.attributes[key];
1530
- }
1531
- //Append original attributes + new data attributes to option
1532
- $tag.append($('<option/>').attr(attributes));
1533
- });
1534
- }
1535
- else {
1536
-
1537
- var attributes = {
1538
- 'value': option.value,
1539
- 'label': option.label || option.value,
1540
- 'title': option.title,
1541
- 'class': option['class'],
1542
- 'selected': !!option['selected'],
1543
- 'disabled': !!option['disabled']
1544
- };
1545
- //Loop through attributes object and add key-value for each attribute
1546
- for (var key in option.attributes) {
1547
- attributes['data-' + key] = option.attributes[key];
1548
- }
1549
- //Append original attributes + new data attributes to option
1550
- $tag = $('<option/>').attr(attributes);
1551
-
1552
- $tag.text(option.label || option.value);
1553
- }
1554
-
1555
- $select.append($tag);
1556
- });
1557
-
1558
- this.rebuild();
1559
- },
1560
-
1561
- /**
1562
- * Enable the multiselect.
1563
- */
1564
- enable: function() {
1565
- this.$select.prop('disabled', false);
1566
- this.$button.prop('disabled', false)
1567
- .removeClass('disabled');
1568
- },
1569
-
1570
- /**
1571
- * Disable the multiselect.
1572
- */
1573
- disable: function() {
1574
- this.$select.prop('disabled', true);
1575
- this.$button.prop('disabled', true)
1576
- .addClass('disabled');
1577
- },
1578
-
1579
- /**
1580
- * Set the options.
1581
- *
1582
- * @param {Array} options
1583
- */
1584
- setOptions: function(options) {
1585
- this.options = this.mergeOptions(options);
1586
- },
1587
-
1588
- /**
1589
- * Merges the given options with the default options.
1590
- *
1591
- * @param {Array} options
1592
- * @returns {Array}
1593
- */
1594
- mergeOptions: function(options) {
1595
- return $.extend(true, {}, this.defaults, this.options, options);
1596
- },
1597
-
1598
- /**
1599
- * Checks whether a select all checkbox is present.
1600
- *
1601
- * @returns {Boolean}
1602
- */
1603
- hasSelectAll: function() {
1604
- return $('li.multiselect-all', this.$ul).length > 0;
1605
- },
1606
-
1607
- /**
1608
- * Update opt groups.
1609
- */
1610
- updateOptGroups: function() {
1611
- var $groups = $('li.multiselect-group', this.$ul)
1612
- var selectedClass = this.options.selectedClass;
1613
-
1614
- $groups.each(function() {
1615
- var $options = $(this).nextUntil('li.multiselect-group')
1616
- .not('.multiselect-filter-hidden')
1617
- .not('.disabled');
1618
-
1619
- var checked = true;
1620
- $options.each(function() {
1621
- var $input = $('input', this);
1622
-
1623
- if (!$input.prop('checked')) {
1624
- checked = false;
1625
- }
1626
- });
1627
-
1628
- if (selectedClass) {
1629
- if (checked) {
1630
- $(this).addClass(selectedClass);
1631
- }
1632
- else {
1633
- $(this).removeClass(selectedClass);
1634
- }
1635
- }
1636
-
1637
- $('input', this).prop('checked', checked);
1638
- });
1639
- },
1640
-
1641
- /**
1642
- * Updates the select all checkbox based on the currently displayed and selected checkboxes.
1643
- */
1644
- updateSelectAll: function(notTriggerOnSelectAll) {
1645
- if (this.hasSelectAll()) {
1646
- var allBoxes = $("li:not(.multiselect-item):not(.multiselect-filter-hidden):not(.multiselect-group):not(.disabled) input:enabled", this.$ul);
1647
- var allBoxesLength = allBoxes.length;
1648
- var checkedBoxesLength = allBoxes.filter(":checked").length;
1649
- var selectAllLi = $("li.multiselect-all", this.$ul);
1650
- var selectAllInput = selectAllLi.find("input");
1651
-
1652
- if (checkedBoxesLength > 0 && checkedBoxesLength === allBoxesLength) {
1653
- selectAllInput.prop("checked", true);
1654
- selectAllLi.addClass(this.options.selectedClass);
1655
- }
1656
- else {
1657
- selectAllInput.prop("checked", false);
1658
- selectAllLi.removeClass(this.options.selectedClass);
1659
- }
1660
- }
1661
- },
1662
-
1663
- /**
1664
- * Update the button text and its title based on the currently selected options.
1665
- */
1666
- updateButtonText: function() {
1667
- var options = this.getSelected();
1668
-
1669
- // First update the displayed button text.
1670
- if (this.options.enableHTML) {
1671
- $('.multiselect .multiselect-selected-text', this.$container).html(this.options.buttonText(options, this.$select));
1672
- }
1673
- else {
1674
- $('.multiselect .multiselect-selected-text', this.$container).text(this.options.buttonText(options, this.$select));
1675
- }
1676
-
1677
- // Now update the title attribute of the button.
1678
- $('.multiselect', this.$container).attr('title', this.options.buttonTitle(options, this.$select));
1679
- },
1680
-
1681
- /**
1682
- * Get all selected options.
1683
- *
1684
- * @returns {jQUery}
1685
- */
1686
- getSelected: function() {
1687
- return $('option', this.$select).filter(":selected");
1688
- },
1689
-
1690
- /**
1691
- * Gets a select option by its value.
1692
- *
1693
- * @param {String} value
1694
- * @returns {jQuery}
1695
- */
1696
- getOptionByValue: function (value) {
1697
-
1698
- var options = $('option', this.$select);
1699
- var valueToCompare = value.toString();
1700
-
1701
- for (var i = 0; i < options.length; i = i + 1) {
1702
- var option = options[i];
1703
- if (option.value === valueToCompare) {
1704
- return $(option);
1705
- }
1706
- }
1707
- },
1708
-
1709
- /**
1710
- * Get the input (radio/checkbox) by its value.
1711
- *
1712
- * @param {String} value
1713
- * @returns {jQuery}
1714
- */
1715
- getInputByValue: function (value) {
1716
-
1717
- var checkboxes = $('li input:not(.multiselect-search)', this.$ul);
1718
- var valueToCompare = value.toString();
1719
-
1720
- for (var i = 0; i < checkboxes.length; i = i + 1) {
1721
- var checkbox = checkboxes[i];
1722
- if (checkbox.value === valueToCompare) {
1723
- return $(checkbox);
1724
- }
1725
- }
1726
- },
1727
-
1728
- /**
1729
- * Used for knockout integration.
1730
- */
1731
- updateOriginalOptions: function() {
1732
- this.originalOptions = this.$select.clone()[0].options;
1733
- },
1734
-
1735
- asyncFunction: function(callback, timeout, self) {
1736
- var args = Array.prototype.slice.call(arguments, 3);
1737
- return setTimeout(function() {
1738
- callback.apply(self || window, args);
1739
- }, timeout);
1740
- },
1741
-
1742
- setAllSelectedText: function(allSelectedText) {
1743
- this.options.allSelectedText = allSelectedText;
1744
- this.updateButtonText();
1745
- }
1746
- };
1747
-
1748
- $.fn.multiselect = function(option, parameter, extraOptions) {
1749
- return this.each(function() {
1750
- var data = $(this).data('multiselect');
1751
- var options = typeof option === 'object' && option;
1752
-
1753
- // Initialize the multiselect.
1754
- if (!data) {
1755
- data = new Multiselect(this, options);
1756
- $(this).data('multiselect', data);
1757
- }
1758
-
1759
- // Call multiselect method.
1760
- if (typeof option === 'string') {
1761
- data[option](parameter, extraOptions);
1762
-
1763
- if (option === 'destroy') {
1764
- $(this).data('multiselect', false);
1765
- }
1766
- }
1767
- });
1768
- };
1769
-
1770
- $.fn.multiselect.Constructor = Multiselect;
1771
-
1772
- $(function() {
1773
- $("select[data-role=multiselect]").multiselect();
1774
- });
1775
-
1776
- });