mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-04 06:57:03 +03:00
Clone 3.5.1 from github
This commit is contained in:
parent
5d281486d0
commit
091c4ec811
65 changed files with 6957 additions and 7 deletions
225
vendors/knockout/src/virtualElements.js
vendored
Normal file
225
vendors/knockout/src/virtualElements.js
vendored
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
(function() {
|
||||
// "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
|
||||
// may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
|
||||
// If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
|
||||
// of that virtual hierarchy
|
||||
//
|
||||
// The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
|
||||
// without having to scatter special cases all over the binding and templating code.
|
||||
|
||||
// IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
|
||||
// but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
|
||||
// So, use node.text where available, and node.nodeValue elsewhere
|
||||
var commentNodesHaveTextProperty = document && document.createComment("test").text === "<!--test-->";
|
||||
|
||||
var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+([\s\S]+))?\s*-->$/ : /^\s*ko(?:\s+([\s\S]+))?\s*$/;
|
||||
var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
|
||||
var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
|
||||
|
||||
function isStartComment(node) {
|
||||
return (node.nodeType == 8) && startCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);
|
||||
}
|
||||
|
||||
function isEndComment(node) {
|
||||
return (node.nodeType == 8) && endCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);
|
||||
}
|
||||
|
||||
function isUnmatchedEndComment(node) {
|
||||
return isEndComment(node) && !(ko.utils.domData.get(node, matchedEndCommentDataKey));
|
||||
}
|
||||
|
||||
var matchedEndCommentDataKey = "__ko_matchedEndComment__"
|
||||
|
||||
function getVirtualChildren(startComment, allowUnbalanced) {
|
||||
var currentNode = startComment;
|
||||
var depth = 1;
|
||||
var children = [];
|
||||
while (currentNode = currentNode.nextSibling) {
|
||||
if (isEndComment(currentNode)) {
|
||||
ko.utils.domData.set(currentNode, matchedEndCommentDataKey, true);
|
||||
depth--;
|
||||
if (depth === 0)
|
||||
return children;
|
||||
}
|
||||
|
||||
children.push(currentNode);
|
||||
|
||||
if (isStartComment(currentNode))
|
||||
depth++;
|
||||
}
|
||||
if (!allowUnbalanced)
|
||||
throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
|
||||
return null;
|
||||
}
|
||||
|
||||
function getMatchingEndComment(startComment, allowUnbalanced) {
|
||||
var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
|
||||
if (allVirtualChildren) {
|
||||
if (allVirtualChildren.length > 0)
|
||||
return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
|
||||
return startComment.nextSibling;
|
||||
} else
|
||||
return null; // Must have no matching end comment, and allowUnbalanced is true
|
||||
}
|
||||
|
||||
function getUnbalancedChildTags(node) {
|
||||
// e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
|
||||
// from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->
|
||||
var childNode = node.firstChild, captureRemaining = null;
|
||||
if (childNode) {
|
||||
do {
|
||||
if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes
|
||||
captureRemaining.push(childNode);
|
||||
else if (isStartComment(childNode)) {
|
||||
var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
|
||||
if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set
|
||||
childNode = matchingEndComment;
|
||||
else
|
||||
captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
|
||||
} else if (isEndComment(childNode)) {
|
||||
captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
|
||||
}
|
||||
} while (childNode = childNode.nextSibling);
|
||||
}
|
||||
return captureRemaining;
|
||||
}
|
||||
|
||||
ko.virtualElements = {
|
||||
allowedBindings: {},
|
||||
|
||||
childNodes: function(node) {
|
||||
return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
|
||||
},
|
||||
|
||||
emptyNode: function(node) {
|
||||
if (!isStartComment(node))
|
||||
ko.utils.emptyDomNode(node);
|
||||
else {
|
||||
var virtualChildren = ko.virtualElements.childNodes(node);
|
||||
for (var i = 0, j = virtualChildren.length; i < j; i++)
|
||||
ko.removeNode(virtualChildren[i]);
|
||||
}
|
||||
},
|
||||
|
||||
setDomNodeChildren: function(node, childNodes) {
|
||||
if (!isStartComment(node))
|
||||
ko.utils.setDomNodeChildren(node, childNodes);
|
||||
else {
|
||||
ko.virtualElements.emptyNode(node);
|
||||
var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
|
||||
for (var i = 0, j = childNodes.length; i < j; i++)
|
||||
endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
|
||||
}
|
||||
},
|
||||
|
||||
prepend: function(containerNode, nodeToPrepend) {
|
||||
var insertBeforeNode;
|
||||
|
||||
if (isStartComment(containerNode)) {
|
||||
// Start comments must always have a parent and at least one following sibling (the end comment)
|
||||
insertBeforeNode = containerNode.nextSibling;
|
||||
containerNode = containerNode.parentNode;
|
||||
} else {
|
||||
insertBeforeNode = containerNode.firstChild;
|
||||
}
|
||||
|
||||
if (!insertBeforeNode) {
|
||||
containerNode.appendChild(nodeToPrepend);
|
||||
} else if (nodeToPrepend !== insertBeforeNode) { // IE will sometimes crash if you try to insert a node before itself
|
||||
containerNode.insertBefore(nodeToPrepend, insertBeforeNode);
|
||||
}
|
||||
},
|
||||
|
||||
insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
|
||||
if (!insertAfterNode) {
|
||||
ko.virtualElements.prepend(containerNode, nodeToInsert);
|
||||
} else {
|
||||
// Children of start comments must always have a parent and at least one following sibling (the end comment)
|
||||
var insertBeforeNode = insertAfterNode.nextSibling;
|
||||
|
||||
if (isStartComment(containerNode)) {
|
||||
containerNode = containerNode.parentNode;
|
||||
}
|
||||
|
||||
if (!insertBeforeNode) {
|
||||
containerNode.appendChild(nodeToInsert);
|
||||
} else if (nodeToInsert !== insertBeforeNode) { // IE will sometimes crash if you try to insert a node before itself
|
||||
containerNode.insertBefore(nodeToInsert, insertBeforeNode);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
firstChild: function(node) {
|
||||
if (!isStartComment(node)) {
|
||||
if (node.firstChild && isEndComment(node.firstChild)) {
|
||||
throw new Error("Found invalid end comment, as the first child of " + node);
|
||||
}
|
||||
return node.firstChild;
|
||||
} else if (!node.nextSibling || isEndComment(node.nextSibling)) {
|
||||
return null;
|
||||
} else {
|
||||
return node.nextSibling;
|
||||
}
|
||||
},
|
||||
|
||||
nextSibling: function(node) {
|
||||
if (isStartComment(node)) {
|
||||
node = getMatchingEndComment(node);
|
||||
}
|
||||
|
||||
if (node.nextSibling && isEndComment(node.nextSibling)) {
|
||||
if (isUnmatchedEndComment(node.nextSibling)) {
|
||||
throw Error("Found end comment without a matching opening comment, as child of " + node);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return node.nextSibling;
|
||||
}
|
||||
},
|
||||
|
||||
hasBindingValue: isStartComment,
|
||||
|
||||
virtualNodeBindingValue: function(node) {
|
||||
var regexMatch = (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
|
||||
return regexMatch ? regexMatch[1] : null;
|
||||
},
|
||||
|
||||
normaliseVirtualElementDomStructure: function(elementVerified) {
|
||||
// Workaround for https://github.com/SteveSanderson/knockout/issues/155
|
||||
// (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
|
||||
// that are direct descendants of <ul> into the preceding <li>)
|
||||
if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
|
||||
return;
|
||||
|
||||
// Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
|
||||
// must be intended to appear *after* that child, so move them there.
|
||||
var childNode = elementVerified.firstChild;
|
||||
if (childNode) {
|
||||
do {
|
||||
if (childNode.nodeType === 1) {
|
||||
var unbalancedTags = getUnbalancedChildTags(childNode);
|
||||
if (unbalancedTags) {
|
||||
// Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
|
||||
var nodeToInsertBefore = childNode.nextSibling;
|
||||
for (var i = 0; i < unbalancedTags.length; i++) {
|
||||
if (nodeToInsertBefore)
|
||||
elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
|
||||
else
|
||||
elementVerified.appendChild(unbalancedTags[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (childNode = childNode.nextSibling);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
ko.exportSymbol('virtualElements', ko.virtualElements);
|
||||
ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
|
||||
ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
|
||||
//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified
|
||||
ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
|
||||
//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified
|
||||
ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
|
||||
ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
|
||||
Loading…
Add table
Add a link
Reference in a new issue