mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-03 14:37:02 +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,12 +1,12 @@
|
|||
(function(undefined) {
|
||||
(() => {
|
||||
var componentLoadingOperationUniqueId = 0;
|
||||
|
||||
ko.bindingHandlers['component'] = {
|
||||
'init': function(element, valueAccessor, ignored1, ignored2, bindingContext) {
|
||||
'init': (element, valueAccessor, ignored1, ignored2, bindingContext) => {
|
||||
var currentViewModel,
|
||||
currentLoadingOperationId,
|
||||
afterRenderSub,
|
||||
disposeAssociatedComponentViewModel = function () {
|
||||
disposeAssociatedComponentViewModel = () => {
|
||||
var currentViewModelDispose = currentViewModel && currentViewModel['dispose'];
|
||||
if (typeof currentViewModelDispose === 'function') {
|
||||
currentViewModelDispose.call(currentViewModel);
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
ko.virtualElements.emptyNode(element);
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, disposeAssociatedComponentViewModel);
|
||||
|
||||
ko.computed(function () {
|
||||
ko.computed(() => {
|
||||
var value = ko.utils.unwrapObservable(valueAccessor()),
|
||||
componentName, componentParams;
|
||||
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
var asyncContext = ko.bindingEvent.startPossiblyAsyncContentBinding(element, bindingContext);
|
||||
|
||||
var loadingOperationId = currentLoadingOperationId = ++componentLoadingOperationUniqueId;
|
||||
ko.components.get(componentName, function(componentDefinition) {
|
||||
ko.components.get(componentName, componentDefinition => {
|
||||
// If this is not the current load operation for this element, ignore it.
|
||||
if (currentLoadingOperationId !== loadingOperationId) {
|
||||
return;
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
|
||||
var componentViewModel = createViewModel(componentDefinition, componentParams, componentInfo),
|
||||
childBindingContext = asyncContext['createChildContext'](componentViewModel, {
|
||||
'extend': function(ctx) {
|
||||
'extend': ctx => {
|
||||
ctx['$component'] = componentViewModel;
|
||||
ctx['$componentTemplateNodes'] = originalChildNodes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
(function (undefined) {
|
||||
(() => {
|
||||
// Overridable API for determining which component name applies to a given node. By overriding this,
|
||||
// you can for example map specific tagNames to components that are not preregistered.
|
||||
ko.components['getComponentNameForNode'] = function(node) {
|
||||
ko.components['getComponentNameForNode'] = node => {
|
||||
var tagNameLower = ko.utils.tagNameLower(node);
|
||||
if (ko.components.isRegistered(tagNameLower)) {
|
||||
// Try to determine that this node can be considered a *custom* element; see https://github.com/knockout/knockout/issues/1603
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
ko.components.addBindingsForCustomElement = function(allBindings, node, bindingContext, valueAccessors) {
|
||||
ko.components.addBindingsForCustomElement = (allBindings, node, bindingContext, valueAccessors) => {
|
||||
// Determine if it's really a custom element matching a component
|
||||
if (node.nodeType === 1) {
|
||||
var componentName = ko.components['getComponentNameForNode'](node);
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
var componentBindingValue = { 'name': componentName, 'params': getComponentParamsFromCustomElement(node, bindingContext) };
|
||||
|
||||
allBindings['component'] = valueAccessors
|
||||
? function() { return componentBindingValue; }
|
||||
? () => componentBindingValue
|
||||
: componentBindingValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -42,10 +42,10 @@
|
|||
|
||||
if (paramsAttribute) {
|
||||
var params = nativeBindingProviderInstance['parseBindingsString'](paramsAttribute, bindingContext, elem, { 'valueAccessors': true, 'bindingParams': true }),
|
||||
rawParamComputedValues = ko.utils.objectMap(params, function(paramValue, paramName) {
|
||||
return ko.computed(paramValue, null, { disposeWhenNodeIsRemoved: elem });
|
||||
}),
|
||||
result = ko.utils.objectMap(rawParamComputedValues, function(paramValueComputed, paramName) {
|
||||
rawParamComputedValues = ko.utils.objectMap(params, paramValue =>
|
||||
ko.computed(paramValue, null, { disposeWhenNodeIsRemoved: elem })
|
||||
),
|
||||
result = ko.utils.objectMap(rawParamComputedValues, paramValueComputed => {
|
||||
var paramValue = paramValueComputed.peek();
|
||||
// Does the evaluation of the parameter value unwrap any observables?
|
||||
if (!paramValueComputed.isActive()) {
|
||||
|
|
@ -58,12 +58,8 @@
|
|||
// This means the component doesn't have to worry about multiple unwrapping. If the value is a
|
||||
// writable observable, the computed will also be writable and pass the value on to the observable.
|
||||
return ko.computed({
|
||||
'read': function() {
|
||||
return ko.utils.unwrapObservable(paramValueComputed());
|
||||
},
|
||||
'write': ko.isWriteableObservable(paramValue) && function(value) {
|
||||
paramValueComputed()(value);
|
||||
},
|
||||
'read': () => ko.utils.unwrapObservable(paramValueComputed()),
|
||||
'write': ko.isWriteableObservable(paramValue) && (value => paramValueComputed()(value)),
|
||||
disposeWhenNodeIsRemoved: elem
|
||||
});
|
||||
}
|
||||
|
|
@ -77,11 +73,10 @@
|
|||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
// For consistency, absence of a "params" attribute is treated the same as the presence of
|
||||
// any empty one. Otherwise component viewmodels need special code to check whether or not
|
||||
// 'params' or 'params.$raw' is null/undefined before reading subproperties, which is annoying.
|
||||
return { '$raw': {} };
|
||||
}
|
||||
// For consistency, absence of a "params" attribute is treated the same as the presence of
|
||||
// any empty one. Otherwise component viewmodels need special code to check whether or not
|
||||
// 'params' or 'params.$raw' is null/undefined before reading subproperties, which is annoying.
|
||||
return { '$raw': {} };
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
86
vendors/knockout/src/components/defaultLoader.js
vendored
86
vendors/knockout/src/components/defaultLoader.js
vendored
|
|
@ -1,4 +1,4 @@
|
|||
(function(undefined) {
|
||||
(() => {
|
||||
|
||||
// The default loader is responsible for two things:
|
||||
// 1. Maintaining the default in-memory registry of component configuration objects
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
var defaultConfigRegistry = {};
|
||||
|
||||
ko.components.register = function(componentName, config) {
|
||||
ko.components.register = (componentName, config) => {
|
||||
if (!config) {
|
||||
throw new Error('Invalid configuration for ' + componentName);
|
||||
}
|
||||
|
|
@ -24,37 +24,35 @@
|
|||
defaultConfigRegistry[componentName] = config;
|
||||
};
|
||||
|
||||
ko.components.isRegistered = function(componentName) {
|
||||
return Object.prototype.hasOwnProperty.call(defaultConfigRegistry, componentName);
|
||||
};
|
||||
ko.components.isRegistered = componentName =>
|
||||
Object.prototype.hasOwnProperty.call(defaultConfigRegistry, componentName);
|
||||
|
||||
ko.components.unregister = function(componentName) {
|
||||
ko.components.unregister = componentName => {
|
||||
delete defaultConfigRegistry[componentName];
|
||||
ko.components.clearCachedDefinition(componentName);
|
||||
};
|
||||
|
||||
ko.components.defaultLoader = {
|
||||
'getConfig': function(componentName, callback) {
|
||||
'getConfig': (componentName, callback) => {
|
||||
var result = ko.components.isRegistered(componentName)
|
||||
? defaultConfigRegistry[componentName]
|
||||
: null;
|
||||
callback(result);
|
||||
},
|
||||
|
||||
'loadComponent': function(componentName, config, callback) {
|
||||
'loadComponent': (componentName, config, callback) => {
|
||||
var errorCallback = makeErrorCallback(componentName);
|
||||
possiblyGetConfigFromAmd(errorCallback, config, function(loadedConfig) {
|
||||
resolveConfig(componentName, errorCallback, loadedConfig, callback);
|
||||
});
|
||||
possiblyGetConfigFromAmd(errorCallback, config, loadedConfig =>
|
||||
resolveConfig(componentName, errorCallback, loadedConfig, callback)
|
||||
);
|
||||
},
|
||||
|
||||
'loadTemplate': function(componentName, templateConfig, callback) {
|
||||
resolveTemplate(makeErrorCallback(componentName), templateConfig, callback);
|
||||
},
|
||||
'loadTemplate': (componentName, templateConfig, callback) =>
|
||||
resolveTemplate(makeErrorCallback(componentName), templateConfig, callback)
|
||||
,
|
||||
|
||||
'loadViewModel': function(componentName, viewModelConfig, callback) {
|
||||
resolveViewModel(makeErrorCallback(componentName), viewModelConfig, callback);
|
||||
}
|
||||
'loadViewModel': (componentName, viewModelConfig, callback) =>
|
||||
resolveViewModel(makeErrorCallback(componentName), viewModelConfig, callback)
|
||||
};
|
||||
|
||||
var createViewModelKey = 'createViewModel';
|
||||
|
|
@ -68,7 +66,7 @@
|
|||
function resolveConfig(componentName, errorCallback, config, callback) {
|
||||
var result = {},
|
||||
makeCallBackWhenZero = 2,
|
||||
tryIssueCallback = function() {
|
||||
tryIssueCallback = () => {
|
||||
if (--makeCallBackWhenZero === 0) {
|
||||
callback(result);
|
||||
}
|
||||
|
|
@ -77,23 +75,23 @@
|
|||
viewModelConfig = config['viewModel'];
|
||||
|
||||
if (templateConfig) {
|
||||
possiblyGetConfigFromAmd(errorCallback, templateConfig, function(loadedConfig) {
|
||||
ko.components._getFirstResultFromLoaders('loadTemplate', [componentName, loadedConfig], function(resolvedTemplate) {
|
||||
possiblyGetConfigFromAmd(errorCallback, templateConfig, loadedConfig =>
|
||||
ko.components._getFirstResultFromLoaders('loadTemplate', [componentName, loadedConfig], resolvedTemplate => {
|
||||
result['template'] = resolvedTemplate;
|
||||
tryIssueCallback();
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
} else {
|
||||
tryIssueCallback();
|
||||
}
|
||||
|
||||
if (viewModelConfig) {
|
||||
possiblyGetConfigFromAmd(errorCallback, viewModelConfig, function(loadedConfig) {
|
||||
ko.components._getFirstResultFromLoaders('loadViewModel', [componentName, loadedConfig], function(resolvedViewModel) {
|
||||
possiblyGetConfigFromAmd(errorCallback, viewModelConfig, loadedConfig =>
|
||||
ko.components._getFirstResultFromLoaders('loadViewModel', [componentName, loadedConfig], resolvedViewModel => {
|
||||
result[createViewModelKey] = resolvedViewModel;
|
||||
tryIssueCallback();
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
} else {
|
||||
tryIssueCallback();
|
||||
}
|
||||
|
|
@ -106,12 +104,12 @@
|
|||
} else if (templateConfig instanceof Array) {
|
||||
// Assume already an array of DOM nodes - pass through unchanged
|
||||
callback(templateConfig);
|
||||
} else if (isDocumentFragment(templateConfig)) {
|
||||
} else if (templateConfig instanceof DocumentFragment) {
|
||||
// Document fragment - use its child nodes
|
||||
callback(ko.utils.makeArray(templateConfig.childNodes));
|
||||
} else if (templateConfig['element']) {
|
||||
var element = templateConfig['element'];
|
||||
if (isDomElement(element)) {
|
||||
if (element instanceof HTMLElement) {
|
||||
// Element instance - copy its child nodes
|
||||
callback(cloneNodesFromTemplateSourceElement(element));
|
||||
} else if (typeof element === 'string') {
|
||||
|
|
@ -136,18 +134,14 @@
|
|||
// By design, this does *not* supply componentInfo to the constructor, as the intent is that
|
||||
// componentInfo contains non-viewmodel data (e.g., the component's element) that should only
|
||||
// be used in factory functions, not viewmodel constructors.
|
||||
callback(function (params /*, componentInfo */) {
|
||||
return new viewModelConfig(params);
|
||||
});
|
||||
callback(params => new viewModelConfig(params));
|
||||
} else if (typeof viewModelConfig[createViewModelKey] === 'function') {
|
||||
// Already a factory function - use it as-is
|
||||
callback(viewModelConfig[createViewModelKey]);
|
||||
} else if ('instance' in viewModelConfig) {
|
||||
// Fixed object instance - promote to createViewModel format for API consistency
|
||||
var fixedInstance = viewModelConfig['instance'];
|
||||
callback(function (params, componentInfo) {
|
||||
return fixedInstance;
|
||||
});
|
||||
callback(() => fixedInstance);
|
||||
} else if ('viewModel' in viewModelConfig) {
|
||||
// Resolved AMD module whose value is of the form { viewModel: ... }
|
||||
resolveViewModel(errorCallback, viewModelConfig['viewModel'], callback);
|
||||
|
|
@ -160,34 +154,18 @@
|
|||
if ('template' == ko.utils.tagNameLower(elemInstance)) {
|
||||
// For browsers with proper <template> element support (i.e., where the .content property
|
||||
// gives a document fragment), use that document fragment.
|
||||
if (isDocumentFragment(elemInstance.content)) {
|
||||
if (elemInstance.content instanceof DocumentFragment) {
|
||||
return ko.utils.cloneNodes(elemInstance.content.childNodes);
|
||||
}
|
||||
}
|
||||
throw 'Template Source Element not a <template>';
|
||||
}
|
||||
|
||||
function isDomElement(obj) {
|
||||
if (window['HTMLElement']) {
|
||||
return obj instanceof HTMLElement;
|
||||
} else {
|
||||
return obj && obj.tagName && obj.nodeType === 1;
|
||||
}
|
||||
}
|
||||
|
||||
function isDocumentFragment(obj) {
|
||||
if (window['DocumentFragment']) {
|
||||
return obj instanceof DocumentFragment;
|
||||
} else {
|
||||
return obj && obj.nodeType === 11;
|
||||
}
|
||||
}
|
||||
|
||||
function possiblyGetConfigFromAmd(errorCallback, config, callback) {
|
||||
if (typeof config['require'] === 'string') {
|
||||
// The config is the value of an AMD module
|
||||
if (amdRequire || window['require']) {
|
||||
(amdRequire || window['require'])([config['require']], function (module) {
|
||||
(amdRequire || window['require'])([config['require']], module => {
|
||||
if (module && typeof module === 'object' && module.__esModule && module['default']) {
|
||||
module = module['default'];
|
||||
}
|
||||
|
|
@ -202,8 +180,8 @@
|
|||
}
|
||||
|
||||
function makeErrorCallback(componentName) {
|
||||
return function (message) {
|
||||
throw new Error('Component \'' + componentName + '\': ' + message);
|
||||
return message => {
|
||||
throw new Error('Component \'' + componentName + '\': ' + message)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
(function(undefined) {
|
||||
(() => {
|
||||
var loadingSubscribablesCache = {}, // Tracks component loads that are currently in flight
|
||||
loadedDefinitionsCache = {}; // Tracks component loads that have already completed
|
||||
|
||||
ko.components = {
|
||||
get: function(componentName, callback) {
|
||||
get: (componentName, callback) => {
|
||||
var cachedDefinition = getObjectOwnProperty(loadedDefinitionsCache, componentName);
|
||||
if (cachedDefinition) {
|
||||
// It's already loaded and cached. Reuse the same definition object.
|
||||
// Note that for API consistency, even cache hits complete asynchronously by default.
|
||||
// You can bypass this by putting synchronous:true on your component config.
|
||||
if (cachedDefinition.isSynchronousComponent) {
|
||||
ko.dependencyDetection.ignore(function() { // See comment in loaderRegistryBehaviors.js for reasoning
|
||||
callback(cachedDefinition.definition);
|
||||
});
|
||||
ko.dependencyDetection.ignore(() => // See comment in loaderRegistryBehaviors.js for reasoning
|
||||
callback(cachedDefinition.definition)
|
||||
);
|
||||
} else {
|
||||
ko.tasks.schedule(function() { callback(cachedDefinition.definition); });
|
||||
ko.tasks.schedule(() => callback(cachedDefinition.definition) );
|
||||
}
|
||||
} else {
|
||||
// Join the loading process that is already underway, or start a new one.
|
||||
|
|
@ -22,9 +22,9 @@
|
|||
}
|
||||
},
|
||||
|
||||
clearCachedDefinition: function(componentName) {
|
||||
delete loadedDefinitionsCache[componentName];
|
||||
},
|
||||
clearCachedDefinition: componentName =>
|
||||
delete loadedDefinitionsCache[componentName]
|
||||
,
|
||||
|
||||
_getFirstResultFromLoaders: getFirstResultFromLoaders
|
||||
};
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
subscribable = loadingSubscribablesCache[componentName] = new ko.subscribable();
|
||||
subscribable.subscribe(callback);
|
||||
|
||||
beginLoadingComponent(componentName, function(definition, config) {
|
||||
beginLoadingComponent(componentName, (definition, config) => {
|
||||
var isSynchronousComponent = !!(config && config['synchronous']);
|
||||
loadedDefinitionsCache[componentName] = { definition: definition, isSynchronousComponent: isSynchronousComponent };
|
||||
delete loadingSubscribablesCache[componentName];
|
||||
|
|
@ -57,9 +57,7 @@
|
|||
// See comment in loaderRegistryBehaviors.js for reasoning
|
||||
subscribable['notifySubscribers'](definition);
|
||||
} else {
|
||||
ko.tasks.schedule(function() {
|
||||
subscribable['notifySubscribers'](definition);
|
||||
});
|
||||
ko.tasks.schedule(() => subscribable['notifySubscribers'](definition));
|
||||
}
|
||||
});
|
||||
completedAsync = true;
|
||||
|
|
@ -69,12 +67,12 @@
|
|||
}
|
||||
|
||||
function beginLoadingComponent(componentName, callback) {
|
||||
getFirstResultFromLoaders('getConfig', [componentName], function(config) {
|
||||
getFirstResultFromLoaders('getConfig', [componentName], config => {
|
||||
if (config) {
|
||||
// We have a config, so now load its definition
|
||||
getFirstResultFromLoaders('loadComponent', [componentName, config], function(definition) {
|
||||
callback(definition, config);
|
||||
});
|
||||
getFirstResultFromLoaders('loadComponent', [componentName, config], definition =>
|
||||
callback(definition, config)
|
||||
);
|
||||
} else {
|
||||
// The component has no config - it's unknown to all the loaders.
|
||||
// Note that this is not an error (e.g., a module loading error) - that would abort the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue