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 1.4.6 to 2.0.0

src/index.js

19

CHANGELOG.md
Changelog
=========
# 2.x
## 2.0.x
### 2.0.0
- Fixed [#47](https://github.com/patrick-steele-idem/morphdom/issues/47) - Detect and handle reorder of siblings
- `onNodeAdded` is now called for all on child nodes and not just the root node (closes [PR #57](https://github.com/patrick-steele-idem/morphdom/pull/57))
- Simplified code and reduced overall code size
- NOTE: Performance is about the same or slightly better than the previous version of `morphdom` based on benchmarks
- Added examples:[./examples/](./examples/README.md)
#### Breaking changes
- `onNodeAdded` is now called for all on child nodes (not just the root node)
- Removed options:
- `onBeforeMorphEl` (use `onBeforeElUpdated` instead)
- `onBeforeMorphElChildren` (use `onBeforeElChildrenUpdated` instead)
# 1.x

@@ -5,0 +24,0 @@

388

dist/morphdom-umd.js
(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';
// Create a range object for efficently rendering strings to elements.

@@ -32,11 +33,2 @@ var range;

function empty(o) {
for (var k in o) {
if (o.hasOwnProperty(k)) {
return false;
}
}
return true;
}
function toElement(str) {

@@ -159,7 +151,7 @@ if (!range && document.createRange) {

for (i = attrs.length - 1; i >= 0; i--) {
for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
attrNamespaceURI = attr.namespaceURI;

@@ -169,10 +161,10 @@ if (attrNamespaceURI) {

fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
if (fromValue !== attrValue) {
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
}
if (fromValue !== attrValue) {
if (attrNamespaceURI) {
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
} else {
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);

@@ -187,3 +179,3 @@ }

for (i = attrs.length - 1; i >= 0; i--) {
for (i = attrs.length - 1; i >= 0; --i) {
attr = attrs[i];

@@ -194,6 +186,10 @@ if (attr.specified !== false) {

if (!hasAttributeNS(toNode, attrNamespaceURI, attrNamespaceURI ? attrName = attr.localName || attrName : attrName)) {
if (attrNamespaceURI) {
if (attrNamespaceURI) {
attrName = attrName = attr.localName || attrName;
if (!hasAttributeNS(toNode, attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attr.localName);
} else {
}
} else {
if (!hasAttributeNS(toNode, null, attrName)) {
fromNode.removeAttribute(attrName);

@@ -238,39 +234,29 @@ }

// XXX optimization: if the nodes are equal, don't morph them
/*
if (fromNode.isEqualNode(toNode)) {
return fromNode;
}
*/
var savedEls = {}; // Used to save off DOM elements with IDs
var unmatchedEls = {};
var getNodeKey = options.getNodeKey || defaultGetNodeKey;
var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
var onNodeAdded = options.onNodeAdded || noop;
var onBeforeElUpdated = options.onBeforeElUpdated || options.onBeforeMorphEl || 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 || options.onBeforeMorphElChildren || noop;
var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
var childrenOnly = options.childrenOnly === true;
var movedEls = [];
function removeNodeHelper(node, nestedInSavedEl) {
var id = getNodeKey(node);
// If the node has an ID then save it off since we will want
// to reuse it in case the target DOM tree has a DOM element
// with the same ID
if (id) {
savedEls[id] = node;
} else if (!nestedInSavedEl) {
// If we are not nested in a saved element then we know that this node has been
// completely discarded and will not exist in the final DOM.
onNodeDiscarded(node);
}
// This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
var fromNodesLookup = {};
function walkDiscardedChildNodes(node) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
removeNodeHelper(curChild, nestedInSavedEl || id);
if (!getNodeKey(curChild)) {
// Only report the node as discarded if it is not keyed. We do this because
// at the end we loop through all keyed elements that were unmatched
// and then discard them in one final pass.
onNodeDiscarded(curChild);
if (curChild.firstChild) {
walkDiscardedChildNodes(curChild);
}
}
curChild = curChild.nextSibling;

@@ -281,18 +267,55 @@ }

function walkDiscardedChildNodes(node) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
function removeNode(node, parentNode) {
if (onBeforeNodeDiscarded(node) === false) {
return;
}
if (parentNode) {
parentNode.removeChild(node);
}
if (!getNodeKey(curChild)) {
// We only want to handle nodes that don't have an ID to avoid double
// walking the same saved element.
onNodeDiscarded(node);
walkDiscardedChildNodes(node);
}
onNodeDiscarded(curChild);
// // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
// function indexTree(root) {
// var treeWalker = document.createTreeWalker(
// root,
// NodeFilter.SHOW_ELEMENT);
//
// var el;
// while((el = treeWalker.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
// Walk recursively
walkDiscardedChildNodes(curChild);
// // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
//
// function indexTree(node) {
// var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
// var el;
// while((el = nodeIterator.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
function indexTree(node) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
var key = getNodeKey(curChild);
if (key) {
fromNodesLookup[key] = curChild;
}
// Walk recursively
indexTree(curChild);
curChild = curChild.nextSibling;

@@ -303,19 +326,26 @@ }

function removeNode(node, parentNode, alreadyVisited) {
if (onBeforeNodeDiscarded(node) === false) {
return;
}
indexTree(fromNode);
parentNode.removeChild(node);
if (alreadyVisited) {
if (!getNodeKey(node)) {
onNodeDiscarded(node);
walkDiscardedChildNodes(node);
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);
}
}
} else {
removeNodeHelper(node);
handleNodeAdded(curChild);
curChild = nextSibling;
}
}
function morphEl(fromEl, toEl, alreadyVisited, childrenOnly) {
function morphEl(fromEl, toEl, childrenOnly) {
var toElKey = getNodeKey(toEl);

@@ -325,3 +355,3 @@ if (toElKey) {

// DOM so clear it out of the saved elements collection
delete savedEls[toElKey];
delete fromNodesLookup[toElKey];
}

@@ -345,47 +375,67 @@

var curFromNodeChild = fromEl.firstChild;
var curToNodeId;
var curToNodeKey;
var fromNextSibling;
var toNextSibling;
var savedEl;
var unmatchedEl;
var matchingFromEl;
outer: while (curToNodeChild) {
toNextSibling = curToNodeChild.nextSibling;
curToNodeId = getNodeKey(curToNodeChild);
curToNodeKey = getNodeKey(curToNodeChild);
while (curFromNodeChild) {
var curFromNodeId = getNodeKey(curFromNodeChild);
var curFromNodeKey = getNodeKey(curFromNodeChild);
fromNextSibling = curFromNodeChild.nextSibling;
if (!alreadyVisited) {
if (curFromNodeId && (unmatchedEl = unmatchedEls[curFromNodeId])) {
unmatchedEl.parentNode.replaceChild(curFromNodeChild, unmatchedEl);
morphEl(curFromNodeChild, unmatchedEl, alreadyVisited);
curFromNodeChild = fromNextSibling;
continue;
}
}
var curFromNodeType = curFromNodeChild.nodeType;
var isCompatible = undefined;
if (curFromNodeType === curToNodeChild.nodeType) {
var isCompatible = false;
if (curFromNodeType === ELEMENT_NODE) {
// Both nodes being compared are Element nodes
// Both nodes being compared are Element nodes
if (curFromNodeType === ELEMENT_NODE) {
if (compareNodeNames(curFromNodeChild, curToNodeChild)) {
// We have compatible DOM elements
if (curFromNodeId || curToNodeId) {
// If either DOM element has an ID then we
// handle those differently since we want to
// match up by ID
if (curToNodeId === curFromNodeId) {
isCompatible = true;
if (curToNodeKey) {
// The target node has a key so we want to match it up with the correct element
// in the original DOM tree
if (curToNodeKey !== curFromNodeKey) {
// The current element in the original DOM tree does not have a matching key so
// let's check our lookup to see if there is a matching element in the original
// DOM tree
if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
if (curFromNodeChild.nextSibling === matchingFromEl) {
// Special case for single element removals. To avoid removing the original
// DOM node out of the tree (since that can break CSS transitions, etc.),
// we will instead discard the current node and wait until the next
// iteration to properly match up the keyed target element with its matching
// element in the original tree
isCompatible = false;
} else {
// We found a matching keyed element somewhere in the original DOM tree.
// Let's moving the original DOM node into the current position and morph
// it.
// NOTE: We use insertBefore instead of replaceChild because we want to go through
// the `removeNode()` function for the node that is being discarded so that
// all lifecycle hooks are correctly invoked
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
if (!curFromNodeKey) {
removeNode(curFromNodeChild, fromEl);
}
fromNextSibling = curFromNodeChild.nextSibling;
curFromNodeChild = matchingFromEl;
}
} else {
// The nodes are not compatible since the "to" node has a key and there
// is no matching keyed node in the source tree
isCompatible = false;
}
} else {
isCompatible = true;
}
} else if (curFromNodeKey) {
// The original has a key
isCompatible = false;
}
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
if (isCompatible) {

@@ -395,6 +445,7 @@ // We found compatible DOM elements so transform

// target DOM node.
morphEl(curFromNodeChild, curToNodeChild, alreadyVisited);
morphEl(curFromNodeChild, curToNodeChild);
}
// Both nodes being compared are Text or Comment nodes
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
// Both nodes being compared are Text or Comment nodes
isCompatible = true;

@@ -405,58 +456,38 @@ // Simply update nodeValue on the original node to

}
}
if (isCompatible) {
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
if (isCompatible) {
// Advance both the "to" child and the "from" child since we found a match
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
// No compatible match so remove the old node from the DOM
// and continue trying to find a match in the original DOM
removeNode(curFromNodeChild, fromEl, alreadyVisited);
// No compatible match so remove the old node from the DOM and continue trying to find a
// match in the original DOM. However, we only do this if the from node is not keyed
// since it is possible that a keyed node might match up with a node somewhere else in the
// target tree and we don't want to discard it just yet since it still might find a
// home in the final DOM tree. After everything is done we will remove any keyed nodes
// that didn't find a home
if (!curFromNodeKey) {
removeNode(curFromNodeChild, fromEl);
}
curFromNodeChild = fromNextSibling;
}
if (curToNodeId) {
if ((savedEl = savedEls[curToNodeId])) {
if (compareNodeNames(savedEl, curToNodeChild)) {
morphEl(savedEl, curToNodeChild, true);
// We want to append the saved element instead
curToNodeChild = savedEl;
} else {
delete savedEls[curToNodeId];
onNodeDiscarded(savedEl);
}
} else {
// The current DOM element in the target tree has an ID
// but we did not find a match in any of the
// corresponding siblings. We just put the target
// element in the old DOM tree but if we later find an
// element in the old DOM tree that has a matching ID
// then we will replace the target element with the
// corresponding old element and morph the old element
unmatchedEls[curToNodeId] = curToNodeChild;
}
}
// If we got this far then we did not find a candidate match for
// our "to node" and we exhausted all of the children "from"
// nodes. Therefore, we will just append the current "to node"
// nodes. Therefore, we will just append the current "to" node
// to the end
if (onBeforeNodeAdded(curToNodeChild) !== false) {
fromEl.appendChild(curToNodeChild);
onNodeAdded(curToNodeChild);
if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
fromEl.appendChild(matchingFromEl);
morphEl(matchingFromEl, curToNodeChild);
} else {
if (onBeforeNodeAdded(curToNodeChild) !== false) {
fromEl.appendChild(curToNodeChild);
handleNodeAdded(curToNodeChild);
}
}
if (curToNodeChild.nodeType === ELEMENT_NODE &&
(curToNodeId || curToNodeChild.firstChild)) {
// The element that was just added to the original DOM may
// have some nested elements with a key/ID that needs to be
// matched up with other elements. We'll add the element to
// a list so that we can later process the nested elements
// if there are any unmatched keyed elements that were
// discarded
movedEls.push(curToNodeChild);
}
curToNodeChild = toNextSibling;

@@ -471,3 +502,5 @@ curFromNodeChild = fromNextSibling;

fromNextSibling = curFromNodeChild.nextSibling;
removeNode(curFromNodeChild, fromEl, alreadyVisited);
if (!getNodeKey(curFromNodeChild)) {
removeNode(curFromNodeChild, fromEl);
}
curFromNodeChild = fromNextSibling;

@@ -516,67 +549,10 @@ }

} else {
morphEl(morphedNode, toNode, false, childrenOnly);
morphEl(morphedNode, toNode, childrenOnly);
/**
* What we will do here is walk the tree for the DOM element that was
* moved from the target DOM tree to the original DOM tree and we will
* look for keyed elements that could be matched to keyed elements that
* were earlier discarded. If we find a match then we will move the
* saved element into the final DOM tree.
*/
var handleMovedEl = function(el) {
var curChild = el.firstChild;
while (curChild) {
var nextSibling = curChild.nextSibling;
var key = getNodeKey(curChild);
if (key) {
var savedEl = savedEls[key];
if (savedEl && compareNodeNames(curChild, savedEl)) {
curChild.parentNode.replaceChild(savedEl, curChild);
// true: already visited the saved el tree
morphEl(savedEl, curChild, true);
curChild = nextSibling;
if (empty(savedEls)) {
return false;
}
continue;
}
}
if (curChild.nodeType === ELEMENT_NODE) {
handleMovedEl(curChild);
}
curChild = nextSibling;
for (var k in fromNodesLookup) {
if (fromNodesLookup.hasOwnProperty(k)) {
var elToRemove = fromNodesLookup[k];
removeNode(elToRemove, elToRemove.parentNode);
}
};
// The loop below is used to possibly match up any discarded
// elements in the original DOM tree with elemenets from the
// target tree that were moved over without visiting their
// children
if (!empty(savedEls)) {
handleMovedElsLoop:
while (movedEls.length) {
var movedElsTemp = movedEls;
movedEls = [];
for (var i=0; i<movedElsTemp.length; i++) {
if (handleMovedEl(movedElsTemp[i]) === false) {
// There are no more unmatched elements so completely end
// the loop
break handleMovedElsLoop;
}
}
}
}
// Fire the "onNodeDiscarded" event for any saved elements
// that never found a new home in the morphed DOM
for (var savedElId in savedEls) {
if (savedEls.hasOwnProperty(savedElId)) {
var savedEl = savedEls[savedElId];
onNodeDiscarded(savedEl);
walkDiscardedChildNodes(savedEl);
}
}
}

@@ -583,0 +559,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={}};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 empty(o){for(var k in o){if(o.hasOwnProperty(k)){return false}}return true}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;attrValue=attr.value;attrNamespaceURI=attr.namespaceURI;if(attrNamespaceURI){attrName=attr.localName||attrName;fromValue=fromNode.getAttributeNS(attrNamespaceURI,attrName)}else{fromValue=fromNode.getAttribute(attrName)}if(fromValue!==attrValue){if(attrNamespaceURI){fromNode.setAttributeNS(attrNamespaceURI,attrName,attrValue)}else{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(!hasAttributeNS(toNode,attrNamespaceURI,attrNamespaceURI?attrName=attr.localName||attrName:attrName)){if(attrNamespaceURI){fromNode.removeAttributeNS(attrNamespaceURI,attr.localName)}else{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 savedEls={};var unmatchedEls={};var getNodeKey=options.getNodeKey||defaultGetNodeKey;var onBeforeNodeAdded=options.onBeforeNodeAdded||noop;var onNodeAdded=options.onNodeAdded||noop;var onBeforeElUpdated=options.onBeforeElUpdated||options.onBeforeMorphEl||noop;var onElUpdated=options.onElUpdated||noop;var onBeforeNodeDiscarded=options.onBeforeNodeDiscarded||noop;var onNodeDiscarded=options.onNodeDiscarded||noop;var onBeforeElChildrenUpdated=options.onBeforeElChildrenUpdated||options.onBeforeMorphElChildren||noop;var childrenOnly=options.childrenOnly===true;var movedEls=[];function removeNodeHelper(node,nestedInSavedEl){var id=getNodeKey(node);if(id){savedEls[id]=node}else if(!nestedInSavedEl){onNodeDiscarded(node)}if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){removeNodeHelper(curChild,nestedInSavedEl||id);curChild=curChild.nextSibling}}}function walkDiscardedChildNodes(node){if(node.nodeType===ELEMENT_NODE){var curChild=node.firstChild;while(curChild){if(!getNodeKey(curChild)){onNodeDiscarded(curChild);walkDiscardedChildNodes(curChild)}curChild=curChild.nextSibling}}}function removeNode(node,parentNode,alreadyVisited){if(onBeforeNodeDiscarded(node)===false){return}parentNode.removeChild(node);if(alreadyVisited){if(!getNodeKey(node)){onNodeDiscarded(node);walkDiscardedChildNodes(node)}}else{removeNodeHelper(node)}}function morphEl(fromEl,toEl,alreadyVisited,childrenOnly){var toElKey=getNodeKey(toEl);if(toElKey){delete savedEls[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 curToNodeId;var fromNextSibling;var toNextSibling;var savedEl;var unmatchedEl;outer:while(curToNodeChild){toNextSibling=curToNodeChild.nextSibling;curToNodeId=getNodeKey(curToNodeChild);while(curFromNodeChild){var curFromNodeId=getNodeKey(curFromNodeChild);fromNextSibling=curFromNodeChild.nextSibling;if(!alreadyVisited){if(curFromNodeId&&(unmatchedEl=unmatchedEls[curFromNodeId])){unmatchedEl.parentNode.replaceChild(curFromNodeChild,unmatchedEl);morphEl(curFromNodeChild,unmatchedEl,alreadyVisited);curFromNodeChild=fromNextSibling;continue}}var curFromNodeType=curFromNodeChild.nodeType;if(curFromNodeType===curToNodeChild.nodeType){var isCompatible=false;if(curFromNodeType===ELEMENT_NODE){if(compareNodeNames(curFromNodeChild,curToNodeChild)){if(curFromNodeId||curToNodeId){if(curToNodeId===curFromNodeId){isCompatible=true}}else{isCompatible=true}}if(isCompatible){morphEl(curFromNodeChild,curToNodeChild,alreadyVisited)}}else if(curFromNodeType===TEXT_NODE||curFromNodeType==COMMENT_NODE){isCompatible=true;curFromNodeChild.nodeValue=curToNodeChild.nodeValue}if(isCompatible){curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling;continue outer}}removeNode(curFromNodeChild,fromEl,alreadyVisited);curFromNodeChild=fromNextSibling}if(curToNodeId){if(savedEl=savedEls[curToNodeId]){if(compareNodeNames(savedEl,curToNodeChild)){morphEl(savedEl,curToNodeChild,true);curToNodeChild=savedEl}else{delete savedEls[curToNodeId];onNodeDiscarded(savedEl)}}else{unmatchedEls[curToNodeId]=curToNodeChild}}if(onBeforeNodeAdded(curToNodeChild)!==false){fromEl.appendChild(curToNodeChild);onNodeAdded(curToNodeChild)}if(curToNodeChild.nodeType===ELEMENT_NODE&&(curToNodeId||curToNodeChild.firstChild)){movedEls.push(curToNodeChild)}curToNodeChild=toNextSibling;curFromNodeChild=fromNextSibling}while(curFromNodeChild){fromNextSibling=curFromNodeChild.nextSibling;removeNode(curFromNodeChild,fromEl,alreadyVisited);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,false,childrenOnly);var handleMovedEl=function(el){var curChild=el.firstChild;while(curChild){var nextSibling=curChild.nextSibling;var key=getNodeKey(curChild);if(key){var savedEl=savedEls[key];if(savedEl&&compareNodeNames(curChild,savedEl)){curChild.parentNode.replaceChild(savedEl,curChild);morphEl(savedEl,curChild,true);curChild=nextSibling;if(empty(savedEls)){return false}continue}}if(curChild.nodeType===ELEMENT_NODE){handleMovedEl(curChild)}curChild=nextSibling}};if(!empty(savedEls)){handleMovedElsLoop:while(movedEls.length){var movedElsTemp=movedEls;movedEls=[];for(var i=0;i<movedElsTemp.length;i++){if(handleMovedEl(movedElsTemp[i])===false){break handleMovedElsLoop}}}}for(var savedElId in savedEls){if(savedEls.hasOwnProperty(savedElId)){var savedEl=savedEls[savedElId];onNodeDiscarded(savedEl);walkDiscardedChildNodes(savedEl)}}}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={};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){if(fromNodesLookup.hasOwnProperty(k)){var elToRemove=fromNodesLookup[k];removeNode(elToRemove,elToRemove.parentNode)}}}if(!childrenOnly&&morphedNode!==fromNode&&fromNode.parentNode){fromNode.parentNode.replaceChild(morphedNode,fromNode)}return morphedNode}module.exports=morphdom;return module.exports});
{
"name": "morphdom",
"description": "Morph a DOM tree to another DOM tree (no virtual DOM needed)",
"main": "lib/index.js",
"main": "src/index.js",
"scripts": {

@@ -9,3 +9,3 @@ "test": "npm run test-browser && npm run lint",

"all": "npm run all-browser && npm run lint",
"lint": "jshint lib/",
"lint": "jshint src/",
"test-browser": "node test/mocha-phantomjs/run.js test",

@@ -16,3 +16,4 @@ "benchmark-browser": "node test/mocha-phantomjs/run.js benchmark",

"mocha-phantomjs-run": "mocha-phantomjs ./test/mocha-phantomjs/generated/test-page.html",
"prepublish": "./prepublish.sh"
"prepublish": "./prepublish.sh",
"start": "node examples/server.js"
},

@@ -26,7 +27,10 @@ "author": "Patrick Steele-Idem <pnidem@gmail.com>",

"devDependencies": {
"async": "^2.0.0",
"browser-refresh-taglib": "^1.1.0",
"chai": "^2.3.0",
"express": "^4.14.0",
"ignoring-watcher": "^1.0.5",
"jshint": "^2.7.0",
"lasso": "^2.4.1",
"lasso-marko": "^2.0.4",
"lasso-marko": "^2.0.7",
"marko": "^3.3.0",

@@ -42,3 +46,3 @@ "mocha": "^2.2.4",

"dependencies": {},
"version": "1.4.6",
"version": "2.0.0",
"keywords": [

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

@@ -13,3 +13,3 @@ morphdom

The transformation is done in a single pass and is designed to minimize changes to the DOM while still ensuring that the morphed DOM exactly matches the target DOM. In addition, the algorithm used by this module will automatically match up elements that have corresponding IDs and that are found in both the original and target DOM tree.
The transformation is done in a single pass of both the original DOM tree and the target DOM tree and is designed to minimize changes to the DOM while still ensuring that the morphed DOM exactly matches the target DOM. In addition, the algorithm used by this module will automatically match up elements that have corresponding IDs and that are found in both the original and target DOM tree.

@@ -59,2 +59,6 @@ # Usage

# Examples
See: [./examples/](./examples/README.md)
# Browser Support

@@ -176,360 +180,206 @@

<table>
<thead>
<tr>
<td></td>
<td>
virtual-dom
</td>
<td>
morphdom
</td>
</tr>
</thead>
<tbody>
<tr>
<td class="test-name">
change-tagname
</td>
<td>
0.01ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
change-tagname-ids
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
data-table
</td>
<td>
0.81ms
</td>
<td>
0.28ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested
</td>
<td>
0.01ms
</td>
<td>
0.20ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-2
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-3
</td>
<td>
0.01ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-4
</td>
<td>
0.03ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-5
</td>
<td>
0.03ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-6
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
ids-nested-7
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
ids-prepend
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
input-element
</td>
<td>
0.01ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
input-element-disabled
</td>
<td>
0.01ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
input-element-enabled
</td>
<td>
0.01ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
large
</td>
<td>
1.27ms
</td>
<td>
1.65ms
</td>
</tr>
<tr>
<td class="test-name">
lengthen
</td>
<td>
0.03ms
</td>
<td>
0.15ms
</td>
</tr>
<tr>
<td class="test-name">
one
</td>
<td>
0.01ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
reverse
</td>
<td>
0.03ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
reverse-ids
</td>
<td>
0.02ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
select-element
</td>
<td>
0.04ms
</td>
<td>
0.03ms
</td>
</tr>
<tr>
<td class="test-name">
shorten
</td>
<td>
0.02ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
simple
</td>
<td>
0.02ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
simple-ids
</td>
<td>
0.04ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
simple-text-el
</td>
<td>
0.02ms
</td>
<td>
0.01ms
</td>
</tr>
<tr>
<td class="test-name">
svg
</td>
<td>
0.01ms
</td>
<td>
0.02ms
</td>
</tr>
<tr>
<td class="test-name">
tag-to-text
</td>
<td>
0.00ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
text-to-tag
</td>
<td>
0.01ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
text-to-text
</td>
<td>
0.00ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
textarea
</td>
<td>
0.01ms
</td>
<td>
0.00ms
</td>
</tr>
<tr>
<td class="test-name">
todomvc
</td>
<td>
0.30ms
</td>
<td>
0.37ms
</td>
</tr>
<tr>
<td class="test-name">
two
</td>
<td>
0.01ms
</td>
<td>
0.01ms
</td>
</tr>
</tbody>
</table>
<div class="results">
<ul>
<li> Total time for morphdom: 359.02ms (winner) </li>
<li> Total time for virtual-dom: 438.30ms </li>
</ul>
<table>
<thead>
<tr>
<td></td>
<td> morphdom </td>
<td> virtual-dom </td>
</tr>
</thead>
<tbody>
<tr>
<td class="test-name"> change-tagname </td>
<td> <b>0.01ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> change-tagname-ids </td>
<td> <b>0.01ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> data-table </td>
<td> <b>0.22ms</b> </td>
<td> 0.65ms </td>
</tr>
<tr>
<td class="test-name"> data-table2 </td>
<td> <b>0.96ms</b> </td>
<td> 2.00ms </td>
</tr>
<tr>
<td class="test-name"> id-change-tag-name </td>
<td> <b>0.00ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested </td>
<td> <b>0.01ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested-2 </td>
<td> 0.02ms </td>
<td> <b>0.02ms</b> </td>
</tr>
<tr>
<td class="test-name"> ids-nested-3 </td>
<td> <b>0.01ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested-4 </td>
<td> <b>0.02ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested-5 </td>
<td> <b>0.02ms</b> </td>
<td> 0.04ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested-6 </td>
<td> <b>0.01ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> ids-nested-7 </td>
<td> 0.02ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> ids-prepend </td>
<td> <b>0.02ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> input-element </td>
<td> 0.01ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> input-element-disabled </td>
<td> 0.01ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> input-element-enabled </td>
<td> 0.01ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> large </td>
<td> 1.56ms </td>
<td> <b>0.98ms</b> </td>
</tr>
<tr>
<td class="test-name"> lengthen </td>
<td> <b>0.02ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> one </td>
<td> <b>0.00ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> reverse </td>
<td> <b>0.01ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> reverse-ids </td>
<td> 0.03ms </td>
<td> <b>0.02ms</b> </td>
</tr>
<tr>
<td class="test-name"> select-element </td>
<td> 0.04ms </td>
<td> <b>0.03ms</b> </td>
</tr>
<tr>
<td class="test-name"> shorten </td>
<td> 0.02ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> simple </td>
<td> <b>0.01ms</b> </td>
<td> 0.01ms </td>
</tr>
<tr>
<td class="test-name"> simple-ids </td>
<td> 0.04ms </td>
<td> <b>0.03ms</b> </td>
</tr>
<tr>
<td class="test-name"> simple-text-el </td>
<td> <b>0.01ms</b> </td>
<td> 0.02ms </td>
</tr>
<tr>
<td class="test-name"> svg </td>
<td> 0.02ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> svg-append </td>
<td> 0.04ms </td>
<td> <b>0.04ms</b> </td>
</tr>
<tr>
<td class="test-name"> svg-append-new </td>
<td> <b>0.01ms</b> </td>
<td> 0.04ms </td>
</tr>
<tr>
<td class="test-name"> svg-no-default-namespace </td>
<td> 0.03ms </td>
<td> <b>0.02ms</b> </td>
</tr>
<tr>
<td class="test-name"> svg-xlink </td>
<td> 0.03ms </td>
<td> <b>0.00ms</b> </td>
</tr>
<tr>
<td class="test-name"> tag-to-text </td>
<td> <b>0.00ms</b> </td>
<td> 0.00ms </td>
</tr>
<tr>
<td class="test-name"> text-to-tag </td>
<td> <b>0.00ms</b> </td>
<td> 0.00ms </td>
</tr>
<tr>
<td class="test-name"> text-to-text </td>
<td> <b>0.00ms</b> </td>
<td> 0.00ms </td>
</tr>
<tr>
<td class="test-name"> textarea </td>
<td> 0.01ms </td>
<td> <b>0.01ms</b> </td>
</tr>
<tr>
<td class="test-name"> todomvc </td>
<td> 0.36ms </td>
<td> <b>0.25ms</b> </td>
</tr>
<tr>
<td class="test-name"> two </td>
<td> <b>0.01ms</b> </td>
<td> 0.01ms </td>
</tr>
</tbody>
</table>
</div>
_NOTE: Safari 9.0.2 (11601.3.9)_
_NOTE: Safari Version 9.1.1 (11601.6.17)_

@@ -539,2 +389,3 @@ # Maintainers

* [Patrick Steele-Idem](https://github.com/patrick-steele-idem) (Twitter: [@psteeleidem](http://twitter.com/psteeleidem))
* [Paul Grenier](https://github.com/AutoSponge) (Twitter: [@autosponge](https://twitter.com/autosponge))

@@ -541,0 +392,0 @@ # Contribute

Sorry, the diff of this file is not supported yet

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