mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 21:19:21 +03:00
Use JavaScript Optional chaining in vendors/*
This commit is contained in:
parent
e5e4675c1b
commit
ef8b1f40e4
28 changed files with 619 additions and 750 deletions
|
|
@ -13,10 +13,17 @@
|
|||
ko.bindingContext = class {
|
||||
constructor(dataItemOrAccessor, parentContext, dataItemAlias, extendCallback, options)
|
||||
{
|
||||
var self = this,
|
||||
shouldInheritData = dataItemOrAccessor === inheritParentVm,
|
||||
realDataItemOrAccessor = shouldInheritData ? undefined : dataItemOrAccessor,
|
||||
isFunc = typeof(realDataItemOrAccessor) == "function" && !ko.isObservable(realDataItemOrAccessor),
|
||||
subscribable,
|
||||
dataDependency = options && options['dataDependency'],
|
||||
|
||||
// The binding context object includes static properties for the current, parent, and root view models.
|
||||
// If a view model is actually stored in an observable, the corresponding binding context object, and
|
||||
// any child contexts, must be updated when the view model is changed.
|
||||
function updateContext() {
|
||||
updateContext = () => {
|
||||
// Most of the time, the context will directly get a view model object, but if a function is given,
|
||||
// we call the function to retrieve the view model. If the function accesses any observables or returns
|
||||
// an observable, the dependency is tracked, and those observables can later cause the binding
|
||||
|
|
@ -71,14 +78,7 @@
|
|||
}
|
||||
|
||||
return self['$data'];
|
||||
}
|
||||
|
||||
var self = this,
|
||||
shouldInheritData = dataItemOrAccessor === inheritParentVm,
|
||||
realDataItemOrAccessor = shouldInheritData ? undefined : dataItemOrAccessor,
|
||||
isFunc = typeof(realDataItemOrAccessor) == "function" && !ko.isObservable(realDataItemOrAccessor),
|
||||
subscribable,
|
||||
dataDependency = options && options['dataDependency'];
|
||||
};
|
||||
|
||||
if (options && options['exportDependencies']) {
|
||||
// The "exportDependencies" option means that the calling code will track any dependencies and re-create
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@ ko.bindingHandlers['attr'] = {
|
|||
namespace ? element.removeAttributeNS(namespace, attrName) : element.removeAttribute(attrName);
|
||||
} else {
|
||||
attrValue = attrValue.toString();
|
||||
}
|
||||
|
||||
if (!toRemove) {
|
||||
namespace ? element.setAttributeNS(namespace, attrName, attrValue) : element.setAttribute(attrName, attrValue);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
var classesWrittenByBindingKey = '__ko__cssValue',
|
||||
toggleClasses = (node, classNames, force) => {
|
||||
if (classNames) {
|
||||
classNames.split(/\s+/).forEach(className =>
|
||||
node.classList.toggle(className, force)
|
||||
);
|
||||
}
|
||||
};
|
||||
toggleClasses = (node, classNames, force) =>
|
||||
classNames && classNames.split(/\s+/).forEach(className =>
|
||||
node.classList.toggle(className, force)
|
||||
);
|
||||
|
||||
ko.bindingHandlers['css'] = {
|
||||
'update': (element, valueAccessor) => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor());
|
||||
if (value !== null && typeof value == "object") {
|
||||
if (typeof value == "object") {
|
||||
ko.utils.objectForEach(value, (className, shouldHaveClass) => {
|
||||
shouldHaveClass = ko.utils.unwrapObservable(shouldHaveClass);
|
||||
toggleClasses(element, className, !!shouldHaveClass);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ ko.bindingHandlers['enable'] = {
|
|||
var value = ko.utils.unwrapObservable(valueAccessor());
|
||||
if (value && element.disabled)
|
||||
element.removeAttribute("disabled");
|
||||
else if ((!value) && (!element.disabled))
|
||||
else if (!value && !element.disabled)
|
||||
element.disabled = true;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@
|
|||
function makeEventHandlerShortcut(eventName) {
|
||||
ko.bindingHandlers[eventName] = {
|
||||
'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||
var newValueAccessor = () => {
|
||||
return {
|
||||
[eventName]: valueAccessor()
|
||||
};
|
||||
};
|
||||
return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);
|
||||
return ko.bindingHandlers['event']['init'].call(this, element,
|
||||
() => ({[eventName]: valueAccessor()}), // newValueAccessor
|
||||
allBindings, viewModel, bindingContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,19 +15,18 @@ ko.bindingHandlers['event'] = {
|
|||
var eventsToHandle = valueAccessor() || {};
|
||||
ko.utils.objectForEach(eventsToHandle, eventName => {
|
||||
if (typeof eventName == "string") {
|
||||
element.addEventListener(eventName, function (event) {
|
||||
element.addEventListener(eventName, (...args) => {
|
||||
var handlerReturnValue;
|
||||
var handlerFunction = valueAccessor()[eventName];
|
||||
if (!handlerFunction)
|
||||
return;
|
||||
|
||||
try {
|
||||
viewModel = bindingContext['$data'];
|
||||
// Take all the event args, and prefix with the viewmodel
|
||||
handlerReturnValue = handlerFunction.apply(viewModel, [viewModel, ...arguments]);
|
||||
} finally {
|
||||
if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
|
||||
event.preventDefault();
|
||||
if (handlerFunction) {
|
||||
try {
|
||||
viewModel = bindingContext['$data'];
|
||||
// Take all the event args, and prefix with the viewmodel
|
||||
handlerReturnValue = handlerFunction.apply(viewModel, [viewModel, ...args]);
|
||||
} finally {
|
||||
if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
|
||||
args[0].preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(function () {
|
||||
(() => {
|
||||
|
||||
// Makes a binding like with or if
|
||||
function makeWithIfBinding(bindingKey, isWith, isNot) {
|
||||
|
|
@ -7,8 +7,7 @@ function makeWithIfBinding(bindingKey, isWith, isNot) {
|
|||
var savedNodes, contextOptions = {}, needAsyncContext;
|
||||
|
||||
if (isWith) {
|
||||
var as = allBindings.get('as');
|
||||
contextOptions = { 'as': as, 'exportDependencies': true };
|
||||
contextOptions = { 'as': allBindings.get('as'), 'exportDependencies': true };
|
||||
}
|
||||
|
||||
needAsyncContext = allBindings['has'](ko.bindingEvent.descendantsComplete);
|
||||
|
|
|
|||
|
|
@ -5,17 +5,15 @@ ko.bindingHandlers['options'] = {
|
|||
throw new Error("options binding applies only to SELECT elements");
|
||||
|
||||
// Remove all existing <option>s.
|
||||
while (element.length > 0) {
|
||||
element.remove(0);
|
||||
let l = element.length;
|
||||
while (l--) {
|
||||
element.remove(l);
|
||||
}
|
||||
|
||||
// Ensures that the binding processor doesn't try to bind the options
|
||||
return { 'controlsDescendantBindings': true };
|
||||
},
|
||||
'update': (element, valueAccessor, allBindings) => {
|
||||
function selectedOptions() {
|
||||
return Array.from(element.options).filter(node => node.selected);
|
||||
}
|
||||
|
||||
var selectWasPreviouslyEmpty = element.length == 0,
|
||||
multiple = element.multiple,
|
||||
|
|
@ -25,7 +23,36 @@ ko.bindingHandlers['options'] = {
|
|||
arrayToDomNodeChildrenOptions = {},
|
||||
captionValue,
|
||||
filteredArray,
|
||||
previousSelectedValues = [];
|
||||
previousSelectedValues = [],
|
||||
|
||||
selectedOptions = () => Array.from(element.options).filter(node => node.selected),
|
||||
|
||||
applyToObject = (object, predicate, defaultValue) => {
|
||||
var predicateType = typeof predicate;
|
||||
if (predicateType == "function") // Given a function; run it against the data value
|
||||
return predicate(object);
|
||||
else if (predicateType == "string") // Given a string; treat it as a property name on the data value
|
||||
return object[predicate];
|
||||
// Given no optionsText arg; use the data value itself
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
setSelectionCallback = (arrayEntry, newOptions) => {
|
||||
if (itemUpdate && valueAllowUnset) {
|
||||
// The model value is authoritative, so make sure its value is the one selected
|
||||
ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);
|
||||
} else if (previousSelectedValues.length) {
|
||||
// IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
|
||||
// That's why we first added them without selection. Now it's time to set the selection.
|
||||
var isSelected = previousSelectedValues.includes(ko.selectExtensions.readValue(newOptions[0]));
|
||||
newOptions[0].selected = isSelected;
|
||||
|
||||
// If this option was changed from being selected during a single-item update, notify the change
|
||||
if (itemUpdate && !isSelected) {
|
||||
ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!valueAllowUnset) {
|
||||
if (multiple) {
|
||||
|
|
@ -54,22 +81,12 @@ ko.bindingHandlers['options'] = {
|
|||
// If a falsy value is provided (e.g. null), we'll simply empty the select element
|
||||
}
|
||||
|
||||
function applyToObject(object, predicate, defaultValue) {
|
||||
var predicateType = typeof predicate;
|
||||
if (predicateType == "function") // Given a function; run it against the data value
|
||||
return predicate(object);
|
||||
else if (predicateType == "string") // Given a string; treat it as a property name on the data value
|
||||
return object[predicate];
|
||||
else // Given no optionsText arg; use the data value itself
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// The following functions can run at two different times:
|
||||
// The first is when the whole array is being updated directly from this binding handler.
|
||||
// The second is when an observable value for a specific array entry is updated.
|
||||
// oldOptions will be empty in the first case, but will be filled with the previously generated option in the second.
|
||||
var itemUpdate = false;
|
||||
function optionForArrayItem(arrayEntry, index, oldOptions) {
|
||||
var itemUpdate = false,
|
||||
optionForArrayItem = (arrayEntry, index, oldOptions) => {
|
||||
if (oldOptions.length) {
|
||||
previousSelectedValues = !valueAllowUnset && oldOptions[0].selected ? [ ko.selectExtensions.readValue(oldOptions[0]) ] : [];
|
||||
itemUpdate = true;
|
||||
|
|
@ -88,29 +105,12 @@ ko.bindingHandlers['options'] = {
|
|||
ko.utils.setTextContent(option, optionText);
|
||||
}
|
||||
return [option];
|
||||
}
|
||||
};
|
||||
|
||||
// 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'] = option => element.removeChild(option);
|
||||
|
||||
function setSelectionCallback(arrayEntry, newOptions) {
|
||||
if (itemUpdate && valueAllowUnset) {
|
||||
// The model value is authoritative, so make sure its value is the one selected
|
||||
ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);
|
||||
} else if (previousSelectedValues.length) {
|
||||
// IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
|
||||
// That's why we first added them without selection. Now it's time to set the selection.
|
||||
var isSelected = previousSelectedValues.includes(ko.selectExtensions.readValue(newOptions[0]));
|
||||
newOptions[0].selected = isSelected;
|
||||
|
||||
// If this option was changed from being selected during a single-item update, notify the change
|
||||
if (itemUpdate && !isSelected) {
|
||||
ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var callback = setSelectionCallback;
|
||||
if (allBindings['has']('optionsAfterRender') && typeof allBindings.get('optionsAfterRender') == "function") {
|
||||
callback = (arrayEntry, newOptions) => {
|
||||
|
|
@ -123,25 +123,23 @@ ko.bindingHandlers['options'] = {
|
|||
|
||||
if (!valueAllowUnset) {
|
||||
// Determine if the selection has changed as a result of updating the options list
|
||||
var selectionChanged;
|
||||
var selectionChanged, prevLength = previousSelectedValues.length;
|
||||
if (multiple) {
|
||||
// For a multiple-select box, compare the new selection count to the previous one
|
||||
// But if nothing was selected before, the selection can't have changed
|
||||
selectionChanged = previousSelectedValues.length && selectedOptions().length < previousSelectedValues.length;
|
||||
selectionChanged = prevLength && selectedOptions().length < prevLength;
|
||||
} else {
|
||||
// For a single-select box, compare the current value to the previous value
|
||||
// But if nothing was selected before or nothing is selected now, just look for a change in selection
|
||||
selectionChanged = (previousSelectedValues.length && element.selectedIndex >= 0)
|
||||
selectionChanged = (prevLength && element.selectedIndex >= 0)
|
||||
? (ko.selectExtensions.readValue(element.options[element.selectedIndex]) !== previousSelectedValues[0])
|
||||
: (previousSelectedValues.length || element.selectedIndex >= 0);
|
||||
: (prevLength || element.selectedIndex >= 0);
|
||||
}
|
||||
|
||||
// Ensure consistency between model value and selected option.
|
||||
// If the dropdown was changed so that selection is no longer the same,
|
||||
// notify the value or selectedOptions binding.
|
||||
if (selectionChanged) {
|
||||
ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
|
||||
}
|
||||
selectionChanged && ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
|
||||
}
|
||||
|
||||
if (valueAllowUnset || ko.dependencyDetection.isInitial()) {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@ ko.bindingHandlers['submit'] = {
|
|||
try { handlerReturnValue = value.call(bindingContext['$data'], element); }
|
||||
finally {
|
||||
if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
|
||||
if (event.preventDefault)
|
||||
event.preventDefault();
|
||||
else
|
||||
event.returnValue = false;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,23 +18,9 @@ ko.utils.findMovesInArrayComparison = (left, right, limitFailedCompares) => {
|
|||
};
|
||||
|
||||
ko.utils.compareArrays = (() => {
|
||||
var statusNotInOld = 'added', statusNotInNew = 'deleted';
|
||||
var statusNotInOld = 'added', statusNotInNew = 'deleted',
|
||||
|
||||
// Simple calculation based on Levenshtein distance.
|
||||
function compareArrays(oldArray, newArray, options) {
|
||||
// For backward compatibility, if the third arg is actually a bool, interpret
|
||||
// it as the old parameter 'dontLimitMoves'. Newer code should use { dontLimitMoves: true }.
|
||||
options = (typeof options === 'boolean') ? { 'dontLimitMoves': options } : (options || {});
|
||||
oldArray = oldArray || [];
|
||||
newArray = newArray || [];
|
||||
|
||||
if (oldArray.length < newArray.length)
|
||||
return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, options);
|
||||
else
|
||||
return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, options);
|
||||
}
|
||||
|
||||
function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, options) {
|
||||
compareSmallArrayToBigArray = (smlArray, bigArray, statusNotInSml, statusNotInBig, options) => {
|
||||
var myMin = Math.min,
|
||||
myMax = Math.max,
|
||||
editDistanceMatrix = [],
|
||||
|
|
@ -94,7 +80,18 @@ ko.utils.compareArrays = (() => {
|
|||
ko.utils.findMovesInArrayComparison(notInBig, notInSml, !options['dontLimitMoves'] && smlIndexMax * 10);
|
||||
|
||||
return editScript.reverse();
|
||||
}
|
||||
};
|
||||
|
||||
return compareArrays;
|
||||
// Simple calculation based on Levenshtein distance.
|
||||
return (oldArray, newArray, options) => {
|
||||
// For backward compatibility, if the third arg is actually a bool, interpret
|
||||
// it as the old parameter 'dontLimitMoves'. Newer code should use { dontLimitMoves: true }.
|
||||
options = (typeof options === 'boolean') ? { 'dontLimitMoves': options } : (options || {});
|
||||
oldArray = oldArray || [];
|
||||
newArray = newArray || [];
|
||||
|
||||
return (oldArray.length < newArray.length)
|
||||
? compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, options)
|
||||
: compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, options);
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue