Skip to content

Commit

Permalink
Consistently use TreeApi.Composed api for composed dom manipulation; …
Browse files Browse the repository at this point in the history
…use TreeApi.Logical methods to get node leaves. Avoid making a Polymer.dom when TreeApi.Logical can provide the needed info.
  • Loading branch information
Steven Orvell committed Dec 10, 2015
1 parent 8272d5e commit 5033fdb
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 79 deletions.
2 changes: 1 addition & 1 deletion src/lib/dom-api-classlist.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

_distributeParent: function() {
if (!useShadow) {
this.domApi._distributeParent();
this.domApi._maybeDistributeParent();
}
},

Expand Down
71 changes: 33 additions & 38 deletions src/lib/dom-api-shady.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
return;
}

var nativeInsertBefore = Element.prototype.insertBefore;
var nativeRemoveChild = Element.prototype.removeChild;
var nativeAppendChild = Element.prototype.appendChild;
var nativeCloneNode = Element.prototype.cloneNode;
var nativeImportNode = Document.prototype.importNode;

Expand Down Expand Up @@ -73,11 +70,10 @@
// if adding to a shadyRoot, add to host instead
var container = this.node._isShadyRoot ? this.node.host : this.node;
if (ref_node) {
nativeInsertBefore.call(container, node, ref_node);
TreeApi.Composed.insertBefore(container, node, ref_node);
} else {
nativeAppendChild.call(container, node);
TreeApi.Composed.appendChild(container, node);
}
TreeApi.Composed.recordInsertBefore(container, node, ref_node);
}
this.notifyObserver();
return node;
Expand Down Expand Up @@ -105,8 +101,8 @@
This method also performs dom composition.
*/
removeChild: function(node) {
if (dom(node).parentNode !== this.node) {
console.warn('The node to be removed is not a child of this node',
if (TreeApi.Logical.getParentNode(node) !== this.node) {
throw Error('The node to be removed is not a child of this node: ' +
node);
}
if (!this._removeNode(node)) {
Expand All @@ -115,8 +111,7 @@
// not guaranteed to physically be in container; e.g.
// undistributed nodes.
if (container === node.parentNode) {
nativeRemoveChild.call(container, node);
TreeApi.Composed.recordRemoveChild(container, node);
TreeApi.Composed.removeChild(container, node);
}
}
this.notifyObserver();
Expand All @@ -128,16 +123,14 @@
// note that it's possible for both the node's host and its parent
// to require distribution... both cases are handled here.
_removeNode: function(node) {
TreeApi.Composed.recordRemoveChild(
TreeApi.Composed.getParentNode(node), node);
// important that we want to do this only if the node has a logical parent
var logicalParent = TreeApi.Logical.hasParentNode(node) &&
TreeApi.Logical.getParentNode(node);
var distributed;
var root = this._ownerShadyRootForNode(node);
if (logicalParent) {
// distribute node's parent iff needed
distributed = dom(node)._distributeParent();
distributed = dom(node)._maybeDistributeParent();
TreeApi.Logical.recordRemoveChild(node, logicalParent);
// remove node from root and distribute it iff needed
if (root && this._removeDistributedChildren(root, node)) {
Expand Down Expand Up @@ -175,7 +168,7 @@
if (node._isShadyRoot) {
root = node;
} else {
var parent = Polymer.dom(node).parentNode;
var parent = TreeApi.Logical.getParentNode(node);
if (parent) {
root = parent._isShadyRoot ? parent :
this._ownerShadyRootForNode(parent);
Expand All @@ -196,9 +189,9 @@
// distributeContent(true), which updates insertion points manually
// and forces distribution.
var fragContent = (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) &&
!node.__noContent && Polymer.dom(node).querySelector(CONTENT);
!node.__noContent && dom(node).querySelector(CONTENT);
var wrappedContent = fragContent &&
(Polymer.dom(fragContent).parentNode.nodeType !==
(TreeApi.Logical.getParentNode(fragContent).nodeType !==
Node.DOCUMENT_FRAGMENT_NODE);
var hasContent = fragContent || (node.localName === CONTENT);
// There are 2 possible cases where a distribution may need to occur:
Expand Down Expand Up @@ -234,7 +227,7 @@
!node.__noContent) {
var c$ = dom(node).querySelectorAll(CONTENT);
for (var i=0, n, np, na; (i<c$.length) && (n=c$[i]); i++) {
np = dom(n).parentNode;
np = TreeApi.Logical.getParentNode(n);
// don't allow node's parent to be fragment itself
if (np === node) {
np = parent;
Expand All @@ -254,7 +247,7 @@
if (this.node.shadyRoot) {
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
nativeRemoveChild.call(parent, node);
TreeApi.Composed.removeChild(parent, node);
}
return true;
}
Expand All @@ -267,7 +260,7 @@
for (var i=0, c; i < i$.length; i++) {
c = i$[i];
TreeApi.Logical.saveChildNodes(c);
TreeApi.Logical.saveChildNodes(dom(c).parentNode);
TreeApi.Logical.saveChildNodes(TreeApi.Logical.getParentNode(c));
}
},

Expand Down Expand Up @@ -301,8 +294,7 @@
var node = dc$[j];
var parent = node.parentNode;
if (parent) {
nativeRemoveChild.call(parent, node);
TreeApi.Composed.recordRemoveChild(parent, node);
TreeApi.Composed.removeChild(parent, node);
}
}
}
Expand All @@ -315,14 +307,14 @@
if (node == container) {
return true;
}
node = dom(node).parentNode;
node = TreeApi.Logical.getParentNode(node);
}
},

_removeOwnerShadyRoot: function(node) {
// optimization: only reset the tree if node is actually in a root
if (this._hasCachedOwnerRoot(node)) {
var c$ = dom(node).childNodes;
var c$ = TreeApi.Logical.getChildNodes(node);
for (var i=0, l=c$.length, n; (i<l) && (n=c$[i]); i++) {
this._removeOwnerShadyRoot(n);
}
Expand Down Expand Up @@ -358,7 +350,7 @@
_query: function(matcher, node) {
node = node || this.node;
var list = [];
this._queryElements(dom(node).childNodes, matcher, list);
this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, list);
return list;
},

Expand All @@ -374,7 +366,7 @@
if (matcher(node)) {
list.push(node);
}
this._queryElements(dom(node).childNodes, matcher, list);
this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, list);
},

getDestinationInsertionPoints: function() {
Expand All @@ -393,15 +385,15 @@

setAttribute: function(name, value) {
this.node.setAttribute(name, value);
this._distributeParent();
this._maybeDistributeParent();
},

removeAttribute: function(name) {
this.node.removeAttribute(name);
this._distributeParent();
this._maybeDistributeParent();
},

_distributeParent: function() {
_maybeDistributeParent: function() {
if (this._nodeNeedsDistribution(this.parentNode)) {
this._lazyDistribute(this.parentNode);
return true;
Expand All @@ -427,7 +419,7 @@
this.node.ownerDocument;
var n = nativeImportNode.call(doc, externalNode, false);
if (deep) {
var c$ = dom(externalNode).childNodes;
var c$ = TreeApi.Logical.getChildNodes(externalNode);
var d = dom(n);
for (var i=0, nc; i < c$.length; i++) {
nc = dom(doc).importNode(c$[i], true);
Expand Down Expand Up @@ -455,45 +447,48 @@

children: {
get: function() {
return Array.prototype.filter.call(this.childNodes, function(n) {
return (n.nodeType === Node.ELEMENT_NODE);
});
if (TreeApi.Logical.hasChildNodes(this.node)) {
return Array.prototype.filter.call(this.childNodes, function(n) {
return (n.nodeType === Node.ELEMENT_NODE);
});
} else {
return TreeApi.arrayCopyChildren(this.node);
}
},
configurable: true
},

parentNode: {
get: function() {
return this.node.__parentNode ||
TreeApi.Composed.getParentNode(this.node);
return TreeApi.Logical.getParentNode(this.node);
},
configurable: true
},

firstChild: {
get: function() {
return this.node.__firstChild || this.node.firstChild;
return TreeApi.Logical.getFirstChild(this.node);
},
configurable: true
},

lastChild: {
get: function() {
return this.node.__lastChild || this.node.lastChild;
return TreeApi.Logical.getLastChild(this.node);
},
configurable: true
},

nextSibling: {
get: function() {
return this.node.__nextSibling || this.node.nextSibling;
return TreeApi.Logical.getNextSibling(this.node);
},
configurable: true
},

previousSibling: {
get: function() {
return this.node.__previousSibling || this.node.previousSibling;
return TreeApi.Logical.getPreviousSibling(this.node);
},
configurable: true
},
Expand Down
4 changes: 2 additions & 2 deletions src/lib/dom-api.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
var c$ = this.childNodes;
for (var i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) {
if (c.localName === CONTENT) {
var d$ = DomApi.factory(c).getDistributedNodes();
var d$ = dom(c).getDistributedNodes();
for (var j=0; j < d$.length; j++) {
list.push(d$[j]);
}
Expand Down Expand Up @@ -140,7 +140,7 @@

var CONTENT = DomApi.CONTENT = 'content';

DomApi.factory = function(node, patch) {
var dom = DomApi.factory = function(node, patch) {
node = node || document;
if (!node.__domApi) {
node.__domApi = new DomApi(node, patch);
Expand Down
76 changes: 49 additions & 27 deletions src/lib/dom-tree-api.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

// native add/remove
var nativeInsertBefore = Element.prototype.insertBefore;
var nativeAppendChild = Element.prototype.appendChild;
var nativeRemoveChild = Element.prototype.removeChild;

/**
Expand Down Expand Up @@ -63,6 +64,10 @@
},

getChildNodes: function(node) {
// note: we're distinguishing here between undefined and false-y:
// hasChildNodes uses undefined check to see if this element has logical
// children; the false-y check indicates whether or not we should rebuild
// the cached childNodes array.
if (this.hasChildNodes(node)) {
if (!node.__childNodes) {
node.__childNodes = [];
Expand All @@ -80,7 +85,23 @@
},

getParentNode: function(node) {
return node.__parentNode || node.parentNode;
return node.__parentNode || TreeApi.Composed.getParentNode(node);
},

getFirstChild: function(node) {
return node.__firstChild || TreeApi.Composed.getFirstChild(node);
},

getLastChild: function(node) {
return node.__lastChild || TreeApi.Composed.getLastChild(node);
},

getNextSibling: function(node) {
return node.__nextSibling || TreeApi.Composed.getNextSibling(node);
},

getPreviousSibling: function(node) {
return node.__previousSibling || TreeApi.Composed.getPreviousSibling(node);
},

// Capture the list of light children. It's important to do this before we
Expand Down Expand Up @@ -119,20 +140,23 @@
},

_linkNode: function(node, container, ref_node) {
// update node <-> ref_node
// update ref_node.previousSibling <-> node
node.__previousSibling = ref_node ? ref_node.__previousSibling :
container.__lastChild;
if (node.__previousSibling) {
node.__previousSibling.__nextSibling = node;
}
// update node <-> ref_node
node.__nextSibling = ref_node;
if (ref_node) {
ref_node.__previousSibling = node;
if (node.__nextSibling) {
node.__nextSibling.__previousSibling = node;
}
// update node <-> container
node.__parentNode = container;
if (ref_node && ref_node === container.__firstChild) {
container.__firstChild = node;
if (ref_node) {
if (ref_node === container.__firstChild) {
container.__firstChild = node;
}
} else {
container.__lastChild = node;
if (!container.__firstChild) {
Expand Down Expand Up @@ -182,13 +206,20 @@
return node.parentNode;
},

recordInsertBefore: function(parent, node, ref_node) {
getFirstChild: function(node) {
return node.firstChild;
},

recordRemoveChild: function(parent, node) {
getLastChild: function(node) {
return node.lastChild;
},

recordParentNode: function(node, parent) {
getNextSibling: function(node) {
return node.nextSibling;
},

getPreviousSibling: function(node) {
return node.previousSibling;
},

// composed tracking needs to reset composed children here in case
Expand All @@ -200,24 +231,15 @@
},

insertBefore: function(parentNode, newChild, refChild) {
var newChildParent = this.getParentNode(newChild);
if (newChildParent !== parentNode) {
this.recordRemoveChild(newChildParent, newChild);
}
// remove child from its old parent first
this.removeChild(newChild);
// insert it into the real DOM
nativeInsertBefore.call(parentNode, newChild, refChild || null);
this.recordParentNode(newChild, parentNode);
},

removeChild: function(node) {
var parentNode = this.getParentNode(node);
if (parentNode) {
this.recordParentNode(node, null);
// remove it from the real DOM
nativeRemoveChild.call(parentNode, node);
}
return nativeInsertBefore.call(parentNode, newChild, refChild || null);
},

appendChild: function(parentNode, newChild) {
return nativeAppendChild.call(parentNode, newChild);
},

removeChild: function(parentNode, node) {
return nativeRemoveChild.call(parentNode, node);
}

};
Expand Down
Loading

0 comments on commit 5033fdb

Please sign in to comment.