Comparing version 2.0.1 to 2.0.2
@@ -8,2 +8,10 @@ Changelog | ||
### 2.0.2 | ||
- Fixed [#78](https://github.com/patrick-steele-idem/morphdom/issues/78) - Elements under `onBeforeElChildrenUpdated` element removed if they have `id` set | ||
### 2.0.1 | ||
- Small optimization and more tests | ||
### 2.0.0 | ||
@@ -10,0 +18,0 @@ |
@@ -241,8 +241,24 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.morphdom = f()}})(function(){var define,module,exports;module={exports:(exports={})}; | ||
var fromNodesLookup = {}; | ||
var keyedRemovalList; | ||
function walkDiscardedChildNodes(node) { | ||
function addKeyedRemoval(key) { | ||
if (keyedRemovalList) { | ||
keyedRemovalList.push(key); | ||
} else { | ||
keyedRemovalList = [key]; | ||
} | ||
} | ||
function walkDiscardedChildNodes(node, skipKeyedNodes) { | ||
if (node.nodeType === ELEMENT_NODE) { | ||
var curChild = node.firstChild; | ||
while (curChild) { | ||
if (!getNodeKey(curChild)) { | ||
var key = undefined; | ||
if (skipKeyedNodes && (key = getNodeKey(curChild))) { | ||
// If we are skipping keyed nodes then we add the key | ||
// to a list so that it can be handled at the very end. | ||
addKeyedRemoval(key); | ||
} else { | ||
// Only report the node as discarded if it is not keyed. We do this because | ||
@@ -253,3 +269,3 @@ // at the end we loop through all keyed elements that were unmatched | ||
if (curChild.firstChild) { | ||
walkDiscardedChildNodes(curChild); | ||
walkDiscardedChildNodes(curChild, skipKeyedNodes); | ||
} | ||
@@ -263,3 +279,11 @@ } | ||
function removeNode(node, parentNode) { | ||
/** | ||
* Removes a DOM node out of the original DOM | ||
* | ||
* @param {Node} node The node to remove | ||
* @param {Node} parentNode The nodes parent | ||
* @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded. | ||
* @return {undefined} | ||
*/ | ||
function removeNode(node, parentNode, skipKeyedNodes) { | ||
if (onBeforeNodeDiscarded(node) === false) { | ||
@@ -274,3 +298,3 @@ return; | ||
onNodeDiscarded(node); | ||
walkDiscardedChildNodes(node); | ||
walkDiscardedChildNodes(node, skipKeyedNodes); | ||
} | ||
@@ -348,2 +372,4 @@ | ||
var toElKey = getNodeKey(toEl); | ||
var curFromNodeKey; | ||
if (toElKey) { | ||
@@ -382,3 +408,3 @@ // If an element with an ID is being morphed then it is will be in the final | ||
while (curFromNodeChild) { | ||
var curFromNodeKey = getNodeKey(curFromNodeChild); | ||
curFromNodeKey = getNodeKey(curFromNodeChild); | ||
fromNextSibling = curFromNodeChild.nextSibling; | ||
@@ -419,4 +445,11 @@ | ||
if (!curFromNodeKey) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if (curFromNodeKey) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -467,4 +500,10 @@ fromNextSibling = curFromNodeChild.nextSibling; | ||
// that didn't find a home | ||
if (!curFromNodeKey) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if (curFromNodeKey) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -498,4 +537,10 @@ | ||
fromNextSibling = curFromNodeChild.nextSibling; | ||
if (!getNodeKey(curFromNodeChild)) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if ((curFromNodeKey = getNodeKey(curFromNodeChild))) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -547,6 +592,13 @@ curFromNodeChild = fromNextSibling; | ||
for (var k in fromNodesLookup) { | ||
var elToRemove = fromNodesLookup[k]; | ||
if (elToRemove) { | ||
removeNode(elToRemove, elToRemove.parentNode); | ||
// We now need to loop over any keyed nodes that might need to be | ||
// removed. We only do the removal if we know that the keyed node | ||
// never found a match. When a keyed node is matched up we remove | ||
// it out of fromNodesLookup and we use fromNodesLookup to determine | ||
// if a keyed node has been matched up or not | ||
if (keyedRemovalList) { | ||
for (var i=0, len=keyedRemovalList.length; i<len; i++) { | ||
var elToRemove = fromNodesLookup[keyedRemovalList[i]]; | ||
if (elToRemove) { | ||
removeNode(elToRemove, elToRemove.parentNode, false); | ||
} | ||
} | ||
@@ -553,0 +605,0 @@ } |
@@ -1,1 +0,1 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.morphdom=f()}})(function(){var define,module,exports;module={exports:exports={}};"use strict";var range;var testEl=typeof document!=="undefined"?document.body||document.createElement("div"):{};var XHTML="http://www.w3.org/1999/xhtml";var ELEMENT_NODE=1;var TEXT_NODE=3;var COMMENT_NODE=8;var hasAttributeNS;if(testEl.hasAttributeNS){hasAttributeNS=function(el,namespaceURI,name){return el.hasAttributeNS(namespaceURI,name)}}else if(testEl.hasAttribute){hasAttributeNS=function(el,namespaceURI,name){return el.hasAttribute(name)}}else{hasAttributeNS=function(el,namespaceURI,name){return!!el.getAttributeNode(name)}}function toElement(str){if(!range&&document.createRange){range=document.createRange();range.selectNode(document.body)}var fragment;if(range&&range.createContextualFragment){fragment=range.createContextualFragment(str)}else{fragment=document.createElement("body");fragment.innerHTML=str}return fragment.childNodes[0]}var specialElHandlers={OPTION:function(fromEl,toEl){fromEl.selected=toEl.selected;if(fromEl.selected){fromEl.setAttribute("selected","")}else{fromEl.removeAttribute("selected","")}},INPUT:function(fromEl,toEl){fromEl.checked=toEl.checked;if(fromEl.checked){fromEl.setAttribute("checked","")}else{fromEl.removeAttribute("checked")}if(fromEl.value!==toEl.value){fromEl.value=toEl.value}if(!hasAttributeNS(toEl,null,"value")){fromEl.removeAttribute("value")}fromEl.disabled=toEl.disabled;if(fromEl.disabled){fromEl.setAttribute("disabled","")}else{fromEl.removeAttribute("disabled")}},TEXTAREA:function(fromEl,toEl){var newValue=toEl.value;if(fromEl.value!==newValue){fromEl.value=newValue}if(fromEl.firstChild){fromEl.firstChild.nodeValue=newValue}}};function noop(){}var compareNodeNames=function(a,b){return a.nodeName===b.nodeName&&a.namespaceURI===b.namespaceURI};function createElementNS(name,namespaceURI){return!namespaceURI||namespaceURI===XHTML?document.createElement(name):document.createElementNS(namespaceURI,name)}function morphAttrs(fromNode,toNode){var attrs=toNode.attributes;var i;var attr;var attrName;var attrNamespaceURI;var attrValue;var fromValue;for(i=attrs.length-1;i>=0;--i){attr=attrs[i];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;attrValue=attr.value;if(attrNamespaceURI){attrName=attr.localName||attrName;fromValue=fromNode.getAttributeNS(attrNamespaceURI,attrName);if(fromValue!==attrValue){fromNode.setAttributeNS(attrNamespaceURI,attrName,attrValue)}}else{fromValue=fromNode.getAttribute(attrName);if(fromValue!==attrValue){fromNode.setAttribute(attrName,attrValue)}}}attrs=fromNode.attributes;for(i=attrs.length-1;i>=0;--i){attr=attrs[i];if(attr.specified!==false){attrName=attr.name;attrNamespaceURI=attr.namespaceURI;if(attrNamespaceURI){attrName=attrName=attr.localName||attrName;if(!hasAttributeNS(toNode,attrNamespaceURI,attrName)){fromNode.removeAttributeNS(attrNamespaceURI,attr.localName)}}else{if(!hasAttributeNS(toNode,null,attrName)){fromNode.removeAttribute(attrName)}}}}}function moveChildren(fromEl,toEl){var curChild=fromEl.firstChild;while(curChild){var nextChild=curChild.nextSibling;toEl.appendChild(curChild);curChild=nextChild}return toEl}function defaultGetNodeKey(node){return node.id}function morphdom(fromNode,toNode,options){if(!options){options={}}if(typeof toNode==="string"){if(fromNode.nodeName==="#document"||fromNode.nodeName==="HTML"){var toNodeHtml=toNode;toNode=document.createElement("html");toNode.innerHTML=toNodeHtml}else{toNode=toElement(toNode)}}var getNodeKey=options.getNodeKey||defaultGetNodeKey;var onBeforeNodeAdded=options.onBeforeNodeAdded||noop;var onNodeAdded=options.onNodeAdded||noop;var onBeforeElUpdated=options.onBeforeElUpdated||noop;var onElUpdated=options.onElUpdated||noop;var onBeforeNodeDiscarded=options.onBeforeNodeDiscarded||noop;var onNodeDiscarded=options.onNodeDiscarded||noop;var onBeforeElChildrenUpdated=options.onBeforeElChildrenUpdated||noop;var childrenOnly=options.childrenOnly===true;var fromNodesLookup={};function walkDiscardedChildNodes(node){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){if(!getNodeKey(curChild)){onNodeDiscarded(curChild);if(curChild.firstChild){walkDiscardedChildNodes(curChild)}}curChild=curChild.nextSibling}}}function removeNode(node,parentNode){if(onBeforeNodeDiscarded(node)===false){return}if(parentNode){parentNode.removeChild(node)}onNodeDiscarded(node);walkDiscardedChildNodes(node)}function indexTree(node){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){var key=getNodeKey(curChild);if(key){fromNodesLookup[key]=curChild}indexTree(curChild);curChild=curChild.nextSibling}}}indexTree(fromNode);function handleNodeAdded(el){onNodeAdded(el);var curChild=el.firstChild;while(curChild){var nextSibling=curChild.nextSibling;var key=getNodeKey(curChild);if(key){var unmatchedFromEl=fromNodesLookup[key];if(unmatchedFromEl&&compareNodeNames(curChild,unmatchedFromEl)){curChild.parentNode.replaceChild(unmatchedFromEl,curChild);morphEl(unmatchedFromEl,curChild)}}handleNodeAdded(curChild);curChild=nextSibling}}function morphEl(fromEl,toEl,childrenOnly){var toElKey=getNodeKey(toEl);if(toElKey){delete fromNodesLookup[toElKey]}if(!childrenOnly){if(onBeforeElUpdated(fromEl,toEl)===false){return}morphAttrs(fromEl,toEl);onElUpdated(fromEl);if(onBeforeElChildrenUpdated(fromEl,toEl)===false){return}}if(fromEl.nodeName!=="TEXTAREA"){var curToNodeChild=toEl.firstChild;var curFromNodeChild=fromEl.firstChild;var curToNodeKey;var fromNextSibling;var toNextSibling;var matchingFromEl;outer:while(curToNodeChild){toNextSibling=curToNodeChild.nextSibling;curToNodeKey=getNodeKey(curToNodeChild);while(curFromNodeChild){var curFromNodeKey=getNodeKey(curFromNodeChild);fromNextSibling=curFromNodeChild.nextSibling;var curFromNodeType=curFromNodeChild.nodeType;var isCompatible=undefined;if(curFromNodeType===curToNodeChild.nodeType){if(curFromNodeType===ELEMENT_NODE){if(curToNodeKey){if(curToNodeKey!==curFromNodeKey){if(matchingFromEl=fromNodesLookup[curToNodeKey]){if(curFromNodeChild.nextSibling===matchingFromEl){isCompatible=false}else{fromEl.insertBefore(matchingFromEl,curFromNodeChild);if(!curFromNodeKey){removeNode(curFromNodeChild,fromEl)}fromNextSibling=curFromNodeChild.nextSibling;curFromNodeChild=matchingFromEl}}else{isCompatible=false}}}else if(curFromNodeKey){isCompatible=false}isCompatible=isCompatible!==false&&compareNodeNames(curFromNodeChild,curToNodeChild);if(isCompatible){morphEl(curFromNodeChild,curToNodeChild)}}else if(curFromNodeType===TEXT_NODE||curFromNodeType==COMMENT_NODE){isCompatible=true;curFromNodeChild.nodeValue=curToNodeChild.nodeValue}}if(isCompatible){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}if(!curFromNodeKey){removeNode(curFromNodeChild,fromEl)}curFromNodeChild=fromNextSibling}if(curToNodeKey&&(matchingFromEl=fromNodesLookup[curToNodeKey])&&compareNodeNames(matchingFromEl,curToNodeChild)){fromEl.appendChild(matchingFromEl);morphEl(matchingFromEl,curToNodeChild)}else{if(onBeforeNodeAdded(curToNodeChild)!==false){fromEl.appendChild(curToNodeChild);handleNodeAdded(curToNodeChild)}}curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling}while(curFromNodeChild){fromNextSibling=curFromNodeChild.nextSibling;if(!getNodeKey(curFromNodeChild)){removeNode(curFromNodeChild,fromEl)}curFromNodeChild=fromNextSibling}}var specialElHandler=specialElHandlers[fromEl.nodeName];if(specialElHandler){specialElHandler(fromEl,toEl)}}var morphedNode=fromNode;var morphedNodeType=morphedNode.nodeType;var toNodeType=toNode.nodeType;if(!childrenOnly){if(morphedNodeType===ELEMENT_NODE){if(toNodeType===ELEMENT_NODE){if(!compareNodeNames(fromNode,toNode)){onNodeDiscarded(fromNode);morphedNode=moveChildren(fromNode,createElementNS(toNode.nodeName,toNode.namespaceURI))}}else{morphedNode=toNode}}else if(morphedNodeType===TEXT_NODE||morphedNodeType===COMMENT_NODE){if(toNodeType===morphedNodeType){morphedNode.nodeValue=toNode.nodeValue;return morphedNode}else{morphedNode=toNode}}}if(morphedNode===toNode){onNodeDiscarded(fromNode)}else{morphEl(morphedNode,toNode,childrenOnly);for(var k in fromNodesLookup){var elToRemove=fromNodesLookup[k];if(elToRemove){removeNode(elToRemove,elToRemove.parentNode)}}}if(!childrenOnly&&morphedNode!==fromNode&&fromNode.parentNode){fromNode.parentNode.replaceChild(morphedNode,fromNode)}return morphedNode}module.exports=morphdom;return module.exports}); | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.morphdom=f()}})(function(){var define,module,exports;module={exports:exports={}};"use strict";var range;var testEl=typeof document!=="undefined"?document.body||document.createElement("div"):{};var XHTML="http://www.w3.org/1999/xhtml";var ELEMENT_NODE=1;var TEXT_NODE=3;var COMMENT_NODE=8;var hasAttributeNS;if(testEl.hasAttributeNS){hasAttributeNS=function(el,namespaceURI,name){return el.hasAttributeNS(namespaceURI,name)}}else if(testEl.hasAttribute){hasAttributeNS=function(el,namespaceURI,name){return el.hasAttribute(name)}}else{hasAttributeNS=function(el,namespaceURI,name){return!!el.getAttributeNode(name)}}function toElement(str){if(!range&&document.createRange){range=document.createRange();range.selectNode(document.body)}var fragment;if(range&&range.createContextualFragment){fragment=range.createContextualFragment(str)}else{fragment=document.createElement("body");fragment.innerHTML=str}return fragment.childNodes[0]}var specialElHandlers={OPTION:function(fromEl,toEl){fromEl.selected=toEl.selected;if(fromEl.selected){fromEl.setAttribute("selected","")}else{fromEl.removeAttribute("selected","")}},INPUT:function(fromEl,toEl){fromEl.checked=toEl.checked;if(fromEl.checked){fromEl.setAttribute("checked","")}else{fromEl.removeAttribute("checked")}if(fromEl.value!==toEl.value){fromEl.value=toEl.value}if(!hasAttributeNS(toEl,null,"value")){fromEl.removeAttribute("value")}fromEl.disabled=toEl.disabled;if(fromEl.disabled){fromEl.setAttribute("disabled","")}else{fromEl.removeAttribute("disabled")}},TEXTAREA:function(fromEl,toEl){var newValue=toEl.value;if(fromEl.value!==newValue){fromEl.value=newValue}if(fromEl.firstChild){fromEl.firstChild.nodeValue=newValue}}};function noop(){}var compareNodeNames=function(a,b){return a.nodeName===b.nodeName&&a.namespaceURI===b.namespaceURI};function createElementNS(name,namespaceURI){return!namespaceURI||namespaceURI===XHTML?document.createElement(name):document.createElementNS(namespaceURI,name)}function morphAttrs(fromNode,toNode){var attrs=toNode.attributes;var i;var attr;var attrName;var attrNamespaceURI;var attrValue;var fromValue;for(i=attrs.length-1;i>=0;--i){attr=attrs[i];attrName=attr.name;attrNamespaceURI=attr.namespaceURI;attrValue=attr.value;if(attrNamespaceURI){attrName=attr.localName||attrName;fromValue=fromNode.getAttributeNS(attrNamespaceURI,attrName);if(fromValue!==attrValue){fromNode.setAttributeNS(attrNamespaceURI,attrName,attrValue)}}else{fromValue=fromNode.getAttribute(attrName);if(fromValue!==attrValue){fromNode.setAttribute(attrName,attrValue)}}}attrs=fromNode.attributes;for(i=attrs.length-1;i>=0;--i){attr=attrs[i];if(attr.specified!==false){attrName=attr.name;attrNamespaceURI=attr.namespaceURI;if(attrNamespaceURI){attrName=attrName=attr.localName||attrName;if(!hasAttributeNS(toNode,attrNamespaceURI,attrName)){fromNode.removeAttributeNS(attrNamespaceURI,attr.localName)}}else{if(!hasAttributeNS(toNode,null,attrName)){fromNode.removeAttribute(attrName)}}}}}function moveChildren(fromEl,toEl){var curChild=fromEl.firstChild;while(curChild){var nextChild=curChild.nextSibling;toEl.appendChild(curChild);curChild=nextChild}return toEl}function defaultGetNodeKey(node){return node.id}function morphdom(fromNode,toNode,options){if(!options){options={}}if(typeof toNode==="string"){if(fromNode.nodeName==="#document"||fromNode.nodeName==="HTML"){var toNodeHtml=toNode;toNode=document.createElement("html");toNode.innerHTML=toNodeHtml}else{toNode=toElement(toNode)}}var getNodeKey=options.getNodeKey||defaultGetNodeKey;var onBeforeNodeAdded=options.onBeforeNodeAdded||noop;var onNodeAdded=options.onNodeAdded||noop;var onBeforeElUpdated=options.onBeforeElUpdated||noop;var onElUpdated=options.onElUpdated||noop;var onBeforeNodeDiscarded=options.onBeforeNodeDiscarded||noop;var onNodeDiscarded=options.onNodeDiscarded||noop;var onBeforeElChildrenUpdated=options.onBeforeElChildrenUpdated||noop;var childrenOnly=options.childrenOnly===true;var fromNodesLookup={};var keyedRemovalList;function addKeyedRemoval(key){if(keyedRemovalList){keyedRemovalList.push(key)}else{keyedRemovalList=[key]}}function walkDiscardedChildNodes(node,skipKeyedNodes){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){var key=undefined;if(skipKeyedNodes&&(key=getNodeKey(curChild))){addKeyedRemoval(key)}else{onNodeDiscarded(curChild);if(curChild.firstChild){walkDiscardedChildNodes(curChild,skipKeyedNodes)}}curChild=curChild.nextSibling}}}function removeNode(node,parentNode,skipKeyedNodes){if(onBeforeNodeDiscarded(node)===false){return}if(parentNode){parentNode.removeChild(node)}onNodeDiscarded(node);walkDiscardedChildNodes(node,skipKeyedNodes)}function indexTree(node){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){var key=getNodeKey(curChild);if(key){fromNodesLookup[key]=curChild}indexTree(curChild);curChild=curChild.nextSibling}}}indexTree(fromNode);function handleNodeAdded(el){onNodeAdded(el);var curChild=el.firstChild;while(curChild){var nextSibling=curChild.nextSibling;var key=getNodeKey(curChild);if(key){var unmatchedFromEl=fromNodesLookup[key];if(unmatchedFromEl&&compareNodeNames(curChild,unmatchedFromEl)){curChild.parentNode.replaceChild(unmatchedFromEl,curChild);morphEl(unmatchedFromEl,curChild)}}handleNodeAdded(curChild);curChild=nextSibling}}function morphEl(fromEl,toEl,childrenOnly){var toElKey=getNodeKey(toEl);var curFromNodeKey;if(toElKey){delete fromNodesLookup[toElKey]}if(!childrenOnly){if(onBeforeElUpdated(fromEl,toEl)===false){return}morphAttrs(fromEl,toEl);onElUpdated(fromEl);if(onBeforeElChildrenUpdated(fromEl,toEl)===false){return}}if(fromEl.nodeName!=="TEXTAREA"){var curToNodeChild=toEl.firstChild;var curFromNodeChild=fromEl.firstChild;var curToNodeKey;var fromNextSibling;var toNextSibling;var matchingFromEl;outer:while(curToNodeChild){toNextSibling=curToNodeChild.nextSibling;curToNodeKey=getNodeKey(curToNodeChild);while(curFromNodeChild){curFromNodeKey=getNodeKey(curFromNodeChild);fromNextSibling=curFromNodeChild.nextSibling;var curFromNodeType=curFromNodeChild.nodeType;var isCompatible=undefined;if(curFromNodeType===curToNodeChild.nodeType){if(curFromNodeType===ELEMENT_NODE){if(curToNodeKey){if(curToNodeKey!==curFromNodeKey){if(matchingFromEl=fromNodesLookup[curToNodeKey]){if(curFromNodeChild.nextSibling===matchingFromEl){isCompatible=false}else{fromEl.insertBefore(matchingFromEl,curFromNodeChild);if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}fromNextSibling=curFromNodeChild.nextSibling;curFromNodeChild=matchingFromEl}}else{isCompatible=false}}}else if(curFromNodeKey){isCompatible=false}isCompatible=isCompatible!==false&&compareNodeNames(curFromNodeChild,curToNodeChild);if(isCompatible){morphEl(curFromNodeChild,curToNodeChild)}}else if(curFromNodeType===TEXT_NODE||curFromNodeType==COMMENT_NODE){isCompatible=true;curFromNodeChild.nodeValue=curToNodeChild.nodeValue}}if(isCompatible){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}if(curFromNodeKey){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}if(curToNodeKey&&(matchingFromEl=fromNodesLookup[curToNodeKey])&&compareNodeNames(matchingFromEl,curToNodeChild)){fromEl.appendChild(matchingFromEl);morphEl(matchingFromEl,curToNodeChild)}else{if(onBeforeNodeAdded(curToNodeChild)!==false){fromEl.appendChild(curToNodeChild);handleNodeAdded(curToNodeChild)}}curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling}while(curFromNodeChild){fromNextSibling=curFromNodeChild.nextSibling;if(curFromNodeKey=getNodeKey(curFromNodeChild)){addKeyedRemoval(curFromNodeKey)}else{removeNode(curFromNodeChild,fromEl,true)}curFromNodeChild=fromNextSibling}}var specialElHandler=specialElHandlers[fromEl.nodeName];if(specialElHandler){specialElHandler(fromEl,toEl)}}var morphedNode=fromNode;var morphedNodeType=morphedNode.nodeType;var toNodeType=toNode.nodeType;if(!childrenOnly){if(morphedNodeType===ELEMENT_NODE){if(toNodeType===ELEMENT_NODE){if(!compareNodeNames(fromNode,toNode)){onNodeDiscarded(fromNode);morphedNode=moveChildren(fromNode,createElementNS(toNode.nodeName,toNode.namespaceURI))}}else{morphedNode=toNode}}else if(morphedNodeType===TEXT_NODE||morphedNodeType===COMMENT_NODE){if(toNodeType===morphedNodeType){morphedNode.nodeValue=toNode.nodeValue;return morphedNode}else{morphedNode=toNode}}}if(morphedNode===toNode){onNodeDiscarded(fromNode)}else{morphEl(morphedNode,toNode,childrenOnly);if(keyedRemovalList){for(var i=0,len=keyedRemovalList.length;i<len;i++){var elToRemove=fromNodesLookup[keyedRemovalList[i]];if(elToRemove){removeNode(elToRemove,elToRemove.parentNode,false)}}}}if(!childrenOnly&&morphedNode!==fromNode&&fromNode.parentNode){fromNode.parentNode.replaceChild(morphedNode,fromNode)}return morphedNode}module.exports=morphdom;return module.exports}); |
@@ -43,3 +43,3 @@ { | ||
"dependencies": {}, | ||
"version": "2.0.1", | ||
"version": "2.0.2", | ||
"keywords": [ | ||
@@ -46,0 +46,0 @@ "dom", |
@@ -240,8 +240,24 @@ 'use strict'; | ||
var fromNodesLookup = {}; | ||
var keyedRemovalList; | ||
function walkDiscardedChildNodes(node) { | ||
function addKeyedRemoval(key) { | ||
if (keyedRemovalList) { | ||
keyedRemovalList.push(key); | ||
} else { | ||
keyedRemovalList = [key]; | ||
} | ||
} | ||
function walkDiscardedChildNodes(node, skipKeyedNodes) { | ||
if (node.nodeType === ELEMENT_NODE) { | ||
var curChild = node.firstChild; | ||
while (curChild) { | ||
if (!getNodeKey(curChild)) { | ||
var key = undefined; | ||
if (skipKeyedNodes && (key = getNodeKey(curChild))) { | ||
// If we are skipping keyed nodes then we add the key | ||
// to a list so that it can be handled at the very end. | ||
addKeyedRemoval(key); | ||
} else { | ||
// Only report the node as discarded if it is not keyed. We do this because | ||
@@ -252,3 +268,3 @@ // at the end we loop through all keyed elements that were unmatched | ||
if (curChild.firstChild) { | ||
walkDiscardedChildNodes(curChild); | ||
walkDiscardedChildNodes(curChild, skipKeyedNodes); | ||
} | ||
@@ -262,3 +278,11 @@ } | ||
function removeNode(node, parentNode) { | ||
/** | ||
* Removes a DOM node out of the original DOM | ||
* | ||
* @param {Node} node The node to remove | ||
* @param {Node} parentNode The nodes parent | ||
* @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded. | ||
* @return {undefined} | ||
*/ | ||
function removeNode(node, parentNode, skipKeyedNodes) { | ||
if (onBeforeNodeDiscarded(node) === false) { | ||
@@ -273,3 +297,3 @@ return; | ||
onNodeDiscarded(node); | ||
walkDiscardedChildNodes(node); | ||
walkDiscardedChildNodes(node, skipKeyedNodes); | ||
} | ||
@@ -347,2 +371,4 @@ | ||
var toElKey = getNodeKey(toEl); | ||
var curFromNodeKey; | ||
if (toElKey) { | ||
@@ -381,3 +407,3 @@ // If an element with an ID is being morphed then it is will be in the final | ||
while (curFromNodeChild) { | ||
var curFromNodeKey = getNodeKey(curFromNodeChild); | ||
curFromNodeKey = getNodeKey(curFromNodeChild); | ||
fromNextSibling = curFromNodeChild.nextSibling; | ||
@@ -418,4 +444,11 @@ | ||
if (!curFromNodeKey) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if (curFromNodeKey) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -466,4 +499,10 @@ fromNextSibling = curFromNodeChild.nextSibling; | ||
// that didn't find a home | ||
if (!curFromNodeKey) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if (curFromNodeKey) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -497,4 +536,10 @@ | ||
fromNextSibling = curFromNodeChild.nextSibling; | ||
if (!getNodeKey(curFromNodeChild)) { | ||
removeNode(curFromNodeChild, fromEl); | ||
if ((curFromNodeKey = getNodeKey(curFromNodeChild))) { | ||
// Since the node is keyed it might be matched up later so we defer | ||
// the actual removal to later | ||
addKeyedRemoval(curFromNodeKey); | ||
} else { | ||
// NOTE: we skip nested keyed nodes from being removed since there is | ||
// still a chance they will be matched up later | ||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */); | ||
} | ||
@@ -546,6 +591,13 @@ curFromNodeChild = fromNextSibling; | ||
for (var k in fromNodesLookup) { | ||
var elToRemove = fromNodesLookup[k]; | ||
if (elToRemove) { | ||
removeNode(elToRemove, elToRemove.parentNode); | ||
// We now need to loop over any keyed nodes that might need to be | ||
// removed. We only do the removal if we know that the keyed node | ||
// never found a match. When a keyed node is matched up we remove | ||
// it out of fromNodesLookup and we use fromNodesLookup to determine | ||
// if a keyed node has been matched up or not | ||
if (keyedRemovalList) { | ||
for (var i=0, len=keyedRemovalList.length; i<len; i++) { | ||
var elToRemove = fromNodesLookup[keyedRemovalList[i]]; | ||
if (elToRemove) { | ||
removeNode(elToRemove, elToRemove.parentNode, false); | ||
} | ||
} | ||
@@ -552,0 +604,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
144852
2575