Commit 6241c2e8 authored by David Stutz's avatar David Stutz

Merge pull request #17 from Devristo/master

KnockoutJS data binding support.
parents 0bafa7ce 00ebed1b
/** /**
* bootstrap-multiselect.js 1.0.0 * bootstrap-multiselect.js 1.0.0
* https://github.com/davidstutz/bootstrap-multiselect * https://github.com/davidstutz/bootstrap-multiselect
* *
* Copyright 2012 David Stutz * Copyright 2012 David Stutz
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
...@@ -18,163 +18,200 @@ ...@@ -18,163 +18,200 @@
*/ */
!function ($) { !function ($) {
"use strict"; // jshint ;_; "use strict"; // jshint ;_;
function Multiselect(select, options) { if(ko && ko.bindingHandlers && !ko.bindingHandlers.multiselect){
ko.bindingHandlers.multiselect = {
this.options = this.getOptions(options); init: function (element) {
this.select = $(select); var ms = $(element).data('multiselect');
this.container = $(this.options.buttonContainer)
.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>') if(!ms)
.append('<ul class="dropdown-menu"></ul>'); throw new Error("Bootstrap-multiselect's multiselect() has to be called on element before applying the Knockout View model!");
// Set max height of dropdown menu to activate auto scrollbar. var prev = ms.options.onChange;
if (this.options.maxHeight) {
$('ul', this.container).css({ ms.options.onChange = function(option, checked){
'max-height': this.options.maxHeight + 'px', // We dont want to refresh the multiselect since it would delete / recreate all items
'overflow-y': 'auto', $(element).data('blockRefresh', true);
'overflow-x': 'hidden',
}); // Force the binding to be updated by triggering the change event on the select element
} $(element).trigger('change');
// Manually add the multiple attribute, if its not already set. // Call any defined change handler
if (!this.select.attr('multiple')) { return prev(option, checked);
this.select.attr('multiple', true); }
} },
update: function (element) {
// Build the dropdown. var blockRefresh = $(element).data('blockRefresh') || false;
$('option', this.select).each($.proxy(function(index, element) { if (!blockRefresh) { $(element).multiselect("refresh"); }
if ($(element).is(':selected')) { $.data(element, 'blockRefresh', false);
$(element).attr('selected', 'selected'); }
$(element).prop('selected', 'selected'); };
} }
$('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>'); function Multiselect(select, options) {
var selected = $(element).prop('selected') || false; this.options = this.getOptions(options);
var checkbox = $('ul li input[value="' + $(element).val() + '"]', this.container); this.select = $(select);
this.container = $(this.options.buttonContainer)
checkbox.prop('checked', selected); .append('<button type="button" class="dropdown-toggle ' + this.options.buttonClass + '" data-toggle="dropdown">' + this.options.buttonText($('option:selected', select)) + '</button>')
.append('<ul class="dropdown-menu"></ul>');
if (selected) {
checkbox.parents('li').addClass('active'); // Set max height of dropdown menu to activate auto scrollbar.
} if (this.options.maxHeight) {
}, this)); $('ul', this.container).css({
'max-height': this.options.maxHeight + 'px',
this.select.hide() 'overflow-y': 'auto',
.after(this.container); 'overflow-x': 'hidden',
});
// Bind the change event on the dropdown elements. }
$('ul li input[type="checkbox"]', this.container).on('change', $.proxy(function(event) {
var checked = $(event.target).prop('checked') || false; // Manually add the multiple attribute, if its not already set.
if (!this.select.attr('multiple')) {
if (checked) { this.select.attr('multiple', true);
$(event.target).parents('li').addClass('active'); }
}
else { this.addOptions(select, options);
$(event.target).parents('li').removeClass('active');
} this.select
.hide()
var option = $('option[value="' + $(event.target).val() + '"]', this.select); .after(this.container);
};
if (checked) {
option.attr('selected', 'selected'); Multiselect.prototype = {
option.prop('selected', 'selected'); addOptions: function(select, options){
}
else {
option.removeAttr('selected'); // Build the dropdown.
} $('option', this.select).each($.proxy(function(index, element) {
console.log(option); if ($(element).is(':selected')) {
var options = $('option:selected', this.select); $(element).attr('selected', 'selected');
$('button', this.container).html(this.options.buttonText(options)); $(element).prop('selected', 'selected');
}
this.options.onChange(option, checked);
}, this)); $('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>');
$('ul li a', this.container).on('click', function(event) { var selected = $(element).prop('selected') || false;
event.stopPropagation(); var checkbox = $('ul li input[value="' + $(element).val() + '"]', this.container);
});
}; checkbox.prop('checked', selected);
Multiselect.prototype = { if (selected) {
checkbox.parents('li').addClass('active');
defaults: { }
// Default text function will either print 'None selected' in case no option is selected, }, this));
// or a list of the selected options up to a length of 3 selected options.
// If more than 3 options are selected, the number of selected options is printed. // Bind the change event on the dropdown elements.
buttonText: function(options) { $('ul li input[type="checkbox"]', this.container).on('change', $.proxy(function(event) {
if (options.length == 0) { var checked = $(event.target).prop('checked') || false;
return 'None selected <b class="caret"></b>';
} if (checked) {
else if (options.length > 3) { $(event.target).parents('li').addClass('active');
return options.length + ' selected <b class="caret"></b>'; }
} else {
else { $(event.target).parents('li').removeClass('active');
var selected = ''; }
options.each(function() {
selected += $(this).text() + ', '; var option = $('option[value="' + $(event.target).val() + '"]', this.select);
});
return selected.substr(0, selected.length -2) + ' <b class="caret"></b>'; if (checked) {
} option.attr('selected', 'selected');
}, option.prop('selected', 'selected');
// Is triggered on change of the selected options. }
onChange: function() { else {
option.removeAttr('selected');
}, }
buttonClass: 'btn', console.log(option);
buttonWidth: 'auto', var options = $('option:selected', this.select);
buttonContainer: '<div class="btn-group" />', $('button', this.container).html(this.options.buttonText(options));
// Maximum height of thet dropdown menu.
// If maximum height is exceeded a scrollbar will be displayed. this.options.onChange(option, checked);
maxHeight: 400, }, this));
},
$('ul li a', this.container).on('click', function(event) {
constructor: Multiselect, event.stopPropagation();
});
reset: function() { },
defaults: {
}, // Default text function will either print 'None selected' in case no option is selected,
// or a list of the selected options up to a length of 3 selected options.
// Destroy - unbind - the plugin. // If more than 3 options are selected, the number of selected options is printed.
destroy: function() { buttonText: function(options) {
this.container.remove(); if (options.length == 0) {
this.select.show(); return 'None selected <b class="caret"></b>';
}, }
else if (options.length > 3) {
// Refreshs the checked options based on the current state of the select. return options.length + ' selected <b class="caret"></b>';
refresh: function() { }
$('option', this.select).each($.proxy(function(index, element) { else {
if ($(element).is(':selected')) { var selected = '';
$('ul li input[value="' + $(element).val() + '"]', this.container).prop('checked', true); options.each(function() {
$('ul li input[value="' + $(element).val() + '"]', this.container).parents('li').addClass('active'); selected += $(this).text() + ', ';
} });
else { return selected.substr(0, selected.length -2) + ' <b class="caret"></b>';
$('ul li input[value="' + $(element).val() + '"]', this.container).prop('checked', false); }
$('ul li input[value="' + $(element).val() + '"]', this.container).parents('li').removeClass('active'); },
} // Is triggered on change of the selected options.
}, this)); onChange: function() {
$('button', this.container).html(this.options.buttonText($('option:selected', this.select))); },
}, buttonClass: 'btn',
buttonWidth: 'auto',
// Get options by merging defaults and given options. buttonContainer: '<div class="btn-group" />',
getOptions: function(options) { // Maximum height of thet dropdown menu.
return $.extend({}, this.defaults, options); // If maximum height is exceeded a scrollbar will be displayed.
} maxHeight: 400,
}; },
$.fn.multiselect = function (option) { constructor: Multiselect,
return this.each(function () {
var data = $(this).data('multiselect'), reset: function() {
options = typeof option == 'object' && option;
},
if (!data) {
$(this).data('multiselect', (data = new Multiselect(this, options))); // Destroy - unbind - the plugin.
} destroy: function() {
this.container.remove();
if (typeof option == 'string') { this.select.show();
data[option](); },
}
}); // Refreshs the checked options based on the current state of the select.
} refresh: function() {
}(window.jQuery); $('ul', this.container).html('');
\ No newline at end of file this.addOptions(this.select, this.options);
$('option', this.select).each($.proxy(function(index, element) {
if ($(element).is(':selected')) {
$('ul li input[value="' + $(element).val() + '"]', this.container).prop('checked', true);
$('ul li input[value="' + $(element).val() + '"]', this.container).parents('li').addClass('active');
}
else {
$('ul li input[value="' + $(element).val() + '"]', this.container).prop('checked', false);
$('ul li input[value="' + $(element).val() + '"]', this.container).parents('li').removeClass('active');
}
}, this));
$('button', this.container).html(this.options.buttonText($('option:selected', this.select)));
},
// Get options by merging defaults and given options.
getOptions: function(options) {
return $.extend({}, this.defaults, options);
}
};
$.fn.multiselect = function (option) {
return this.each(function () {
var data = $(this).data('multiselect'),
options = typeof option == 'object' && option;
if (!data) {
$(this).data('multiselect', (data = new Multiselect(this, options)));
}
if (typeof option == 'string') {
data[option]();
}
});
}
}(window.jQuery);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment