aboutsummaryrefslogblamecommitdiffstats
path: root/json_diff.js
blob: 07068cb8d787735fba077e228e6de99d498fdedf (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                                                                                          
 



                                                                     
 
                       
 






























































                                                                                         















































































                                                                                           
                            
                                                       










                                                  

                                  
#!/usr/bin/rhino
/*
This is for now just reimplementation of tlrobinson's json-diff (http://tlrobinson.net/projects/javascript-fun/jsondiff/).

However, later I would like to incorporate algorightm from
https://github.com/cmsd2/xdiff (which is an implementation in Ruby of
http://pages.cs.wisc.edu/~yuanwang/xdiff.html)
 */

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 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 typeofReal(value) {
  return Array.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");
  }
}

/* vim: set ts=2 et sw=2 tw=80: */