mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-28 19:49:20 +03:00
84 lines
3.6 KiB
JavaScript
84 lines
3.6 KiB
JavaScript
ko.bindingHandlers['textInput'] = {
|
|
'init': (element, valueAccessor, allBindings) => {
|
|
|
|
var previousElementValue = element.value,
|
|
timeoutHandle,
|
|
elementValueBeforeEvent;
|
|
|
|
var updateModel = event => {
|
|
clearTimeout(timeoutHandle);
|
|
elementValueBeforeEvent = timeoutHandle = undefined;
|
|
|
|
var elementValue = element.value;
|
|
if (previousElementValue !== elementValue) {
|
|
// Provide a way for tests to know exactly which event was processed
|
|
if (DEBUG && event) element['_ko_textInputProcessedEvent'] = event.type;
|
|
previousElementValue = elementValue;
|
|
ko.expressionRewriting.writeValueToProperty(valueAccessor(), allBindings, 'textInput', elementValue);
|
|
}
|
|
};
|
|
|
|
var deferUpdateModel = event => {
|
|
if (!timeoutHandle) {
|
|
// The elementValueBeforeEvent variable is set *only* during the brief gap between an
|
|
// event firing and the updateModel function running. This allows us to ignore model
|
|
// updates that are from the previous state of the element, usually due to techniques
|
|
// such as rateLimit. Such updates, if not ignored, can cause keystrokes to be lost.
|
|
elementValueBeforeEvent = element.value;
|
|
var handler = DEBUG ? updateModel.bind(element, {type: event.type}) : updateModel;
|
|
timeoutHandle = ko.utils.setTimeout(handler, 4);
|
|
}
|
|
};
|
|
|
|
var updateView = () => {
|
|
var modelValue = ko.utils.unwrapObservable(valueAccessor());
|
|
|
|
if (modelValue === null || modelValue === undefined) {
|
|
modelValue = '';
|
|
}
|
|
|
|
if (elementValueBeforeEvent !== undefined && modelValue === elementValueBeforeEvent) {
|
|
ko.utils.setTimeout(updateView, 4);
|
|
return;
|
|
}
|
|
|
|
// Update the element only if the element and model are different. On some browsers, updating the value
|
|
// will move the cursor to the end of the input, which would be bad while the user is typing.
|
|
if (element.value !== modelValue) {
|
|
element.value = modelValue;
|
|
previousElementValue = element.value; // In case the browser changes the value (see #2281)
|
|
}
|
|
};
|
|
|
|
var onEvent = (event, handler) =>
|
|
ko.utils.registerEventHandler(element, event, handler);
|
|
|
|
if (DEBUG && ko.bindingHandlers['textInput']['_forceUpdateOn']) {
|
|
// Provide a way for tests to specify exactly which events are bound
|
|
ko.bindingHandlers['textInput']['_forceUpdateOn'].forEach(eventName => {
|
|
if (eventName.slice(0,5) == 'after') {
|
|
onEvent(eventName.slice(5), deferUpdateModel);
|
|
} else {
|
|
onEvent(eventName, updateModel);
|
|
}
|
|
});
|
|
} else {
|
|
onEvent('input', updateModel);
|
|
}
|
|
|
|
// Bind to the change event so that we can catch programmatic updates of the value that fire this event.
|
|
onEvent('change', updateModel);
|
|
|
|
// To deal with browsers that don't notify any kind of event for some changes (IE, Safari, etc.)
|
|
onEvent('blur', updateModel);
|
|
|
|
ko.computed(updateView, { disposeWhenNodeIsRemoved: element });
|
|
}
|
|
};
|
|
ko.expressionRewriting.twoWayBindings['textInput'] = true;
|
|
|
|
// textinput is an alias for textInput
|
|
ko.bindingHandlers['textinput'] = {
|
|
// preprocess is the only way to set up a full alias
|
|
'preprocess': (value, name, addBinding) => addBinding('textInput', value)
|
|
};
|