Commit db4d64e9 authored by Aaron-P's avatar Aaron-P

Improved knockout binding

Improves the initialization of the multiselect by waiting for other select related bindings to finish first.
Moved the subscription to other binder events to init so they aren't re-executed all the time.
Added support for value binding.
Added support for observable configuration properties.
Observable subscription rate-limited (by @IDisposable).
Simplified how selection changes are processed (simpler code, not sure about performance).
parent 847873e4
......@@ -11,71 +11,67 @@
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
ko.bindingHandlers.multiselect = {
after: ['options', 'value', 'selectedOptions'],
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var listOfSelectedItems = allBindingsAccessor().selectedOptions;
var config = ko.utils.unwrapObservable(valueAccessor());
$(element).multiselect(config);
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var $element = $(element);
var config = ko.toJS(valueAccessor());
$element.multiselect(config);
var options = allBindings.get('options');
if (ko.isObservable(options)) {
ko.computed(function () {
options();
setTimeout(function () {
var ms = $element.data('multiselect');
if (ms)
ms.updateOriginalOptions();//Not sure how beneficial this is.
$element.multiselect('rebuild');
}, 1);
});
}
if (isObservableArray(listOfSelectedItems)) {
// Set the initial selection state on the multiselect list.
$(element).multiselect('select', ko.utils.unwrapObservable(listOfSelectedItems));
// Subscribe to the selectedOptions: ko.observableArray
listOfSelectedItems.subscribe(function (changes) {
var addedArray = [], deletedArray = [];
forEach(changes, function (change) {
switch (change.status) {
case 'added':
addedArray.push(change.value);
break;
case 'deleted':
deletedArray.push(change.value);
break;
}
});
if (addedArray.length > 0) {
$(element).multiselect('select', addedArray);
}
if (deletedArray.length > 0) {
$(element).multiselect('deselect', deletedArray);
}
}, null, "arrayChange");
//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.
var value = allBindings.get('value');
if (ko.isObservable(value)) {
ko.computed(function () {
value();
setTimeout(function () {
$element.multiselect('refresh');
}, 1);
}).extend( { rateLimit: 100, notifyWhenChangesStop: true });
}
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
//Switched from arrayChange subscription to general subscription using 'refresh'.
//Not sure performance is any better using 'select' and 'deselect'.
var selectedOptions = allBindings.get('selectedOptions');
if (ko.isObservable(selectedOptions)) {
ko.computed(function () {
selectedOptions();
setTimeout(function () {
$element.multiselect('refresh');
}, 1);
}).extend({ rateLimit: 100, notifyWhenChangesStop: true });
}
var listOfItems = allBindingsAccessor().options,
ms = $(element).data('multiselect'),
config = ko.utils.unwrapObservable(valueAccessor());
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$element.multiselect('destroy');
});
},
if (isObservableArray(listOfItems)) {
// Subscribe to the options: ko.observableArray incase it changes later
listOfItems.subscribe(function (theArray) {
$(element).multiselect('rebuild');
});
}
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var $element = $(element);
var config = ko.toJS(valueAccessor());
if (!ms) {
$(element).multiselect(config);
}
else {
ms.updateOriginalOptions();
}
$element.multiselect('setOptions', config);
$element.multiselect('rebuild');
}
};
}
function isObservableArray(obj) {
return ko.isObservable(obj) && !(obj.destroyAll === undefined);
}
function forEach(array, callback) {
for (var index = 0; index < array.length; ++index) {
callback(array[index]);
......
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