PluginProbe
QuadMenu – Mega Menu / 1.8.8
QuadMenu – Mega Menu v1.8.8
3.3.8 3.3.7 3.3.6 trunk 1.8.4 1.8.5 1.8.7 1.8.8 1.8.9 1.9.0 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 88 releases
quadmenu / lib / ReduxCore / assets / js / vendor / jsonview.js

jsonview.js in QuadMenu – Mega Menu 1.8.8, at lib/ReduxCore/assets/js/vendor/jsonview.js

265 lines 10.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1
2 /* global console, jsonView */
3 /*
4 * ViewJSON
5 * Version 1.0
6 * A Google Chrome extension to display JSON in a user-friendly format
7 *
8 * This is a chromeified version of the JSONView Firefox extension by Ben Hollis:
9 * http://jsonview.com
10 * http://code.google.com/p/jsonview
11 *
12 * Also based on the XMLTree Chrome extension by Moonty & alan.stroop
13 * https://chrome.google.com/extensions/detail/gbammbheopgpmaagmckhpjbfgdfkpadb
14 *
15 * port by Jamie Wilkinson (@jamiew) | http://jamiedubs.com | http://github.com/jamiew
16 * MIT license / copyfree (f) F.A.T. Lab http://fffff.at
17 * Speed Project Approved: 2h
18 */
19
20 function collapse(evt) {
21 var collapser = evt.target;
22 var target = collapser.parentNode.getElementsByClassName('collapsible');
23 if (!target.length) {
24 return;
25 }
26 target = target[0];
27 if (target.style.display === 'none') {
28 var ellipsis = target.parentNode.getElementsByClassName('ellipsis')[0];
29 target.parentNode.removeChild(ellipsis);
30 target.style.display = '';
31 } else {
32 target.style.display = 'none';
33 var ellipsis = document.createElement('span');
34 ellipsis.className = 'ellipsis';
35 ellipsis.innerHTML = ' … ';
36 target.parentNode.insertBefore(ellipsis, target);
37 }
38 collapser.innerHTML = (collapser.innerHTML === '-') ? '+' : '-';
39 }
40
41 function addCollapser(item) {
42 // This mainly filters out the root object (which shouldn't be collapsible)
43 if (item.nodeName !== 'LI') {
44 return;
45 }
46 var collapser = document.createElement('div');
47 collapser.className = 'collapser';
48 collapser.innerHTML = '-';
49 collapser.addEventListener('click', collapse, false);
50 item.insertBefore(collapser, item.firstChild);
51 }
52
53 function jsonView(id, target) {
54 this.debug = false;
55 if (id.indexOf("#") !== -1) {
56 this.idType = "id";
57 this.id = id.replace('#', '');
58 } else if (id.indexOf(".") !== -1) {
59 this.idType = "class";
60 this.id = id.replace('.', '');
61 } else {
62 if (this.debug) { console.log("Can't find that element"); }
63 return;
64 }
65
66 this.data = document.getElementById(this.id).innerHTML;
67 if (typeof(target) !== undefined) {
68 if (target.indexOf("#") !== -1) {
69 this.targetType = "id";
70 this.target = target.replace('#', '');
71 } else if (id.indexOf(".") !== -1) {
72 this.targetType = "class";
73 this.target = target.replace('.', '');
74 } else {
75 if (this.debug) { console.log("Can't find the target element"); }
76 return;
77 }
78 }
79 // Note: now using "*.json*" URI matching rather than these page regexes -- save CPU cycles!
80 // var is_json = /^\s*(\{.*\})\s*$/.test(this.data);
81 // var is_jsonp = /^.*\(\s*(\{.*\})\s*\)$/.test(this.data);
82 // if(is_json || is_jsonp){
83 // Our manifest specifies that we only do URLs matching '.json', so attempt to sanitize any HTML
84 // added by Chrome's "text/plain" or "text/html" handlers
85 if (/^\<pre.*\>(.*)\<\/pre\>$/.test(this.data)) {
86 if (this.debug) { console.log("JSONView: data is wrapped in <pre>...</pre>, stripping HTML..."); }
87 this.data = this.data.replace(/<(?:.|\s)*?>/g, ''); //Aggressively strip HTML.
88 }
89 // Test if what remains is JSON or JSONp
90 var json_regex = /^\s*([\[\{].*[\}\]])\s*$/; // Ghetto, but it works
91 var jsonp_regex = /^[\s\u200B\uFEFF]*([\w$\[\]\.]+)[\s\u200B\uFEFF]*\([\s\u200B\uFEFF]*([\[{][\s\S]*[\]}])[\s\u200B\uFEFF]*\);?[\s\u200B\uFEFF]*$/;
92 var jsonp_regex2 = /([\[\{][\s\S]*[\]\}])\)/; // more liberal support... this allows us to pass the jsonp.json & jsonp2.json tests
93 var is_json = json_regex.test(this.data);
94 var is_jsonp = jsonp_regex.test(this.data);
95 if (this.debug) { console.log("JSONView: is_json=" + is_json + " is_jsonp=" + is_jsonp); }
96 if (is_json || is_jsonp) {
97 if (this.debug) { console.log("JSONView: sexytime!"); }
98 // JSONFormatter json->HTML prototype straight from Firefox JSONView
99 // For reference: http://code.google.com/p/jsonview
100
101 function JSONFormatter() {
102 // No magic required.
103 }
104 JSONFormatter.prototype = {
105 htmlEncode: function(t) {
106 return t != null ? t.toString().replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;") : '';
107 },
108 decorateWithSpan: function(value, className) {
109 return '<span class="' + className + '">' + this.htmlEncode(value) + '</span>';
110 },
111 // Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment.
112 valueToHTML: function(value) {
113 var valueType = typeof value;
114 var output = "";
115 if (value === null) {
116 output += this.decorateWithSpan('null', 'null');
117 } else if (value && value.constructor === Array) {
118 output += this.arrayToHTML(value);
119 } else if (valueType === 'object') {
120 output += this.objectToHTML(value);
121 } else if (valueType === 'number') {
122 output += this.decorateWithSpan(value, 'num');
123 } else if (valueType === 'string') {
124 if (/^(http|https):\/\/[^\s]+$/.test(value)) {
125 output += '<a href="' + value + '">' + this.htmlEncode(value) + '</a>';
126 } else {
127 output += this.decorateWithSpan('"' + value + '"', 'string');
128 }
129 } else if (valueType === 'boolean') {
130 output += this.decorateWithSpan(value, 'bool');
131 }
132 return output;
133 },
134 // Convert an array into an HTML fragment
135 arrayToHTML: function(json) {
136 var output = '[<ul class="array collapsible">';
137 var hasContents = false;
138 for (var prop in json) {
139 hasContents = true;
140 output += '<li>';
141 output += this.valueToHTML(json[prop]);
142 output += '</li>';
143 }
144 output += '</ul>]';
145 if (!hasContents) {
146 output = "[ ]";
147 }
148 return output;
149 },
150 // Convert a JSON object to an HTML fragment
151 objectToHTML: function(json) {
152 var output = '{<ul class="obj collapsible">';
153 var hasContents = false;
154 for (var prop in json) {
155 hasContents = true;
156 output += '<li>';
157 output += '<span class="prop">' + this.htmlEncode(prop) + '</span>: ';
158 output += this.valueToHTML(json[prop]);
159 output += '</li>';
160 }
161 output += '</ul>}';
162 if (!hasContents) {
163 output = "{ }";
164 }
165 return output;
166 },
167 // Convert a whole JSON object into a formatted HTML document.
168 jsonToHTML: function(json, callback, uri) {
169 var output = '';
170 if (callback) {
171 output += '<div class="callback">' + callback + ' (</div>';
172 output += '<div id="json">';
173 } else {
174 output += '<div id="json">';
175 }
176 output += this.valueToHTML(json);
177 output += '</div>';
178 if (callback) {
179 output += '<div class="callback">)</div>';
180 }
181 return this.toHTML(output, uri);
182 },
183 // Produce an error document for when parsing fails.
184 errorPage: function(error, data, uri) {
185 // var output = '<div id="error">' + this.stringbundle.GetStringFromName('errorParsing') + '</div>';
186 // output += '<h1>' + this.stringbundle.GetStringFromName('docContents') + ':</h1>';
187 var output = '<div id="error">Error parsing JSON: ' + error.message + '</div>';
188 output += '<h1>' + error.stack + ':</h1>';
189 output += '<div id="json">' + this.htmlEncode(data) + '</div>';
190 return this.toHTML(output, uri + ' - Error');
191 },
192 // Wrap the HTML fragment in a full document. Used by jsonToHTML and errorPage.
193 toHTML: function(content) {
194 return content;
195 }
196 };
197 // Sanitize & output -- all magic from JSONView Firefox
198 this.jsonFormatter = new JSONFormatter();
199 // This regex attempts to match a JSONP structure:
200 // * Any amount of whitespace (including unicode nonbreaking spaces) between the start of the file and the callback name
201 // * Callback name (any valid JavaScript function name according to ECMA-262 Edition 3 spec)
202 // * Any amount of whitespace (including unicode nonbreaking spaces)
203 // * Open parentheses
204 // * Any amount of whitespace (including unicode nonbreaking spaces)
205 // * Either { or [, the only two valid characters to start a JSON string.
206 // * Any character, any number of times
207 // * Either } or ], the only two valid closing characters of a JSON string.
208 // * Any amount of whitespace (including unicode nonbreaking spaces)
209 // * A closing parenthesis, an optional semicolon, and any amount of whitespace (including unicode nonbreaking spaces) until the end of the file.
210 // This will miss anything that has comments, or more than one callback, or requires modification before use.
211 var outputDoc = '';
212 // text = text.match(jsonp_regex)[1];
213 var cleanData = '',
214 callback = '';
215 var callback_results = jsonp_regex.exec(this.data);
216 if (callback_results && callback_results.length === 3) {
217 if (this.debug) { console.log("THIS IS JSONp"); }
218 callback = callback_results[1];
219 cleanData = callback_results[2];
220 } else {
221 if (this.debug) { console.log("Vanilla JSON"); }
222 cleanData = this.data;
223 }
224 if (this.debug) { console.log(cleanData); }
225 // Covert, and catch exceptions on failure
226 try {
227 // var jsonObj = this.nativeJSON.decode(cleanData);
228 var jsonObj = JSON.parse(cleanData);
229 if (jsonObj) {
230 outputDoc = this.jsonFormatter.jsonToHTML(jsonObj, callback);
231 } else {
232 throw "There was no object!";
233 }
234 } catch (e) {
235 if (this.debug) { console.log(e); }
236 outputDoc = this.jsonFormatter.errorPage(e, this.data);
237 }
238 var links = '<style type="text/css">.jsonViewOutput .prop{font-weight:700;}.jsonViewOutput .null{color:red;}.jsonViewOutput .string{color:green;}.jsonViewOutput .collapser{position:absolute;left:-1em;cursor:pointer;}.jsonViewOutput li{position:relative;}.jsonViewOutput li:after{content:\',\';}.jsonViewOutput li:last-child:after{content:\'\';}.jsonViewOutput #error{-moz-border-radius:8px;border:1px solid #970000;background-color:#F7E8E8;margin:.5em;padding:.5em;}.jsonViewOutput .errormessage{font-family:monospace;}.jsonViewOutput #json{font-family:monospace;font-size:1.1em;}.jsonViewOutput ul{list-style:none;margin:0 0 0 2em;padding:0;}.jsonViewOutput h1{font-size:1.2em;}.jsonViewOutput .callback + #json{padding-left:1em;}.jsonViewOutput .callback{font-family:monospace;color:#A52A2A;}.jsonViewOutput .bool,.jsonViewOutput .num{color:blue;}</style>';
239 if (this.targetType !== undefined) {
240 this.idType = this.targetType;
241 this.id = this.target;
242 }
243 var el;
244 if (this.idType === "class") {
245 el = document.getElementsByClassName(this.id);
246 if (el) {
247 el.className += el.className ? ' jsonViewOutput' : 'jsonViewOutput';
248 el.innerHTML = links + outputDoc;
249 }
250 } else if (this.idType === "id") {
251 el = document.getElementById(this.id);
252 if (el) {
253 el.className += el.className ? ' jsonViewOutput' : 'jsonViewOutput';
254 el.innerHTML = links + outputDoc;
255 }
256 el.innerHTML = links + outputDoc;
257 }
258 var items = document.getElementsByClassName('collapsible');
259 for (var i = 0; i < items.length; i++) {
260 addCollapser(items[i].parentNode);
261 }
262 } else {
263 // console.log("JSONView: this is not json, not formatting.");
264 }
265 }