Socket
Socket
Sign inDemoInstall

morphdom

Package Overview
Dependencies
0
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.1 to 0.1.2

215

lib/index.js

@@ -10,2 +10,5 @@ var specialAttrHandlers = {

el.value = value;
},
INPUT$checked: function(el, value) {
el.checked = value == null ? false : true;
}

@@ -16,2 +19,10 @@ };

function invokeSpecialAttrHandler(node, tagName, attrName, attrValue) {
var specialHandler = specialAttrHandlers[tagName + '$' + attrName.toLowerCase()];
if (specialHandler) {
specialHandler(node, attrValue);
}
}
function morphAttrs(fromNode, toNode) {

@@ -32,10 +43,4 @@ var attrs = toNode.attributes;

foundAttrs[attrName] = true;
var specialHandler = specialAttrHandlers[tagName + '$' + attrName.toLowerCase()];
fromNode.setAttribute(attrName, attrValue);
if (specialHandler) {
specialHandler(fromNode, attrValue);
}
invokeSpecialAttrHandler(fromNode, tagName, attrName, attrValue);
}

@@ -54,2 +59,3 @@ }

fromNode.removeAttribute(attrName);
invokeSpecialAttrHandler(fromNode, tagName, attrName, null);
}

@@ -78,2 +84,17 @@ }

