// 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"); } }