1/** 2 * jQuery json-viewer 3 * @author: Alexandre Bodelot <[email protected]> 4 * @link: https://github.com/abodelot/jquery.json-viewer 5 */ 6(function($) { 7 8 /** 9 * Check if arg is either an array with at least 1 element, or a dict with at least 1 key 10 * @return boolean 11 */ 12 function isCollapsable(arg) { 13 return arg instanceof Object && Object.keys(arg).length > 0; 14 } 15 16 /** 17 * Check if a string represents a valid url 18 * @return boolean 19 */ 20 function isUrl(string) { 21 var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i; 22 return urlRegexp.test(string); 23 } 24 25 /** 26 * Transform a json object into html representation 27 * @return string 28 */ 29 function json2html(json, options) { 30 var html = ''; 31 if (typeof json === 'string') { 32 // Escape tags and quotes 33 json = json 34 .replace(/&/g, '&') 35 .replace(/</g, '<') 36 .replace(/>/g, '>') 37 .replace(/'/g, ''') 38 .replace(/"/g, '"'); 39 40 if (options.withLinks && isUrl(json)) { 41 html += '<a href="' + json + '" class="json-string" target="_blank">' + json + '</a>'; 42 } else { 43 // Escape double quotes in the rendered non-URL string. 44 json = json.replace(/"/g, '\\"'); 45 html += '<span class="json-string">"' + json + '"</span>'; 46 } 47 } else if (typeof json === 'number') { 48 html += '<span class="json-literal">' + json + '</span>'; 49 } else if (typeof json === 'boolean') { 50 html += '<span class="json-literal">' + json + '</span>'; 51 } else if (json === null) { 52 html += '<span class="json-literal">null</span>'; 53 } else if (json instanceof Array) { 54 if (json.length > 0) { 55 html += '[<ol class="json-array">'; 56 for (var i = 0; i < json.length; ++i) { 57 html += '<li>'; 58 // Add toggle button if item is collapsable 59 if (isCollapsable(json[i])) { 60 html += '<a href class="json-toggle"></a>'; 61 } 62 html += json2html(json[i], options); 63 // Add comma if item is not last 64 if (i < json.length - 1) { 65 html += ','; 66 } 67 html += '</li>'; 68 } 69 html += '</ol>]'; 70 } else { 71 html += '[]'; 72 } 73 } else if (typeof json === 'object') { 74 var keyCount = Object.keys(json).length; 75 if (keyCount > 0) { 76 html += '{<ul class="json-dict">'; 77 for (var key in json) { 78 if (Object.prototype.hasOwnProperty.call(json, key)) { 79 html += '<li>'; 80 var keyRepr = options.withQuotes ? 81 '<span class="json-string">"' + key + '"</span>' : key; 82 // Add toggle button if item is collapsable 83 if (isCollapsable(json[key])) { 84 html += '<a href class="json-toggle">' + keyRepr + '</a>'; 85 } else { 86 html += keyRepr; 87 } 88 html += ': ' + json2html(json[key], options); 89 // Add comma if item is not last 90 if (--keyCount > 0) { 91 html += ','; 92 } 93 html += '</li>'; 94 } 95 } 96 html += '</ul>}'; 97 } else { 98 html += '{}'; 99 } 100 } 101 return html; 102 } 103 104 /** 105 * jQuery plugin method 106 * @param json: a javascript object 107 * @param options: an optional options hash 108 */ 109 $.fn.jsonViewer = function(json, options) { 110 // Merge user options with default options 111 options = Object.assign({}, { 112 collapsed: false, 113 rootCollapsable: true, 114 withQuotes: false, 115 withLinks: true 116 }, options); 117 118 // jQuery chaining 119 return this.each(function() { 120 121 // Transform to HTML 122 var html = json2html(json, options); 123 if (options.rootCollapsable && isCollapsable(json)) { 124 html = '<a href class="json-toggle"></a>' + html; 125 } 126 127 // Insert HTML in target DOM element 128 $(this).html(html); 129 $(this).addClass('json-document'); 130 131 // Bind click on toggle buttons 132 $(this).off('click'); 133 $(this).on('click', 'a.json-toggle', function() { 134 var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
135 target.toggle(); 136 if (target.is(':visible')) { 137 target.siblings('.json-placeholder').remove(); 138 } else { 139 var count = target.children('li').length; 140 var placeholder = count + (count > 1 ? ' items' : ' item'); 141 target.after('<a href class="json-placeholder">' + placeholder + '</a>'); 142 } 143 return false; 144 }); 145 146 // Simulate click on toggle button when placeholder is clicked 147 $(this).on('click', 'a.json-placeholder', function() { 148 $(this).siblings('a.json-toggle').click(); 149 return false; 150 }); 151 152 if (options.collapsed == true) { 153 // Trigger click to collapse all nodes 154 $(this).find('a.json-toggle').click(); 155 } 156 }); 157 }; 158})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.