source: Dev/branches/rest-dojo-ui/client/dojox/wire/Wire.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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