Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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