﻿(function($) { $.fn.customShow = function(speed, callback) { $(this).show(speed, function() { if (jQuery.browser.msie) $(this).get(0).style.removeAttribute('filter'); if (callback != undefined) callback(); }); }; $.fn.customHide = function(speed, callback) { $(this).hide(speed, function() { if (jQuery.browser.msie) $(this).get(0).style.removeAttribute('filter'); if (callback != undefined) callback(); }); }; })(jQuery);

/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Uses the built In easIng capabilities added In jQuery 1.1
* to offer multiple easIng options
*
* Copyright (c) 2007 George Smith
* Licensed under the MIT License:
*   http://www.opensource.org/licenses/mit-license.php
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend(jQuery.easing,
{
    def: 'easeOutQuad',
    swing: function(x, t, b, c, d) {
        //alert(jQuery.easing.default);
        return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
    },
    easeInQuad: function(x, t, b, c, d) {
        return c * (t /= d) * t + b;
    },
    easeOutQuad: function(x, t, b, c, d) {
        return -c * (t /= d) * (t - 2) + b;
    },
    easeInOutQuad: function(x, t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t + b;
        return -c / 2 * ((--t) * (t - 2) - 1) + b;
    },
    easeInCubic: function(x, t, b, c, d) {
        return c * (t /= d) * t * t + b;
    },
    easeOutCubic: function(x, t, b, c, d) {
        return c * ((t = t / d - 1) * t * t + 1) + b;
    },
    easeInOutCubic: function(x, t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
        return c / 2 * ((t -= 2) * t * t + 2) + b;
    },
    easeInQuart: function(x, t, b, c, d) {
        return c * (t /= d) * t * t * t + b;
    },
    easeOutQuart: function(x, t, b, c, d) {
        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
    },
    easeInOutQuart: function(x, t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
        return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
    },
    easeInQuint: function(x, t, b, c, d) {
        return c * (t /= d) * t * t * t * t + b;
    },
    easeOutQuint: function(x, t, b, c, d) {
        return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
    },
    easeInOutQuint: function(x, t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
        return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
    },
    easeInSine: function(x, t, b, c, d) {
        return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
    },
    easeOutSine: function(x, t, b, c, d) {
        return c * Math.sin(t / d * (Math.PI / 2)) + b;
    },
    easeInOutSine: function(x, t, b, c, d) {
        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
    },
    easeInExpo: function(x, t, b, c, d) {
        return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
    },
    easeOutExpo: function(x, t, b, c, d) {
        return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
    },
    easeInOutExpo: function(x, t, b, c, d) {
        if (t == 0) return b;
        if (t == d) return b + c;
        if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
        return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
    },
    easeInCirc: function(x, t, b, c, d) {
        return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
    },
    easeOutCirc: function(x, t, b, c, d) {
        return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
    },
    easeInOutCirc: function(x, t, b, c, d) {
        if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
        return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
    },
    easeInElastic: function(x, t, b, c, d) {
        var s = 1.70158; var p = 0; var a = c;
        if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3;
        if (a < Math.abs(c)) { a = c; var s = p / 4; }
        else var s = p / (2 * Math.PI) * Math.asin(c / a);
        return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    },
    easeOutElastic: function(x, t, b, c, d) {
        var s = 1.70158; var p = 0; var a = c;
        if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3;
        if (a < Math.abs(c)) { a = c; var s = p / 4; }
        else var s = p / (2 * Math.PI) * Math.asin(c / a);
        return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
    },
    easeInOutElastic: function(x, t, b, c, d) {
        var s = 1.70158; var p = 0; var a = c;
        if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5);
        if (a < Math.abs(c)) { a = c; var s = p / 4; }
        else var s = p / (2 * Math.PI) * Math.asin(c / a);
        if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
    },
    easeInBack: function(x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c * (t /= d) * t * ((s + 1) * t - s) + b;
    },
    easeOutBack: function(x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
    },
    easeInOutBack: function(x, t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
        return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
    },
    easeInBounce: function(x, t, b, c, d) {
        return c - jQuery.easing.easeOutBounce(x, d - t, 0, c, d) + b;
    },
    easeOutBounce: function(x, t, b, c, d) {
        if ((t /= d) < (1 / 2.75)) {
            return c * (7.5625 * t * t) + b;
        } else if (t < (2 / 2.75)) {
            return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
        } else if (t < (2.5 / 2.75)) {
            return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
        } else {
            return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
        }
    },
    easeInOutBounce: function(x, t, b, c, d) {
        if (t < d / 2) return jQuery.easing.easeInBounce(x, t * 2, 0, c, d) * .5 + b;
        return jQuery.easing.easeOutBounce(x, t * 2 - d, 0, c, d) * .5 + c * .5 + b;
    }
});

/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/

/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
*       used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
*                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
*                             If set to null or omitted, the cookie will be a session cookie and will not be retained
*                             when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
*                        require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/

/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};

/**
* Cornerz 0.6 - Bullet Proof Corners
* Jonah Fox (jonah@parkerfox.co.uk) 2008
* 
* Usage: $('.myclass').curve(options)
* options is a hash with the following parameters. Bracketed is the default
*   radius (10)
*   borderWidth (read from BorderTopWidth or 0)
*   background ("white"). Note that this is not calculated from the HTML as it is expensive
*   borderColor (read from BorderTopColor)
*   corners ("tl br tr bl"). Specify which borders
*   fixIE ("padding") - attmepts to fix IE by incrementing the property by 1 if the outer width/height is odd.

CHANGELIST from  v0.4

0.5 - Now attempts to fix the odd dimension problem in IE 
0.6 - Added semicolons for packing and fixed a problem with odd border width's in IE

*/

; (function($) {

    if ($.browser.msie && document.namespaces["v"] == null) {
        document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
        var ss = document.createStyleSheet().owningElement;
        ss.styleSheet.cssText = "v\\:*{behavior:url(#default#VML);}"
    }

    $.fn.cornerz = function(options) {

        function canvasCorner(t, l, r, bw, bc, bg) {
            var sa, ea, cw, sx, sy, x, y, p = 1.57, css = "position:absolute;";
            if (t)
            { sa = -p; sy = r; y = 0; css += "top:-" + bw + "px;"; }
            else
            { sa = p; sy = 0; y = r; css += "bottom:-" + bw + "px;"; }
            if (l)
            { ea = p * 2; sx = r; x = 0; css += "left:-" + bw + "px;" }
            else
            { ea = 0; sx = 0; x = r; css += "right:-" + bw + "px;"; }

            var canvas = $("<canvas width=" + r + "px height=" + r + "px style='" + css + "' ></canvas>");
            var ctx = canvas[0].getContext('2d');
            ctx.beginPath();
            ctx.lineWidth = bw * 2;
            ctx.arc(sx, sy, r, sa, ea, !(t ^ l));
            ctx.strokeStyle = bc;
            ctx.stroke();
            ctx.lineWidth = 0;
            ctx.lineTo(x, y);
            ctx.fillStyle = bg;
            ctx.fill();
            return canvas;
        };

        function canvasCorners(corners, r, bw, bc, bg) {
            var hh = $("<div style='display: inherit' />"); // trying out style='float:left' 
            $.each(corners.split(" "), function() {
                hh.append(canvasCorner(this[0] == "t", this[1] == "l", r, bw, bc, bg));
            });
            return hh;
        };

        function vmlCurve(r, b, c, m, ml, mt, right_fix) {
            var l = m - ml - right_fix;
            var t = m - mt;
            return "<v:arc filled='False' strokeweight='" + b + "px' strokecolor='" + c + "' startangle='0' endangle='361' style=' top:" + t + "px;left: " + l + ";width:" + r + "px; height:" + r + "px' />";
        }


        function vmlCorners(corners, r, bw, bc, bg, w) {
            var h = "<div style='text-align:left; '>";
            $.each($.trim(corners).split(" "), function() {
                var css, ml = 1, mt = 1, right_fix = 0;
                if (this.charAt(0) == "t") {
                    css = "top:-" + bw + "px;";
                }
                else {
                    css = "bottom:-" + bw + "px;";
                    mt = r + 1;
                }
                if (this.charAt(1) == "l")
                    css += "left:-" + bw + "px;";
                else {
                    css += "right:-" + (bw) + "px; "; // odd width gives wrong margin?
                    ml = r;
                    right_fix = 1;
                }

                h += "<div style='" + css + "; position: absolute; overflow:hidden; width:" + r + "px; height: " + r + "px;'>";
                h += "<v:group  style='width:1000px;height:1000px;position:absolute;' coordsize='1000,1000' >";
                h += vmlCurve(r * 3, r + bw, bg, -r / 2, ml, mt, right_fix);
                if (bw > 0)
                    h += vmlCurve(r * 2 - bw, bw, bc, Math.floor(bw / 2 + 0.5), ml, mt, right_fix);
                h += "</v:group>";
                h += "</div>";
            });
            h += "</div>";

            return h;
        };

        var settings = {
            corners: "tl tr bl br",
            radius: 10,
            background: "white",
            borderWidth: 0,
            fixIE: true
        };
        $.extend(settings, options || {});

        var incrementProperty = function(elem, prop, x) {
            var y = parseInt(elem.css(prop)) || 0;
            elem.css(prop, x + y);
        }


        return this.each(function() {

            var $$ = $(this);
            var r = settings.radius * 1.0;
            var bw = (settings.borderWidth || parseInt($$.css("borderTopWidth")) || 0) * 1.0;
            var bg = settings.background;
            var bc = settings.borderColor;
            bc = bc || (bw > 0 ? $$.css("borderTopColor") : bg);

            var cs = settings.corners;

            if ($.browser.msie) {//need to use innerHTML rather than jQuery
                h = vmlCorners(cs, r, bw, bc, bg, $(this).width());
                this.innerHTML += h;

            }
            else  //canvasCorners returns a DOM element
                $$.append(canvasCorners(cs, r, bw, bc, bg));


            if (this.style.position != "absolute")
                this.style.position = "relative";

            this.style.zoom = 1; // give it a layout in IE

            if ($.browser.msie && settings.fixIE) {
                var ow = $$.outerWidth();
                var oh = $$.outerHeight();

                if (ow % 2 == 1) {
                    incrementProperty($$, "padding-right", 1);
                    incrementProperty($$, "margin-right", 1);
                }

                if (oh % 2 == 1) {
                    incrementProperty($$, "padding-bottom", 1);
                    incrementProperty($$, "margin-bottom", 1);
                }
            }

        }

    );

    }
})(jQuery);

/*
json.js

Public Domain
    
The global object JSON contains three methods.

JSON.stringify(value) takes a JavaScript value and produces a JSON 
text. The value must not be cyclical.

JSON.parse(text) takes a JSON text and produces a JavaScript value. 
It will throw SyntaxError if there is an error in parsing the JSON
text. This method is fully JavaScript-based and therefore can be
several magnitudes slower than JSON.eval. However, it is also more
permissive than JSON.eval. For example, JSON.parse permits use of
JavaScript-style comments in JSON text.

JSON.eval(text) takes a JSON text and produces a JavaScript value.
It will throw SyntaxError if there is an error in parsing the JSON
text. JSON.eval is much faster (as it internally relies on the 
JavaScript eval method after making safety checks) and stricter in 
complaince to JSON text.
    
NOTE: This implementation is hand-synchronized with the reference 
implementation available over at http://www.json.org/json.js.
*/

/*jslint evil: true */

var JSON = function() {
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        meta = {   // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"': '\\"',
            '\\': '\\\\'
        },
        s = {
            'boolean': function(x) {
                return String(x);
            },
            number: function(x) {
                return isFinite(x) ? String(x) : 'null';
            },
            string: function(x) {
                // If the string contains no control characters, no quote 
                // characters, and no backslash characters, then we can 
                // simply slap some quotes around it. Otherwise we must 
                // also replace the offending characters with safe
                // sequences.
                return escapeable.test(x) ?
                    '"' + x.replace(escapeable, function(a) {
                        var c = meta[a];
                        if (typeof c === 'string') {
                            return c;
                        }
                        return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                    }) + '"' :
                    '"' + x + '"';
            },
            object: function(x) {
                function p(n) {
                    // Format integers to have at least two digits.
                    return n < 10 ? '0' + n : n;
                }
                if (x) {
                    var a = [], b, f, i, l, v;
                    if (x instanceof Array) {
                        a[0] = '[';
                        l = x.length;
                        for (i = 0; i < l; i += 1) {
                            v = x[i];
                            f = s[typeof v];
                            if (f) {
                                v = f(v);
                                if (typeof v === 'string') {
                                    if (b) {
                                        a[a.length] = ',';
                                    }
                                    a[a.length] = v;
                                    b = true;
                                }
                            }
                        }
                        a[a.length] = ']';
                    } else if (x instanceof Date) {
                        var tz = x.getTimezoneOffset();
                        if (tz !== 0) {
                            var tzh = Math.floor(Math.abs(tz) / 60);
                            var tzm = Math.abs(tz) % 60;
                            tz = (tz < 0 ? '+' : '-') + p(tzh) + ':' + p(tzm);
                        }
                        else {
                            tz = 'Z';
                        }
                        return '"' +
                                x.getFullYear() + '-' +
                                p(x.getMonth() + 1) + '-' +
                                p(x.getDate()) + 'T' +
                                p(x.getHours()) + ':' +
                                p(x.getMinutes()) + ':' +
                                p(x.getSeconds()) + tz + '"';
                    } else if (x instanceof Object) {
                        a[0] = '{';
                        // Iterate through all of the keys in the 
                        // object, ignoring the proto chain and keys 
                        // that are not strings.
                        for (i in x) {
                            if (typeof i === 'string' &&
                                Object.prototype.hasOwnProperty.apply(x, [i])) {
                                v = x[i];
                                f = s[typeof v];
                                if (f) {
                                    v = f(v);
                                    if (typeof v === 'string') {
                                        if (b) {
                                            a[a.length] = ',';
                                        }
                                        a.push(s.string(i), ':', v);
                                        b = true;
                                    }
                                }
                            }
                        }
                        a[a.length] = '}';
                    } else {
                        return;
                    }
                    return a.join('');
                }
                return 'null';
            }
        };
    return {
        copyright: '(c)2005 JSON.org',
        license: 'http://www.crockford.com/JSON/license.html',
        /*
        Stringify a JavaScript value, producing a JSON text.
        */
        stringify: function(v) {
            var f = s[typeof v];
            if (f) {
                v = f(v);
                if (typeof v === 'string') {
                    return v;
                }
            }
            return null;
        },
        /*
        Parse a JSON text, producing a JavaScript value.
        If the text is not JSON parseable, then a SyntaxError is thrown.
        */
        'eval': function(text, reviver) {

            // The walk method is used to recursively walk the resulting structure so
            // that modifications can be made.

            function walk(holder, key) {
                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }

            // Parsing happens in three stages. In the first stage, we replace certain
            // Unicode characters with escape sequences. JavaScript handles many characters
            // incorrectly, either silently deleting them, or treating them as line endings.

            if (cx.test(text)) {
                text = text.replace(cx, function(a) {
                    return '\\u' +
                            ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

            // In the second stage, we run the text against
            // regular expressions that look for non-JSON patterns. We are especially
            // concerned with '()' and 'new' because they can cause invocation, and '='
            // because it can cause mutation. But just to be safe, we want to reject all
            // unexpected forms.

            // We split the second stage into 4 regexp operations in order to work around
            // crippling inefficiencies in IE's and Safari's regexp engines. First we
            // replace all backslash pairs with '@' (a non-JSON character). Second, we
            // replace all simple value tokens with ']' characters. Third, we delete all
            // open brackets that follow a colon or comma or that begin the text. Finally,
            // we look to see that the remaining characters are only whitespace or ']' or
            // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (!/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
                replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
                replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                throw new SyntaxError("eval");
            }

            // In the third stage we use the eval function to compile the text into a
            // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
            // in JavaScript: it can begin a block or an object literal. We wrap the text
            // in parens to eliminate the ambiguity.

            var result = eval('(' + text + ')');

            // In the optional fourth stage, we recursively walk the new structure, passing
            // each name/value pair to a reviver function for possible transformation.

            return typeof reviver === 'function' ?
                walk({ '': result }, '') : result;
        },

        parse: function(text) {
            var at = 0,     // The index of the current character
                ch = ' ',   // The current character
                result,     // The final result
                value;      // The value function

            function error(m) {
                var e = new SyntaxError(m);
                e.at = at - 1;
                e.text = text;
                throw e;
            }

            function next() {
                ch = text.charAt(at);
                at += 1;
                return ch;
            }

            function white() {
                while (ch) {
                    if (ch <= ' ') {
                        next();
                    } else if (ch === '/') {
                        switch (next()) {
                            case '/':
                                while (next() && ch !== '\n' && ch !== '\r') { }
                                break;
                            case '*':
                                next();
                                for (; ; ) {
                                    if (ch) {
                                        if (ch === '*') {
                                            if (next() === '/') {
                                                next();
                                                break;
                                            }
                                        } else {
                                            next();
                                        }
                                    } else {
                                        error("Unterminated comment");
                                    }
                                }
                                break;
                            default:
                                error("Syntax error");
                        }
                    } else {
                        break;
                    }
                }
            }

            function string() {
                var i, s = '', t, u;

                if (ch === '"') {
                    outer: while (next()) {
                        if (ch === '"') {
                            next();
                            return s;
                        } else if (ch === '\\') {
                            switch (next()) {
                                case 'b':
                                    s += '\b';
                                    break;
                                case 'f':
                                    s += '\f';
                                    break;
                                case 'n':
                                    s += '\n';
                                    break;
                                case 'r':
                                    s += '\r';
                                    break;
                                case 't':
                                    s += '\t';
                                    break;
                                case 'u':
                                    u = 0;
                                    for (i = 0; i < 4; i += 1) {
                                        t = parseInt(next(), 16);
                                        if (!isFinite(t)) {
                                            break outer;
                                        }
                                        u = u * 16 + t;
                                    }
                                    s += String.fromCharCode(u);
                                    break;
                                default:
                                    s += ch;
                            }
                        } else {
                            s += ch;
                        }
                    }
                }
                error("Bad string");
            }

            function array() {
                var a = [];

                if (ch === '[') {
                    next();
                    white();
                    if (ch === ']') {
                        next();
                        return a;
                    }
                    while (ch) {
                        a.push(value());
                        white();
                        if (ch === ']') {
                            next();
                            return a;
                        } else if (ch !== ',') {
                            break;
                        }
                        next();
                        white();
                    }
                }
                error("Bad array");
            }

            function object() {
                var k, o = {};

                if (ch === '{') {
                    next();
                    white();
                    if (ch === '}') {
                        next();
                        return o;
                    }
                    while (ch) {
                        k = string();
                        white();
                        if (ch !== ':') {
                            break;
                        }
                        next();
                        o[k] = value();
                        white();
                        if (ch === '}') {
                            next();
                            return o;
                        } else if (ch !== ',') {
                            break;
                        }
                        next();
                        white();
                    }
                }
                error("Bad object");
            }

            function number() {
                var n = '', v;
                if (ch === '-') {
                    n = '-';
                    next();
                }
                while (ch >= '0' && ch <= '9') {
                    n += ch;
                    next();
                }
                if (ch === '.') {
                    n += '.';
                    while (next() && ch >= '0' && ch <= '9') {
                        n += ch;
                    }
                }
                if (ch === 'e' || ch === 'E') {
                    n += 'e';
                    next();
                    if (ch === '-' || ch === '+') {
                        n += ch;
                        next();
                    }
                    while (ch >= '0' && ch <= '9') {
                        n += ch;
                        next();
                    }
                }
                v = +n;
                if (!isFinite(v)) {
                    ////error("Bad number");
                } else {
                    return v;
                }
            }

            function word() {
                switch (ch) {
                    case 't':
                        if (next() === 'r' && next() === 'u' && next() === 'e') {
                            next();
                            return true;
                        }
                        break;
                    case 'f':
                        if (next() === 'a' && next() === 'l' && next() === 's' &&
                                next() === 'e') {
                            next();
                            return false;
                        }
                        break;
                    case 'n':
                        if (next() === 'u' && next() === 'l' && next() === 'l') {
                            next();
                            return null;
                        }
                        break;
                }
                error("Syntax error");
            }

            value = function() {
                white();
                switch (ch) {
                    case '{':
                        return object();
                    case '[':
                        return array();
                    case '"':
                        return string();
                    case '-':
                        return number();
                    default:
                        return ch >= '0' && ch <= '9' ? number() : word();
                }
            };

            result = value();
            white();
            if (ch) {
                error("Syntax error");
            }
            return result;
        }
    };
} ();

