jquery.jsonview.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. (function(jQuery) {
  2. var $, Collapser, JSONFormatter, JSONView;
  3. JSONFormatter = (function() {
  4. function JSONFormatter(options) {
  5. if (options == null) {
  6. options = {};
  7. }
  8. this.options = options;
  9. }
  10. JSONFormatter.prototype.htmlEncode = function(html) {
  11. if (html !== null) {
  12. return html.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
  13. } else {
  14. return '';
  15. }
  16. };
  17. JSONFormatter.prototype.jsString = function(s) {
  18. s = JSON.stringify(s).slice(1, -1);
  19. return this.htmlEncode(s);
  20. };
  21. JSONFormatter.prototype.decorateWithSpan = function(value, className) {
  22. return "<span class=\"" + className + "\">" + (this.htmlEncode(value)) + "</span>";
  23. };
  24. JSONFormatter.prototype.valueToHTML = function(value, level) {
  25. var valueType;
  26. if (level == null) {
  27. level = 0;
  28. }
  29. valueType = Object.prototype.toString.call(value).match(/\s(.+)]/)[1].toLowerCase();
  30. return this["" + valueType + "ToHTML"].call(this, value, level);
  31. };
  32. JSONFormatter.prototype.nullToHTML = function(value) {
  33. return this.decorateWithSpan('null', 'null');
  34. };
  35. JSONFormatter.prototype.numberToHTML = function(value) {
  36. return this.decorateWithSpan(value, 'num');
  37. };
  38. JSONFormatter.prototype.stringToHTML = function(value) {
  39. var multilineClass, newLinePattern;
  40. if (/^(http|https|file):\/\/[^\s]+$/i.test(value)) {
  41. return "<a href=\"" + (this.htmlEncode(value)) + "\"><span class=\"q\">\"</span>" + (this.jsString(value)) + "<span class=\"q\">\"</span></a>";
  42. } else {
  43. multilineClass = '';
  44. value = this.jsString(value);
  45. if (this.options.nl2br) {
  46. newLinePattern = /([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g;
  47. if (newLinePattern.test(value)) {
  48. multilineClass = ' multiline';
  49. value = (value + '').replace(newLinePattern, '$1' + '<br />');
  50. }
  51. }
  52. return "<span class=\"string" + multilineClass + "\">\"" + value + "\"</span>";
  53. }
  54. };
  55. JSONFormatter.prototype.booleanToHTML = function(value) {
  56. return this.decorateWithSpan(value, 'bool');
  57. };
  58. JSONFormatter.prototype.arrayToHTML = function(array, level) {
  59. var collapsible, hasContents, index, numProps, output, value, _i, _len;
  60. if (level == null) {
  61. level = 0;
  62. }
  63. hasContents = false;
  64. output = '';
  65. numProps = array.length;
  66. for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
  67. value = array[index];
  68. hasContents = true;
  69. output += '<li>' + this.valueToHTML(value, level + 1);
  70. if (numProps > 1) {
  71. output += ',';
  72. }
  73. output += '</li>';
  74. numProps--;
  75. }
  76. if (hasContents) {
  77. collapsible = level === 0 ? '' : ' collapsible';
  78. return "[<ul class=\"array level" + level + collapsible + "\">" + output + "</ul>]";
  79. } else {
  80. return '[ ]';
  81. }
  82. };
  83. JSONFormatter.prototype.objectToHTML = function(object, level) {
  84. var collapsible, hasContents, numProps, output, prop, value;
  85. if (level == null) {
  86. level = 0;
  87. }
  88. hasContents = false;
  89. output = '';
  90. numProps = 0;
  91. for (prop in object) {
  92. numProps++;
  93. }
  94. for (prop in object) {
  95. value = object[prop];
  96. hasContents = true;
  97. output += "<li><span class=\"prop\"><span class=\"q\">\"</span>" + (this.jsString(prop)) + "<span class=\"q\">\"</span></span>: " + (this.valueToHTML(value, level + 1));
  98. if (numProps > 1) {
  99. output += ',';
  100. }
  101. output += '</li>';
  102. numProps--;
  103. }
  104. if (hasContents) {
  105. collapsible = level === 0 ? '' : ' collapsible';
  106. return "{<ul class=\"obj level" + level + collapsible + "\">" + output + "</ul>}";
  107. } else {
  108. return '{ }';
  109. }
  110. };
  111. JSONFormatter.prototype.jsonToHTML = function(json) {
  112. return "<div class=\"jsonview\">" + (this.valueToHTML(json)) + "</div>";
  113. };
  114. return JSONFormatter;
  115. })();
  116. (typeof module !== "undefined" && module !== null) && (module.exports = JSONFormatter);
  117. Collapser = {
  118. bindEvent: function(item, collapsed) {
  119. var collapser;
  120. collapser = document.createElement('div');
  121. collapser.className = 'collapser';
  122. collapser.innerHTML = collapsed ? '+' : '-';
  123. collapser.addEventListener('click', (function(_this) {
  124. return function(event) {
  125. return _this.toggle(event.target);
  126. };
  127. })(this));
  128. item.insertBefore(collapser, item.firstChild);
  129. if (collapsed) {
  130. return this.collapse(collapser);
  131. }
  132. },
  133. expand: function(collapser) {
  134. var ellipsis, target;
  135. target = this.collapseTarget(collapser);
  136. ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0];
  137. target.parentNode.removeChild(ellipsis);
  138. target.style.display = '';
  139. return collapser.innerHTML = '-';
  140. },
  141. collapse: function(collapser) {
  142. var ellipsis, target;
  143. target = this.collapseTarget(collapser);
  144. target.style.display = 'none';
  145. ellipsis = document.createElement('span');
  146. ellipsis.className = 'ellipsis';
  147. ellipsis.innerHTML = ' &hellip; ';
  148. target.parentNode.insertBefore(ellipsis, target);
  149. return collapser.innerHTML = '+';
  150. },
  151. toggle: function(collapser) {
  152. var target;
  153. target = this.collapseTarget(collapser);
  154. if (target.style.display === 'none') {
  155. return this.expand(collapser);
  156. } else {
  157. return this.collapse(collapser);
  158. }
  159. },
  160. collapseTarget: function(collapser) {
  161. var target, targets;
  162. targets = collapser.parentNode.getElementsByClassName('collapsible');
  163. if (!targets.length) {
  164. return;
  165. }
  166. return target = targets[0];
  167. }
  168. };
  169. $ = jQuery;
  170. JSONView = {
  171. collapse: function(el) {
  172. if (el.innerHTML === '-') {
  173. return Collapser.collapse(el);
  174. }
  175. },
  176. expand: function(el) {
  177. if (el.innerHTML === '+') {
  178. return Collapser.expand(el);
  179. }
  180. },
  181. toggle: function(el) {
  182. return Collapser.toggle(el);
  183. }
  184. };
  185. return $.fn.JSONView = function() {
  186. var args, defaultOptions, formatter, json, method, options, outputDoc;
  187. args = arguments;
  188. if (JSONView[args[0]] != null) {
  189. method = args[0];
  190. return this.each(function() {
  191. var $this, level;
  192. $this = $(this);
  193. if (args[1] != null) {
  194. level = args[1];
  195. return $this.find(".jsonview .collapsible.level" + level).siblings('.collapser').each(function() {
  196. return JSONView[method](this);
  197. });
  198. } else {
  199. return $this.find('.jsonview > ul > li > .collapsible').siblings('.collapser').each(function() {
  200. return JSONView[method](this);
  201. });
  202. }
  203. });
  204. } else {
  205. json = args[0];
  206. options = args[1] || {};
  207. defaultOptions = {
  208. collapsed: false,
  209. nl2br: false
  210. };
  211. options = $.extend(defaultOptions, options);
  212. formatter = new JSONFormatter({
  213. nl2br: options.nl2br
  214. });
  215. if (Object.prototype.toString.call(json) === '[object String]') {
  216. json = JSON.parse(json);
  217. }
  218. outputDoc = formatter.jsonToHTML(json);
  219. return this.each(function() {
  220. var $this, item, items, _i, _len, _results;
  221. $this = $(this);
  222. $this.html(outputDoc);
  223. items = $this[0].getElementsByClassName('collapsible');
  224. _results = [];
  225. for (_i = 0, _len = items.length; _i < _len; _i++) {
  226. item = items[_i];
  227. if (item.parentNode.nodeName === 'LI') {
  228. _results.push(Collapser.bindEvent(item.parentNode, options.collapsed));
  229. } else {
  230. _results.push(void 0);
  231. }
  232. }
  233. return _results;
  234. });
  235. }
  236. };
  237. })(jQuery);