source: Dev/trunk/src/client/dojox/wire/Wire.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 11.3 KB
Line 
1dojo.provide("dojox.wire.Wire");
2
3dojo.require("dojox.wire._base");
4
5dojo.declare("dojox.wire.Wire", null, {
6        // summary:
7        //              A default and base Wire to access an object property
8        // description:
9        //              This class accesses a property of an object with a dotted notation
10        //              specified to 'property' property, such as "a.b.c", which identifies
11        //              a descendant property, "object.a.b.c".
12        //              Property names in the dotted notation may have an array index, such
13        //              as "a[0]", to identify an array element, literally, "object.a[0]".
14        //              When a notation start with an array index, such as "[0].a", it
15        //              specifies an array element of the root object (array),
16        //              "object[0].a".
17        //              This class also serves as a base class for other Wire classes,
18        //              preparing a root object and converting a return value, so that
19        //              sub-classes just can implement _getValue() and _setValue() called
20        //              from getValue() and setValue() implemented by this calss.
21       
22        _wireClass: "dojox.wire.Wire",
23       
24        constructor: function(/*Object*/args){
25                // summary:
26                //              Initialize properties
27                // description:
28                //              If 'converter' property is specified and is a string for
29                //              a converter class, an instanceof the converter class is
30                //              created.
31                // args:
32                //              Arguments to initialize properties:
33                //
34                //              - object: A root object (or another Wire to access a root object)
35                //              - property: A dotted notation to a descendant property
36                //              - type: A type of the return value (for the source Wire)
37                //              - converter: A converter object (or class name) to convert the return
38                //                      value (for the source Wire)
39                dojo.mixin(this, args);
40
41                if(this.converter){
42                        if(dojo.isString(this.converter)){
43                                //First check the object tree for it.  Might be defined variable
44                                //name/global function (like a jsId, or just a function name).
45                                var convertObject = dojo.getObject(this.converter);
46                                if(dojo.isFunction(convertObject)){
47                                        //We need to see if this is a pure function or an object constructor...
48                                        try{
49                                                var testObj = new convertObject();
50                                                if(testObj && !dojo.isFunction(testObj["convert"])){
51                                                        //Looks like a 'pure' function...
52                                                        this.converter = {convert: convertObject};
53                                                }else{
54                                                        this.converter = testObj;
55                                                }
56                                        }catch(e){
57                                                //Do if this fails.
58                                        }
59                                }else if(dojo.isObject(convertObject)){
60                                        //It's an object, like a jsId ... see if it has a convert function
61                                        if(dojo.isFunction(convertObject["convert"])){
62                                                this.converter = convertObject;
63                                        }
64                                }
65
66                                //No object with that name (Converter is still a string),
67                                //then look for a class that needs to be dynamically loaded...
68                                if(dojo.isString(this.converter)){
69                                        var converterClass = dojox.wire._getClass(this.converter);
70                                        if(converterClass){
71                                                this.converter = new converterClass();
72                                        }else{
73                                                this.converter = undefined;
74                                        }
75                                }
76                        }else if(dojo.isFunction(this.converter)){
77                                this.converter = {convert: this.converter};
78                        }
79                }
80        },
81
82        getValue: function(/*Object||Array*/defaultObject){
83                // summary:
84                //              Return a value of an object
85                // description:
86                //              This method first determines a root object as follows:
87                //
88                //                      1. If 'object' property specified,
89                //                      1.1 If 'object' is a Wire, its getValue() method is called to
90                //                      obtain a root object.
91                //                      1.2 Otherwise, use 'object' as a root object.
92                //                      2. Otherwise, use 'defaultObject' argument.
93                //                      3. If 'property' is specified, it is used to get a property
94                //                              value.
95                //
96                //              Then, if a sub-class implements _getValue() method, it is
97                //              called with the root object to get the return value.
98                //              Otherwise, the root object (typically, a property valye) is
99                //              used for the return value.
100                //              Finally, if 'type' property is specified, the return value is
101                //              converted to the specified primitive type ("string", "number",
102                //              "boolean" and "array").
103                //              If 'converter' property is specified, its convert() method is
104                //              called to convert the value.
105                // defaultObject:
106                //              A default root object
107                // returns:
108                //              A value found
109                var object = undefined;
110                if(dojox.wire.isWire(this.object)){
111                        object = this.object.getValue(defaultObject);
112                }else{
113                        object = (this.object || defaultObject);
114                }
115
116                if(this.property){
117                        var list = this.property.split('.');
118                        for(var i in list){
119                                if(!object){
120                                        return object; //anything (null, undefined, etc)
121                                }
122                                object = this._getPropertyValue(object, list[i]);
123                        }
124                }
125
126                var value = undefined;
127                if(this._getValue){
128                        value = this._getValue(object);
129                }else{
130                        value = object;
131                }
132
133                if(value){
134                        if(this.type){
135                                if(this.type == "string"){
136                                        value = value.toString();
137                                }else if(this.type == "number"){
138                                        value = parseInt(value, 10);
139                                }else if(this.type == "boolean"){
140                                        value = (value != "false");
141                                }else if(this.type == "array"){
142                                        if(!dojo.isArray(value)){
143                                                value = [value];
144                                        }
145                                }
146                        }
147                        if(this.converter && this.converter.convert){
148                                value = this.converter.convert(value, this); // optional "this" context
149                        }
150                }
151                return value; //anything
152        },
153
154        setValue: function(/*anything*/value, /*Object||Array*/defaultObject){
155                // summary:
156                //              Set a value to an object
157                // description:
158                //              This method first determines a root object as follows:
159                //
160                //                      1. If 'object' property specified,
161                //                      1.1 If 'object' is a Wire, its getValue() method is called to
162                //                              obtain a root object.
163                //                      1.2 Otherwise, use 'object' as a root object.
164                //                      2. Otherwise, use 'defaultObject' argument.
165                //                      3. If 'property' is specified, it is used to get a property
166                //                              value.
167                //
168                //              Then, if a sub-class implements _setValue() method, it is
169                //              called with the root object and 'value' argument to set
170                //              the value.
171                //              Otherwise, 'value' is set to a property specified with
172                //              'property' property.
173                //              If the root object is undefined and 'object' property is a Wire
174                //              and a new object is created and returned by _setValue() it is
175                //              set through 'object' (setValue() method).
176                // value:
177                //              A value to set
178                // defaultObject:
179                //              A default root object
180                var object = undefined;
181                if(dojox.wire.isWire(this.object)){
182                        object = this.object.getValue(defaultObject);
183                }else{
184                        object = (this.object || defaultObject);
185                }
186
187                var property = undefined;
188                var o;
189                if(this.property){
190                        if(!object){
191                                if(dojox.wire.isWire(this.object)){
192                                        object = {};
193                                        this.object.setValue(object, defaultObject);
194                                }else{
195                                        throw new Error(this._wireClass + ".setValue(): invalid object");
196                                }
197                        }
198                        var list = this.property.split('.');
199                        var last = list.length - 1;
200                        for(var i = 0; i < last; i++){
201                                var p = list[i];
202                                o = this._getPropertyValue(object, p);
203                                if(!o){
204                                        o = {};
205                                        this._setPropertyValue(object, p, o);
206                                }
207                                object = o;
208                        }
209                        property = list[last];
210                }
211
212                if(this._setValue){
213                        if(property){
214                                o = this._getPropertyValue(object, property);
215                                if(!o){
216                                        o = {};
217                                        this._setPropertyValue(object, property, o);
218                                }
219                                object = o;
220                        }
221                        var newObject = this._setValue(object, value);
222                        if(!object && newObject){
223                                if(dojox.wire.isWire(this.object)){
224                                        this.object.setValue(newObject, defaultObject);
225                                }else{
226                                        throw new Error(this._wireClass + ".setValue(): invalid object");
227                                }
228                        }
229                }else{
230                        if(property){
231                                this._setPropertyValue(object, property, value);
232                        }else{
233                                if(dojox.wire.isWire(this.object)){
234                                        this.object.setValue(value, defaultObject);
235                                }else{
236                                        throw new Error(this._wireClass + ".setValue(): invalid property");
237                                }
238                        }
239                }
240        },
241
242        _getPropertyValue: function(/*Object||Array*/object, /*String*/property){
243                // summary:
244                //              Return a property value of an object
245                // description:
246                //              A value for 'property' of 'object' is returned.
247                //              If 'property' ends with an array index, it is used to indentify
248                //              an element of an array property.
249                //              If 'object' implements getPropertyValue(), it is called with
250                //              'property' to obtain the property value.
251                //              If 'object' implements a getter for the property, it is called
252                //              to obtain the property value.
253                // object:
254                //              A default root object
255                // property:
256                //              A property name
257                // returns:
258                //              A value found, otherwise 'undefined'
259                var value = undefined;
260                var i1 = property.indexOf('[');
261                if(i1 >= 0){
262                        var i2 = property.indexOf(']');
263                        var index = property.substring(i1 + 1, i2);
264                        var array = null;
265                        if(i1 === 0){ // object is array
266                                array = object;
267                        }else{
268                                property = property.substring(0, i1);
269                                array = this._getPropertyValue(object, property);
270                                if(array && !dojo.isArray(array)){
271                                        array = [array];
272                                }
273                        }
274                        if(array){
275                                value = array[index];
276                        }
277                }else if(object.getPropertyValue){
278                        value = object.getPropertyValue(property);
279                }else{
280                        var getter = "get" + property.charAt(0).toUpperCase() + property.substring(1);
281                        if(this._useGet(object)){
282                                value = object.get(property);
283                        }else if(this._useAttr(object)){
284                                value = object.attr(property);
285                        } else if(object[getter]){
286                                value = object[getter]();
287                        }else{
288                                value = object[property];
289                        }
290                }
291                return value; //anything
292        },
293
294        _setPropertyValue: function(/*Object||Array*/object, /*String*/property, /*anything*/value){
295                // summary:
296                //              Set a property value to an object
297                // description:
298                //              'value' is set to 'property' of 'object'.
299                //              If 'property' ends with an array index, it is used to indentify
300                //              an element of an array property to set the value.
301                //              If 'object' implements setPropertyValue(), it is called with
302                //              'property' and 'value' to set the property value.
303                //              If 'object' implements a setter for the property, it is called
304                //              with 'value' to set the property value.
305                // object:
306                //              An object
307                // property:
308                //              A property name
309                // value:
310                //              A value to set
311                var i1 = property.indexOf('[');
312                if(i1 >= 0){
313                        var i2 = property.indexOf(']');
314                        var index = property.substring(i1 + 1, i2);
315                        var array = null;
316                        if(i1 === 0){ // object is array
317                                array = object;
318                        }else{
319                                property = property.substring(0, i1);
320                                array = this._getPropertyValue(object, property);
321                                if(!array){
322                                        array = [];
323                                        this._setPropertyValue(object, property, array);
324                                }
325                        }
326                        array[index] = value;
327                }else if(object.setPropertyValue){
328                        object.setPropertyValue(property, value);
329                }else{
330                        var setter = "set" + property.charAt(0).toUpperCase() + property.substring(1);
331                        if(this._useSet(object)){
332                                object.set(property, value);
333                        }else if(this._useAttr(object)){
334                                object.attr(property, value);
335                        }else if(object[setter]){
336                                object[setter](value);
337                        }else{
338                                object[property] = value;
339                        }
340                }
341        },
342
343        _useGet: function(object){
344                // summary:
345                //              Function to detect if dijit.get support exists on the target
346                // object:
347                //              The target object to set the property of.
348                var useGet = false;
349                if(dojo.isFunction(object.get)){
350                        useGet = true;
351                }
352                return useGet;
353        },
354
355        _useSet: function(object){
356                // summary:
357                //              Function to detect if dijit.set support exists on the target
358                // object:
359                //              The target object to set the property of.
360                var useSet = false;
361                if(dojo.isFunction(object.set)){
362                        useSet = true;
363                }
364                return useSet;
365        },
366
367        _useAttr: function(object){
368                // summary:
369                //              Function to detect if dijit.attr support exists on the target
370                // object:
371                //              The target object to set the property of.
372                var useAttr = false;
373                if(dojo.isFunction(object.attr)){
374                        useAttr = true;
375                }
376                return useAttr;
377        }
378});
Note: See TracBrowser for help on using the repository browser.