I want to change what happens by default when a button is pressed - I need to prevent buttons from being double-clicked.
One option is wrapping the functions the buttons are bound to in _.once() or _.throttle() from underscore, but it would be better if this were handled higher up the stack.
So I found this question: knockoutjs overriding bindinghandlers and the fiddle referenced in the answer (http://jsfiddle.net/rniemeyer/PksAn/) and tried to do something with it. Below is the original code from the fiddle.
(function(){
var originalInit = ko.bindingHandlers.click.init,
originalUpdate = ko.bindingHandlers.click.update;
ko.bindingHandlers.click = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var wrappedValueAccessor = function() {
return function(data, event) {
ko.bindingHandlers.click.preOnClick.call(viewModel, data, event);
valueAccessor().call(viewModel, data, event);
ko.bindingHandlers.click.postOnClick.call(viewModel, data, event);
};
};
originalInit(element, wrappedValueAccessor, allBindingsAccessor, viewModel);
},
update: originalUpdate,
preOnClick: function(data, event) {
},
postOnClick: function(data, event) {
}
};
})();
I tried to wrap wrappedValueAccessor with _.throttle() and I also tried wrapping the nested function but it turns out that valueAccessor() is returning a new function each time and I think that this is what I'm supposed to wrap.
That code is here: (from knockout-2.2.1.debug.js starting at line 2043)
function makeValueAccessor(bindingKey) {
return function () { return parsedBindings[bindingKey] }
}
Which means I'd have to get into the internals of knockout which seems wrong.
So my question is, am I on to the right idea here or is the approach completely wrong. Is there a better way to do this?
You can just create a debounce
version of your valueAccessor
returned handler function and store it, and return that debounced version from the wrappedValueAccessor
function:
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var debouncedAccessor = _.debounce(valueAccessor(), 800, true)
var wrappedValueAccessor = function() {
return debouncedAccessor;
};
originalInit(element, wrappedValueAccessor, allBindingsAccessor, viewModel);
},
Demo JSFiddle.