-
-
Save jmvtrinidad/f64f87e923011f225e0e79ef05a4a5ca to your computer and use it in GitHub Desktop.
Boostrap multiselect knockout bindings for objects.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) { | |
ko.bindingHandlers.multiselect = { | |
after: ['options', 'value', 'selectedOptions', 'enable', 'disable'], | |
preprocess: function (value, name, addBindingCallback) { | |
var option = eval('(' + value + ')') || {}; | |
if (option.observableKey) { | |
addBindingCallback('optionsAfterRender', 'function(option, item) { ko.applyBindingsToNode(option, { attr: { "data-key": (item || {})["' + | |
option.observableKey + | |
'"] } }, item) }'); | |
} | |
return value; | |
}, | |
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { | |
var $element = $(element); | |
var config = ko.toJS(valueAccessor()); | |
$element.multiselect(config); | |
if (allBindings.has('options')) { | |
var options = allBindings.get('options'); | |
if (ko.isObservable(options)) { | |
ko.computed({ | |
read: function () { | |
options(); | |
setTimeout(function () { | |
var ms = $element.data('multiselect'); | |
if (ms) | |
ms.updateOriginalOptions();//Not sure how beneficial this is. | |
$element.multiselect('rebuild'); | |
}, 1); | |
}, | |
disposeWhenNodeIsRemoved: element | |
}); | |
} | |
} | |
//value and selectedOptions are two-way, so these will be triggered even by our own actions. | |
//It needs some way to tell if they are triggered because of us or because of outside change. | |
//It doesn't loop but it's a waste of processing. | |
if (allBindings.has('value')) { | |
var value = allBindings.get('value'); | |
if (ko.isObservable(value)) { | |
ko.computed({ | |
read: function () { | |
value(); | |
setTimeout(function () { | |
$element.multiselect('refresh'); | |
}, 1); | |
}, | |
disposeWhenNodeIsRemoved: element | |
}).extend({ rateLimit: 100, notifyWhenChangesStop: true }); | |
} | |
} | |
//Switched from arrayChange subscription to general subscription using 'refresh'. | |
//Not sure performance is any better using 'select' and 'deselect'. | |
if (allBindings.has('selectedOptions')) { | |
var selectedOptions = allBindings.get('selectedOptions'); | |
if (ko.isObservable(selectedOptions)) { | |
ko.computed({ | |
read: function () { | |
// Added to handle knockout binding to an object...not just a value | |
// multiselect needs the selected property on the options, else it wont show them on refresh | |
if ((config.optionsKey !== undefined) && | |
(config.optionsKey !== null) && | |
(config.optionsKey.length > 0) && | |
(config.observableKey !== undefined) && | |
(config.observableKey !== null) && | |
(config.observableKey.length > 0)) { | |
var observableKey = config.observableKey; | |
var selectedValues = selectedOptions() | |
.map(function(selectedOption) { | |
return ko.isObservable(selectedOption[observableKey]) | |
? selectedOption[observableKey]() | |
: selectedOption[observableKey]; | |
}); | |
setTimeout(function () { | |
$element.multiselect('rebuild'); | |
}, 1); | |
if (selectedValues.length) { | |
setTimeout(function () { | |
$element.multiselect('select', selectedValues); | |
}, 1); | |
} | |
} | |
}, | |
disposeWhenNodeIsRemoved: element | |
}).extend({ rateLimit: 100, notifyWhenChangesStop: true }); | |
} | |
} | |
var setEnabled = function (enable) { | |
setTimeout(function () { | |
if (enable) | |
$element.multiselect('enable'); | |
else | |
$element.multiselect('disable'); | |
}); | |
}; | |
if (allBindings.has('enable')) { | |
var enable = allBindings.get('enable'); | |
if (ko.isObservable(enable)) { | |
ko.computed({ | |
read: function () { | |
setEnabled(enable()); | |
}, | |
disposeWhenNodeIsRemoved: element | |
}).extend({ rateLimit: 100, notifyWhenChangesStop: true }); | |
} else { | |
setEnabled(enable); | |
} | |
} | |
if (allBindings.has('disable')) { | |
var disable = allBindings.get('disable'); | |
if (ko.isObservable(disable)) { | |
ko.computed({ | |
read: function () { | |
setEnabled(!disable()); | |
}, | |
disposeWhenNodeIsRemoved: element | |
}).extend({ rateLimit: 100, notifyWhenChangesStop: true }); | |
} else { | |
setEnabled(!disable); | |
} | |
} | |
ko.utils.domNodeDisposal.addDisposeCallback(element, function () { | |
$element.multiselect('destroy'); | |
}); | |
}, | |
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { | |
var $element = $(element); | |
var config = ko.toJS(valueAccessor()); | |
$element.multiselect('setOptions', config); | |
$element.multiselect('rebuild'); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment