patchJSON();

(function($){$.toJSON=function(o)
{if(typeof(JSON)=='object'&&JSON.stringify)
return JSON.stringify(o);var type=typeof(o);if(o===null)
return"null";if(type=="undefined")
return undefined;if(type=="number"||type=="boolean")
return o+"";if(type=="string")
return $.quoteString(o);if(type=='object')
{if(typeof o.toJSON=="function")
return $.toJSON(o.toJSON());if(o.constructor===Date)
{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
if(o.constructor===Array)
{var ret=[];for(var i=0;i<o.length;i++)
ret.push($.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;if(typeof o[k]=="function")
continue;var val=$.toJSON(o[k]);pairs.push(name+":"+val);}
return"{"+pairs.join(", ")+"}";}};$.evalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
try { return JSON.parse(src); } catch(e) { }; try { return eval("("+src+")"); } catch(e) { };};$.secureEvalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};$.quoteString=function(string)
{if(string.match(_escapeable))
{return'"'+string.replace(_escapeable,function(a)
{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);

function patchJSON() {
     // Check if JSON exists, or if
     // JSON has already been patched or updated
     if ((!this.JSON) || (JSON.stringify(undefined) !== 'undefined'))
         return false;  //JSON has already been patched or updated;
     var builtinStringify = JSON.stringify;
     JSON.stringify = newStringify;

     // Date.prototype.toJSON returns null for Dates with a non finite value
     var origDateToJSON = Date.prototype.toJSON;
     if ((origDateToJSON.toString()) ===
     "\nfunction toJSON() {\n    [native code]\n}\n") {
         Date.prototype.toJSON = function(value) {
             if (isNaN(this.valueOf())) return null;
             else {
                return origDateToJSON.call(this, value);
            }
         }
     }
     return true;

     function newStringify(value, replacer, space) {

         // Return undefined when value parameter is undefined
         // or when toJSON exists and returns undefined
         if ((value === undefined) && !(replacer)) return undefined;
         if (value && typeof value === 'object' &&
                 typeof value.toJSON === 'function' &&
                 !replacer && value.toJSON("") === undefined)
             return undefined;

         // Return undefined when value paramenter is a function
         if ((typeof value === "function") && !(replacer)) return undefined;

         // Ignore the replacer and do not throw an error if the replacer
         // is not a function or array.
         if (replacer && (typeof replacer !== "function")
             && !(replacer instanceof Array))
             replacer = null;

         if (space !== undefined) {
             // Treat empty string as no space
             if (space === "") space = 0;
             else if (typeof space === "object") {
                 // If space is a Number object or String object
                 // use it's primitive value
                 if ((space instanceof Number) || (space instanceof String))
                     space = space.valueOf();
                 // Ignore objects other than Number and Strings
                 else space = 0;
             }
             // If space is set to a value greater than 10, space should be
             // defaulted to 10. If space is not integral, use the floor value
             // If space string has a length greater than 10,
             // space should be defaulted to first 10 characters
             if (typeof space === "number") space = Math.min(10,
                 Math.floor(Math.abs(space)));
             else if (typeof space === "string") {
                 if (space.length > 10)
                    space = space.slice(0, 10);
             }
             else space = 0;
         }

         // Return primitive number, string or boolean value stored
         // in the Number, String or Boolean object
         function newReplacer(key, value) {
             // Execute the replacerand get it's return value
             var tmpValue = replacer.call(this, key, value);
             // If value is a Number or String or Boolean object
             // use its primitive value
             if (typeof tmpValue === "object") {
                 if ((tmpValue instanceof Number) || (tmpValue instanceof String) ||
                 (tmpValue instanceof Boolean)) tmpValue = tmpValue.valueOf();
             }
             return tmpValue;
         }

         try {
             // Check if the replacer returns undefined or a function
             // If it does, return undefined
             var tmpValue = value;
             if (replacer && typeof replacer === "function") {
                 tmpValue = newReplacer.call({ "": tmpValue }, "", tmpValue);
                 if ((tmpValue === undefined) ||
                 (typeof tmpValue == 'function')) return undefined;
                 return builtinStringify(value, newReplacer, space);
             }
             else return builtinStringify(value, replacer, space);
         }
         // Throw a Type Error if value is a cyclic objects
         catch (e) {
             var replacementException = e;
             if (e.number === -2146823254) {
                replacementException = new TypeError();
                 replacementException.description = e.description;
                 replacementException.message = e.message;
                 replacementException.number = e.number;
             }
             throw replacementException;
         }
     }
}
