(function(jQuery) { var $, Collapser, JSONFormatter, JSONView; JSONFormatter = (function() { function JSONFormatter(options) { if (options == null) { options = {}; } this.options = options; } JSONFormatter.prototype.htmlEncode = function(html) { if (html !== null) { return html.toString().replace(/&/g, "&").replace(/"/g, """).replace(//g, ">"); } else { return ''; } }; JSONFormatter.prototype.jsString = function(s) { s = JSON.stringify(s).slice(1, -1); return this.htmlEncode(s); }; JSONFormatter.prototype.decorateWithSpan = function(value, className) { return "" + (this.htmlEncode(value)) + ""; }; JSONFormatter.prototype.valueToHTML = function(value, level) { var valueType; if (level == null) { level = 0; } valueType = Object.prototype.toString.call(value).match(/\s(.+)]/)[1].toLowerCase(); return this["" + valueType + "ToHTML"].call(this, value, level); }; JSONFormatter.prototype.nullToHTML = function(value) { return this.decorateWithSpan('null', 'null'); }; JSONFormatter.prototype.numberToHTML = function(value) { return this.decorateWithSpan(value, 'num'); }; JSONFormatter.prototype.stringToHTML = function(value) { var multilineClass, newLinePattern; if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) { return "\"" + (this.jsString(value)) + "\""; } else { multilineClass = ''; value = this.jsString(value); if (this.options.nl2br) { newLinePattern = /([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g; if (newLinePattern.test(value)) { multilineClass = ' multiline'; value = (value + '').replace(newLinePattern, '$1' + '
'); } } return "\"" + value + "\""; } }; JSONFormatter.prototype.booleanToHTML = function(value) { return this.decorateWithSpan(value, 'bool'); }; JSONFormatter.prototype.arrayToHTML = function(array, level) { var collapsible, hasContents, index, numProps, output, value, _i, _len; if (level == null) { level = 0; } hasContents = false; output = ''; numProps = array.length; for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) { value = array[index]; hasContents = true; output += '
  • ' + this.valueToHTML(value, level + 1); if (numProps > 1) { output += ','; } output += '
  • '; numProps--; } if (hasContents) { collapsible = level === 0 ? '' : ' collapsible'; return "[]"; } else { return '[ ]'; } }; JSONFormatter.prototype.objectToHTML = function(object, level) { var collapsible, hasContents, numProps, output, prop, value; if (level == null) { level = 0; } hasContents = false; output = ''; numProps = 0; for (prop in object) { numProps++; } for (prop in object) { value = object[prop]; hasContents = true; output += "
  • \"" + (this.jsString(prop)) + "\": " + (this.valueToHTML(value, level + 1)); if (numProps > 1) { output += ','; } output += '
  • '; numProps--; } if (hasContents) { collapsible = level === 0 ? '' : ' collapsible'; return "{}"; } else { return '{ }'; } }; JSONFormatter.prototype.jsonToHTML = function(json) { return "
    " + (this.valueToHTML(json)) + "
    "; }; return JSONFormatter; })(); (typeof module !== "undefined" && module !== null) && (module.exports = JSONFormatter); Collapser = { bindEvent: function(item, collapsed) { var collapser; collapser = document.createElement('div'); collapser.className = 'collapser'; collapser.innerHTML = collapsed ? '+' : '-'; collapser.addEventListener('click', (function(_this) { return function(event) { return _this.toggle(event.target); }; })(this)); item.insertBefore(collapser, item.firstChild); if (collapsed) { return this.collapse(collapser); } }, expand: function(collapser) { var ellipsis, target; target = this.collapseTarget(collapser); ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0]; target.parentNode.removeChild(ellipsis); target.style.display = ''; return collapser.innerHTML = '-'; }, collapse: function(collapser) { var ellipsis, target; target = this.collapseTarget(collapser); target.style.display = 'none'; ellipsis = document.createElement('span'); ellipsis.className = 'ellipsis'; ellipsis.innerHTML = ' … '; target.parentNode.insertBefore(ellipsis, target); return collapser.innerHTML = '+'; }, toggle: function(collapser) { var target; target = this.collapseTarget(collapser); if (target.style.display === 'none') { return this.expand(collapser); } else { return this.collapse(collapser); } }, collapseTarget: function(collapser) { var target, targets; targets = collapser.parentNode.getElementsByClassName('collapsible'); if (!targets.length) { return; } return target = targets[0]; } }; $ = jQuery; JSONView = { collapse: function(el) { if (el.innerHTML === '-') { return Collapser.collapse(el); } }, expand: function(el) { if (el.innerHTML === '+') { return Collapser.expand(el); } }, toggle: function(el) { return Collapser.toggle(el); } }; return $.fn.JSONView = function() { var args, defaultOptions, formatter, json, method, options, outputDoc; args = arguments; if (JSONView[args[0]] != null) { method = args[0]; return this.each(function() { var $this, level; $this = $(this); if (args[1] != null) { level = args[1]; return $this.find(".jsonview .collapsible.level" + level).siblings('.collapser').each(function() { return JSONView[method](this); }); } else { return $this.find('.jsonview > ul > li > .collapsible').siblings('.collapser').each(function() { return JSONView[method](this); }); } }); } else { json = args[0]; options = args[1] || {}; defaultOptions = { collapsed: false, nl2br: false }; options = $.extend(defaultOptions, options); formatter = new JSONFormatter({ nl2br: options.nl2br }); if (Object.prototype.toString.call(json) === '[object String]') { json = JSON.parse(json); } outputDoc = formatter.jsonToHTML(json); return this.each(function() { var $this, item, items, _i, _len, _results; $this = $(this); $this.html(outputDoc); items = $this[0].getElementsByClassName('collapsible'); _results = []; for (_i = 0, _len = items.length; _i < _len; _i++) { item = items[_i]; if (item.parentNode.nodeName === 'LI') { _results.push(Collapser.bindEvent(item.parentNode, options.collapsed)); } else { _results.push(void 0); } } return _results; }); } }; })(jQuery);