Socket
Socket
Sign inDemoInstall

morphdom

Package Overview
Dependencies
Maintainers
1
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

morphdom - npm Package Compare versions

Comparing version 2.0.4 to 2.1.0

docs/virtual-dom.md

8

CHANGELOG.md

@@ -6,2 +6,10 @@ Changelog

## 2.1.x
### 2.1.0
- Added simple mechanism to support using cached nodes ([Pull Request #81](https://github.com/patrick-steele-idem/morphdom/pull/81) by [@AutoSponge](https://github.com/AutoSponge))
- Fixes: [Issue #77 - Memoized elements are removed & added anyway](https://github.com/patrick-steele-idem/morphdom/issues/77)
- Added support for diffing a real DOM tree with a virtual DOM tree. See: [./docs/virtual-dom.md](./docs/virtual-dom.md)
## 2.0.x

@@ -8,0 +16,0 @@

114

dist/morphdom-umd.js

@@ -6,7 +6,10 @@ (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 testEl = (typeof document !== 'undefined') ?
document.body || document.createElement('div') :
var doc = typeof document !== 'undefined' && document;
var testEl = doc ?
doc.body || doc.createElement('div') :
{};
var XHTML = 'http://www.w3.org/1999/xhtml';
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
var ELEMENT_NODE = 1;

@@ -35,5 +38,5 @@ var TEXT_NODE = 3;

function toElement(str) {
if (!range && document.createRange) {
range = document.createRange();
range.selectNode(document.body);
if (!range && doc.createRange) {
range = doc.createRange();
range.selectNode(doc.body);
}

@@ -45,3 +48,3 @@

} else {
fragment = document.createElement('body');
fragment = doc.createElement('body');
fragment.innerHTML = str;

@@ -110,13 +113,31 @@ }

/**
* Returns true if two node's names and namespace URIs are the same.
* Returns true if two node's names are the same.
*
* NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
* nodeName and different namespace URIs.
*
* @param {Element} a
* @param {Element} b
* @param {Element} b The target element
* @return {boolean}
*/
var compareNodeNames = function(a, b) {
return a.nodeName === b.nodeName &&
a.namespaceURI === b.namespaceURI;
};
function compareNodeNames(fromEl, toEl) {
var fromNodeName = fromEl.nodeName;
var toNodeName = toEl.nodeName;
if (fromNodeName === toNodeName) {
return true;
}
if (toEl.actualize &&
fromNodeName.charCodeAt(0) < 91 && /* from tag name is upper case */
toNodeName.charCodeAt(0) > 90 /* target tag name is lower case */) {
// If the target element is a virtual DOM node then we may need to normalize the tag name
// before comparing. Normal HTML elements that are in the "http://www.w3.org/1999/xhtml"
// are converted to upper case
return fromNodeName === toNodeName.toUpperCase();
} else {
return false;
}
}
/**

@@ -132,5 +153,5 @@ * Create an element, optionally with a known namespace URI.

function createElementNS(name, namespaceURI) {
return !namespaceURI || namespaceURI === XHTML ?
document.createElement(name) :
document.createElementNS(namespaceURI, name);
return !namespaceURI || namespaceURI === NS_XHTML ?
doc.createElement(name) :
doc.createElementNS(namespaceURI, name);
}

@@ -155,20 +176,24 @@

for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
if (toNode.assignAttributes) {
toNode.assignAttributes(fromNode);
} else {
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 (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.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
}
}

@@ -189,6 +214,6 @@ }

if (attrNamespaceURI) {
attrName = attrName = attr.localName || attrName;
attrName = attr.localName || attrName;
if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attr.localName);
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
}

@@ -229,3 +254,3 @@ } else {

var toNodeHtml = toNode;
toNode = document.createElement('html');
toNode = doc.createElement('html');
toNode.innerHTML = toNodeHtml;

@@ -384,2 +409,6 @@ } else {

if (toNode.isSameNode && toNode.isSameNode(fromNode)) {
return;
}
if (!childrenOnly) {

@@ -412,2 +441,6 @@ if (onBeforeElUpdated(fromEl, toEl) === false) {

while (curFromNodeChild) {
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
return;
}
curFromNodeKey = getNodeKey(curFromNodeChild);

@@ -524,3 +557,11 @@ fromNextSibling = curFromNodeChild.nextSibling;

} else {
if (onBeforeNodeAdded(curToNodeChild) !== false) {
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
if (onBeforeNodeAddedResult !== false) {
if (onBeforeNodeAddedResult) {
curToNodeChild = onBeforeNodeAddedResult;
}
if (curToNodeChild.actualize) {
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
}
fromEl.appendChild(curToNodeChild);

@@ -610,2 +651,5 @@ handleNodeAdded(curToNodeChild);

if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
if (morphedNode.actualize) {
morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
}
// If we had to swap out the from node with a new node because the old

@@ -612,0 +656,0 @@ // node was not compatible with the target node then we need to

@@ -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={};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});
(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 doc=typeof document!=="undefined"&&document;var testEl=doc?doc.body||doc.createElement("div"):{};var NS_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&&doc.createRange){range=doc.createRange();range.selectNode(doc.body)}var fragment;if(range&&range.createContextualFragment){fragment=range.createContextualFragment(str)}else{fragment=doc.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(){}function compareNodeNames(fromEl,toEl){var fromNodeName=fromEl.nodeName;var toNodeName=toEl.nodeName;if(fromNodeName===toNodeName){return true}if(toEl.actualize&&fromNodeName.charCodeAt(0)<91&&toNodeName.charCodeAt(0)>90){return fromNodeName===toNodeName.toUpperCase()}else{return false}}function createElementNS(name,namespaceURI){return!namespaceURI||namespaceURI===NS_XHTML?doc.createElement(name):doc.createElementNS(namespaceURI,name)}function morphAttrs(fromNode,toNode){var attrs=toNode.attributes;var i;var attr;var attrName;var attrNamespaceURI;var attrValue;var fromValue;if(toNode.assignAttributes){toNode.assignAttributes(fromNode)}else{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=attr.localName||attrName;if(!hasAttributeNS(toNode,attrNamespaceURI,attrName)){fromNode.removeAttributeNS(attrNamespaceURI,attrName)}}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=doc.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(toNode.isSameNode&&toNode.isSameNode(fromNode)){return}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){if(curToNodeChild.isSameNode&&curToNodeChild.isSameNode(curFromNodeChild)){return}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{var onBeforeNodeAddedResult=onBeforeNodeAdded(curToNodeChild);if(onBeforeNodeAddedResult!==false){if(onBeforeNodeAddedResult){curToNodeChild=onBeforeNodeAddedResult}if(curToNodeChild.actualize){curToNodeChild=curToNodeChild.actualize(fromEl.ownerDocument||doc)}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){if(morphedNode.actualize){morphedNode=morphedNode.actualize(fromNode.ownerDocument||doc)}fromNode.parentNode.replaceChild(morphedNode,fromNode)}return morphedNode}module.exports=morphdom;return module.exports});

@@ -19,3 +19,3 @@ {

"author": "Patrick Steele-Idem <pnidem@gmail.com>",
"license": "ISC",
"license": "MIT",
"repository": {

@@ -29,2 +29,3 @@ "type": "git",

"chai": "^2.3.0",
"diffhtml": "^0.9.2",
"express": "^4.14.0",

@@ -36,2 +37,3 @@ "ignoring-watcher": "^1.0.5",

"marko": "^3.3.0",
"marko-vdom": "^0.3.0",
"mocha": "^2.2.4",

@@ -46,3 +48,3 @@ "mocha-phantomjs": "^4.1.0",

"dependencies": {},
"version": "2.0.4",
"version": "2.1.0",
"keywords": [

@@ -49,0 +51,0 @@ "dom",

@@ -7,3 +7,3 @@ morphdom

Lightweight module for morphing an existing DOM node tree to match a target DOM node tree. It's fast and works with the real DOM—no virtual DOM here!
Lightweight module for morphing an existing DOM node tree to match a target DOM node tree. It's fast and works with the real DOM—no virtual DOM needed!

@@ -16,2 +16,4 @@ This module was created to solve the problem of updating the DOM in response to a UI component or page being rerendered. One way to update the DOM is to simply toss away the existing DOM tree and replace it with a new DOM tree (e.g., `myContainer.innerHTML = newHTML`). While replacing an existing DOM tree with an entirely new DOM tree will actually be very fast, it comes with a cost. The cost is that all of the internal state associated with the existing DOM nodes (scroll positions, input caret positions, CSS transition states, etc.) will be lost. Instead of replacing the existing DOM tree with a new DOM tree we want to _transform_ the existing DOM tree to match the new DOM tree while minimizing the number of changes to the existing DOM tree. This is exactly what the `morphdom` module does! Give it an existing DOM node tree and a target DOM node tree and it will efficiently transform the existing DOM node tree to exactly match the target DOM node tree with the minimum amount of changes.

Support for diffing the real DOM with a virtual DOM was introduced in `v2.1.0`. Virtual DOM nodes are expected to implement the minimal subset of the real DOM API required by `morphdom` and virtual DOM nodes are automatically upgraded real DOM nodes if they need to be moved into the real DOM. For more details, please see: [docs/virtual-dom.md](./docs/virtual-dom.md).
# Usage

@@ -83,2 +85,3 @@

- **getNodeKey** (`Function(node)`) - Called to get the `Node`'s unique identifier. This is used by `morphdom` to rearrange elements rather than creating and destroying an element that already exists. This defaults to using the `Node`'s `id` attribute.
- **onBeforeNodeAdded** (`Function(node)`) - Called before a `Node` in the `to` tree is added to the `from` tree. If this function returns `false` then the node will not be added.

@@ -125,10 +128,16 @@ - **onNodeAdded** (`Function(node)`) - Called after a `Node` in the `to` tree has been added to the `from` tree.

No, the DOM _data structure_ is not slow. The DOM is a key part of any web browser so it must be fast. Walking a DOM tree and reading the attributes on DOM nodes is _not_ slow. However, if you attempt to read a computed property on a DOM node that requires a relayout of the page then _that_ will be slow. However, `morphdom` only cares about the following properties of a DOM node:
No, the DOM _data structure_ is not slow. The DOM is a key part of any web browser so it must be fast. Walking a DOM tree and reading the attributes on DOM nodes is _not_ slow. However, if you attempt to read a computed property on a DOM node that requires a relayout of the page then _that_ will be slow. However, `morphdom` only cares about the following properties and methods of a DOM node:
- `node.firstChild`
- `node.tagName`
- `node.nextSibling`
- `node.attributes`
- `node.nodeType`
- `node.nodeName`
- `node.nodeValue`
- `node.attributes`
- `node.value`
- `node.selected`
- `node.disabled`
- `actualize(document)` (non-standard, used to upgrade a virtual DOM node to a real DOM node)
- `hasAttributeNS(namespaceURI, name)`
- `isSameNode(anotherNode)`

@@ -167,2 +176,3 @@ ## What about the virtual DOM?

- __[Composer.js](https://lyonbros.github.io/composer.js/)__ (`v1.2.1`) - Composer is a set of stackable libraries for building complex single-page apps. It uses morphdom in its rendering engine for efficient and non-destructive updates to the DOM.
- __[yo-yo.js](https://github.com/maxogden/yo-yo)__ (`v1.2.2`) - A tiny library for building modular UI components using DOM diffing and ES6 tagged template literals. yo-yo powers a tiny, isomorphic framework called [choo](https://github.com/yoshuawuyts/choo) (`v3.3.0`), which is designed to be fun.

@@ -169,0 +179,0 @@ _NOTE: If you are using a `morphdom` in your project please send a PR to add your project here_

@@ -5,7 +5,10 @@ 'use strict';

var testEl = (typeof document !== 'undefined') ?
document.body || document.createElement('div') :
var doc = typeof document !== 'undefined' && document;
var testEl = doc ?
doc.body || doc.createElement('div') :
{};
var XHTML = 'http://www.w3.org/1999/xhtml';
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
var ELEMENT_NODE = 1;

@@ -34,5 +37,5 @@ var TEXT_NODE = 3;

function toElement(str) {
if (!range && document.createRange) {
range = document.createRange();
range.selectNode(document.body);
if (!range && doc.createRange) {
range = doc.createRange();
range.selectNode(doc.body);
}

@@ -44,3 +47,3 @@

} else {
fragment = document.createElement('body');
fragment = doc.createElement('body');
fragment.innerHTML = str;

@@ -109,13 +112,31 @@ }

/**
* Returns true if two node's names and namespace URIs are the same.
* Returns true if two node's names are the same.
*
* NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
* nodeName and different namespace URIs.
*
* @param {Element} a
* @param {Element} b
* @param {Element} b The target element
* @return {boolean}
*/
var compareNodeNames = function(a, b) {
return a.nodeName === b.nodeName &&
a.namespaceURI === b.namespaceURI;
};
function compareNodeNames(fromEl, toEl) {
var fromNodeName = fromEl.nodeName;
var toNodeName = toEl.nodeName;
if (fromNodeName === toNodeName) {
return true;
}
if (toEl.actualize &&
fromNodeName.charCodeAt(0) < 91 && /* from tag name is upper case */
toNodeName.charCodeAt(0) > 90 /* target tag name is lower case */) {
// If the target element is a virtual DOM node then we may need to normalize the tag name
// before comparing. Normal HTML elements that are in the "http://www.w3.org/1999/xhtml"
// are converted to upper case
return fromNodeName === toNodeName.toUpperCase();
} else {
return false;
}
}
/**

@@ -131,5 +152,5 @@ * Create an element, optionally with a known namespace URI.

function createElementNS(name, namespaceURI) {
return !namespaceURI || namespaceURI === XHTML ?
document.createElement(name) :
document.createElementNS(namespaceURI, name);
return !namespaceURI || namespaceURI === NS_XHTML ?
doc.createElement(name) :
doc.createElementNS(namespaceURI, name);
}

@@ -154,20 +175,24 @@

for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
if (toNode.assignAttributes) {
toNode.assignAttributes(fromNode);
} else {
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 (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.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
}
}

@@ -188,6 +213,6 @@ }

if (attrNamespaceURI) {
attrName = attrName = attr.localName || attrName;
attrName = attr.localName || attrName;
if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attr.localName);
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
}

@@ -228,3 +253,3 @@ } else {

var toNodeHtml = toNode;
toNode = document.createElement('html');
toNode = doc.createElement('html');
toNode.innerHTML = toNodeHtml;

@@ -383,2 +408,6 @@ } else {

if (toNode.isSameNode && toNode.isSameNode(fromNode)) {
return;
}
if (!childrenOnly) {

@@ -411,2 +440,6 @@ if (onBeforeElUpdated(fromEl, toEl) === false) {

while (curFromNodeChild) {
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
return;
}
curFromNodeKey = getNodeKey(curFromNodeChild);

@@ -523,3 +556,11 @@ fromNextSibling = curFromNodeChild.nextSibling;

} else {
if (onBeforeNodeAdded(curToNodeChild) !== false) {
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
if (onBeforeNodeAddedResult !== false) {
if (onBeforeNodeAddedResult) {
curToNodeChild = onBeforeNodeAddedResult;
}
if (curToNodeChild.actualize) {
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
}
fromEl.appendChild(curToNodeChild);

@@ -609,2 +650,5 @@ handleNodeAdded(curToNodeChild);

if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
if (morphedNode.actualize) {
morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
}
// If we had to swap out the from node with a new node because the old

@@ -611,0 +655,0 @@ // node was not compatible with the target node then we need to

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc