mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 13:09:21 +03:00
Bugfix: compose mail select contacts for cc/bcc failed
Cleanup: Inputosaurus and Knockout Change: Knockout domData now uses WeakMap Replaced: Knockout domManipulation with a documentFragment
This commit is contained in:
parent
fe7c7fede4
commit
ebe2c0536f
23 changed files with 410 additions and 889 deletions
|
|
@ -260,12 +260,6 @@
|
|||
: ko.utils.objectMap(bindings, value => () => value);
|
||||
}
|
||||
|
||||
// This function is used if the binding provider doesn't include a getBindingAccessors function.
|
||||
// It must be called with 'this' set to the provider instance.
|
||||
function getBindingsAndMakeAccessors(node, context) {
|
||||
return makeAccessorsFromFunction(this['getBindings'].bind(this, node, context));
|
||||
}
|
||||
|
||||
function validateThatBindingIsAllowedForVirtualElements(bindingName) {
|
||||
var validator = ko.virtualElements.allowedBindings[bindingName];
|
||||
if (!validator)
|
||||
|
|
@ -276,22 +270,7 @@
|
|||
var nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
|
||||
|
||||
if (nextInQueue) {
|
||||
var currentChild,
|
||||
provider = ko.bindingProvider['instance'],
|
||||
preprocessNode = provider['preprocessNode'];
|
||||
|
||||
// Preprocessing allows a binding provider to mutate a node before bindings are applied to it. For example it's
|
||||
// possible to insert new siblings after it, and/or replace the node with a different one. This can be used to
|
||||
// implement custom binding syntaxes, such as {{ value }} for string interpolation, or custom element types that
|
||||
// trigger insertion of <template> contents at that point in the document.
|
||||
if (preprocessNode) {
|
||||
while (currentChild = nextInQueue) {
|
||||
nextInQueue = ko.virtualElements.nextSibling(currentChild);
|
||||
preprocessNode.call(provider, currentChild);
|
||||
}
|
||||
// Reset nextInQueue for the next loop
|
||||
nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
|
||||
}
|
||||
var currentChild;
|
||||
|
||||
while (currentChild = nextInQueue) {
|
||||
// Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
|
||||
|
|
@ -310,7 +289,7 @@
|
|||
// Perf optimisation: Apply bindings only if...
|
||||
// (1) We need to store the binding info for the node (all element nodes)
|
||||
// (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
|
||||
var shouldApplyBindings = isElement || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);
|
||||
var shouldApplyBindings = isElement || ko.bindingProvider.nodeHasBindings(nodeVerified);
|
||||
if (shouldApplyBindings)
|
||||
bindingContextForDescendants = applyBindingsToNodeInternal(nodeVerified, null, bindingContext)['bindingContextForDescendants'];
|
||||
|
||||
|
|
@ -379,14 +358,11 @@
|
|||
if (sourceBindings && typeof sourceBindings !== 'function') {
|
||||
bindings = sourceBindings;
|
||||
} else {
|
||||
var provider = ko.bindingProvider['instance'],
|
||||
getBindings = provider['getBindingAccessors'] || getBindingsAndMakeAccessors;
|
||||
|
||||
// Get the binding from the provider within a computed observable so that we can update the bindings whenever
|
||||
// the binding context is updated or if the binding provider accesses observables.
|
||||
var bindingsUpdater = ko.computed(
|
||||
() => {
|
||||
bindings = sourceBindings ? sourceBindings(bindingContext, node) : getBindings.call(provider, node, bindingContext);
|
||||
bindings = sourceBindings ? sourceBindings(bindingContext, node) : ko.bindingProvider.getBindingAccessors(node, bindingContext);
|
||||
// Register a dependency on the binding context to support observable view models.
|
||||
if (bindings) {
|
||||
if (bindingContext[contextSubscribable]) {
|
||||
|
|
|
|||
75
vendors/knockout/src/binding/bindingProvider.js
vendored
75
vendors/knockout/src/binding/bindingProvider.js
vendored
|
|
@ -1,34 +1,26 @@
|
|||
(function() {
|
||||
var defaultBindingAttributeName = "data-bind";
|
||||
(() => {
|
||||
const defaultBindingAttributeName = "data-bind",
|
||||
|
||||
ko.bindingProvider = function() {
|
||||
this.bindingCache = {};
|
||||
};
|
||||
bindingCache = {},
|
||||
|
||||
ko.utils.extend(ko.bindingProvider.prototype, {
|
||||
'nodeHasBindings': node => {
|
||||
switch (node.nodeType) {
|
||||
case 1: // Element
|
||||
return node.getAttribute(defaultBindingAttributeName) != null;
|
||||
case 8: // Comment node
|
||||
return ko.virtualElements.hasBindingValue(node);
|
||||
default: return false;
|
||||
}
|
||||
createBindingsStringEvaluatorViaCache = (bindingsString, cache, options) => {
|
||||
var cacheKey = bindingsString + (options && options['valueAccessors'] || '');
|
||||
return cache[cacheKey]
|
||||
|| (cache[cacheKey] = createBindingsStringEvaluator(bindingsString, options));
|
||||
},
|
||||
|
||||
'getBindings': function(node, bindingContext) {
|
||||
var bindingsString = this['getBindingsString'](node, bindingContext);
|
||||
return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
|
||||
},
|
||||
|
||||
'getBindingAccessors': function(node, bindingContext) {
|
||||
var bindingsString = this['getBindingsString'](node, bindingContext);
|
||||
return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node, { 'valueAccessors': true }) : null;
|
||||
createBindingsStringEvaluator = (bindingsString, options) => {
|
||||
// Build the source for a function that evaluates "expression"
|
||||
// For each scope variable, add an extra level of "with" nesting
|
||||
// Example result: with(sc1) { with(sc0) { return (expression) } }
|
||||
var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
|
||||
functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
|
||||
return new Function("$context", "$element", functionBody);
|
||||
},
|
||||
|
||||
// The following function is only used internally by this default provider.
|
||||
// It's not part of the interface definition for a general binding provider.
|
||||
'getBindingsString': (node, bindingContext) => {
|
||||
getBindingsString = node => {
|
||||
switch (node.nodeType) {
|
||||
case 1: return node.getAttribute(defaultBindingAttributeName); // Element
|
||||
case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
|
||||
|
|
@ -38,31 +30,32 @@
|
|||
|
||||
// The following function is only used internally by this default provider.
|
||||
// It's not part of the interface definition for a general binding provider.
|
||||
'parseBindingsString': function(bindingsString, bindingContext, node, options) {
|
||||
parseBindingsString = (bindingsString, bindingContext, node, options) => {
|
||||
try {
|
||||
var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache, options);
|
||||
var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, bindingCache, options);
|
||||
return bindingFunction(bindingContext, node);
|
||||
} catch (ex) {
|
||||
ex.message = "Unable to parse bindings.\nBindings value: " + bindingsString + "\nMessage: " + ex.message;
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
|
||||
ko.bindingProvider = new class
|
||||
{
|
||||
nodeHasBindings(node) {
|
||||
switch (node.nodeType) {
|
||||
case 1: // Element
|
||||
return node.getAttribute(defaultBindingAttributeName) != null;
|
||||
case 8: // Comment node
|
||||
return ko.virtualElements.hasBindingValue(node);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ko.bindingProvider['instance'] = new ko.bindingProvider();
|
||||
getBindingAccessors(node, bindingContext) {
|
||||
var bindingsString = getBindingsString(node, bindingContext);
|
||||
return bindingsString ? parseBindingsString(bindingsString, bindingContext, node, { 'valueAccessors': true }) : null;
|
||||
}
|
||||
};
|
||||
|
||||
function createBindingsStringEvaluatorViaCache(bindingsString, cache, options) {
|
||||
var cacheKey = bindingsString + (options && options['valueAccessors'] || '');
|
||||
return cache[cacheKey]
|
||||
|| (cache[cacheKey] = createBindingsStringEvaluator(bindingsString, options));
|
||||
}
|
||||
|
||||
function createBindingsStringEvaluator(bindingsString, options) {
|
||||
// Build the source for a function that evaluates "expression"
|
||||
// For each scope variable, add an extra level of "with" nesting
|
||||
// Example result: with(sc1) { with(sc0) { return (expression) } }
|
||||
var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),
|
||||
functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
|
||||
return new Function("$context", "$element", functionBody);
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,3 @@ ko.bindingHandlers['hasfocus'] = {
|
|||
}
|
||||
};
|
||||
ko.expressionRewriting.twoWayBindings['hasfocus'] = true;
|
||||
|
||||
ko.bindingHandlers['hasFocus'] = ko.bindingHandlers['hasfocus']; // Make "hasFocus" an alias
|
||||
ko.expressionRewriting.twoWayBindings['hasFocus'] = 'hasfocus';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,20 @@ ko.bindingHandlers['html'] = {
|
|||
// Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
|
||||
return { 'controlsDescendantBindings': true };
|
||||
},
|
||||
'update': (element, valueAccessor) =>
|
||||
'update': (element, valueAccessor) => {
|
||||
// setHtml will unwrap the value if needed
|
||||
ko.utils.setHtml(element, valueAccessor())
|
||||
ko.utils.emptyDomNode(element);
|
||||
|
||||
// There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
|
||||
let html = ko.utils.unwrapObservable(valueAccessor());
|
||||
|
||||
if (html != null) {
|
||||
if (typeof html != 'string')
|
||||
html = html.toString();
|
||||
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = html;
|
||||
element.appendChild(template.content);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -162,12 +162,8 @@ ko.expressionRewriting = (() => {
|
|||
|
||||
preProcessBindings: preProcessBindings,
|
||||
|
||||
keyValueArrayContainsKey: (keyValueArray, key) => {
|
||||
for (var i = 0; i < keyValueArray.length; i++)
|
||||
if (keyValueArray[i]['key'] == key)
|
||||
return true;
|
||||
return false;
|
||||
},
|
||||
keyValueArrayContainsKey: (keyValueArray, key) =>
|
||||
-1 < keyValueArray.findIndex(v => v['key'] == key),
|
||||
|
||||
// Internal, private KO utility for updating model properties from within bindings
|
||||
// property: If the property being updated is (or might be) an observable, pass it here
|
||||
|
|
|
|||
13
vendors/knockout/src/binding/selectExtensions.js
vendored
13
vendors/knockout/src/binding/selectExtensions.js
vendored
|
|
@ -36,25 +36,22 @@
|
|||
}
|
||||
break;
|
||||
case 'SELECT':
|
||||
if (value === "" || value === null) // A blank string or null value will select the caption
|
||||
value = undefined;
|
||||
var selection = -1;
|
||||
// A blank string or null value will select the caption
|
||||
var selection = -1, noValue = ("" === value || null == value);
|
||||
for (var i = 0, n = element.options.length, optionValue; i < n; ++i) {
|
||||
optionValue = ko.selectExtensions.readValue(element.options[i]);
|
||||
// Include special check to handle selecting a caption with a blank string value
|
||||
if (optionValue == value || (optionValue === "" && value === undefined)) {
|
||||
if (optionValue == value || (optionValue === "" && noValue)) {
|
||||
selection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allowUnset || selection >= 0 || (value === undefined && element.size > 1)) {
|
||||
if (allowUnset || selection >= 0 || (noValue && element.size > 1)) {
|
||||
element.selectedIndex = selection;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ((value === null) || (value === undefined))
|
||||
value = "";
|
||||
element.value = value;
|
||||
element.value = (value == null) ? "" : value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue