/*! jQuery JSONView. Licensed under the MIT License. */ (function(jQuery) { var $, Collapser, JSONFormatter, JSONView, JSON_VALUE_TYPES; JSON_VALUE_TYPES = ['object', 'array', 'number', 'string', 'boolean', 'null']; 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(); if (this.options.strict && !jQuery.inArray(valueType, JSON_VALUE_TYPES)) { throw new Error("" + valueType + " is not a valid JSON value type"); } return this["" + valueType + "ToHTML"].call(this, value, level); }; JSONFormatter.prototype.nullToHTML = function(value) { return this.decorateWithSpan('null', 'null'); }; JSONFormatter.prototype.undefinedToHTML = function() { return this.decorateWithSpan('undefined', 'undefined'); }; 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, key, 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; key = this.options.escape ? this.jsString(prop) : prop; output += "
  • \"" + key + "\": " + (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 = (function() { function Collapser() {} Collapser.bindEvent = function(item, options) { var collapser; item.firstChild.addEventListener('click', (function(_this) { return function(event) { return _this.toggle(event.target.parentNode.firstChild, options); }; })(this)); collapser = document.createElement('div'); collapser.className = 'collapser'; collapser.innerHTML = options.collapsed ? '+' : '-'; collapser.addEventListener('click', (function(_this) { return function(event) { return _this.toggle(event.target, options); }; })(this)); item.insertBefore(collapser, item.firstChild); if (options.collapsed) { return this.collapse(collapser); } }; Collapser.expand = function(collapser) { var ellipsis, target; target = this.collapseTarget(collapser); if (target.style.display === '') { return; } ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0]; target.parentNode.removeChild(ellipsis); target.style.display = ''; return collapser.innerHTML = '-'; }; Collapser.collapse = function(collapser) { var ellipsis, target; target = this.collapseTarget(collapser); if (target.style.display === 'none') { return; } target.style.display = 'none'; ellipsis = document.createElement('span'); ellipsis.className = 'ellipsis'; ellipsis.innerHTML = ' … '; target.parentNode.insertBefore(ellipsis, target); return collapser.innerHTML = '+'; }; Collapser.toggle = function(collapser, options) { var action, collapsers, target, _i, _len, _results; if (options == null) { options = {}; } target = this.collapseTarget(collapser); action = target.style.display === 'none' ? 'expand' : 'collapse'; if (options.recursive_collapser) { collapsers = collapser.parentNode.getElementsByClassName('collapser'); _results = []; for (_i = 0, _len = collapsers.length; _i < _len; _i++) { collapser = collapsers[_i]; _results.push(this[action](collapser)); } return _results; } else { return this[action](collapser); } }; Collapser.collapseTarget = function(collapser) { var target, targets; targets = collapser.parentNode.getElementsByClassName('collapsible'); if (!targets.length) { return; } return target = targets[0]; }; return Collapser; })(); $ = 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, recursive_collapser: false, escape: true, strict: false }; options = $.extend(defaultOptions, options); formatter = new JSONFormatter(options); 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)); } else { _results.push(void 0); } } return _results; }); } }; })(jQuery);