Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / pkgs / data-xml-debug.js
1 /*!
2  * Ext JS Library 3.0.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.data.XmlWriter
9  * @extends Ext.data.DataWriter
10  * DataWriter extension for writing an array or single {@link Ext.data.Record} object(s) in preparation for executing a remote CRUD action via XML.
11  */
12 Ext.data.XmlWriter = Ext.extend(Ext.data.DataWriter, {
13     /**
14      * Final action of a write event.  Apply the written data-object to params.
15      * @param {String} action [Ext.data.Api.create|read|update|destroy]
16      * @param {Record[]} rs
17      * @param {Object} http params
18      * @param {Object} data object populated according to DataReader meta-data "root" and "idProperty"
19      */
20     render : function(action, rs, params, data) {
21         // no impl.
22     },
23     /**
24      * createRecord
25      * @param {Ext.data.Record} rec
26      */
27     createRecord : function(rec) {
28         // no impl
29     },
30     /**
31      * updateRecord
32      * @param {Ext.data.Record} rec
33      */
34     updateRecord : function(rec) {
35         // no impl.
36
37     },
38     /**
39      * destroyRecord
40      * @param {Ext.data.Record} rec
41      */
42     destroyRecord : function(rec) {
43         // no impl
44     }
45 });/**
46  * @class Ext.data.XmlReader
47  * @extends Ext.data.DataReader
48  * <p>Data reader class to create an Array of {@link Ext.data.Record} objects from an XML document
49  * based on mappings in a provided {@link Ext.data.Record} constructor.</p>
50  * <p><b>Note</b>: that in order for the browser to parse a returned XML document, the Content-Type
51  * header in the HTTP response must be set to "text/xml" or "application/xml".</p>
52  * <p>Example code:</p>
53  * <pre><code>
54 var Employee = Ext.data.Record.create([
55    {name: 'name', mapping: 'name'},     // "mapping" property not needed if it is the same as "name"
56    {name: 'occupation'}                 // This field will use "occupation" as the mapping.
57 ]);
58 var myReader = new Ext.data.XmlReader({
59    totalRecords: "results", // The element which contains the total dataset size (optional)
60    record: "row",           // The repeated element which contains row information
61    id: "id"                 // The element within the row that provides an ID for the record (optional)
62 }, Employee);
63 </code></pre>
64  * <p>
65  * This would consume an XML file like this:
66  * <pre><code>
67 &lt;?xml version="1.0" encoding="UTF-8"?>
68 &lt;dataset>
69  &lt;results>2&lt;/results>
70  &lt;row>
71    &lt;id>1&lt;/id>
72    &lt;name>Bill&lt;/name>
73    &lt;occupation>Gardener&lt;/occupation>
74  &lt;/row>
75  &lt;row>
76    &lt;id>2&lt;/id>
77    &lt;name>Ben&lt;/name>
78    &lt;occupation>Horticulturalist&lt;/occupation>
79  &lt;/row>
80 &lt;/dataset>
81 </code></pre>
82  * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records
83  * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
84  * paged from the remote server.
85  * @cfg {String} record The DomQuery path to the repeated element which contains record information.
86  * @cfg {String} success The DomQuery path to the success attribute used by forms.
87  * @cfg {String} idPath The DomQuery path relative from the record element to the element that contains
88  * a record identifier value.
89  * @constructor
90  * Create a new XmlReader.
91  * @param {Object} meta Metadata configuration options
92  * @param {Object} recordType Either an Array of field definition objects as passed to
93  * {@link Ext.data.Record#create}, or a Record constructor object created using {@link Ext.data.Record#create}.
94  */
95 Ext.data.XmlReader = function(meta, recordType){
96     meta = meta || {};
97     Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
98 };
99 Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
100     /**
101      * This method is only used by a DataProxy which has retrieved data from a remote server.
102      * @param {Object} response The XHR object which contains the parsed XML document.  The response is expected
103      * to contain a property called <tt>responseXML</tt> which refers to an XML document object.
104      * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
105      * a cache of Ext.data.Records.
106      */
107     read : function(response){
108         var doc = response.responseXML;
109         if(!doc) {
110             throw {message: "XmlReader.read: XML Document not available"};
111         }
112         return this.readRecords(doc);
113     },
114
115     /**
116      * Create a data block containing Ext.data.Records from an XML document.
117      * @param {Object} doc A parsed XML document.
118      * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
119      * a cache of Ext.data.Records.
120      */
121     readRecords : function(doc){
122         /**
123          * After any data loads/reads, the raw XML Document is available for further custom processing.
124          * @type XMLDocument
125          */
126         this.xmlData = doc;
127         var root = doc.documentElement || doc;
128         var q = Ext.DomQuery;
129         var recordType = this.recordType, fields = recordType.prototype.fields;
130         var sid = this.meta.idPath || this.meta.id;
131         var totalRecords = 0, success = true;
132         if(this.meta.totalRecords){
133             totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
134         }
135
136         if(this.meta.success){
137             var sv = q.selectValue(this.meta.success, root, true);
138             success = sv !== false && sv !== 'false';
139         }
140         var records = [];
141         var ns = q.select(this.meta.record, root);
142         for(var i = 0, len = ns.length; i < len; i++) {
143             var n = ns[i];
144             var values = {};
145             var id = sid ? q.selectValue(sid, n) : undefined;
146             for(var j = 0, jlen = fields.length; j < jlen; j++){
147                 var f = fields.items[j];
148                 var v = q.selectValue(Ext.value(f.mapping, f.name, true), n, f.defaultValue);
149                 v = f.convert(v, n);
150                 values[f.name] = v;
151             }
152             var record = new recordType(values, id);
153             record.node = n;
154             records[records.length] = record;
155         }
156
157         return {
158             success : success,
159             records : records,
160             totalRecords : totalRecords || records.length
161         };
162     },
163
164     // TODO: implement readResponse for XmlReader
165     readResponse : Ext.emptyFn
166 });/**\r
167  * @class Ext.data.XmlStore\r
168  * @extends Ext.data.Store\r
169  * <p>Small helper class to make creating {@link Ext.data.Store}s from XML data easier.\r
170  * A XmlStore will be automatically configured with a {@link Ext.data.XmlReader}.</p>\r
171  * <p>A store configuration would be something like:<pre><code>\r
172 var store = new Ext.data.XmlStore({\r
173     // store configs\r
174     autoDestroy: true,\r
175     storeId: 'myStore',\r
176     url: 'sheldon.xml', // automatically configures a HttpProxy\r
177     // reader configs\r
178     record: 'Item', // records will have an "Item" tag\r
179     idPath: 'ASIN',\r
180     totalRecords: '@TotalResults'\r
181     fields: [\r
182         // set up the fields mapping into the xml doc\r
183         // The first needs mapping, the others are very basic\r
184         {name: 'Author', mapping: 'ItemAttributes > Author'},\r
185         'Title', 'Manufacturer', 'ProductGroup'\r
186     ]\r
187 });\r
188  * </code></pre></p>\r
189  * <p>This store is configured to consume a returned object of the form:<pre><code>\r
190 &#60?xml version="1.0" encoding="UTF-8"?>\r
191 &#60ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2009-05-15">\r
192     &#60Items>\r
193         &#60Request>\r
194             &#60IsValid>True&#60/IsValid>\r
195             &#60ItemSearchRequest>\r
196                 &#60Author>Sidney Sheldon&#60/Author>\r
197                 &#60SearchIndex>Books&#60/SearchIndex>\r
198             &#60/ItemSearchRequest>\r
199         &#60/Request>\r
200         &#60TotalResults>203&#60/TotalResults>\r
201         &#60TotalPages>21&#60/TotalPages>\r
202         &#60Item>\r
203             &#60ASIN>0446355453&#60/ASIN>\r
204             &#60DetailPageURL>\r
205                 http://www.amazon.com/\r
206             &#60/DetailPageURL>\r
207             &#60ItemAttributes>\r
208                 &#60Author>Sidney Sheldon&#60/Author>\r
209                 &#60Manufacturer>Warner Books&#60/Manufacturer>\r
210                 &#60ProductGroup>Book&#60/ProductGroup>\r
211                 &#60Title>Master of the Game&#60/Title>\r
212             &#60/ItemAttributes>\r
213         &#60/Item>\r
214     &#60/Items>\r
215 &#60/ItemSearchResponse>\r
216  * </code></pre>\r
217  * An object literal of this form could also be used as the {@link #data} config option.</p>\r
218  * <p><b>Note:</b> Although not listed here, this class accepts all of the configuration options of \r
219  * <b>{@link Ext.data.XmlReader XmlReader}</b>.</p>\r
220  * @constructor\r
221  * @param {Object} config\r
222  * @xtype xmlstore\r
223  */\r
224 Ext.data.XmlStore = Ext.extend(Ext.data.Store, {\r
225     /**\r
226      * @cfg {Ext.data.DataReader} reader @hide\r
227      */\r
228     constructor: function(config){\r
229         Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {\r
230             reader: new Ext.data.XmlReader(config)\r
231         }));\r
232     }\r
233 });\r
234 Ext.reg('xmlstore', Ext.data.XmlStore);