mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-11-03 02:48:49 +03:00
KnockoutJS to ES2015/ES6
TODO: use the new Proxy for ko.observable
This commit is contained in:
parent
a0f8ac0dad
commit
72ed2b08b2
56 changed files with 941 additions and 1873 deletions
|
|
@ -1,6 +1,6 @@
|
|||
var attrHtmlToJavaScriptMap = { 'class': 'className', 'for': 'htmlFor' };
|
||||
ko.bindingHandlers['attr'] = {
|
||||
'update': function(element, valueAccessor, allBindings) {
|
||||
'update': (element, valueAccessor, allBindings) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor()) || {};
|
||||
ko.utils.objectForEach(value, function(attrName, attrValue) {
|
||||
attrValue = ko.utils.unwrapObservable(attrValue);
|
||||
|
|
|
|||
|
|
@ -1,137 +0,0 @@
|
|||
(function() {
|
||||
|
||||
function addOrRemoveItem(array, value, included) {
|
||||
var existingEntryIndex = ko.utils.arrayIndexOf(ko.utils.peekObservable(array), value);
|
||||
if (existingEntryIndex < 0) {
|
||||
if (included)
|
||||
array.push(value);
|
||||
} else {
|
||||
if (!included)
|
||||
array.splice(existingEntryIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
ko.bindingHandlers['checked'] = {
|
||||
'after': ['value', 'attr'],
|
||||
'init': function (element, valueAccessor, allBindings) {
|
||||
var checkedValue = ko.pureComputed(function() {
|
||||
// Treat "value" like "checkedValue" when it is included with "checked" binding
|
||||
if (allBindings['has']('checkedValue')) {
|
||||
return ko.utils.unwrapObservable(allBindings.get('checkedValue'));
|
||||
} else if (useElementValue) {
|
||||
if (allBindings['has']('value')) {
|
||||
return ko.utils.unwrapObservable(allBindings.get('value'));
|
||||
} else {
|
||||
return element.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function updateModel() {
|
||||
// This updates the model value from the view value.
|
||||
// It runs in response to DOM events (click) and changes in checkedValue.
|
||||
var isChecked = element.checked,
|
||||
elemValue = checkedValue();
|
||||
|
||||
// When we're first setting up this computed, don't change any model state.
|
||||
if (ko.computedContext.isInitial()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We can ignore unchecked radio buttons, because some other radio
|
||||
// button will be checked, and that one can take care of updating state.
|
||||
// Also ignore value changes to an already unchecked checkbox.
|
||||
if (!isChecked && (isRadio || ko.computedContext.getDependenciesCount())) {
|
||||
return;
|
||||
}
|
||||
|
||||
var modelValue = ko.dependencyDetection.ignore(valueAccessor);
|
||||
if (valueIsArray) {
|
||||
var writableValue = rawValueIsNonArrayObservable ? modelValue.peek() : modelValue,
|
||||
saveOldValue = oldElemValue;
|
||||
oldElemValue = elemValue;
|
||||
|
||||
if (saveOldValue !== elemValue) {
|
||||
// When we're responding to the checkedValue changing, and the element is
|
||||
// currently checked, replace the old elem value with the new elem value
|
||||
// in the model array.
|
||||
if (isChecked) {
|
||||
addOrRemoveItem(writableValue, elemValue, true);
|
||||
addOrRemoveItem(writableValue, saveOldValue, false);
|
||||
}
|
||||
} else {
|
||||
// When we're responding to the user having checked/unchecked a checkbox,
|
||||
// add/remove the element value to the model array.
|
||||
addOrRemoveItem(writableValue, elemValue, isChecked);
|
||||
}
|
||||
|
||||
if (rawValueIsNonArrayObservable && ko.isWriteableObservable(modelValue)) {
|
||||
modelValue(writableValue);
|
||||
}
|
||||
} else {
|
||||
if (isCheckbox) {
|
||||
if (elemValue === undefined) {
|
||||
elemValue = isChecked;
|
||||
} else if (!isChecked) {
|
||||
elemValue = undefined;
|
||||
}
|
||||
}
|
||||
ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);
|
||||
}
|
||||
};
|
||||
|
||||
function updateView() {
|
||||
// This updates the view value from the model value.
|
||||
// It runs in response to changes in the bound (checked) value.
|
||||
var modelValue = ko.utils.unwrapObservable(valueAccessor()),
|
||||
elemValue = checkedValue();
|
||||
|
||||
if (valueIsArray) {
|
||||
// When a checkbox is bound to an array, being checked represents its value being present in that array
|
||||
element.checked = ko.utils.arrayIndexOf(modelValue, elemValue) >= 0;
|
||||
oldElemValue = elemValue;
|
||||
} else if (isCheckbox && elemValue === undefined) {
|
||||
// When a checkbox is bound to any other value (not an array) and "checkedValue" is not defined,
|
||||
// being checked represents the value being trueish
|
||||
element.checked = !!modelValue;
|
||||
} else {
|
||||
// Otherwise, being checked means that the checkbox or radio button's value corresponds to the model value
|
||||
element.checked = (checkedValue() === modelValue);
|
||||
}
|
||||
};
|
||||
|
||||
var isCheckbox = element.type == "checkbox",
|
||||
isRadio = element.type == "radio";
|
||||
|
||||
// Only bind to check boxes and radio buttons
|
||||
if (!isCheckbox && !isRadio) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rawValue = valueAccessor(),
|
||||
valueIsArray = isCheckbox && (ko.utils.unwrapObservable(rawValue) instanceof Array),
|
||||
rawValueIsNonArrayObservable = !(valueIsArray && rawValue.push && rawValue.splice),
|
||||
useElementValue = isRadio || valueIsArray,
|
||||
oldElemValue = valueIsArray ? checkedValue() : undefined;
|
||||
|
||||
// Set up two computeds to update the binding:
|
||||
|
||||
// The first responds to changes in the checkedValue value and to element clicks
|
||||
ko.computed(updateModel, null, { disposeWhenNodeIsRemoved: element });
|
||||
ko.utils.registerEventHandler(element, "click", updateModel);
|
||||
|
||||
// The second responds to changes in the model value (the one associated with the checked binding)
|
||||
ko.computed(updateView, null, { disposeWhenNodeIsRemoved: element });
|
||||
|
||||
rawValue = undefined;
|
||||
}
|
||||
};
|
||||
ko.expressionRewriting.twoWayBindings['checked'] = true;
|
||||
|
||||
ko.bindingHandlers['checkedValue'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
element.value = ko.utils.unwrapObservable(valueAccessor());
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var classesWrittenByBindingKey = '__ko__cssValue';
|
||||
|
||||
ko.bindingHandlers['class'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.stringTrim(ko.utils.unwrapObservable(valueAccessor()));
|
||||
ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
|
||||
element[classesWrittenByBindingKey] = value;
|
||||
|
|
@ -10,10 +10,10 @@ ko.bindingHandlers['class'] = {
|
|||
};
|
||||
|
||||
ko.bindingHandlers['css'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor());
|
||||
if (value !== null && typeof value == "object") {
|
||||
ko.utils.objectForEach(value, function(className, shouldHaveClass) {
|
||||
ko.utils.objectForEach(value, (className, shouldHaveClass) => {
|
||||
shouldHaveClass = ko.utils.unwrapObservable(shouldHaveClass);
|
||||
ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
ko.bindingHandlers['enable'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor());
|
||||
if (value && element.disabled)
|
||||
element.removeAttribute("disabled");
|
||||
|
|
@ -9,7 +9,6 @@ ko.bindingHandlers['enable'] = {
|
|||
};
|
||||
|
||||
ko.bindingHandlers['disable'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
|
||||
}
|
||||
'update': (element, valueAccessor) =>
|
||||
ko.bindingHandlers['enable']['update'](element, () => !ko.utils.unwrapObservable(valueAccessor()))
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
function makeEventHandlerShortcut(eventName) {
|
||||
ko.bindingHandlers[eventName] = {
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
var newValueAccessor = function () {
|
||||
var newValueAccessor = () => {
|
||||
var result = {};
|
||||
result[eventName] = valueAccessor();
|
||||
return result;
|
||||
|
|
@ -14,9 +14,9 @@ function makeEventHandlerShortcut(eventName) {
|
|||
}
|
||||
|
||||
ko.bindingHandlers['event'] = {
|
||||
'init' : function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
'init' : (element, valueAccessor, allBindings, viewModel, bindingContext) => {
|
||||
var eventsToHandle = valueAccessor() || {};
|
||||
ko.utils.objectForEach(eventsToHandle, function(eventName) {
|
||||
ko.utils.objectForEach(eventsToHandle, eventName => {
|
||||
if (typeof eventName == "string") {
|
||||
ko.utils.registerEventHandler(element, eventName, function (event) {
|
||||
var handlerReturnValue;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
|
||||
// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
|
||||
ko.bindingHandlers['foreach'] = {
|
||||
makeTemplateValueAccessor: function(valueAccessor) {
|
||||
return function() {
|
||||
makeTemplateValueAccessor: valueAccessor => {
|
||||
return () => {
|
||||
var modelValue = valueAccessor(),
|
||||
unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here
|
||||
|
||||
|
|
@ -28,12 +28,11 @@ ko.bindingHandlers['foreach'] = {
|
|||
};
|
||||
};
|
||||
},
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
|
||||
},
|
||||
'update': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindings, viewModel, bindingContext);
|
||||
}
|
||||
'init': (element, valueAccessor) =>
|
||||
ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor))
|
||||
,
|
||||
'update': (element, valueAccessor, allBindings, viewModel, bindingContext) =>
|
||||
ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindings, viewModel, bindingContext)
|
||||
};
|
||||
ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
|
||||
ko.virtualElements.allowedBindings['foreach'] = true;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
|
||||
var hasfocusLastValue = '__ko_hasfocusLastValue';
|
||||
ko.bindingHandlers['hasfocus'] = {
|
||||
'init': function(element, valueAccessor, allBindings) {
|
||||
var handleElementFocusChange = function(isFocused) {
|
||||
'init': (element, valueAccessor, allBindings) => {
|
||||
var handleElementFocusChange = isFocused => {
|
||||
// Where possible, ignore which event was raised and determine focus state using activeElement,
|
||||
// as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
|
||||
// However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
|
||||
|
|
@ -29,7 +29,7 @@ ko.bindingHandlers['hasfocus'] = {
|
|||
// Assume element is not focused (prevents "blur" being called initially)
|
||||
element[hasfocusLastValue] = false;
|
||||
},
|
||||
'update': function(element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = !!ko.utils.unwrapObservable(valueAccessor());
|
||||
|
||||
if (!element[hasfocusUpdatingProperty] && element[hasfocusLastValue] !== value) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
ko.bindingHandlers['html'] = {
|
||||
'init': function() {
|
||||
'init': () => {
|
||||
// Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
|
||||
return { 'controlsDescendantBindings': true };
|
||||
},
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) =>
|
||||
// setHtml will unwrap the value if needed
|
||||
ko.utils.setHtml(element, valueAccessor());
|
||||
}
|
||||
ko.utils.setHtml(element, valueAccessor())
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
(function () {
|
||||
|
||||
// Makes a binding like with or if
|
||||
function makeWithIfBinding(bindingKey, isWith, isNot) {
|
||||
ko.bindingHandlers[bindingKey] = {
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
var didDisplayOnLastUpdate, savedNodes, contextOptions = {}, completeOnRender, needAsyncContext, renderOnEveryChange;
|
||||
|
||||
if (isWith) {
|
||||
var as = allBindings.get('as'), noChildContext = allBindings.get('noChildContext');
|
||||
renderOnEveryChange = !(as && noChildContext);
|
||||
contextOptions = { 'as': as, 'noChildContext': noChildContext, 'exportDependencies': renderOnEveryChange };
|
||||
}
|
||||
|
||||
completeOnRender = allBindings.get("completeOn") == "render";
|
||||
needAsyncContext = completeOnRender || allBindings['has'](ko.bindingEvent.descendantsComplete);
|
||||
|
||||
ko.computed(function() {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor()),
|
||||
shouldDisplay = !isNot !== !value, // equivalent to isNot ? !value : !!value,
|
||||
isInitial = !savedNodes,
|
||||
childContext;
|
||||
|
||||
if (!renderOnEveryChange && shouldDisplay === didDisplayOnLastUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (needAsyncContext) {
|
||||
bindingContext = ko.bindingEvent.startPossiblyAsyncContentBinding(element, bindingContext);
|
||||
}
|
||||
|
||||
if (shouldDisplay) {
|
||||
if (!isWith || renderOnEveryChange) {
|
||||
contextOptions['dataDependency'] = ko.computedContext.computed();
|
||||
}
|
||||
|
||||
if (isWith) {
|
||||
childContext = bindingContext['createChildContext'](typeof value == "function" ? value : valueAccessor, contextOptions);
|
||||
} else if (ko.computedContext.getDependenciesCount()) {
|
||||
childContext = bindingContext['extend'](null, contextOptions);
|
||||
} else {
|
||||
childContext = bindingContext;
|
||||
}
|
||||
}
|
||||
|
||||
// Save a copy of the inner nodes on the initial update, but only if we have dependencies.
|
||||
if (isInitial && ko.computedContext.getDependenciesCount()) {
|
||||
savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
|
||||
}
|
||||
|
||||
if (shouldDisplay) {
|
||||
if (!isInitial) {
|
||||
ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(savedNodes));
|
||||
}
|
||||
|
||||
ko.applyBindingsToDescendants(childContext, element);
|
||||
} else {
|
||||
ko.virtualElements.emptyNode(element);
|
||||
|
||||
if (!completeOnRender) {
|
||||
ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);
|
||||
}
|
||||
}
|
||||
|
||||
didDisplayOnLastUpdate = shouldDisplay;
|
||||
|
||||
}, null, { disposeWhenNodeIsRemoved: element });
|
||||
|
||||
return { 'controlsDescendantBindings': true };
|
||||
}
|
||||
};
|
||||
ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
|
||||
ko.virtualElements.allowedBindings[bindingKey] = true;
|
||||
}
|
||||
|
||||
// Construct the actual binding handlers
|
||||
makeWithIfBinding('if');
|
||||
makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
|
||||
makeWithIfBinding('with', true /* isWith */);
|
||||
|
||||
})();
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
ko.bindingHandlers['let'] = {
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
// Make a modified binding context, with extra properties, and apply it to descendant elements
|
||||
var innerContext = bindingContext['extend'](valueAccessor);
|
||||
ko.applyBindingsToDescendants(innerContext, element);
|
||||
|
||||
return { 'controlsDescendantBindings': true };
|
||||
}
|
||||
};
|
||||
ko.virtualElements.allowedBindings['let'] = true;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var captionPlaceholder = {};
|
||||
ko.bindingHandlers['options'] = {
|
||||
'init': function(element) {
|
||||
'init': element => {
|
||||
if (ko.utils.tagNameLower(element) !== "select")
|
||||
throw new Error("options binding applies only to SELECT elements");
|
||||
|
||||
|
|
@ -12,9 +12,9 @@ ko.bindingHandlers['options'] = {
|
|||
// Ensures that the binding processor doesn't try to bind the options
|
||||
return { 'controlsDescendantBindings': true };
|
||||
},
|
||||
'update': function (element, valueAccessor, allBindings) {
|
||||
'update': (element, valueAccessor, allBindings) => {
|
||||
function selectedOptions() {
|
||||
return ko.utils.arrayFilter(element.options, function (node) { return node.selected; });
|
||||
return ko.utils.arrayFilter(element.options, node => node.selected);
|
||||
}
|
||||
|
||||
var selectWasPreviouslyEmpty = element.length == 0,
|
||||
|
|
@ -41,9 +41,9 @@ ko.bindingHandlers['options'] = {
|
|||
unwrappedArray = [unwrappedArray];
|
||||
|
||||
// Filter out any entries marked as destroyed
|
||||
filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
|
||||
return includeDestroyed || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
|
||||
});
|
||||
filteredArray = ko.utils.arrayFilter(unwrappedArray, item =>
|
||||
includeDestroyed || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy'])
|
||||
);
|
||||
|
||||
// If caption is included, add it to the array
|
||||
if (allBindings['has']('optionsCaption')) {
|
||||
|
|
@ -95,10 +95,7 @@ ko.bindingHandlers['options'] = {
|
|||
|
||||
// By using a beforeRemove callback, we delay the removal until after new items are added. This fixes a selection
|
||||
// problem in IE<=8 and Firefox. See https://github.com/knockout/knockout/issues/1208
|
||||
arrayToDomNodeChildrenOptions['beforeRemove'] =
|
||||
function (option) {
|
||||
element.removeChild(option);
|
||||
};
|
||||
arrayToDomNodeChildrenOptions['beforeRemove'] = option => element.removeChild(option);
|
||||
|
||||
function setSelectionCallback(arrayEntry, newOptions) {
|
||||
if (itemUpdate && valueAllowUnset) {
|
||||
|
|
@ -119,7 +116,7 @@ ko.bindingHandlers['options'] = {
|
|||
|
||||
var callback = setSelectionCallback;
|
||||
if (allBindings['has']('optionsAfterRender') && typeof allBindings.get('optionsAfterRender') == "function") {
|
||||
callback = function(arrayEntry, newOptions) {
|
||||
callback = (arrayEntry, newOptions) => {
|
||||
setSelectionCallback(arrayEntry, newOptions);
|
||||
ko.dependencyDetection.ignore(allBindings.get('optionsAfterRender'), null, [newOptions[0], arrayEntry !== captionPlaceholder ? arrayEntry : undefined]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
ko.bindingHandlers['selectedOptions'] = {
|
||||
'init': function (element, valueAccessor, allBindings) {
|
||||
function updateFromView() {
|
||||
var value = valueAccessor(), valueToWrite = [];
|
||||
ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
|
||||
if (node.selected)
|
||||
valueToWrite.push(ko.selectExtensions.readValue(node));
|
||||
});
|
||||
ko.expressionRewriting.writeValueToProperty(value, allBindings, 'selectedOptions', valueToWrite);
|
||||
}
|
||||
|
||||
function updateFromModel() {
|
||||
var newValue = ko.utils.unwrapObservable(valueAccessor()),
|
||||
previousScrollTop = element.scrollTop;
|
||||
|
||||
if (newValue && typeof newValue.length == "number") {
|
||||
ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
|
||||
node.selected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
|
||||
});
|
||||
}
|
||||
|
||||
element.scrollTop = previousScrollTop;
|
||||
}
|
||||
|
||||
if (ko.utils.tagNameLower(element) != "select") {
|
||||
throw new Error("selectedOptions binding applies only to SELECT elements");
|
||||
}
|
||||
|
||||
var updateFromModelComputed;
|
||||
ko.bindingEvent.subscribe(element, ko.bindingEvent.childrenComplete, function () {
|
||||
if (!updateFromModelComputed) {
|
||||
ko.utils.registerEventHandler(element, "change", updateFromView);
|
||||
updateFromModelComputed = ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });
|
||||
} else {
|
||||
updateFromView();
|
||||
}
|
||||
}, null, { 'notifyImmediately': true });
|
||||
},
|
||||
'update': function() {} // Keep for backwards compatibility with code that may have wrapped binding
|
||||
};
|
||||
ko.expressionRewriting.twoWayBindings['selectedOptions'] = true;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
ko.bindingHandlers['style'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor() || {});
|
||||
ko.utils.objectForEach(value, function(styleName, styleValue) {
|
||||
ko.utils.objectForEach(value, (styleName, styleValue) => {
|
||||
styleValue = ko.utils.unwrapObservable(styleValue);
|
||||
|
||||
if (styleValue === null || styleValue === undefined || styleValue === false) {
|
||||
|
|
@ -13,9 +13,7 @@ ko.bindingHandlers['style'] = {
|
|||
// Is styleName a custom CSS property?
|
||||
element.style.setProperty(styleName, styleValue);
|
||||
} else {
|
||||
styleName = styleName.replace(/-(\w)/g, function (all, letter) {
|
||||
return letter.toUpperCase();
|
||||
});
|
||||
styleName = styleName.replace(/-(\w)/g, (all, letter) => letter.toUpperCase());
|
||||
|
||||
var previousStyle = element.style[styleName];
|
||||
element.style[styleName] = styleValue;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
ko.bindingHandlers['submit'] = {
|
||||
'init': function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
'init': (element, valueAccessor, allBindings, viewModel, bindingContext) => {
|
||||
if (typeof valueAccessor() != "function")
|
||||
throw new Error("The value for a submit binding must be a function");
|
||||
ko.utils.registerEventHandler(element, "submit", function (event) {
|
||||
ko.utils.registerEventHandler(element, "submit", event => {
|
||||
var handlerReturnValue;
|
||||
var value = valueAccessor();
|
||||
try { handlerReturnValue = value.call(bindingContext['$data'], element); }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
ko.bindingHandlers['text'] = {
|
||||
'init': function() {
|
||||
'init': () => {
|
||||
// Prevent binding on the dynamically-injected text node (as developers are unlikely to expect that, and it has security implications).
|
||||
// It should also make things faster, as we no longer have to consider whether the text node might be bindable.
|
||||
return { 'controlsDescendantBindings': true };
|
||||
},
|
||||
'update': function (element, valueAccessor) {
|
||||
ko.utils.setTextContent(element, valueAccessor());
|
||||
}
|
||||
'update': (element, valueAccessor) =>
|
||||
ko.utils.setTextContent(element, valueAccessor())
|
||||
};
|
||||
ko.virtualElements.allowedBindings['text'] = true;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
(function () {
|
||||
|
||||
ko.bindingHandlers['textInput'] = {
|
||||
'init': function (element, valueAccessor, allBindings) {
|
||||
'init': (element, valueAccessor, allBindings) => {
|
||||
|
||||
var previousElementValue = element.value,
|
||||
timeoutHandle,
|
||||
elementValueBeforeEvent;
|
||||
|
||||
var updateModel = function (event) {
|
||||
var updateModel = event => {
|
||||
clearTimeout(timeoutHandle);
|
||||
elementValueBeforeEvent = timeoutHandle = undefined;
|
||||
|
||||
|
|
@ -20,7 +18,7 @@ ko.bindingHandlers['textInput'] = {
|
|||
}
|
||||
};
|
||||
|
||||
var deferUpdateModel = function (event) {
|
||||
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
|
||||
|
|
@ -32,11 +30,7 @@ ko.bindingHandlers['textInput'] = {
|
|||
}
|
||||
};
|
||||
|
||||
// IE9 will mess up the DOM if you handle events synchronously which results in DOM changes (such as other bindings);
|
||||
// so we'll make sure all updates are asynchronous
|
||||
var ourUpdate = false;
|
||||
|
||||
var updateView = function () {
|
||||
var updateView = () => {
|
||||
var modelValue = ko.utils.unwrapObservable(valueAccessor());
|
||||
|
||||
if (modelValue === null || modelValue === undefined) {
|
||||
|
|
@ -51,20 +45,17 @@ ko.bindingHandlers['textInput'] = {
|
|||
// 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) {
|
||||
ourUpdate = true; // Make sure we ignore events (propertychange) that result from updating the value
|
||||
element.value = modelValue;
|
||||
ourUpdate = false;
|
||||
previousElementValue = element.value; // In case the browser changes the value (see #2281)
|
||||
}
|
||||
};
|
||||
|
||||
var onEvent = function (event, handler) {
|
||||
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.utils.arrayForEach(ko.bindingHandlers['textInput']['_forceUpdateOn'], function(eventName) {
|
||||
ko.utils.arrayForEach(ko.bindingHandlers['textInput']['_forceUpdateOn'], eventName => {
|
||||
if (eventName.slice(0,5) == 'after') {
|
||||
onEvent(eventName.slice(5), deferUpdateModel);
|
||||
} else {
|
||||
|
|
@ -89,9 +80,5 @@ 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': function (value, name, addBinding) {
|
||||
addBinding('textInput', value);
|
||||
}
|
||||
'preprocess': (value, name, addBinding) => addBinding('textInput', value)
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
ko.bindingHandlers['uniqueName'] = {
|
||||
'init': function (element, valueAccessor) {
|
||||
if (valueAccessor()) {
|
||||
element.name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
ko.bindingHandlers['uniqueName'].currentIndex = 0;
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
ko.bindingHandlers['using'] = {
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
var options;
|
||||
|
||||
if (allBindings['has']('as')) {
|
||||
options = { 'as': allBindings.get('as'), 'noChildContext': allBindings.get('noChildContext') };
|
||||
}
|
||||
|
||||
var innerContext = bindingContext['createChildContext'](valueAccessor, options);
|
||||
ko.applyBindingsToDescendants(innerContext, element);
|
||||
|
||||
return { 'controlsDescendantBindings': true };
|
||||
}
|
||||
};
|
||||
ko.virtualElements.allowedBindings['using'] = true;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
ko.bindingHandlers['value'] = {
|
||||
'init': function (element, valueAccessor, allBindings) {
|
||||
'init': (element, valueAccessor, allBindings) => {
|
||||
var tagName = ko.utils.tagNameLower(element),
|
||||
isInputElement = tagName == "input";
|
||||
|
||||
|
|
@ -18,27 +18,27 @@ ko.bindingHandlers['value'] = {
|
|||
if (typeof requestedEventsToCatch == "string") {
|
||||
eventsToCatch = [requestedEventsToCatch];
|
||||
} else {
|
||||
eventsToCatch = requestedEventsToCatch ? requestedEventsToCatch.filter(function(item, index) {
|
||||
return requestedEventsToCatch.indexOf(item) === index;
|
||||
}) : [];
|
||||
eventsToCatch = requestedEventsToCatch ? requestedEventsToCatch.filter((item, index) =>
|
||||
requestedEventsToCatch.indexOf(item) === index
|
||||
) : [];
|
||||
}
|
||||
ko.utils.arrayRemoveItem(eventsToCatch, "change"); // We'll subscribe to "change" events later
|
||||
}
|
||||
|
||||
var valueUpdateHandler = function() {
|
||||
var valueUpdateHandler = () => {
|
||||
elementValueBeforeEvent = null;
|
||||
var modelValue = valueAccessor();
|
||||
var elementValue = ko.selectExtensions.readValue(element);
|
||||
ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'value', elementValue);
|
||||
}
|
||||
|
||||
ko.utils.arrayForEach(eventsToCatch, function(eventName) {
|
||||
ko.utils.arrayForEach(eventsToCatch, eventName => {
|
||||
// The syntax "after<eventname>" means "run the handler asynchronously after the event"
|
||||
// This is useful, for example, to catch "keydown" events after the browser has updated the control
|
||||
// (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
|
||||
var handler = valueUpdateHandler;
|
||||
if (ko.utils.stringStartsWith(eventName, "after")) {
|
||||
handler = function() {
|
||||
handler = () => {
|
||||
// The elementValueBeforeEvent variable is non-null *only* during the brief gap between
|
||||
// a keyX event firing and the valueUpdateHandler running, which is scheduled to happen
|
||||
// at the earliest asynchronous opportunity. We store this temporary information so that
|
||||
|
|
@ -58,7 +58,7 @@ ko.bindingHandlers['value'] = {
|
|||
|
||||
if (isInputElement && element.type == "file") {
|
||||
// For file input elements, can only write the empty string
|
||||
updateFromModel = function () {
|
||||
updateFromModel = () => {
|
||||
var newValue = ko.utils.unwrapObservable(valueAccessor());
|
||||
if (newValue === null || newValue === undefined || newValue === "") {
|
||||
element.value = "";
|
||||
|
|
@ -67,7 +67,7 @@ ko.bindingHandlers['value'] = {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
updateFromModel = function () {
|
||||
updateFromModel = () => {
|
||||
var newValue = ko.utils.unwrapObservable(valueAccessor());
|
||||
var elementValue = ko.selectExtensions.readValue(element);
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ ko.bindingHandlers['value'] = {
|
|||
|
||||
if (tagName === "select") {
|
||||
var updateFromModelComputed;
|
||||
ko.bindingEvent.subscribe(element, ko.bindingEvent.childrenComplete, function () {
|
||||
ko.bindingEvent.subscribe(element, ko.bindingEvent.childrenComplete, () => {
|
||||
if (!updateFromModelComputed) {
|
||||
ko.utils.registerEventHandler(element, "change", valueUpdateHandler);
|
||||
updateFromModelComputed = ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });
|
||||
|
|
@ -111,6 +111,6 @@ ko.bindingHandlers['value'] = {
|
|||
ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });
|
||||
}
|
||||
},
|
||||
'update': function() {} // Keep for backwards compatibility with code that may have wrapped value binding
|
||||
'update': () => {} // Keep for backwards compatibility with code that may have wrapped value binding
|
||||
};
|
||||
ko.expressionRewriting.twoWayBindings['value'] = true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
ko.bindingHandlers['visible'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor());
|
||||
var isCurrentlyVisible = !(element.style.display == "none");
|
||||
if (value && !isCurrentlyVisible)
|
||||
|
|
@ -10,7 +10,6 @@ ko.bindingHandlers['visible'] = {
|
|||
};
|
||||
|
||||
ko.bindingHandlers['hidden'] = {
|
||||
'update': function (element, valueAccessor) {
|
||||
ko.bindingHandlers['visible']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
|
||||
}
|
||||
'update': (element, valueAccessor) =>
|
||||
ko.bindingHandlers['visible']['update'](element, () => !ko.utils.unwrapObservable(valueAccessor()) )
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue