aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--json_diff.js179
1 files changed, 179 insertions, 0 deletions
diff --git a/json_diff.js b/json_diff.js
new file mode 100644
index 0000000..27973aa
--- /dev/null
+++ b/json_diff.js
@@ -0,0 +1,179 @@
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+var jsonBoxA, jsonBoxB;
+
+var HashStore = {
+ load : function(callback) {
+ if (window.location.hash) {
+ try {
+ var hashObject = JSON.parse(decodeURIComponent(window.location.hash.slice(1)));
+ callback && callback(hashObject.d);
+ return;
+ } catch (e) {
+ console.log()
+ }
+ }
+ callback && callback(null);
+ },
+ sync : function(object) {
+ var hashObject = { d : object };
+ window.location.hash = "#" + encodeURIComponent(JSON.stringify(hashObject));
+ }
+};
+
+function init() {
+ document.addEventListener("click", clickHandler, false);
+
+ jsonBoxA = document.getElementById("jsonA");
+ jsonBoxB = document.getElementById("jsonB");
+
+ HashStore.load(function(data) {
+ if (data) {
+ jsonBoxA.value = data.a;
+ jsonBoxB.value = data.b;
+ }
+ });
+
+ startCompare();
+}
+
+function swapBoxes() {
+ var tmp = jsonBoxA.value;
+ jsonBoxA.value = jsonBoxB.value;
+ jsonBoxB.value = tmp;
+}
+
+function clearBoxes() {
+ jsonBoxA.value = "";
+ jsonBoxB.value = "";
+}
+
+function startCompare() {
+ var aValue = jsonBoxA.value;
+ var bValue = jsonBoxB.value;
+
+ var objA, objB;
+ try {
+ objA = JSON.parse(aValue);
+ jsonBoxA.style.backgroundColor = "";
+ } catch(e) {
+ jsonBoxA.style.backgroundColor = "rgba(255,0,0,0.5)";
+ }
+ try {
+ objB = JSON.parse(bValue);
+ jsonBoxB.style.backgroundColor = "";
+ } catch(e) {
+ jsonBoxB.style.backgroundColor = "rgba(255,0,0,0.5)";
+ }
+
+ HashStore.sync({
+ a : aValue,
+ b : bValue
+ });
+
+ results = document.getElementById("results");
+ removeAllChildren(results);
+
+ compareTree(objA, objB, "root", results);
+}
+
+function compareTree(a, b, name, results) {
+ var typeA = typeofReal(a);
+ var typeB = typeofReal(b);
+
+ 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);
+ }
+ else if (b === undefined) {
+ leafNode.setAttribute("class", "removed");
+ leafNode.appendChild(document.createTextNode(": " + aString));
+ leafNode.appendChild(typeSpanA);
+ }
+ 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);
+ }
+ 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) {
+ if (a.hasOwnProperty(i)) {
+ keys.push(i);
+ }
+ }
+ for (var i in b) {
+ if (b.hasOwnProperty(i)) {
+ 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 removeAllChildren(node) {
+ var child;
+ while (child = node.lastChild) {
+ node.removeChild(child);
+ }
+}
+
+function isArray(value) {
+ return value && typeof value === "object" && value.constructor === Array;
+}
+function typeofReal(value) {
+ return isArray(value) ? "array" : typeof value;
+}
+
+function clickHandler(e) {
+ var 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");
+ }
+}