Skip to content

Instantly share code, notes, and snippets.

@xtranophilist
Last active January 11, 2019 23:42
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save xtranophilist/6145957 to your computer and use it in GitHub Desktop.
Save xtranophilist/6145957 to your computer and use it in GitHub Desktop.
Collection of Knockout.js custom bindings.
//http://stackoverflow.com/questions/13210663/how-to-order-knockout-bindings
ko.bindingHandlers.chosen = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var allBindings = allBindingsAccessor();
var options = {default: 'Select one...'};
$.extend(options, allBindings.chosen)
$(element).attr('data-placeholder', options.default);
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
$(element).chosen();
}
};
//based on http://stackoverflow.com/questions/11448367/knockout-js-bind-to-editable-div-text
ko.bindingHandlers.editableText = {
init: function(element, valueAccessor) {
$(element).attr('contenteditable', true);
$(element).on('blur', function() {
var observable = valueAccessor();
if (typeof (observable) == 'function'){
observable( $(this).text() );
}
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).text(value);
}
};
ko.bindingHandlers.flash = {
init: function(element) {
$(element).hide().fadeIn('slow');
}
};
//It's an extension to observable. Not a binding, but very useful.
//Usage: self.discount = ko.observable(0).extend({ numeric: 2 }); //2 for 2 decimal places.
ko.extenders.numeric = function(target, precision) {
//create a writeable computed observable to intercept writes to our observable
var result = ko.computed({
read: target, //always return the original observables value
write: function(newValue) {
var current = target(),
roundingMultiplier = Math.pow(10, precision),
newValueAsNum = isNaN(newValue) ? current : parseFloat(+newValue),
valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
});
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
ko.bindingHandlers.numeric = {
init: function(element, valueAccessor) {
$(element).on('keydown', function(event) {
// Allow: backspace, delete, tab, escape, and enter
if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
// Allow: Ctrl combinations
(event.ctrlKey === true) ||
//Allow decimal symbol (.)
(event.keyCode === 190) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {
event.preventDefault();
}
}
});
},
update: function(element, valueAccessor) {
}
};
//https://github.com/ivaynberg/select2/wiki/Knockout.js-Integration
ko.bindingHandlers.select2 = {
init: function(element, valueAccessor, allBindingsAccessor) {
var obj = valueAccessor(),
allBindings = allBindingsAccessor(),
lookupKey = allBindings.lookupKey;
$(element).select2(obj);
if (lookupKey) {
var value = ko.utils.unwrapObservable(allBindings.value);
$(element).select2('data', ko.utils.arrayFirst(obj.data.results, function(item) {
return item[lookupKey] === value;
}));
}
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).select2('destroy');
});
},
update: function(element) {
$(element).trigger('change');
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment