started seperating html/css/library components making ready for nodejs

This commit is contained in:
cakewolf 2010-12-07 13:20:50 -05:00
parent 62c71bc367
commit fa5d621ea6
5 changed files with 348 additions and 198 deletions

View file

@ -3,6 +3,10 @@ JSON Diff
Shows the differences between two JSON-encoded objects. Shows the differences between two JSON-encoded objects.
Originally created by Tom Robinson. Improvements by Sami Samhuri. Originally created by Tom Robinson. Improvements by Sami Samhuri and hij1nx.
Copyright 2006-2010 [Tom Robinson](http://tlrobinson.net/). [Some rights reserved](http://creativecommons.org/licenses/by-nc/3.0/us/). Copyright 2006-2010 [Tom Robinson](http://tlrobinson.net/).
[Some rights reserved](http://creativecommons.org/licenses/by-nc/3.0/us/).
[Sami Samhuri] (http://github.com/samsonjs)
[hij1nx] (http://github.com/hij1nx)

73
css/json-diff.css Normal file
View file

@ -0,0 +1,73 @@
body {
background-color: lightblue;
}
#results li > span, #results ul > span {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
padding-right: 5px;
padding-left: 5px;
}
#results li {
margin-top: 1px;
padding-left: 15px;
}
#results ul {
padding-left: 15px;
margin-left: -15px;
padding-top: 0px;
margin-top: 0px;
background: url(open.png) no-repeat 2px 5px;
list-style-type: none;
}
#results ul[closed="yes"] {
background: url(closed.png) no-repeat 2px 5px;
}
#results ul[closed="yes"] > * {
display: none;
}
#results ul[closed="yes"] > *:first-child {
display: block;
}
.typeName {
color: gray;
}
.changed {
background-color: #fcff7f;
}
.changed.key {
background-color: #eee;
}
.added {
background-color: #8bff7f;
}
.removed {
background-color: #fd7f7f;
}
textarea {
width: 49%;
height: 200px;
}
.contentbox {
border: 1px dashed black;
background-color: white;
padding: 15px;
margin: 10px;
}
h2 {
text-align: center;
margin: 0px;;
}
#results {
padding-left: 40px;
}
#inputs {
text-align: center;
}

View file

