mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-08 22:18:28 +03:00
99 lines
4.7 KiB
JavaScript
99 lines
4.7 KiB
JavaScript
ko.utils = {
|
|
extend: (target, source) => source ? Object.assign(target, source) : target,
|
|
|
|
objectForEach: (obj, action) => obj && Object.entries(obj).forEach(prop => action(prop[0], prop[1])),
|
|
|
|
emptyDomNode: domNode => [...domNode.childNodes].forEach(child => ko.removeNode(child)),
|
|
// emptyDomNode: domNode => {while (domNode.lastChild) ko.removeNode(domNode.lastChild)},
|
|
// Safari 14+
|
|
// emptyDomNode: domNode => domNode.replaceChildren(),
|
|
|
|
moveCleanedNodesToContainerElement: nodes => {
|
|
// Ensure it's a real array, as we're about to reparent the nodes and
|
|
// we don't want the underlying collection to change while we're doing that.
|
|
var nodesArray = [...nodes];
|
|
var templateDocument = nodesArray[0]?.ownerDocument || document;
|
|
|
|
var container = templateDocument.createElement('div');
|
|
nodesArray.forEach(node => container.append(ko.cleanNode(node)));
|
|
return container;
|
|
},
|
|
|
|
cloneNodes: (nodesArray, shouldCleanNodes) =>
|
|
Array.prototype.map.call(nodesArray, shouldCleanNodes
|
|
? node => ko.cleanNode(node.cloneNode(true))
|
|
: node => node.cloneNode(true)),
|
|
|
|
setDomNodeChildren: (domNode, childNodes) => {
|
|
ko.utils.emptyDomNode(domNode);
|
|
childNodes && domNode.append(...childNodes);
|
|
},
|
|
|
|
fixUpContinuousNodeArray: (continuousNodeArray, parentNode) => {
|
|
// Before acting on a set of nodes that were previously outputted by a template function, we have to reconcile
|
|
// them against what is in the DOM right now. It may be that some of the nodes have already been removed, or that
|
|
// new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
|
|
// leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
|
|
// So, this function translates the old "map" output array into its best guess of the set of current DOM nodes.
|
|
//
|
|
// Rules:
|
|
// [A] Any leading nodes that have been removed should be ignored
|
|
// These most likely correspond to memoization nodes that were already removed during binding
|
|
// See https://github.com/knockout/knockout/pull/440
|
|
// [B] Any trailing nodes that have been remove should be ignored
|
|
// This prevents the code here from adding unrelated nodes to the array while processing rule [C]
|
|
// See https://github.com/knockout/knockout/pull/1903
|
|
// [C] We want to output a continuous series of nodes. So, ignore any nodes that have already been removed,
|
|
// and include any nodes that have been inserted among the previous collection
|
|
|
|
if (continuousNodeArray.length) {
|
|
// The parent node can be a virtual element; so get the real parent node
|
|
parentNode = (parentNode.nodeType === 8 && parentNode.parentNode) || parentNode;
|
|
|
|
// Rule [A]
|
|
while (continuousNodeArray.length && continuousNodeArray[0].parentNode !== parentNode)
|
|
continuousNodeArray.splice(0, 1);
|
|
|
|
// Rule [B]
|
|
while (continuousNodeArray.length > 1
|
|
&& continuousNodeArray[continuousNodeArray.length - 1].parentNode !== parentNode)
|
|
--continuousNodeArray.length;
|
|
|
|
// Rule [C]
|
|
if (continuousNodeArray.length > 1) {
|
|
var current = continuousNodeArray[0], last = continuousNodeArray[continuousNodeArray.length - 1];
|
|
// Replace with the actual new continuous node set
|
|
continuousNodeArray.length = 0;
|
|
while (current !== last) {
|
|
continuousNodeArray.push(current);
|
|
current = current.nextSibling;
|
|
}
|
|
continuousNodeArray.push(last);
|
|
}
|
|
}
|
|
return continuousNodeArray;
|
|
},
|
|
|
|
stringTrim: string => string == null ? '' :
|
|
string.trim ?
|
|
string.trim() :
|
|
string.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''),
|
|
|
|
domNodeIsAttachedToDocument: node =>
|
|
node.ownerDocument.documentElement.contains(node.nodeType !== 1 ? node.parentNode : node),
|
|
|
|
triggerEvent: (element, eventType) => {
|
|
if (!element?.nodeType)
|
|
throw Error("element must be a DOM node when calling triggerEvent");
|
|
|
|
element.dispatchEvent(new Event(eventType));
|
|
},
|
|
|
|
unwrapObservable: value => ko.isObservable(value) ? value() : value,
|
|
|
|
setTextContent: (element, textContent) =>
|
|
element.textContent = ko.utils.unwrapObservable(textContent)
|
|
};
|
|
|
|
ko.exportSymbol('utils', ko.utils);
|
|
ko.exportSymbol('unwrap', ko.utils.unwrapObservable); // Convenient shorthand, because this is used so commonly
|