Mercurial > hg > isophonics-drupal-site
comparison libraries/json2/json2.js @ 5:c69a71b4f40f
Add slideshow module
author | Chris Cannam |
---|---|
date | Thu, 07 Dec 2017 14:46:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:8948ab6c87d2 | 5:c69a71b4f40f |
---|---|
1 // json2.js | |
2 // 2016-10-28 | |
3 // Public Domain. | |
4 // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |
5 // See http://www.JSON.org/js.html | |
6 // This code should be minified before deployment. | |
7 // See http://javascript.crockford.com/jsmin.html | |
8 | |
9 // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO | |
10 // NOT CONTROL. | |
11 | |
12 // This file creates a global JSON object containing two methods: stringify | |
13 // and parse. This file provides the ES5 JSON capability to ES3 systems. | |
14 // If a project might run on IE8 or earlier, then this file should be included. | |
15 // This file does nothing on ES5 systems. | |
16 | |
17 // JSON.stringify(value, replacer, space) | |
18 // value any JavaScript value, usually an object or array. | |
19 // replacer an optional parameter that determines how object | |
20 // values are stringified for objects. It can be a | |
21 // function or an array of strings. | |
22 // space an optional parameter that specifies the indentation | |
23 // of nested structures. If it is omitted, the text will | |
24 // be packed without extra whitespace. If it is a number, | |
25 // it will specify the number of spaces to indent at each | |
26 // level. If it is a string (such as "\t" or " "), | |
27 // it contains the characters used to indent at each level. | |
28 // This method produces a JSON text from a JavaScript value. | |
29 // When an object value is found, if the object contains a toJSON | |
30 // method, its toJSON method will be called and the result will be | |
31 // stringified. A toJSON method does not serialize: it returns the | |
32 // value represented by the name/value pair that should be serialized, | |
33 // or undefined if nothing should be serialized. The toJSON method | |
34 // will be passed the key associated with the value, and this will be | |
35 // bound to the value. | |
36 | |
37 // For example, this would serialize Dates as ISO strings. | |
38 | |
39 // Date.prototype.toJSON = function (key) { | |
40 // function f(n) { | |
41 // // Format integers to have at least two digits. | |
42 // return (n < 10) | |
43 // ? "0" + n | |
44 // : n; | |
45 // } | |
46 // return this.getUTCFullYear() + "-" + | |
47 // f(this.getUTCMonth() + 1) + "-" + | |
48 // f(this.getUTCDate()) + "T" + | |
49 // f(this.getUTCHours()) + ":" + | |
50 // f(this.getUTCMinutes()) + ":" + | |
51 // f(this.getUTCSeconds()) + "Z"; | |
52 // }; | |
53 | |
54 // You can provide an optional replacer method. It will be passed the | |
55 // key and value of each member, with this bound to the containing | |
56 // object. The value that is returned from your method will be | |
57 // serialized. If your method returns undefined, then the member will | |
58 // be excluded from the serialization. | |
59 | |
60 // If the replacer parameter is an array of strings, then it will be | |
61 // used to select the members to be serialized. It filters the results | |
62 // such that only members with keys listed in the replacer array are | |
63 // stringified. | |
64 | |
65 // Values that do not have JSON representations, such as undefined or | |
66 // functions, will not be serialized. Such values in objects will be | |
67 // dropped; in arrays they will be replaced with null. You can use | |
68 // a replacer function to replace those with JSON values. | |
69 | |
70 // JSON.stringify(undefined) returns undefined. | |
71 | |
72 // The optional space parameter produces a stringification of the | |
73 // value that is filled with line breaks and indentation to make it | |
74 // easier to read. | |
75 | |
76 // If the space parameter is a non-empty string, then that string will | |
77 // be used for indentation. If the space parameter is a number, then | |
78 // the indentation will be that many spaces. | |
79 | |
80 // Example: | |
81 | |
82 // text = JSON.stringify(["e", {pluribus: "unum"}]); | |
83 // // text is '["e",{"pluribus":"unum"}]' | |
84 | |
85 // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t"); | |
86 // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' | |
87 | |
88 // text = JSON.stringify([new Date()], function (key, value) { | |
89 // return this[key] instanceof Date | |
90 // ? "Date(" + this[key] + ")" | |
91 // : value; | |
92 // }); | |
93 // // text is '["Date(---current time---)"]' | |
94 | |
95 // JSON.parse(text, reviver) | |
96 // This method parses a JSON text to produce an object or array. | |
97 // It can throw a SyntaxError exception. | |
98 | |
99 // The optional reviver parameter is a function that can filter and | |
100 // transform the results. It receives each of the keys and values, | |
101 // and its return value is used instead of the original value. | |
102 // If it returns what it received, then the structure is not modified. | |
103 // If it returns undefined then the member is deleted. | |
104 | |
105 // Example: | |
106 | |
107 // // Parse the text. Values that look like ISO date strings will | |
108 // // be converted to Date objects. | |
109 | |
110 // myData = JSON.parse(text, function (key, value) { | |
111 // var a; | |
112 // if (typeof value === "string") { | |
113 // a = | |
114 // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); | |
115 // if (a) { | |
116 // return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], | |
117 // +a[5], +a[6])); | |
118 // } | |
119 // } | |
120 // return value; | |
121 // }); | |
122 | |
123 // myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { | |
124 // var d; | |
125 // if (typeof value === "string" && | |
126 // value.slice(0, 5) === "Date(" && | |
127 // value.slice(-1) === ")") { | |
128 // d = new Date(value.slice(5, -1)); | |
129 // if (d) { | |
130 // return d; | |
131 // } | |
132 // } | |
133 // return value; | |
134 // }); | |
135 | |
136 // This is a reference implementation. You are free to copy, modify, or | |
137 // redistribute. | |
138 | |
139 /*jslint | |
140 eval, for, this | |
141 */ | |
142 | |
143 /*property | |
144 JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, | |
145 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, | |
146 lastIndex, length, parse, prototype, push, replace, slice, stringify, | |
147 test, toJSON, toString, valueOf | |
148 */ | |
149 | |
150 | |
151 // Create a JSON object only if one does not already exist. We create the | |
152 // methods in a closure to avoid creating global variables. | |
153 | |
154 if (typeof JSON !== "object") { | |
155 JSON = {}; | |
156 } | |
157 | |
158 (function () { | |
159 "use strict"; | |
160 | |
161 var rx_one = /^[\],:{}\s]*$/; | |
162 var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; | |
163 var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; | |
164 var rx_four = /(?:^|:|,)(?:\s*\[)+/g; | |
165 var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | |
166 var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; | |
167 | |
168 function f(n) { | |
169 // Format integers to have at least two digits. | |
170 return n < 10 | |
171 ? "0" + n | |
172 : n; | |
173 } | |
174 | |
175 function this_value() { | |
176 return this.valueOf(); | |
177 } | |
178 | |
179 if (typeof Date.prototype.toJSON !== "function") { | |
180 | |
181 Date.prototype.toJSON = function () { | |
182 | |
183 return isFinite(this.valueOf()) | |
184 ? this.getUTCFullYear() + "-" + | |
185 f(this.getUTCMonth() + 1) + "-" + | |
186 f(this.getUTCDate()) + "T" + | |
187 f(this.getUTCHours()) + ":" + | |
188 f(this.getUTCMinutes()) + ":" + | |
189 f(this.getUTCSeconds()) + "Z" | |
190 : null; | |
191 }; | |
192 | |
193 Boolean.prototype.toJSON = this_value; | |
194 Number.prototype.toJSON = this_value; | |
195 String.prototype.toJSON = this_value; | |
196 } | |
197 | |
198 var gap; | |
199 var indent; | |
200 var meta; | |
201 var rep; | |
202 | |
203 | |
204 function quote(string) { | |
205 | |
206 // If the string contains no control characters, no quote characters, and no | |
207 // backslash characters, then we can safely slap some quotes around it. | |
208 // Otherwise we must also replace the offending characters with safe escape | |
209 // sequences. | |
210 | |
211 rx_escapable.lastIndex = 0; | |
212 return rx_escapable.test(string) | |
213 ? "\"" + string.replace(rx_escapable, function (a) { | |
214 var c = meta[a]; | |
215 return typeof c === "string" | |
216 ? c | |
217 : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); | |
218 }) + "\"" | |
219 : "\"" + string + "\""; | |
220 } | |
221 | |
222 | |
223 function str(key, holder) { | |
224 | |
225 // Produce a string from holder[key]. | |
226 | |
227 var i; // The loop counter. | |
228 var k; // The member key. | |
229 var v; // The member value. | |
230 var length; | |
231 var mind = gap; | |
232 var partial; | |
233 var value = holder[key]; | |
234 | |
235 // If the value has a toJSON method, call it to obtain a replacement value. | |
236 | |
237 if (value && typeof value === "object" && | |
238 typeof value.toJSON === "function") { | |
239 value = value.toJSON(key); | |
240 } | |
241 | |
242 // If we were called with a replacer function, then call the replacer to | |
243 // obtain a replacement value. | |
244 | |
245 if (typeof rep === "function") { | |
246 value = rep.call(holder, key, value); | |
247 } | |
248 | |
249 // What happens next depends on the value's type. | |
250 | |
251 switch (typeof value) { | |
252 case "string": | |
253 return quote(value); | |
254 | |
255 case "number": | |
256 | |
257 // JSON numbers must be finite. Encode non-finite numbers as null. | |
258 | |
259 return isFinite(value) | |
260 ? String(value) | |
261 : "null"; | |
262 | |
263 case "boolean": | |
264 case "null": | |
265 | |
266 // If the value is a boolean or null, convert it to a string. Note: | |
267 // typeof null does not produce "null". The case is included here in | |
268 // the remote chance that this gets fixed someday. | |
269 | |
270 return String(value); | |
271 | |
272 // If the type is "object", we might be dealing with an object or an array or | |
273 // null. | |
274 | |
275 case "object": | |
276 | |
277 // Due to a specification blunder in ECMAScript, typeof null is "object", | |
278 // so watch out for that case. | |
279 | |
280 if (!value) { | |
281 return "null"; | |
282 } | |
283 | |
284 // Make an array to hold the partial results of stringifying this object value. | |
285 | |
286 gap += indent; | |
287 partial = []; | |
288 | |
289 // Is the value an array? | |
290 | |
291 if (Object.prototype.toString.apply(value) === "[object Array]") { | |
292 | |
293 // The value is an array. Stringify every element. Use null as a placeholder | |
294 // for non-JSON values. | |
295 | |
296 length = value.length; | |
297 for (i = 0; i < length; i += 1) { | |
298 partial[i] = str(i, value) || "null"; | |
299 } | |
300 | |
301 // Join all of the elements together, separated with commas, and wrap them in | |
302 // brackets. | |
303 | |
304 v = partial.length === 0 | |
305 ? "[]" | |
306 : gap | |
307 ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" | |
308 : "[" + partial.join(",") + "]"; | |
309 gap = mind; | |
310 return v; | |
311 } | |
312 | |
313 // If the replacer is an array, use it to select the members to be stringified. | |
314 | |
315 if (rep && typeof rep === "object") { | |
316 length = rep.length; | |
317 for (i = 0; i < length; i += 1) { | |
318 if (typeof rep[i] === "string") { | |
319 k = rep[i]; | |
320 v = str(k, value); | |
321 if (v) { | |
322 partial.push(quote(k) + ( | |
323 gap | |
324 ? ": " | |
325 : ":" | |
326 ) + v); | |
327 } | |
328 } | |
329 } | |
330 } else { | |
331 | |
332 // Otherwise, iterate through all of the keys in the object. | |
333 | |
334 for (k in value) { | |
335 if (Object.prototype.hasOwnProperty.call(value, k)) { | |
336 v = str(k, value); | |
337 if (v) { | |
338 partial.push(quote(k) + ( | |
339 gap | |
340 ? ": " | |
341 : ":" | |
342 ) + v); | |
343 } | |
344 } | |
345 } | |
346 } | |
347 | |
348 // Join all of the member texts together, separated with commas, | |
349 // and wrap them in braces. | |
350 | |
351 v = partial.length === 0 | |
352 ? "{}" | |
353 : gap | |
354 ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" | |
355 : "{" + partial.join(",") + "}"; | |
356 gap = mind; | |
357 return v; | |
358 } | |
359 } | |
360 | |
361 // If the JSON object does not yet have a stringify method, give it one. | |
362 | |
363 if (typeof JSON.stringify !== "function") { | |
364 meta = { // table of character substitutions | |
365 "\b": "\\b", | |
366 "\t": "\\t", | |
367 "\n": "\\n", | |
368 "\f": "\\f", | |
369 "\r": "\\r", | |
370 "\"": "\\\"", | |
371 "\\": "\\\\" | |
372 }; | |
373 JSON.stringify = function (value, replacer, space) { | |
374 | |
375 // The stringify method takes a value and an optional replacer, and an optional | |
376 // space parameter, and returns a JSON text. The replacer can be a function | |
377 // that can replace values, or an array of strings that will select the keys. | |
378 // A default replacer method can be provided. Use of the space parameter can | |
379 // produce text that is more easily readable. | |
380 | |
381 var i; | |
382 gap = ""; | |
383 indent = ""; | |
384 | |
385 // If the space parameter is a number, make an indent string containing that | |
386 // many spaces. | |
387 | |
388 if (typeof space === "number") { | |
389 for (i = 0; i < space; i += 1) { | |
390 indent += " "; | |
391 } | |
392 | |
393 // If the space parameter is a string, it will be used as the indent string. | |
394 | |
395 } else if (typeof space === "string") { | |
396 indent = space; | |
397 } | |
398 | |
399 // If there is a replacer, it must be a function or an array. | |
400 // Otherwise, throw an error. | |
401 | |
402 rep = replacer; | |
403 if (replacer && typeof replacer !== "function" && | |
404 (typeof replacer !== "object" || | |
405 typeof replacer.length !== "number")) { | |
406 throw new Error("JSON.stringify"); | |
407 } | |
408 | |
409 // Make a fake root object containing our value under the key of "". | |
410 // Return the result of stringifying the value. | |
411 | |
412 return str("", {"": value}); | |
413 }; | |
414 } | |
415 | |
416 | |
417 // If the JSON object does not yet have a parse method, give it one. | |
418 | |
419 if (typeof JSON.parse !== "function") { | |
420 JSON.parse = function (text, reviver) { | |
421 | |
422 // The parse method takes a text and an optional reviver function, and returns | |
423 // a JavaScript value if the text is a valid JSON text. | |
424 | |
425 var j; | |
426 | |
427 function walk(holder, key) { | |
428 | |
429 // The walk method is used to recursively walk the resulting structure so | |
430 // that modifications can be made. | |
431 | |
432 var k; | |
433 var v; | |
434 var value = holder[key]; | |
435 if (value && typeof value === "object") { | |
436 for (k in value) { | |
437 if (Object.prototype.hasOwnProperty.call(value, k)) { | |
438 v = walk(value, k); | |
439 if (v !== undefined) { | |
440 value[k] = v; | |
441 } else { | |
442 delete value[k]; | |
443 } | |
444 } | |
445 } | |
446 } | |
447 return reviver.call(holder, key, value); | |
448 } | |
449 | |
450 | |
451 // Parsing happens in four stages. In the first stage, we replace certain | |
452 // Unicode characters with escape sequences. JavaScript handles many characters | |
453 // incorrectly, either silently deleting them, or treating them as line endings. | |
454 | |
455 text = String(text); | |
456 rx_dangerous.lastIndex = 0; | |
457 if (rx_dangerous.test(text)) { | |
458 text = text.replace(rx_dangerous, function (a) { | |
459 return "\\u" + | |
460 ("0000" + a.charCodeAt(0).toString(16)).slice(-4); | |
461 }); | |
462 } | |
463 | |
464 // In the second stage, we run the text against regular expressions that look | |
465 // for non-JSON patterns. We are especially concerned with "()" and "new" | |
466 // because they can cause invocation, and "=" because it can cause mutation. | |
467 // But just to be safe, we want to reject all unexpected forms. | |
468 | |
469 // We split the second stage into 4 regexp operations in order to work around | |
470 // crippling inefficiencies in IE's and Safari's regexp engines. First we | |
471 // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we | |
472 // replace all simple value tokens with "]" characters. Third, we delete all | |
473 // open brackets that follow a colon or comma or that begin the text. Finally, | |
474 // we look to see that the remaining characters are only whitespace or "]" or | |
475 // "," or ":" or "{" or "}". If that is so, then the text is safe for eval. | |
476 | |
477 if ( | |
478 rx_one.test( | |
479 text | |
480 .replace(rx_two, "@") | |
481 .replace(rx_three, "]") | |
482 .replace(rx_four, "") | |
483 ) | |
484 ) { | |
485 | |
486 // In the third stage we use the eval function to compile the text into a | |
487 // JavaScript structure. The "{" operator is subject to a syntactic ambiguity | |
488 // in JavaScript: it can begin a block or an object literal. We wrap the text | |
489 // in parens to eliminate the ambiguity. | |
490 | |
491 j = eval("(" + text + ")"); | |
492 | |
493 // In the optional fourth stage, we recursively walk the new structure, passing | |
494 // each name/value pair to a reviver function for possible transformation. | |
495 | |
496 return (typeof reviver === "function") | |
497 ? walk({"": j}, "") | |
498 : j; | |
499 } | |
500 | |
501 // If the text is not JSON parseable, then a SyntaxError is thrown. | |
502 | |
503 throw new SyntaxError("JSON.parse"); | |
504 }; | |
505 } | |
506 }()); |