@ -2,171 +2,7 @@
<head> <head>
<title>JSON Diff</title> <title>JSON Diff</title>
<meta charset=utf8> <meta charset=utf8>
<link rel="stylesheet" href="json-diff.css" type="text/css" media="screen" charset="utf-8"> <link rel="stylesheet" href="css/json-diff.css" type="text/css" media="screen" title="no title" charset="utf-8">
<script type="text/javascript" charset="utf-8">
var jsonBoxA, jsonBoxB, n;
function init() {
document.addEventListener("click", clickHandler, false);
jsonBoxA = document.getElementById("jsonA");
jsonBoxB = document.getElementById("jsonB");
startCompare();
}
function swapBoxes() {
console.log('>>> swapBoxes()');
var tmp = jsonBoxA.value;
jsonBoxA.value = jsonBoxB.value;
jsonBoxB.value = tmp;
}
function clearBoxes() {
console.log('>>> clearBoxes()');
jsonBoxA.value = "";
jsonBoxB.value = "";
}
function startCompare() {
console.log('startCompare()');
var objA, objB;
n = 0;
jsonBoxA.style.backgroundColor = "";
jsonBoxB.style.backgroundColor = "";
try {
objA = eval("(" + jsonBoxA.value + ")");
} catch(e) {
jsonBoxA.style.backgroundColor = "rgba(255,0,0,0.5)";
}
try {
objB = eval("(" + jsonBoxB.value + ")");
} catch(e) {
jsonBoxB.style.backgroundColor = "rgba(255,0,0,0.5)";
}
results = document.getElementById("results");
while (results.firstChild)
results.removeChild(results.firstChild);
compareTree(objA, objB, "root", results);
}
function markChanged(node) {
document.getElementById('first').style.display = 'block';
node.setAttribute('id', 'change-' + n);
n += 1;
var nextNode = document.createElement('a');
nextNode.setAttribute('href', '#change-' + n);
nextNode.appendChild(document.createTextNode('↓ next change ↓'))
node.appendChild(nextNode);
}
function compareTree(a, b, name, results) {
var typeA = typeofReal(a);
var typeB = typeofReal(b);
console.log('compareTree(a=(' + typeA + ')' + a +
', b=(' + typeB + ')' + b +
', name=(' + typeof name + ')' + name +
', results=(' + typeof results + ')' + results + ')');
var typeSpanA = document.createElement("span");
typeSpanA.appendChild(document.createTextNode("(" + typeA + ")"))
typeSpanA.setAttribute("class", "typeName");
var typeSpanB = document.createElement("span");
typeSpanB.appendChild(document.createTextNode("(" + typeB + ")"))
typeSpanB.setAttribute("class", "typeName");
var aString = (typeA === "object" || typeA === "array") ? "": String(a) + " ";
var bString = (typeB === "object" || typeB === "array") ? "": String(b) + " ";
var leafNode = document.createElement("span");
leafNode.appendChild(document.createTextNode(name));
if (a === undefined)
{
leafNode.setAttribute("class", "added");
leafNode.appendChild(document.createTextNode(": " + bString));
leafNode.appendChild(typeSpanB);
markChanged(leafNode);
}
else if (b === undefined)
{
leafNode.setAttribute("class", "removed");
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
markChanged(leafNode);
}
else if (typeA !== typeB || (typeA !== "object" && typeA !== "array" && a !== b))
{
leafNode.setAttribute("class", "changed");
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
leafNode.appendChild(document.createTextNode(" => " + bString));
leafNode.appendChild(typeSpanB);
if (name === 'key') leafNode.setAttribute('class', 'changed key');
else markChanged(leafNode);
}
else
{
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
}
if (typeA === "object" || typeA === "array" || typeB === "object" || typeB === "array")
{
var keys = [];
for (var i in a) keys.push(i);
for (var i in b) keys.push(i);
keys.sort();
var listNode = document.createElement("ul");
listNode.appendChild(leafNode);
for (var i = 0; i < keys.length; i++)
{
if (keys[i] === keys[i - 1])
continue;
var li = document.createElement("li");
listNode.appendChild(li);
compareTree(a && a[keys[i]], b && b[keys[i]], keys[i], li);
}
results.appendChild(listNode);
}
else
{
results.appendChild(leafNode);
}
}
function isArray(value) {
return value && typeof value === "object" && value.constructor === Array;
}
function typeofReal(value) {
return isArray(value) ? "array": value === null ? 'null' : typeof value;
}
function clickHandler(e) {
e = e || window.event;
if (e.target.nodeName.toUpperCase() === "UL")
{
if (e.target.getAttribute("closed") === "yes")
e.target.setAttribute("closed", "no");
else
e.target.setAttribute("closed", "yes");
}
}
</script>
</head> </head>
<body onload="init();"> <body onload="init();">
<p align="center" style="margin: 2em;">Courtesy of <a href="http://tlrobinson.net/projects/javascript-fun/jsondiff/">tlrobinson</a>. <p align="center" style="margin: 2em;">Courtesy of <a href="http://tlrobinson.net/projects/javascript-fun/jsondiff/">tlrobinson</a>.
@ -186,39 +22,10 @@ function clickHandler(e) {
</ul> </ul>
</div> </div>
<div class="contentbox" id="inputs"> <div class="contentbox" id="inputs">
<textarea id="jsonA">{ <textarea id="jsonA">
"__class":"SLUser",
"displayName":"Sami Samhuri",
"accountSuspended": false,
"newAttribute":null,
"addressStreet1":null,
"url":null,
"addressZip":null,
"email":"foo@bar.com",
"addressRegion":null,
"businessName":null,
"addressStreet2":null,
"addressCountry":null,
"hashedPassword":"dc7754ea14e2d4f07bb3ec6a099480f318529dce",
"uuid":"dc80bc3053d135e52411ce67bd758211"
}
</textarea> </textarea>
<textarea id="jsonB"> <textarea id="jsonB">
{ </textarea>
"__class":"SLUser",
"displayName":"Foo Bar",
"accountSuspended": false,
"addressStreet1":"123 Fake St",
"url":"bar.com",
"addressZip":"V9C 0E6",
"email":"foo@bar.com",
"addressRegion":"BC",
"businessName":"stuff",
"addressStreet2":null,
"addressCountry":"Canada",
"hashedPassword":"dc7754ea14e2d4f07bb3ec6a099480f318529dce",
"uuid":"d0e11b7c73d483335ac7697b042e36c5"
}</textarea>
<input type="button" value="Compare" id="compare" onclick="startCompare();" /> <input type="button" value="Compare" id="compare" onclick="startCompare();" />
<input type="button" value="Swap" id="swap" onclick="swapBoxes();"/> <input type="button" value="Swap" id="swap" onclick="swapBoxes();"/>
<input type="button" value="Clear" id="clear" onclick="clearBoxes();"/> <input type="button" value="Clear" id="clear" onclick="clearBoxes();"/>
@ -241,5 +48,9 @@ function clickHandler(e) {
<p> <p>
&copy; 2006-2010 Thomas Robinson.&nbsp;<a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/us/">Some rights reserved</a>. </p> &copy; 2006-2010 Thomas Robinson.&nbsp;<a rel="license" href="http://creativecommons.org/licenses/by-nc/3.0/us/">Some rights reserved</a>. </p>
</div> </div>
<script src="js/lib/json-diff.js" type="text/javascript" charset="utf-8"></script>
<script src="js/app.js" type="text/javascript" charset="utf-8"></script>
</body> </body>
</html> </html>

137
js/app.js Normal file
View file

@ -0,0 +1,137 @@
if(!window.console){
window.console = {
log: function(){},
debug: function(){},
warn: function(){},
dir: function(){}
};
}
(function() {
var jsonBoxA,
jsonBoxB,
n;
var samples = {
a: {
"__class":"SLUser",
"displayName":"Sami Samhuri",
"accountSuspended": false,
"newAttribute":null,
"addressStreet1":null,
"url":null,
"addressZip":null,
"email":"foo@bar.com",
"addressRegion":null,
"businessName":null,
"addressStreet2":null,
"addressCountry":null,
"hashedPassword":"dc7754ea14e2d4f07bb3ec6a099480f318529dce",
"uuid":"dc80bc3053d135e52411ce67bd758211"
},
b: {
"__class":"SLUser",
"displayName":"Foo Bar",
"accountSuspended": false,
"addressStreet1":"123 Fake St",
"url":"bar.com",
"addressZip":"V9C 0E6",
"email":"foo@bar.com",
"addressRegion":"BC",
"businessName":"stuff",
"addressStreet2":null,
"addressCountry":"Canada",
"hashedPassword":"dc7754ea14e2d4f07bb3ec6a099480f318529dce",
"uuid":"d0e11b7c73d483335ac7697b042e36c5"
}
};
return {
Init: function() {
console.log('>>> Init()');
document.addEventListener("click", this.clickHandler, false);
jsonBoxA = document.getElementById("jsonA");
jsonBoxB = document.getElementById("jsonB");
jsonDiff.feedback = this.markChanged;
this.populteSamples();
this.startCompare();
}
populteSamples: function() {
console.log('>>> populateSamples()');
jsonBoxA.value = JSON.stringify(samples.a);
jsonBoxB.value = JSON.stringify(samples.b);
},
startCompare: function () {
console.log('>>> startCompare()');
var objA, objB;
n = 0;
jsonBoxA.style.backgroundColor = "";
jsonBoxB.style.backgroundColor = "";
try {
objA = eval("(" + jsonBoxA.value + ")");
} catch(e) {
jsonBoxA.style.backgroundColor = "rgba(255,0,0,0.5)";
}
try {
objB = eval("(" + jsonBoxB.value + ")");
} catch(e) {
jsonBoxB.style.backgroundColor = "rgba(255,0,0,0.5)";
}
results = document.getElementById("results");
while (results.firstChild)
results.removeChild(results.firstChild);
jsonDiff.compareTree(objA, objB, "root", results);
},
markChanged: function(node) {
console.log('>>> markChanged()');
document.getElementById('first').style.display = 'block';
node.setAttribute('id', 'change-' + n);
n += 1;
var nextNode = document.createElement('a');
nextNode.setAttribute('href', '#change-' + n);
nextNode.appendChild(document.createTextNode('↓ next change ↓'))
node.appendChild(nextNode);
},
clickHandler: function(e) {
console.log('>>> clickHandler()');
e = e || window.event;
if (e.target.nodeName.toUpperCase() === "UL")
{
if (e.target.getAttribute("closed") === "yes")
e.target.setAttribute("closed", "no");
else
e.target.setAttribute("closed", "yes");
}
}
}
})().Init();

125
js/lib/json-diff.js Normal file
View file

@ -0,0 +1,125 @@
var jsonDiff = (typeof exports !== "undefined" ? exports : window).jsonDiff = (function(){
function isArray(value) {
if(Array.isArray) {
return Array.isArray(value);
}
else {
return value && typeof value === "object" && value.constructor === Array;
}
}
function typeofReal(value) {
return isArray(value) ? "array": value === null ? 'null' : typeof value;
}
return {
a: [], // first structure
b: [], // second structure
feedback: function() {
},
swapValues: function() {
console.log('>>> swapBoxes()');
this.a = [this.b, this.b = this.a][0];
},
clearValues: function() {
console.log('>>> clearBoxes()');
this.a = this.b = null;
},
compareTree: function(a, b, name, results) {
var self = this;
var typeA = typeofReal(a);
var typeB = typeofReal(b);
console.log('>>> compareTree(a=(' + typeA + ')' + a +
', b=(' + typeB + ')' + b +
', name=(' + typeof name + ')' + name +
', results=(' + typeof results + ')' + results + ')');
var typeSpanA = document.createElement("span");
typeSpanA.appendChild(document.createTextNode("(" + typeA + ")"))
typeSpanA.setAttribute("class", "typeName");
var typeSpanB = document.createElement("span");
typeSpanB.appendChild(document.createTextNode("(" + typeB + ")"))
typeSpanB.setAttribute("class", "typeName");
var aString = (typeA === "object" || typeA === "array") ? "": String(a) + " ";
var bString = (typeB === "object" || typeB === "array") ? "": String(b) + " ";
var leafNode = document.createElement("span");
leafNode.appendChild(document.createTextNode(name));
if (a === undefined)
{
leafNode.setAttribute("class", "added");
leafNode.appendChild(document.createTextNode(": " + bString));
leafNode.appendChild(typeSpanB);
self.feedback(leafNode);
}
else if (b === undefined)
{
leafNode.setAttribute("class", "removed");
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
self.feedback(leafNode);
}
else if (typeA !== typeB || (typeA !== "object" && typeA !== "array" && a !== b))
{
leafNode.setAttribute("class", "changed");
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
leafNode.appendChild(document.createTextNode(" => " + bString));
leafNode.appendChild(typeSpanB);
if (name === 'key') leafNode.setAttribute('class', 'changed key');
else self.feedback(leafNode);
}
else
{
leafNode.appendChild(document.createTextNode(": " + aString));
leafNode.appendChild(typeSpanA);
}
if (typeA === "object" || typeA === "array" || typeB === "object" || typeB === "array")
{
var keys = [];
for (var i in a) keys.push(i);
for (var i in b) keys.push(i);
keys.sort();
var listNode = document.createElement("ul");
listNode.appendChild(leafNode);
for (var i = 0; i < keys.length; i++)
{
if (keys[i] === keys[i - 1])
continue;
var li = document.createElement("li");
listNode.appendChild(li);
self.compareTree(a && a[keys[i]], b && b[keys[i]], keys[i], li);
}
results.appendChild(listNode);
}
else
{
results.appendChild(leafNode);
}
}
};
})();