source: Dev/branches/rest-dojo-ui/client/dojox/data/AppStore.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: 22.1 KB
Line 
1define(["dojo", "dojox", "dojo/data/util/simpleFetch", "dojo/data/util/filter", "dojox/atom/io/Connection"], function(dojo, dojox) {
2
3dojo.experimental("dojox.data.AppStore");
4
5dojo.declare("dojox.data.AppStore",
6        null,{
7
8        // url: [public] string
9        //              So the parser can instantiate the store via markup.
10        url: "",
11       
12        // urlPreventCache: [public] boolean
13        //              Whether or not to pass the preventCache parameter to the connection
14        urlPreventCache: false,
15
16        // xmethod: [public] boolean
17        //              Whether to use X-Method-Override for PUT/DELETE.
18        xmethod: false,
19       
20        _atomIO: null,
21        _feed: null,
22        _requests: null,
23        _processing: null,
24       
25        _updates: null,
26        _adds: null,
27        _deletes: null,
28       
29        constructor: function(/*Object*/args){
30                // summary:
31                //              The APP data store.
32                // description:
33                //              The APP Store is instantiated either in markup or programmatically by supplying a
34                //              url of the Collection to be used.
35                //
36                // args:
37                //              An anonymous object to initialize properties.  It expects the following values:
38                //              url:            The url of the Collection to load.
39                //              urlPreventCache:        Whether or not to append on cache prevention params (as defined by dojo.xhr*)
40               
41                if(args && args.url){
42                        this.url = args.url;
43                }
44                if(args && args.urlPreventCache){
45                        this.urlPreventCache = args.urlPreventCache;
46                }
47                if(!this.url){
48                        throw new Error("A URL is required to instantiate an APP Store object");
49                }
50        },
51       
52        _setFeed: function(feed, data){
53                // summary:
54                //              Sets the internal feed using a dojox.atom.io.model.Feed object.
55                // description:
56                //              Sets the internal feed using a dojox.atom.io.model.Feed object.  Also adds
57                //              a property to the entries to track that they belong to this store. It
58                //              also parses stored requests (since we were waiting on a callback) and
59                //              executes those as well.
60                //
61                // feed: dojox.atom.io.model.Feed object
62                //              The Feed to use for this data store.
63                // data: unused
64                //              Signature for this function is defined by AtomIO.getFeed, since this is a callback.
65                this._feed = feed;
66                var i;
67                for(i=0; i<this._feed.entries.length; i++){
68                        this._feed.entries[i].store = this;
69                }
70                if(this._requests){
71                        for(i=0; i<this._requests.length; i++){
72                                var request = this._requests[i];
73                                if(request.request && request.fh && request.eh){
74                                        this._finishFetchItems(request.request, request.fh, request.eh);
75                                }else if(request.clear){
76                                        this._feed = null;
77                                }else if(request.add){
78                                        this._feed.addEntry(request.add);
79                                }else if(request.remove){
80                                        this._feed.removeEntry(request.remove);
81                                }
82                        }
83                }
84                this._requests = null;
85        },
86       
87        _getAllItems: function(){
88                // summary:
89                //              Function to return all entries in the Feed as an array of items.
90                // description:
91                //              Function to return all entries in the Feed as an array of items.
92                //
93                // returns:
94                //              Array of all entries in the feed.
95                var items = [];
96                for(var i=0; i<this._feed.entries.length; i++){
97                        items.push(this._feed.entries[i]);
98                }
99                return items; //array
100        },
101       
102        _assertIsItem: function(/* item */ item){
103                // summary:
104                //              This function tests whether the item is an item.
105                // description:
106                //              This function tests whether the item passed in is indeed an item
107                //              in the store.
108                //
109                // item:
110                //              The item to test for being contained by the store.
111                if(!this.isItem(item)){
112                        throw new Error("This error message is provided when a function is called in the following form: "
113                                + "getAttribute(argument, attributeName).  The argument variable represents the member "
114                                + "or owner of the object. The error is created when an item that does not belong "
115                                + "to this store is specified as an argument.");
116                }
117        },
118
119        _assertIsAttribute: function(/* String */ attribute){
120                // summary:
121                //              This function tests whether the item is an attribute.
122                // description:
123                //              This function tests whether the item passed in is indeed a valid
124                //              'attribute' like type for the store.
125                // attribute:
126                //              The attribute to test for being contained by the store.
127                //
128                // returns:
129                //              Returns a boolean indicating whether this is a valid attribute.
130                if(typeof attribute !== "string"){
131                        throw new Error("The attribute argument must be a string. The error is created "
132                        + "when a different type of variable is specified such as an array or object.");
133                }
134
135                for(var key in dojox.atom.io.model._actions){
136                        if(key == attribute){
137                                return true;
138                        }
139                }
140                return false;
141        },
142       
143        _addUpdate: function(/* Object */ update){
144                // summary:
145                //              Internal function to add an updated entry to our updates array
146                // description:
147                //              Internal function to add an updated entry to our updates array
148                //
149                // update: dojox.atom.io.model.Entry object
150                //              The updated Entry we've changed.
151                if(!this._updates){
152                        this._updates = [update];
153                }else{
154                        this._updates.push(update);
155                }
156        },
157
158/***************************************
159     dojo.data.api.Read API
160***************************************/
161       
162        getValue: function(     /* item */ item,
163                                                /* attribute-name-string */ attribute,
164                                                /* value? */ defaultValue){
165                // summary:
166                //      See dojo.data.api.Read.getValue()
167                var values = this.getValues(item, attribute);
168                return (values.length > 0)?values[0]:defaultValue; //Object || int || Boolean
169        },
170
171        getValues: function(/* item */ item,
172                                                /* attribute-name-string */ attribute){
173                // summary:
174                //              See dojo.data.api.Read.getValues()
175
176                this._assertIsItem(item);
177                var flag = this._assertIsAttribute(attribute);
178
179                if(flag){
180                        if((attribute === "author" || attribute === "contributor" || attribute === "link") && item[attribute+"s"]){
181                                return item[attribute+"s"];
182                        }
183                        if(attribute === "category" && item.categories){
184                                return item.categories;
185                        }
186                        if(item[attribute]){
187                                item = item[attribute];
188                                if(item.nodeType == "Content"){
189                                        return [item.value];
190                                }
191                                return [item] ;
192                        }
193                }
194                return []; //Array
195        },
196
197        getAttributes: function(/* item */ item){
198                // summary:
199                //              See dojo.data.api.Read.getAttributes()
200                this._assertIsItem(item);
201                var attributes = [];
202                for(var key in dojox.atom.io.model._actions){
203                        if(this.hasAttribute(item, key)){
204                                attributes.push(key);
205                        }
206                }
207                return attributes; //Array
208        },
209
210        hasAttribute: function( /* item */ item,
211                                                        /* attribute-name-string */ attribute){
212                // summary:
213                //              See dojo.data.api.Read.hasAttribute()
214                return this.getValues(item, attribute).length > 0;
215        },
216
217        containsValue: function(/* item */ item,
218                                                        /* attribute-name-string */ attribute,
219                                                        /* anything */ value){
220                // summary:
221                //              See dojo.data.api.Read.containsValue()
222                var regexp = undefined;
223                if(typeof value === "string"){
224                        regexp = dojo.data.util.filter.patternToRegExp(value, false);
225                }
226                return this._containsValue(item, attribute, value, regexp); //boolean.
227        },
228
229        _containsValue: function(       /* item */ item,
230                                                                /* attribute-name-string */ attribute,
231                                                                /* anything */ value,
232                                                                /* RegExp?*/ regexp,
233                                                                /* Boolean?*/ trim){
234                // summary:
235                //              Internal function for looking at the values contained by the item.
236                // description:
237                //              Internal function for looking at the values contained by the item.  This
238                //              function allows for denoting if the comparison should be case sensitive for
239                //              strings or not (for handling filtering cases where string case should not matter)
240                //
241                // item:
242                //              The data item to examine for attribute values.
243                // attribute:
244                //              The attribute to inspect.
245                // value:
246                //              The value to match.
247                // regexp:
248                //              Optional regular expression generated off value if value was of string type to handle wildcarding.
249                //              If present and attribute values are string, then it can be used for comparison instead of 'value'
250                var values = this.getValues(item, attribute);
251                for(var i = 0; i < values.length; ++i){
252                        var possibleValue = values[i];
253                        if(typeof possibleValue === "string" && regexp){
254                                if(trim){
255                                        possibleValue = possibleValue.replace(new RegExp(/^\s+/),""); // START
256                                        possibleValue = possibleValue.replace(new RegExp(/\s+$/),""); // END
257                                }
258                                possibleValue = possibleValue.replace(/\r|\n|\r\n/g, "");
259                                return (possibleValue.match(regexp) !== null);
260                        }else{
261                                //Non-string matching.
262                                if(value === possibleValue){
263                                        return true; // Boolean
264                                }
265                        }
266                }
267                return false; // Boolean
268        },
269
270        isItem: function(/* anything */ something){
271                // summary:
272                //              See dojo.data.api.Read.isItem()
273                return something && something.store && something.store === this; //boolean
274        },
275
276        isItemLoaded: function(/* anything */ something){
277                // summary:
278                //              See dojo.data.api.Read.isItemLoaded()
279                return this.isItem(something);
280        },
281
282        loadItem: function(/* Object */ keywordArgs){
283                // summary:
284                //              See dojo.data.api.Read.loadItem()
285                this._assertIsItem(keywordArgs.item);
286        },
287       
288        _fetchItems: function(request, fetchHandler, errorHandler){
289                // summary:
290                //              Fetch items (Atom entries) that match to a query
291                // description:
292                //              Fetch items (Atom entries) that match to a query
293                // request:
294                //              A request object
295                // fetchHandler:
296                //              A function to call for fetched items
297                // errorHandler:
298                //              A function to call on error
299                if(this._feed){
300                        this._finishFetchItems(request, fetchHandler, errorHandler);
301                }else{
302                        var flag = false;
303                        if(!this._requests){
304                                this._requests = [];
305                                flag = true;
306                        }
307                        this._requests.push({request: request, fh: fetchHandler, eh: errorHandler});
308                        if(flag){
309                                this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
310                                this._atomIO.getFeed(this.url,this._setFeed, null, this);
311                        }
312                }
313        },
314               
315        _finishFetchItems: function(request, fetchHandler, errorHandler){
316                // summary:
317                //              Internal function for finishing a fetch request.
318                // description:
319                //              Internal function for finishing a fetch request.  Needed since the feed
320                //              might not have been loaded, so we finish the fetch in a callback.
321                //
322                // request:
323                //              A request object
324                // fetchHandler:
325                //              A function to call for fetched items
326                // errorHandler:
327                //              A function to call on error
328                var items = null;
329                var arrayOfAllItems = this._getAllItems();
330                if(request.query){
331                        var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false;
332                        items = [];
333
334                        //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
335                        //same value for each item examined.  Much more efficient.
336                        var regexpList = {};
337                        var key;
338                        var value;
339                        for(key in request.query){
340                                value = request.query[key]+'';
341                                if(typeof value === "string"){
342                                        regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
343                                }
344                        }
345
346                        for(var i = 0; i < arrayOfAllItems.length; ++i){
347                                var match = true;
348                                var candidateItem = arrayOfAllItems[i];
349                                for(key in request.query){
350                                        value = request.query[key]+'';
351                                        if(!this._containsValue(candidateItem, key, value, regexpList[key], request.trim)){
352                                                match = false;
353                                        }
354                                }
355                                if(match){
356                                        items.push(candidateItem);
357                                }
358                        }
359                }else{
360                        // We want a copy to pass back in case the parent wishes to sort the array.  We shouldn't allow resort
361                        // of the internal list so that multiple callers can get listsand sort without affecting each other.
362                        if(arrayOfAllItems.length> 0){
363                                items = arrayOfAllItems.slice(0,arrayOfAllItems.length);
364                        }
365                }
366                try{
367                        fetchHandler(items, request);
368                }catch(e){
369                        errorHandler(e, request);
370                }
371        },
372
373        getFeatures: function(){
374                // summary:
375                //              See dojo.data.api.Read.getFeatures()
376                return {
377                        'dojo.data.api.Read': true,
378                        'dojo.data.api.Write': true,
379                        'dojo.data.api.Identity': true
380                };
381        },
382       
383        close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
384                // summary:
385                //              See dojo.data.api.Read.close()
386                // nothing to do here!
387                this._feed = null;
388        },
389
390        getLabel: function(/* item */ item){
391                // summary:
392                //              See dojo.data.api.Read.getLabel()
393                if(this.isItem(item)){
394                        return this.getValue(item, "title", "No Title");
395                }
396                return undefined;
397        },
398
399        getLabelAttributes: function(/* item */ item){
400                // summary:
401                //              See dojo.data.api.Read.getLabelAttributes()
402                return ["title"];
403        },
404
405/***************************************
406     dojo.data.api.Identity API
407***************************************/
408
409        getIdentity: function(/* item */ item){
410                // summary:
411                //              See dojo.data.api.Identity.getIdentity()
412                this._assertIsItem(item);
413                return this.getValue(item, "id");
414        },
415
416        getIdentityAttributes: function(/* item */ item){
417                 //     summary:
418                 //             See dojo.data.api.Identity.getIdentityAttributes()
419                 return ["id"];
420        },
421
422        fetchItemByIdentity: function(keywordArgs){
423                // summary:
424                //              See dojo.data.api.Identity.fetchItemByIdentity()
425
426                this._fetchItems({query:{id:keywordArgs.identity}, onItem: keywordArgs.onItem, scope: keywordArgs.scope},
427                        function(items, request){
428                                var scope = request.scope;
429                                if(!scope){
430                                        scope = dojo.global;
431                                }
432                                if(items.length < 1){
433                                        request.onItem.call(scope, null);
434                                }else{
435                                        request.onItem.call(scope, items[0]);
436                                }
437                }, keywordArgs.onError);
438        },
439
440/***************************************
441     dojo.data.api.Identity API
442***************************************/
443
444        newItem: function(/* Object? */ keywordArgs){
445                // summary:
446                //              See dojo.data.api.Write.newItem()
447                var entry = new dojox.atom.io.model.Entry();
448                var value = null;
449                var temp = null;
450                var i;
451                for(var key in keywordArgs){
452                        if(this._assertIsAttribute(key)){
453                                value = keywordArgs[key];
454                                switch(key){
455                                        case "link":
456                                                for(i in value){
457                                                        temp = value[i];
458                                                        entry.addLink(temp.href,temp.rel,temp.hrefLang,temp.title,temp.type);
459                                                }
460                                                break;
461                                        case "author":
462                                                for(i in value){
463                                                        temp = value[i];
464                                                        entry.addAuthor(temp.name, temp.email, temp.uri);
465                                                }
466                                                break;
467                                        case "contributor":
468                                                for(i in value){
469                                                        temp = value[i];
470                                                        entry.addContributor(temp.name, temp.email, temp.uri);
471                                                }
472                                                break;
473                                        case "category":
474                                                for(i in value){
475                                                        temp = value[i];
476                                                        entry.addCategory(temp.scheme, temp.term, temp.label);
477                                                }
478                                                break;
479                                        case "icon":
480                                        case "id":
481                                        case "logo":
482                                        case "xmlBase":
483                                        case "rights":
484                                                entry[key] = value;
485                                                break;
486                                        case "updated":
487                                        case "published":
488                                        case "issued":
489                                        case "modified":
490                                                entry[key] = dojox.atom.io.model.util.createDate(value);
491                                                break;
492                                        case "content":
493                                        case "summary":
494                                        case "title":
495                                        case "subtitle":
496                                                entry[key] = new dojox.atom.io.model.Content(key);
497                                                entry[key].value = value;
498                                                break;
499                                        default:
500                                                entry[key] = value;
501                                                break;
502                                }
503                        }
504                }
505                entry.store = this;
506                entry.isDirty = true;
507
508                if(!this._adds){
509                        this._adds = [entry];
510                }else{
511                        this._adds.push(entry);
512                }
513
514                if(this._feed){
515                        this._feed.addEntry(entry);
516                }else{
517                        if(this._requests){
518                                this._requests.push({add:entry});
519                        }else{
520                                this._requests = [{add:entry}];
521                                this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
522                                this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
523                        }
524                }
525                return true;
526        },
527
528        deleteItem: function(/* item */ item){
529                // summary:
530                //              See dojo.data.api.Write.deleteItem()
531                this._assertIsItem(item);
532
533                if(!this._deletes){
534                        this._deletes = [item];
535                }else{
536                        this._deletes.push(item);
537                }
538
539                if(this._feed){
540                        this._feed.removeEntry(item);
541                }else{
542                        if(this._requests){
543                                this._requests.push({remove:item});
544                        }else{
545                                this._requests = [{remove:item}];
546                                this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
547                                this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
548                        }
549                }
550                item = null;
551                return true;
552        },
553
554        setValue: function(     /* item */ item,
555                                                /* string */ attribute,
556                                                /* almost anything */ value){
557                // summary:
558                //              See dojo.data.api.Write.setValue()
559                this._assertIsItem(item);
560               
561                var update = {item: item};
562                if(this._assertIsAttribute(attribute)){
563                        switch(attribute){
564                                case "link":
565                                        update.links = item.links;
566                                        this._addUpdate(update);
567                                        item.links = null;
568                                        item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
569                                        item.isDirty = true;
570                                        return true;
571                                case "author":
572                                        update.authors = item.authors;
573                                        this._addUpdate(update);
574                                        item.authors = null;
575                                        item.addAuthor(value.name, value.email, value.uri);
576                                        item.isDirty = true;
577                                        return true;
578                                case "contributor":
579                                        update.contributors = item.contributors;
580                                        this._addUpdate(update);
581                                        item.contributors = null;
582                                        item.addContributor(value.name, value.email, value.uri);
583                                        item.isDirty = true;
584                                        return true;
585                                case "category":
586                                        update.categories = item.categories;
587                                        this._addUpdate(update);
588                                        item.categories = null;
589                                        item.addCategory(value.scheme, value.term, value.label);
590                                        item.isDirty = true;
591                                        return true;
592                                case "icon":
593                                case "id":
594                                case "logo":
595                                case "xmlBase":
596                                case "rights":
597                                        update[attribute] = item[attribute];
598                                        this._addUpdate(update);
599                                        item[attribute] = value;
600                                        item.isDirty = true;
601                                        return true;
602                                case "updated":
603                                case "published":
604                                case "issued":
605                                case "modified":
606                                        update[attribute] = item[attribute];
607                                        this._addUpdate(update);
608                                        item[attribute] = dojox.atom.io.model.util.createDate(value);
609                                        item.isDirty = true;
610                                        return true;
611                                case "content":
612                                case "summary":
613                                case "title":
614                                case "subtitle":
615                                        update[attribute] = item[attribute];
616                                        this._addUpdate(update);
617                                        item[attribute] = new dojox.atom.io.model.Content(attribute);
618                                        item[attribute].value = value;
619                                        item.isDirty = true;
620                                        return true;
621                                default:
622                                        update[attribute] = item[attribute];
623                                        this._addUpdate(update);
624                                        item[attribute] = value;
625                                        item.isDirty = true;
626                                        return true;
627                        }
628                }
629                return false;
630        },
631
632        setValues: function(/* item */ item,
633                                                /* string */ attribute,
634                                                /* array */ values){
635                // summary:
636                //              See dojo.data.api.Write.setValues()
637                if(values.length === 0){
638                        return this.unsetAttribute(item, attribute);
639                }
640                this._assertIsItem(item);
641               
642                var update = {item: item};
643                var value;
644                var i;
645                if(this._assertIsAttribute(attribute)){
646                        switch(attribute){
647                                case "link":
648                                        update.links = item.links;
649                                        item.links = null;
650                                        for(i in values){
651                                                value = values[i];
652                                                item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
653                                        }
654                                        item.isDirty = true;
655                                        return true;
656                                case "author":
657                                        update.authors = item.authors;
658                                        item.authors = null;
659                                        for(i in values){
660                                                value = values[i];
661                                                item.addAuthor(value.name, value.email, value.uri);
662                                        }
663                                        item.isDirty = true;
664                                        return true;
665                                case "contributor":
666                                        update.contributors = item.contributors;
667                                        item.contributors = null;
668                                        for(i in values){
669                                                value = values[i];
670                                                item.addContributor(value.name, value.email, value.uri);
671                                        }
672                                        item.isDirty = true;
673                                        return true;
674                                case "categories":
675                                        update.categories = item.categories;
676                                        item.categories = null;
677                                        for(i in values){
678                                                value = values[i];
679                                                item.addCategory(value.scheme, value.term, value.label);
680                                        }
681                                        item.isDirty = true;
682                                        return true;
683                                case "icon":
684                                case "id":
685                                case "logo":
686                                case "xmlBase":
687                                case "rights":
688                                        update[attribute] = item[attribute];
689                                        item[attribute] = values[0];
690                                        item.isDirty = true;
691                                        return true;
692                                case "updated":
693                                case "published":
694                                case "issued":
695                                case "modified":
696                                        update[attribute] = item[attribute];
697                                        item[attribute] = dojox.atom.io.model.util.createDate(values[0]);
698                                        item.isDirty = true;
699                                        return true;
700                                case "content":
701                                case "summary":
702                                case "title":
703                                case "subtitle":
704                                        update[attribute] = item[attribute];
705                                        item[attribute] = new dojox.atom.io.model.Content(attribute);
706                                        item[attribute].values[0] = values[0];
707                                        item.isDirty = true;
708                                        return true;
709                                default:
710                                        update[attribute] = item[attribute];
711                                        item[attribute] = values[0];
712                                        item.isDirty = true;
713                                        return true;
714                        }
715                }
716                this._addUpdate(update);
717                return false;
718        },
719
720        unsetAttribute: function(       /* item */ item,
721                                                                /* string */ attribute){
722                // summary:
723                //              See dojo.data.api.Write.unsetAttribute()
724                this._assertIsItem(item);
725                if(this._assertIsAttribute(attribute)){
726                        if(item[attribute] !== null){
727                                var update = {item: item};
728                                switch(attribute){
729                                        case "author":
730                                        case "contributor":
731                                        case "link":
732                                                update[attribute+"s"] = item[attribute+"s"];
733                                                break;
734                                        case "category":
735                                                update.categories = item.categories;
736                                                break;
737                                        default:
738                                                update[attribute] = item[attribute];
739                                                break;
740                                }
741                                item.isDirty = true;
742                                item[attribute] = null;
743                                this._addUpdate(update);
744                                return true;
745                        }
746                }
747                return false; // boolean
748        },
749
750        save: function(/* object */ keywordArgs){
751                // summary:
752                //              See dojo.data.api.Write.save()
753                // keywordArgs:
754                //              {
755                //                      onComplete: function
756                //                      onError: function
757                //                      scope: object
758                //              }
759                var i;
760                for(i in this._adds){
761                        this._atomIO.addEntry(this._adds[i], null, function(){}, keywordArgs.onError, false, keywordArgs.scope);
762                }
763                       
764                this._adds = null;
765               
766                for(i in this._updates){
767                        this._atomIO.updateEntry(this._updates[i].item, function(){}, keywordArgs.onError, false, this.xmethod, keywordArgs.scope);
768                }
769                       
770                this._updates = null;
771               
772                for(i in this._deletes){
773                        this._atomIO.removeEntry(this._deletes[i], function(){}, keywordArgs.onError, this.xmethod, keywordArgs.scope);
774                }
775                       
776                this._deletes = null;
777               
778                this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
779               
780                if(keywordArgs.onComplete){
781                        var scope = keywordArgs.scope || dojo.global;
782                        keywordArgs.onComplete.call(scope);
783                }
784        },
785
786        revert: function(){
787                // summary:
788                //              See dojo.data.api.Write.revert()
789                var i;
790                for(i in this._adds){
791                        this._feed.removeEntry(this._adds[i]);
792                }
793                       
794                this._adds = null;
795               
796                var update, item, key;
797                for(i in this._updates){
798                        update = this._updates[i];
799                        item = update.item;
800                        for(key in update){
801                                if(key !== "item"){
802                                        item[key] = update[key];
803                                }
804                        }
805                }
806                this._updates = null;
807               
808                for(i in this._deletes){
809                        this._feed.addEntry(this._deletes[i]);
810                }
811                this._deletes = null;
812                return true;
813        },
814
815        isDirty: function(/* item? */ item){
816                // summary:
817                //              See dojo.data.api.Write.isDirty()
818                if(item){
819                        this._assertIsItem(item);
820                        return item.isDirty?true:false; //boolean
821                }
822                return (this._adds !== null || this._updates !== null); //boolean
823        }
824});
825dojo.extend(dojox.data.AppStore,dojo.data.util.simpleFetch);
826
827return dojox.data.AppStore;
828});
Note: See TracBrowser for help on using the repository browser.