changeset 90:08f93d043ed2 laserkard

saving progress
author Robert McIntyre <rlm@mit.edu>
date Mon, 26 Jul 2010 04:13:05 -0400
parents 7d6514aca622
children 0dd39631299c
files buy3.html css/buy3.css js-lib/buy3.js js-lib/json2.js
diffstat 4 files changed, 598 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/buy3.html	Mon Jul 26 02:22:46 2010 -0400
     1.2 +++ b/buy3.html	Mon Jul 26 04:13:05 2010 -0400
     1.3 @@ -6,6 +6,9 @@
     1.4      <script type="text/javascript" src="awesome_js/cufon-yui.js"></script>
     1.5      <script type="text/javascript" src="js-lib/HeleveticaNeue.font.js"></script>
     1.6      <script type="text/javascript" src="js-lib/buy3.js"></script>
     1.7 +    <script type="text/javascript" src="js-lib/json2.js"></script>
     1.8 +
     1.9 +
    1.10    </head>
    1.11    <body>
    1.12      <div id="color-select"></div>
     2.1 --- a/css/buy3.css	Mon Jul 26 02:22:46 2010 -0400
     2.2 +++ b/css/buy3.css	Mon Jul 26 04:13:05 2010 -0400
     2.3 @@ -1,1 +1,13 @@
     2.4 - 
     2.5 +div#debug {
     2.6 +    position: absolute;
     2.7 +    top:5%;
     2.8 +    right:10%;
     2.9 +    width: 450px;
    2.10 +    border-color:#DD7777;
    2.11 +    border-width:2px;
    2.12 +    background-color:#bf3f9b;
    2.13 +    font: bold 15px "helvetica","arial", "sans-serif";
    2.14 +    color: white;
    2.15 +    height: 200px;
    2.16 +
    2.17 +}
     3.1 --- a/js-lib/buy3.js	Mon Jul 26 02:22:46 2010 -0400
     3.2 +++ b/js-lib/buy3.js	Mon Jul 26 04:13:05 2010 -0400
     3.3 @@ -1,4 +1,7 @@
     3.4  Buy = (function (){ 
     3.5 +
     3.6 +
     3.7 +    //Initilization Functions.
     3.8      var order = 
     3.9  	{color: "red",
    3.10  	 style: "bold",
    3.11 @@ -10,94 +13,123 @@
    3.12      var color;
    3.13      var style;
    3.14      
    3.15 -    //  var select_green;
    3.16 -    //var select_red;
    3.17 -    //var select_blue;
    3.18 -    //var select_black;
    3.19 +  // var state_map = 
    3.20 +  // 	{green :{
    3.21 +  // 	    ref: null,
    3.22 +  // 	    offState : null, 
    3.23 +  // 	    onState : null},
    3.24 +  // 	 red : {
    3.25 +  // 	     offState: {"fill" : "#300", "scale" : 1},
    3.26 +  // 	     onState : {"fill" : "#F00" ,"scale" : 1}, 
    3.27 +  // 	     ref    : null},
    3.28 +  // 	 blue  : {
    3.29 +  // 	     offState : null, 
    3.30 +  // 	     onState : null, 
    3.31 +  // 	     ref : null},
    3.32 +  // 	 black : {offState : null, onState : null, ref : null},
    3.33 +  // 	 display : {ref : null, state : {"fill" : "black"}}};
    3.34 +
    3.35 +    var state_map = 
    3.36 +	{green : {  ref: null, offState : null, onState : null},
    3.37 +	 red : {
    3.38 +	     offState: {"fill" : "#300", "scale" : 1},
    3.39 +	     onState : {"fill" : "#F00" ,"scale" : 1}, 
    3.40 +	     ref    : null},
    3.41 +	 blue  : {
    3.42 +	     offState : null, 
    3.43 +	     onState : null, 
    3.44 +	     ref : null},
    3.45 +	 black : {offState : null, onState : null, ref : null},
    3.46 +	 display : {ref : null, state : {"fill" : "black"}}};
    3.47 +
    3.48 +    var color_select_init = (function (){
    3.49 +	state_map["red"].ref = 
    3.50 +	    color.rect(1, 1, 70, 50, 10).attr(state_map["red"].offState);
    3.51 +	state_map["red"].ref.node.onclick = 
    3.52 +	    (function (){order.color= "red"; update();});
    3.53 +
    3.54 +	state_map["green"].onState =  
    3.55 +	    {"fill" : "#0F0", "scale": 1};
    3.56 +	state_map["green"].offState = 
    3.57 +	    {"fill" : "#030", "scale": 1};
    3.58 +	state_map["green"].ref = 
    3.59 +	    color.rect(80, 1, 70, 50, 10).attr(state_map["green"].offState);
    3.60 +	state_map["green"].ref.node.onclick = 
    3.61 +	    (function (){order.color= "green"; update();});
    3.62 +
    3.63 +	state_map["blue"].onState =  
    3.64 +	    {"fill" : "#00F", "scale": 1};
    3.65 +	state_map["blue"].offState = 
    3.66 +	    {"fill" : "#003", "scale": 1};
    3.67 +	state_map["blue"].ref = 
    3.68 +	    color.rect(160, 1, 70, 50, 10).attr(state_map["blue"].offState);
    3.69 +	state_map["blue"].ref.node.onclick = 
    3.70 +	    (function (){order.color= "blue"; update();});
    3.71 +
    3.72 +	
    3.73 +	toggle_on(state_map[order.color]);
    3.74 +    });
    3.75      
    3.76 -    var select_map = 
    3.77 -	{green : {offAttr : 0, onAttr : 0, ref : 0},
    3.78 -	 red   : {offAttr : 0, onAttr : 0, ref : 0},
    3.79 -	 blue  : {offAttr : 0, onAttr : 0, ref : 0},
    3.80 -	 green : {offAttr : 0, onAttr : 0, ref : 0}};
    3.81 +    var display_init = (function (){
    3.82 +    	state_map["display"].state = 
    3.83 +    	    {"fill": "white"};
    3.84 +    	state_map["display"].ref = 
    3.85 +    	    display.rect(1, 1, 338, 213, 20).attr(state_map["display"].state);
    3.86 +    });
    3.87 +
    3.88 +    var init = (function () {
    3.89 +	
    3.90 +	display = Raphael("card-display", 340 ,215);
    3.91 +	color = Raphael("color-select", 300, 100);
    3.92 +	style = Raphael("style-select", 200, 70);
    3.93 +	color_select_init();
    3.94 +	display_init();
    3.95 +    });
    3.96 +
    3.97 +	
    3.98 +    //Update Functions	    
    3.99      
   3.100      var toggle_on = (function (button){
   3.101 -	button.ref.animate(button.onAttr, 500);
   3.102 +	button.ref.animate(button.onState, 2000);
   3.103      });
   3.104      
   3.105      var toggle_off = (function (button){
   3.106 -	button.ref.animate(button.offAttr, 500);
   3.107 +	button.ref.animate(button.offState, 2000);
   3.108      });
   3.109      
   3.110 -    var color_update = (function (){
   3.111 +    var color_select_update = (function (){
   3.112  	var color = order.color;
   3.113  	return (function (){
   3.114  	    if (order.color === color){}
   3.115  	    else {
   3.116 -		toggle_off(select_map[color]);
   3.117 -		toggle_on(select_map[(order.color)]);
   3.118 +		toggle_off(state_map[color]);
   3.119 +		toggle_on(state_map[(order.color)]);
   3.120  		color = order.color;}
   3.121  	});})(); 
   3.122      
   3.123 +    var display_update = (function (){
   3.124 +    	var color = state_map.display.state.fill 
   3.125 +
   3.126 +    	return (function (){
   3.127 +    	    if (order.color === color){}
   3.128 +    	    else {
   3.129 +    		state_map["display"].ref.animate({"fill" : order.color}, 2000);
   3.130 +    		color = order.color;}})})();
   3.131 +
   3.132      var update = (function (){
   3.133 -	color_update();});
   3.134 +	color_select_update();
   3.135 +	display_update();
   3.136 +	$("#debug").html(JSON.stringify(order));
   3.137 +    });
   3.138      
   3.139 -    var drawInit = (function (){
   3.140 -	//color-select init
   3.141 -	select_map["red"].onAttr =  {"fill" : "#F00"};
   3.142 -	select_map["red"].offAttr = {"fill" : "#300"};
   3.143 -	select_map["red"].ref = 
   3.144 -	    color.rect(1, 1, 70, 50, 10).attr(select_map["red"].offAttr);
   3.145 -	select_map["red"].ref.node.onclick = 
   3.146 -	    (function (){order.color= "red"; update();});
   3.147 -
   3.148 -	select_map["green"].onAttr =  {"fill" : "#0F0"};
   3.149 -	select_map["green"].offAttr = {"fill" : "#030"};
   3.150 -	select_map["green"].ref = 
   3.151 -	    color.rect(80, 1, 70, 50, 10).attr(select_map["green"].offAttr);
   3.152 -	select_map["green"].ref.node.onclick = 
   3.153 -	    (function (){order.color= "green"; update();});
   3.154 -
   3.155 -	select_map["blue"].onAttr =  {"fill" : "#00F"};
   3.156 -	select_map["blue"].offAttr = {"fill" : "#003"};
   3.157 -	select_map["blue"].ref = 
   3.158 -	    color.rect(160, 1, 70, 50, 10).attr(select_map["blue"].offAttr);
   3.159 -	select_map["blue"].ref.node.onclick = 
   3.160 -	    (function (){order.color= "blue"; update();});
   3.161 -
   3.162 -	
   3.163 -	toggle_on(select_map[order.color]);
   3.164 -	
   3.165 -	display.rect(1, 1, 338, 213, 20);
   3.166 -	style.rect(1, 1, 10, 10, 5);
   3.167 -	
   3.168 -	display.print(40, 45, "Robert"  , display.getFont('HelveticaNeue', 700), 30);
   3.169 -	display.print(40, 90, "McIntyre"  , display.getFont('HelveticaNeue', 800), 30);
   3.170 -	
   3.171 -	    
   3.172 -	});
   3.173      
   3.174 -    var init = (function () {
   3.175 -
   3.176 -	    $("#debug").append("init called.");
   3.177 -	    display = Raphael("card-display", 340 ,215);
   3.178 -	    color = Raphael("color-select", 300, 100);
   3.179 -	    style = Raphael("style-select", 200, 70);
   3.180 -	    drawInit();
   3.181 -	    });
   3.182      
   3.183 -  
   3.184 -	    
   3.185 +    // return closure over state
   3.186      return {init : init,
   3.187 -	    update : update};
   3.188 -})();
   3.189 -
   3.190 +	    update : update};})(); 
   3.191  
   3.192  
   3.193  $(document).ready(function() {
   3.194 -	Buy.init();
   3.195 -
   3.196 -
   3.197 -
   3.198 -	
   3.199 +    Buy.init();
   3.200 +    Buy.update();
   3.201      });
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/js-lib/json2.js	Mon Jul 26 04:13:05 2010 -0400
     4.3 @@ -0,0 +1,483 @@
     4.4 +
     4.5 +/*
     4.6 +    http://www.JSON.org/json2.js
     4.7 +    2010-03-20
     4.8 +
     4.9 +    Public Domain.
    4.10 +
    4.11 +    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
    4.12 +
    4.13 +    See http://www.JSON.org/js.html
    4.14 +
    4.15 +
    4.16 +    This code should be minified before deployment.
    4.17 +    See http://javascript.crockford.com/jsmin.html
    4.18 +
    4.19 +    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    4.20 +    NOT CONTROL.
    4.21 +
    4.22 +
    4.23 +    This file creates a global JSON object containing two methods: stringify
    4.24 +    and parse.
    4.25 +
    4.26 +        JSON.stringify(value, replacer, space)
    4.27 +            value       any JavaScript value, usually an object or array.
    4.28 +
    4.29 +            replacer    an optional parameter that determines how object
    4.30 +                        values are stringified for objects. It can be a
    4.31 +                        function or an array of strings.
    4.32 +
    4.33 +            space       an optional parameter that specifies the indentation
    4.34 +                        of nested structures. If it is omitted, the text will
    4.35 +                        be packed without extra whitespace. If it is a number,
    4.36 +                        it will specify the number of spaces to indent at each
    4.37 +                        level. If it is a string (such as '\t' or '&nbsp;'),
    4.38 +                        it contains the characters used to indent at each level.
    4.39 +
    4.40 +            This method produces a JSON text from a JavaScript value.
    4.41 +
    4.42 +            When an object value is found, if the object contains a toJSON
    4.43 +            method, its toJSON method will be called and the result will be
    4.44 +            stringified. A toJSON method does not serialize: it returns the
    4.45 +            value represented by the name/value pair that should be serialized,
    4.46 +            or undefined if nothing should be serialized. The toJSON method
    4.47 +            will be passed the key associated with the value, and this will be
    4.48 +            bound to the value
    4.49 +
    4.50 +            For example, this would serialize Dates as ISO strings.
    4.51 +
    4.52 +                Date.prototype.toJSON = function (key) {
    4.53 +                    function f(n) {
    4.54 +                        // Format integers to have at least two digits.
    4.55 +                        return n < 10 ? '0' + n : n;
    4.56 +                    }
    4.57 +
    4.58 +                    return this.getUTCFullYear()   + '-' +
    4.59 +                         f(this.getUTCMonth() + 1) + '-' +
    4.60 +                         f(this.getUTCDate())      + 'T' +
    4.61 +                         f(this.getUTCHours())     + ':' +
    4.62 +                         f(this.getUTCMinutes())   + ':' +
    4.63 +                         f(this.getUTCSeconds())   + 'Z';
    4.64 +                };
    4.65 +
    4.66 +            You can provide an optional replacer method. It will be passed the
    4.67 +            key and value of each member, with this bound to the containing
    4.68 +            object. The value that is returned from your method will be
    4.69 +            serialized. If your method returns undefined, then the member will
    4.70 +            be excluded from the serialization.
    4.71 +
    4.72 +            If the replacer parameter is an array of strings, then it will be
    4.73 +            used to select the members to be serialized. It filters the results
    4.74 +            such that only members with keys listed in the replacer array are
    4.75 +            stringified.
    4.76 +
    4.77 +            Values that do not have JSON representations, such as undefined or
    4.78 +            functions, will not be serialized. Such values in objects will be
    4.79 +            dropped; in arrays they will be replaced with null. You can use
    4.80 +            a replacer function to replace those with JSON values.
    4.81 +            JSON.stringify(undefined) returns undefined.
    4.82 +
    4.83 +            The optional space parameter produces a stringification of the
    4.84 +            value that is filled with line breaks and indentation to make it
    4.85 +            easier to read.
    4.86 +
    4.87 +            If the space parameter is a non-empty string, then that string will
    4.88 +            be used for indentation. If the space parameter is a number, then
    4.89 +            the indentation will be that many spaces.
    4.90 +
    4.91 +            Example:
    4.92 +
    4.93 +            text = JSON.stringify(['e', {pluribus: 'unum'}]);
    4.94 +            // text is '["e",{"pluribus":"unum"}]'
    4.95 +
    4.96 +
    4.97 +            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
    4.98 +            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
    4.99 +
   4.100 +            text = JSON.stringify([new Date()], function (key, value) {
   4.101 +                return this[key] instanceof Date ?
   4.102 +                    'Date(' + this[key] + ')' : value;
   4.103 +            });
   4.104 +            // text is '["Date(---current time---)"]'
   4.105 +
   4.106 +
   4.107 +        JSON.parse(text, reviver)
   4.108 +            This method parses a JSON text to produce an object or array.
   4.109 +            It can throw a SyntaxError exception.
   4.110 +
   4.111 +            The optional reviver parameter is a function that can filter and
   4.112 +            transform the results. It receives each of the keys and values,
   4.113 +            and its return value is used instead of the original value.
   4.114 +            If it returns what it received, then the structure is not modified.
   4.115 +            If it returns undefined then the member is deleted.
   4.116 +
   4.117 +            Example:
   4.118 +
   4.119 +            // Parse the text. Values that look like ISO date strings will
   4.120 +            // be converted to Date objects.
   4.121 +
   4.122 +            myData = JSON.parse(text, function (key, value) {
   4.123 +                var a;
   4.124 +                if (typeof value === 'string') {
   4.125 +                    a =
   4.126 +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
   4.127 +                    if (a) {
   4.128 +                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
   4.129 +                            +a[5], +a[6]));
   4.130 +                    }
   4.131 +                }
   4.132 +                return value;
   4.133 +            });
   4.134 +
   4.135 +            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
   4.136 +                var d;
   4.137 +                if (typeof value === 'string' &&
   4.138 +                        value.slice(0, 5) === 'Date(' &&
   4.139 +                        value.slice(-1) === ')') {
   4.140 +                    d = new Date(value.slice(5, -1));
   4.141 +                    if (d) {
   4.142 +                        return d;
   4.143 +                    }
   4.144 +                }
   4.145 +                return value;
   4.146 +            });
   4.147 +
   4.148 +
   4.149 +    This is a reference implementation. You are free to copy, modify, or
   4.150 +    redistribute.
   4.151 +*/
   4.152 +
   4.153 +/*jslint evil: true, strict: false */
   4.154 +
   4.155 +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
   4.156 +    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
   4.157 +    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
   4.158 +    lastIndex, length, parse, prototype, push, replace, slice, stringify,
   4.159 +    test, toJSON, toString, valueOf
   4.160 +*/
   4.161 +
   4.162 +
   4.163 +// Create a JSON object only if one does not already exist. We create the
   4.164 +// methods in a closure to avoid creating global variables.
   4.165 +
   4.166 +if (!this.JSON) {
   4.167 +    this.JSON = {};
   4.168 +}
   4.169 +
   4.170 +(function () {
   4.171 +
   4.172 +    function f(n) {
   4.173 +        // Format integers to have at least two digits.
   4.174 +        return n < 10 ? '0' + n : n;
   4.175 +    }
   4.176 +
   4.177 +    if (typeof Date.prototype.toJSON !== 'function') {
   4.178 +
   4.179 +        Date.prototype.toJSON = function (key) {
   4.180 +
   4.181 +            return isFinite(this.valueOf()) ?
   4.182 +                   this.getUTCFullYear()   + '-' +
   4.183 +                 f(this.getUTCMonth() + 1) + '-' +
   4.184 +                 f(this.getUTCDate())      + 'T' +
   4.185 +                 f(this.getUTCHours())     + ':' +
   4.186 +                 f(this.getUTCMinutes())   + ':' +
   4.187 +                 f(this.getUTCSeconds())   + 'Z' : null;
   4.188 +        };
   4.189 +
   4.190 +        String.prototype.toJSON =
   4.191 +        Number.prototype.toJSON =
   4.192 +        Boolean.prototype.toJSON = function (key) {
   4.193 +            return this.valueOf();
   4.194 +        };
   4.195 +    }
   4.196 +
   4.197 +    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
   4.198 +        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
   4.199 +        gap,
   4.200 +        indent,
   4.201 +        meta = {    // table of character substitutions
   4.202 +            '\b': '\\b',
   4.203 +            '\t': '\\t',
   4.204 +            '\n': '\\n',
   4.205 +            '\f': '\\f',
   4.206 +            '\r': '\\r',
   4.207 +            '"' : '\\"',
   4.208 +            '\\': '\\\\'
   4.209 +        },
   4.210 +        rep;
   4.211 +
   4.212 +
   4.213 +    function quote(string) {
   4.214 +
   4.215 +// If the string contains no control characters, no quote characters, and no
   4.216 +// backslash characters, then we can safely slap some quotes around it.
   4.217 +// Otherwise we must also replace the offending characters with safe escape
   4.218 +// sequences.
   4.219 +
   4.220 +        escapable.lastIndex = 0;
   4.221 +        return escapable.test(string) ?
   4.222 +            '"' + string.replace(escapable, function (a) {
   4.223 +                var c = meta[a];
   4.224 +                return typeof c === 'string' ? c :
   4.225 +                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
   4.226 +            }) + '"' :
   4.227 +            '"' + string + '"';
   4.228 +    }
   4.229 +
   4.230 +
   4.231 +    function str(key, holder) {
   4.232 +
   4.233 +// Produce a string from holder[key].
   4.234 +
   4.235 +        var i,          // The loop counter.
   4.236 +            k,          // The member key.
   4.237 +            v,          // The member value.
   4.238 +            length,
   4.239 +            mind = gap,
   4.240 +            partial,
   4.241 +            value = holder[key];
   4.242 +
   4.243 +// If the value has a toJSON method, call it to obtain a replacement value.
   4.244 +
   4.245 +        if (value && typeof value === 'object' &&
   4.246 +                typeof value.toJSON === 'function') {
   4.247 +            value = value.toJSON(key);
   4.248 +        }
   4.249 +
   4.250 +// If we were called with a replacer function, then call the replacer to
   4.251 +// obtain a replacement value.
   4.252 +
   4.253 +        if (typeof rep === 'function') {
   4.254 +            value = rep.call(holder, key, value);
   4.255 +        }
   4.256 +
   4.257 +// What happens next depends on the value's type.
   4.258 +
   4.259 +        switch (typeof value) {
   4.260 +        case 'string':
   4.261 +            return quote(value);
   4.262 +
   4.263 +        case 'number':
   4.264 +
   4.265 +// JSON numbers must be finite. Encode non-finite numbers as null.
   4.266 +
   4.267 +            return isFinite(value) ? String(value) : 'null';
   4.268 +
   4.269 +        case 'boolean':
   4.270 +        case 'null':
   4.271 +
   4.272 +// If the value is a boolean or null, convert it to a string. Note:
   4.273 +// typeof null does not produce 'null'. The case is included here in
   4.274 +// the remote chance that this gets fixed someday.
   4.275 +
   4.276 +            return String(value);
   4.277 +
   4.278 +// If the type is 'object', we might be dealing with an object or an array or
   4.279 +// null.
   4.280 +
   4.281 +        case 'object':
   4.282 +
   4.283 +// Due to a specification blunder in ECMAScript, typeof null is 'object',
   4.284 +// so watch out for that case.
   4.285 +
   4.286 +            if (!value) {
   4.287 +                return 'null';
   4.288 +            }
   4.289 +
   4.290 +// Make an array to hold the partial results of stringifying this object value.
   4.291 +
   4.292 +            gap += indent;
   4.293 +            partial = [];
   4.294 +
   4.295 +// Is the value an array?
   4.296 +
   4.297 +            if (Object.prototype.toString.apply(value) === '[object Array]') {
   4.298 +
   4.299 +// The value is an array. Stringify every element. Use null as a placeholder
   4.300 +// for non-JSON values.
   4.301 +
   4.302 +                length = value.length;
   4.303 +                for (i = 0; i < length; i += 1) {
   4.304 +                    partial[i] = str(i, value) || 'null';
   4.305 +                }
   4.306 +
   4.307 +// Join all of the elements together, separated with commas, and wrap them in
   4.308 +// brackets.
   4.309 +
   4.310 +                v = partial.length === 0 ? '[]' :
   4.311 +                    gap ? '[\n' + gap +
   4.312 +                            partial.join(',\n' + gap) + '\n' +
   4.313 +                                mind + ']' :
   4.314 +                          '[' + partial.join(',') + ']';
   4.315 +                gap = mind;
   4.316 +                return v;
   4.317 +            }
   4.318 +
   4.319 +// If the replacer is an array, use it to select the members to be stringified.
   4.320 +
   4.321 +            if (rep && typeof rep === 'object') {
   4.322 +                length = rep.length;
   4.323 +                for (i = 0; i < length; i += 1) {
   4.324 +                    k = rep[i];
   4.325 +                    if (typeof k === 'string') {
   4.326 +                        v = str(k, value);
   4.327 +                        if (v) {
   4.328 +                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
   4.329 +                        }
   4.330 +                    }
   4.331 +                }
   4.332 +            } else {
   4.333 +
   4.334 +// Otherwise, iterate through all of the keys in the object.
   4.335 +
   4.336 +                for (k in value) {
   4.337 +                    if (Object.hasOwnProperty.call(value, k)) {
   4.338 +                        v = str(k, value);
   4.339 +                        if (v) {
   4.340 +                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
   4.341 +                        }
   4.342 +                    }
   4.343 +                }
   4.344 +            }
   4.345 +
   4.346 +// Join all of the member texts together, separated with commas,
   4.347 +// and wrap them in braces.
   4.348 +
   4.349 +            v = partial.length === 0 ? '{}' :
   4.350 +                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
   4.351 +                        mind + '}' : '{' + partial.join(',') + '}';
   4.352 +            gap = mind;
   4.353 +            return v;
   4.354 +        }
   4.355 +    }
   4.356 +
   4.357 +// If the JSON object does not yet have a stringify method, give it one.
   4.358 +
   4.359 +    if (typeof JSON.stringify !== 'function') {
   4.360 +        JSON.stringify = function (value, replacer, space) {
   4.361 +
   4.362 +// The stringify method takes a value and an optional replacer, and an optional
   4.363 +// space parameter, and returns a JSON text. The replacer can be a function
   4.364 +// that can replace values, or an array of strings that will select the keys.
   4.365 +// A default replacer method can be provided. Use of the space parameter can
   4.366 +// produce text that is more easily readable.
   4.367 +
   4.368 +            var i;
   4.369 +            gap = '';
   4.370 +            indent = '';
   4.371 +
   4.372 +// If the space parameter is a number, make an indent string containing that
   4.373 +// many spaces.
   4.374 +
   4.375 +            if (typeof space === 'number') {
   4.376 +                for (i = 0; i < space; i += 1) {
   4.377 +                    indent += ' ';
   4.378 +                }
   4.379 +
   4.380 +// If the space parameter is a string, it will be used as the indent string.
   4.381 +
   4.382 +            } else if (typeof space === 'string') {
   4.383 +                indent = space;
   4.384 +            }
   4.385 +
   4.386 +// If there is a replacer, it must be a function or an array.
   4.387 +// Otherwise, throw an error.
   4.388 +
   4.389 +            rep = replacer;
   4.390 +            if (replacer && typeof replacer !== 'function' &&
   4.391 +                    (typeof replacer !== 'object' ||
   4.392 +                     typeof replacer.length !== 'number')) {
   4.393 +                throw new Error('JSON.stringify');
   4.394 +            }
   4.395 +
   4.396 +// Make a fake root object containing our value under the key of ''.
   4.397 +// Return the result of stringifying the value.
   4.398 +
   4.399 +            return str('', {'': value});
   4.400 +        };
   4.401 +    }
   4.402 +
   4.403 +
   4.404 +// If the JSON object does not yet have a parse method, give it one.
   4.405 +
   4.406 +    if (typeof JSON.parse !== 'function') {
   4.407 +        JSON.parse = function (text, reviver) {
   4.408 +
   4.409 +// The parse method takes a text and an optional reviver function, and returns
   4.410 +// a JavaScript value if the text is a valid JSON text.
   4.411 +
   4.412 +            var j;
   4.413 +
   4.414 +            function walk(holder, key) {
   4.415 +
   4.416 +// The walk method is used to recursively walk the resulting structure so
   4.417 +// that modifications can be made.
   4.418 +
   4.419 +                var k, v, value = holder[key];
   4.420 +                if (value && typeof value === 'object') {
   4.421 +                    for (k in value) {
   4.422 +                        if (Object.hasOwnProperty.call(value, k)) {
   4.423 +                            v = walk(value, k);
   4.424 +                            if (v !== undefined) {
   4.425 +                                value[k] = v;
   4.426 +                            } else {
   4.427 +                                delete value[k];
   4.428 +                            }
   4.429 +                        }
   4.430 +                    }
   4.431 +                }
   4.432 +                return reviver.call(holder, key, value);
   4.433 +            }
   4.434 +
   4.435 +
   4.436 +// Parsing happens in four stages. In the first stage, we replace certain
   4.437 +// Unicode characters with escape sequences. JavaScript handles many characters
   4.438 +// incorrectly, either silently deleting them, or treating them as line endings.
   4.439 +
   4.440 +            text = String(text);
   4.441 +            cx.lastIndex = 0;
   4.442 +            if (cx.test(text)) {
   4.443 +                text = text.replace(cx, function (a) {
   4.444 +                    return '\\u' +
   4.445 +                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
   4.446 +                });
   4.447 +            }
   4.448 +
   4.449 +// In the second stage, we run the text against regular expressions that look
   4.450 +// for non-JSON patterns. We are especially concerned with '()' and 'new'
   4.451 +// because they can cause invocation, and '=' because it can cause mutation.
   4.452 +// But just to be safe, we want to reject all unexpected forms.
   4.453 +
   4.454 +// We split the second stage into 4 regexp operations in order to work around
   4.455 +// crippling inefficiencies in IE's and Safari's regexp engines. First we
   4.456 +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
   4.457 +// replace all simple value tokens with ']' characters. Third, we delete all
   4.458 +// open brackets that follow a colon or comma or that begin the text. Finally,
   4.459 +// we look to see that the remaining characters are only whitespace or ']' or
   4.460 +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
   4.461 +
   4.462 +            if (/^[\],:{}\s]*$/.
   4.463 +test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
   4.464 +replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
   4.465 +replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
   4.466 +
   4.467 +// In the third stage we use the eval function to compile the text into a
   4.468 +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
   4.469 +// in JavaScript: it can begin a block or an object literal. We wrap the text
   4.470 +// in parens to eliminate the ambiguity.
   4.471 +
   4.472 +                j = eval('(' + text + ')');
   4.473 +
   4.474 +// In the optional fourth stage, we recursively walk the new structure, passing
   4.475 +// each name/value pair to a reviver function for possible transformation.
   4.476 +
   4.477 +                return typeof reviver === 'function' ?
   4.478 +                    walk({'': j}, '') : j;
   4.479 +            }
   4.480 +
   4.481 +// If the text is not JSON parseable, then a SyntaxError is thrown.
   4.482 +
   4.483 +            throw new SyntaxError('JSON.parse');
   4.484 +        };
   4.485 +    }
   4.486 +}());