function removeNode(morpher, node, parentNode) {
if (morpher.onBeforeRemoveNode(node) !== false) {
parentNode.removeChild(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 (node.id) {
saveEl(morpher, node);
} else {
morpher.onFromNodeRemoved(node);
}
}
}
function MorphElTask(fromNode, toNode) {

@@ -85,109 +106,113 @@ this.from = fromNode;

MorphElTask.prototype.run = function(morpher) {
var fromNode = this.from;
var toNode = this.to;
MorphElTask.prototype = {
run: function(morpher) {
var fromNode = this.from;
var toNode = this.to;
morphAttrs(fromNode, toNode);
if (morpher.onBeforeMorphEl(fromNode, toNode) === false) {
return;
}
var curToNode = toNode.firstChild;
var curFromNode = fromNode.firstChild;
var curToNodeId;
morphAttrs(fromNode, toNode);
var fromNextSibling;
var toNextSibling;
var savedEl;
if (morpher.onBeforeMorphElChildren(fromNode, toNode) === false) {
return;
}
outer: while(curToNode) {
toNextSibling = curToNode.nextSibling;
var curToNodeChild = toNode.firstChild;
var curFromNodeChild = fromNode.firstChild;
var curToNodeId;
curToNodeId = curToNode.id;
var fromNextSibling;
var toNextSibling;
var savedEl;
if (curToNodeId && (savedEl = morpher.saved[curToNodeId])) {
delete morpher.saved[curToNodeId]; // Do some cleanup since we need to know which nodes were actually
// completely removed from the DOM
// We are reusing a "from node" with an ID that matches
// the ID of the current "to node"
fromNode.insertBefore(savedEl, curFromNode);
morphEl(morpher, savedEl, curToNode);
curToNode = toNextSibling;
continue;
}
outer: while(curToNodeChild) {
toNextSibling = curToNodeChild.nextSibling;
while(curFromNode) {
morpher.onFromNodeFound(curFromNode);
curToNodeId = curToNodeChild.id;
fromNextSibling = curFromNode.nextSibling;
var curFromNodeType = curFromNode.nodeType;
if (curToNodeId && (savedEl = morpher.saved[curToNodeId])) {
delete morpher.saved[curToNodeId]; // Do some cleanup since we need to know which nodes were actually
// completely removed from the DOM
// We are reusing a "from node" with an ID that matches
// the ID of the current "to node"
fromNode.insertBefore(savedEl, curFromNodeChild);
morphEl(morpher, savedEl, curToNodeChild);
curToNodeChild = toNextSibling;
continue;
}
if (curFromNodeType === curToNode.nodeType) {
var isCompatible = false;
while(curFromNodeChild) {
morpher.onFromNodeFound(curFromNodeChild);
if (curFromNodeType === 1) { // Both nodes being compared are Element nodes
if (curFromNode.tagName === curToNode.tagName) {
// We have compatible DOM elements
if (curFromNode.id || curToNodeId) {
// If either DOM element has an ID then we handle
// those differently since we want to match up
// by ID
if (curToNodeId === curFromNode.id) {
fromNextSibling = curFromNodeChild.nextSibling;
var curFromNodeType = curFromNodeChild.nodeType;
if (curFromNodeType === curToNodeChild.nodeType) {
var isCompatible = false;
if (curFromNodeType === 1) { // Both nodes being compared are Element nodes
if (curFromNodeChild.tagName === curToNodeChild.tagName) {
// We have compatible DOM elements
if (curFromNodeChild.id || curToNodeId) {
// If either DOM element has an ID then we handle
// those differently since we want to match up
// by ID
if (curToNodeId === curFromNodeChild.id) {
isCompatible = true;
}
} else {
isCompatible = true;
}
} else {
isCompatible = true;
}
if (isCompatible) {
// We found compatible DOM elements so add a
// task to morph the compatible DOM elements
morphEl(morpher, curFromNodeChild, curToNodeChild);
}
} else if (curFromNodeType === 3) { // Both nodes being compared are Text nodes
isCompatible = true;
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
}
if (isCompatible) {
// We found compatible DOM elements so add a
// task to morph the compatible DOM elements
morphEl(morpher, curFromNode, curToNode);
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
} else if (curFromNodeType === 3) { // Both nodes being compared are Text nodes
isCompatible = true;
curFromNode.nodeValue = curToNode.nodeValue;
}
if (isCompatible) {
curToNode = toNextSibling;
curFromNode = fromNextSibling;
continue outer;
}
// No compatible match so remove the old node from the DOM
removeNode(morpher, curFromNodeChild, fromNode);
curFromNodeChild = fromNextSibling;
}
// No compatible match so remove the old node from the DOM
fromNode.removeChild(curFromNode);
// 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" to the end
fromNode.appendChild(curToNodeChild);
// 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 (curFromNode.id) {
saveEl(morpher, curFromNode);
} else {
morpher.onFromNodeRemoved(curFromNode);
}
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
}
curFromNode = fromNextSibling;
// We have processed all of the "to nodes". If curFromNodeChild is non-null then
// we still have some from nodes left over that need to be removed
while(curFromNodeChild) {
morpher.onFromNodeFound(curFromNodeChild);
fromNextSibling = curFromNodeChild.nextSibling;
removeNode(morpher, curFromNodeChild, fromNode);
curFromNodeChild = fromNextSibling;
}
// 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" to the end
fromNode.appendChild(curToNode);
curToNode = toNextSibling;
curFromNode = fromNextSibling;
}
};
// We have processed all of the "to nodes". If curFromNode is non-null then
// we still have some from nodes left over that need to be removed
while(curFromNode) {
morpher.onFromNodeFound(curFromNode);
fromNextSibling = curFromNode.nextSibling;
fromNode.removeChild(curFromNode);
morpher.onFromNodeRemoved(curFromNode);
curFromNode = fromNextSibling;
function Morpher(options) {
if (!options) {
options = {};
}
};
function Morpher(options) {
// NOTE: We use a task stack to handle DOM trees of any size by

@@ -198,13 +223,7 @@ // avoiding recursion

this.saved = {}; // Used to save off DOM elements with IDs
var onFromNodeFound = noop;
var onFromNodeRemoved = noop;
if (options) {
onFromNodeFound = options.onFromNodeFound || noop;
onFromNodeRemoved = options.onFromNodeRemoved || noop;
}
this.onFromNodeFound = onFromNodeFound;
this.onFromNodeRemoved = onFromNodeRemoved;
this.onFromNodeFound = options.onFromNodeFound || noop;
this.onFromNodeRemoved = options.onFromNodeRemoved || noop;
this.onBeforeMorphEl = options.onBeforeMorphEl || noop;
this.onBeforeMorphElChildren = options.onBeforeMorphElChildren || noop;
this.onBeforeRemoveNode = options.onBeforeRemoveNode || noop;
}

@@ -234,3 +253,3 @@

}
} else if (morphedNodeType === 3) {
} else if (morphedNodeType === 3) { // Text node
if (toNodeType === 3) {

@@ -237,0 +256,0 @@ morphedNode.nodeValue = toNode.nodeValue;

@@ -29,3 +29,3 @@ {

"dependencies": {},
"version": "0.1.1"
"version": "0.1.2"
}

@@ -42,4 +42,6 @@ morphdom

- *onFromNodeFound* (`Function(Node)`) - A function that will called when a `Node` in the `from` tree is found
- *onFromNodeRemoved* (`Function(Node)`) - A function that will called when a `Node` in the `from` tree has been removed (the children of the removed node will not be traversed)
- *onFromNodeFound* (`Function(node)`) - A function that will called when a `Node` in the `from` tree is found
- *onFromNodeRemoved* (`Function(node)`) - A function that will called when a `Node` in the `from` tree has been removed (the children of the removed node will not be traversed)
- *onBeforeMorphEl* (`Function(fromEl, toEl)`) - A function that will called when a `HTMLElement` in the `from` tree is about to be morphed. If the listener function returns `false` then the element will be skipped.
- *onBeforeMorphElChildren* (`Function(fromEl, toEl)`) - A function that will called when the children of an `HTMLElement` in the `from` tree is about to be morphed. If the listener function returns `false` then the child nodes will be skipped.

@@ -46,0 +48,0 @@ ```javascript

@@ -113,3 +113,3 @@ var chai = require('chai');

if (curNode.nodeType === 1) {
markDescendentsRemoved(curNode);
markDescendentsRemoved(curNode);
}

@@ -234,3 +234,3 @@

it('should transform an input el', function() {
it('should transform an text input el', function() {
var el1 = document.createElement('input');

@@ -249,2 +249,17 @@ el1.type = 'text';

it('should transform a checkbox input el', function() {
var el1 = document.createElement('input');
el1.type = 'checkbox';
el1.setAttribute('checked', '');
el1.checked = false;
var el2 = document.createElement('input');
el2.setAttribute('type', 'text');
el2.setAttribute('checked', '');
morphdom(el1, el2);
expect(el1.checked).to.equal(true);
});
it('should transform an incompatible node and maintain the same parent', function() {

@@ -278,2 +293,25 @@ var parentEl = document.createElement('div');

});
it('should allow morphing to be skipped for a node', function() {
var el1a = document.createElement('div');
var el1b = document.createElement('b');
el1b.setAttribute('class', 'foo');
el1a.appendChild(el1b);
var el2a = document.createElement('div');
var el2b = document.createElement('b');
el2b.setAttribute('class', 'bar');
el2a.appendChild(el2b);
morphdom(el1a, el2a, {
onBeforeMorphEl: function(el) {
if (el.tagName === 'B') {
return false;
}
}
});
expect(el1a.childNodes[0].className).to.equal('foo');
});
});

@@ -280,0 +318,0 @@

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc