Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / src / state / Provider.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /**
8  * @class Ext.state.Provider
9  * Abstract base class for state provider implementations. This class provides methods
10  * for encoding and decoding <b>typed</b> variables including dates and defines the
11  * Provider interface.
12  */
13 Ext.state.Provider = Ext.extend(Ext.util.Observable, {
14     
15     constructor : function(){
16         /**
17          * @event statechange
18          * Fires when a state change occurs.
19          * @param {Provider} this This state provider
20          * @param {String} key The state key which was changed
21          * @param {String} value The encoded value for the state
22          */
23         this.addEvents("statechange");
24         this.state = {};
25         Ext.state.Provider.superclass.constructor.call(this);
26     },
27     
28     /**
29      * Returns the current value for a key
30      * @param {String} name The key name
31      * @param {Mixed} defaultValue A default value to return if the key's value is not found
32      * @return {Mixed} The state data
33      */
34     get : function(name, defaultValue){
35         return typeof this.state[name] == "undefined" ?
36             defaultValue : this.state[name];
37     },
38
39     /**
40      * Clears a value from the state
41      * @param {String} name The key name
42      */
43     clear : function(name){
44         delete this.state[name];
45         this.fireEvent("statechange", this, name, null);
46     },
47
48     /**
49      * Sets the value for a key
50      * @param {String} name The key name
51      * @param {Mixed} value The value to set
52      */
53     set : function(name, value){
54         this.state[name] = value;
55         this.fireEvent("statechange", this, name, value);
56     },
57
58     /**
59      * Decodes a string previously encoded with {@link #encodeValue}.
60      * @param {String} value The value to decode
61      * @return {Mixed} The decoded value
62      */
63     decodeValue : function(cookie){
64         /**
65          * a -> Array
66          * n -> Number
67          * d -> Date
68          * b -> Boolean
69          * s -> String
70          * o -> Object
71          * -> Empty (null)
72          */
73         var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
74             matches = re.exec(unescape(cookie)),
75             all,
76             type,
77             v,
78             kv;
79         if(!matches || !matches[1]){
80             return; // non state cookie
81         }
82         type = matches[1];
83         v = matches[2];
84         switch(type){
85             case 'e':
86                 return null;
87             case 'n':
88                 return parseFloat(v);
89             case 'd':
90                 return new Date(Date.parse(v));
91             case 'b':
92                 return (v == '1');
93             case 'a':
94                 all = [];
95                 if(v != ''){
96                     Ext.each(v.split('^'), function(val){
97                         all.push(this.decodeValue(val));
98                     }, this);
99                 }
100                 return all;
101            case 'o':
102                 all = {};
103                 if(v != ''){
104                     Ext.each(v.split('^'), function(val){
105                         kv = val.split('=');
106                         all[kv[0]] = this.decodeValue(kv[1]);
107                     }, this);
108                 }
109                 return all;
110            default:
111                 return v;
112         }
113     },
114
115     /**
116      * Encodes a value including type information.  Decode with {@link #decodeValue}.
117      * @param {Mixed} value The value to encode
118      * @return {String} The encoded value
119      */
120     encodeValue : function(v){
121         var enc,
122             flat = '',
123             i = 0,
124             len,
125             key;
126         if(v == null){
127             return 'e:1';    
128         }else if(typeof v == 'number'){
129             enc = 'n:' + v;
130         }else if(typeof v == 'boolean'){
131             enc = 'b:' + (v ? '1' : '0');
132         }else if(Ext.isDate(v)){
133             enc = 'd:' + v.toGMTString();
134         }else if(Ext.isArray(v)){
135             for(len = v.length; i < len; i++){
136                 flat += this.encodeValue(v[i]);
137                 if(i != len - 1){
138                     flat += '^';
139                 }
140             }
141             enc = 'a:' + flat;
142         }else if(typeof v == 'object'){
143             for(key in v){
144                 if(typeof v[key] != 'function' && v[key] !== undefined){
145                     flat += key + '=' + this.encodeValue(v[key]) + '^';
146                 }
147             }
148             enc = 'o:' + flat.substring(0, flat.length-1);
149         }else{
150             enc = 's:' + v;
151         }
152         return escape(enc);
153     }
154 });