jquery.json-viewer.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * jQuery json-viewer
  3. * @author: Alexandre Bodelot <alexandre.bodelot@gmail.com>
  4. */
  5. (function($){
  6. /**
  7. * Check if arg is either an array with at least 1 element, or a dict with at least 1 key
  8. * @return boolean
  9. */
  10. function isCollapsable(arg) {
  11. return arg instanceof Object && Object.keys(arg).length > 0;
  12. }
  13. /**
  14. * Check if a string represents a valid url
  15. * @return boolean
  16. */
  17. function isUrl(string) {
  18. var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
  19. return regexp.test(string);
  20. }
  21. /**
  22. * Transform a json object into html representation
  23. * @return string
  24. */
  25. function json2html(json, options) {
  26. var html = '';
  27. if (typeof json === 'string') {
  28. /* Escape tags */
  29. json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  30. if (isUrl(json))
  31. html += '<a href="' + json + '" class="json-string">' + json + '</a>';
  32. else
  33. html += '<span class="json-string">"' + json + '"</span>';
  34. }
  35. else if (typeof json === 'number') {
  36. html += '<span class="json-literal">' + json + '</span>';
  37. }
  38. else if (typeof json === 'boolean') {
  39. html += '<span class="json-literal">' + json + '</span>';
  40. }
  41. else if (json === null) {
  42. html += '<span class="json-literal">null</span>';
  43. }
  44. else if (json instanceof Array) {
  45. if (json.length > 0) {
  46. html += '[<ol class="json-array">';
  47. for (var i = 0; i < json.length; ++i) {
  48. html += '<li>';
  49. /* Add toggle button if item is collapsable */
  50. if (isCollapsable(json[i])) {
  51. html += '<a href class="json-toggle"></a>';
  52. }
  53. html += json2html(json[i], options);
  54. /* Add comma if item is not last */
  55. if (i < json.length - 1) {
  56. html += ',';
  57. }
  58. html += '</li>';
  59. }
  60. html += '</ol>]';
  61. }
  62. else {
  63. html += '[]';
  64. }
  65. }
  66. else if (typeof json === 'object') {
  67. var key_count = Object.keys(json).length;
  68. if (key_count > 0) {
  69. html += '{<ul class="json-dict">';
  70. for (var key in json) {
  71. if (json.hasOwnProperty(key)) {
  72. html += '<li>';
  73. var keyRepr = options.withQuotes ?
  74. '<span class="json-string">"' + key + '"</span>' : key;
  75. /* Add toggle button if item is collapsable */
  76. if (isCollapsable(json[key])) {
  77. html += '<a href class="json-toggle">' + keyRepr + '</a>';
  78. }
  79. else {
  80. html += keyRepr;
  81. }
  82. html += ': ' + json2html(json[key], options);
  83. /* Add comma if item is not last */
  84. if (--key_count > 0)
  85. html += ',';
  86. html += '</li>';
  87. }
  88. }
  89. html += '</ul>}';
  90. }
  91. else {
  92. html += '{}';
  93. }
  94. }
  95. return html;
  96. }
  97. /**
  98. * jQuery plugin method
  99. * @param json: a javascript object
  100. * @param options: an optional options hash
  101. */
  102. $.fn.jsonViewer = function(json, options) {
  103. options = options || {};
  104. /* jQuery chaining */
  105. return this.each(function() {
  106. /* Transform to HTML */
  107. var html = json2html(json, options);
  108. if (isCollapsable(json))
  109. html = '<a href class="json-toggle"></a>' + html;
  110. /* Insert HTML in target DOM element */
  111. $(this).html(html);
  112. /* Bind click on toggle buttons */
  113. $(this).off('click');
  114. $(this).on('click', 'a.json-toggle', function() {
  115. var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
  116. target.toggle();
  117. if (target.is(':visible')) {
  118. target.siblings('.json-placeholder').remove();
  119. }
  120. else {
  121. var count = target.children('li').length;
  122. var placeholder = count + (count > 1 ? ' items' : ' item');
  123. target.after('<a href class="json-placeholder">' + placeholder + '</a>');
  124. }
  125. return false;
  126. });
  127. /* Simulate click on toggle button when placeholder is clicked */
  128. $(this).on('click', 'a.json-placeholder', function() {
  129. $(this).siblings('a.json-toggle').click();
  130. return false;
  131. });
  132. if (options.collapsed == true) {
  133. /* Trigger click to collapse all nodes */
  134. $(this).find('a.json-toggle').click();
  135. }
  136. });
  137. };
  138. })(jQuery);