]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/data/HtmlStore.js
Comment class stub
[eow] / static / dojo-release-1.1.1 / dojox / data / HtmlStore.js
1 if(!dojo._hasResource["dojox.data.HtmlStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.data.HtmlStore"] = true;
3 dojo.provide("dojox.data.HtmlStore");
4
5 dojo.require("dojox.data.dom");
6 dojo.require("dojo.data.util.simpleFetch");
7 dojo.require("dojo.data.util.filter");
8
9 dojo.declare("dojox.data.HtmlStore", null, {
10         constructor: function(/*Object*/args){
11                 //      summary:
12                 //              Initializer for the HTML table store.  
13                 //      description:
14                 //              The HtmlStore can be created in one of two ways: a) by parsing an existing
15                 //              table or list DOM node on the current page or b) by referencing an external url and giving
16                 //              the id of the table or listin that page.  The remote url will be parsed as an html page.
17                 //
18                 //              The HTML table or list should be of the following form:
19                 //
20                 //              |       <table id="myTable">
21                 //              |               <thead>
22                 //              |                       <tr>
23                 //              |                               <th>Attribute1</th>
24                 //              |                               <th>Attribute2</th>
25                 //              |                       </tr>
26                 //              |               </thead>
27                 //              |               <tbody>
28                 //              |                       <tr>
29                 //              |                               <td>Value1.1</td>
30                 //              |                               <td>Value1.2</td>
31                 //              |                       </tr>
32                 //              |                       <tr>
33                 //              |                               <td>Value2.1</td>
34                 //              |                               <td>Value2.2</td>
35                 //              |                       </tr>
36                 //              |               </tbody>
37                 //              |       </table>
38                 //
39                 // -or-
40                 //
41                 //              |       <ul id="myUnorderedList">
42                 //              |               <li>Value.1</li>
43                 //              |               <li>Value.2</li>
44                 //              |       </ul>
45                 //
46                 // -or-
47                 //
48                 //              |       <ol id="myOrderedList">
49                 //              |               <li>Value.1</li>
50                 //              |               <li>Value.2</li>
51                 //              |       </ol>
52                 //
53                 //      args:
54                 //              An anonymous object to initialize properties.  It expects the following values:
55                 //              dataId: The id of the HTML table to use.
56                 //              OR
57                 //              url:    The url of the remote page to load
58                 //              dataId: The id of the table element in the remote page
59                 
60                 if(args.url){
61                         if(!args.dataId)
62                                 throw new Error("dojo.data.HtmlStore: Cannot instantiate using url without an id!");
63                         this.url = args.url;
64                         this.dataId = args.dataId;
65                 }else{
66                         if(args.dataId){
67                                 this._rootNode = dojo.byId(args.dataId);
68                                 this.dataId = this._rootNode.id;
69                         }else{
70                                 this._rootNode = dojo.byId(this.dataId);
71                         }
72                         this._indexItems();
73                 }
74         },
75
76         url: "",     // So the parser can instantiate the store via markup.
77         dataId: "", // So the parser can instantiate the store via markup.
78         
79         _indexItems: function(){
80                 this._getHeadings();
81                 if (this._rootNode.rows){//tables
82                         if(this._rootNode.tBodies && this._rootNode.tBodies.length > 0) {
83                                 this._rootNode = this._rootNode.tBodies[0];
84                         }
85                         var i;
86                         for(i=0; i<this._rootNode.rows.length; i++){
87                                 this._rootNode.rows[i].store = this;
88                                 this._rootNode.rows[i]._ident = i+1;
89                         }
90                 }else{//lists
91                         var c=1;
92                         for(i=0; i<this._rootNode.childNodes.length; i++){
93                                 if(this._rootNode.childNodes[i].nodeType===1){
94                                         this._rootNode.childNodes[i].store = this;
95                                         this._rootNode.childNodes[i]._ident = c;
96                                         c++;
97                                 }
98                         }
99                 }
100         },
101
102         _getHeadings: function(){
103                 //      summary:
104                 //              Function to load the attribute names from the table header so that the 
105                 //              attributes (cells in a row), can have a reasonable name.
106                 //      For list items, returns single implicit heading, ["name"]
107                 this._headings = [];
108                 if(this._rootNode.tHead){
109                         dojo.forEach(this._rootNode.tHead.rows[0].cells, dojo.hitch(this, function(th){
110                                 this._headings.push(dojox.data.dom.textContent(th));
111                         }));
112                 }else{
113                         this._headings = ["name"];
114                 }
115         },
116         
117         _getAllItems: function(){
118                 //      summary:
119                 //              Function to return all rows in the table as an array of items.
120                 var items = [];
121                 var i;
122                 if(this._rootNode.rows){//table
123                         for(i=0; i<this._rootNode.rows.length; i++){
124                                 items.push(this._rootNode.rows[i]);
125                         }
126                 }else{ //list
127                         for(i=0; i<this._rootNode.childNodes.length; i++){
128                                 if (this._rootNode.childNodes[i].nodeType===1){
129                                         items.push(this._rootNode.childNodes[i]);
130                                 }
131                         }
132                 }
133                 return items; //array
134         },
135         
136         _assertIsItem: function(/* item */ item){
137                 //      summary:
138                 //      This function tests whether the item passed in is indeed an item in the store.
139                 //      item: 
140                 //              The item to test for being contained by the store.
141                 if(!this.isItem(item)){ 
142                         throw new Error("dojo.data.HtmlStore: a function was passed an item argument that was not an item");
143                 }
144         },
145
146         _assertIsAttribute: function(/* String */ attribute){
147                 //      summary:
148                 //      This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
149                 //      attribute: 
150                 //              The attribute to test for being contained by the store.
151                 //
152                 //      returns:
153                 //              Returns the index (column) that the attribute resides in the row.
154                 if(typeof attribute !== "string"){ 
155                         throw new Error("dojo.data.HtmlStore: a function was passed an attribute argument that was not an attribute name string");
156                         return -1;
157                 }
158                 return dojo.indexOf(this._headings, attribute); //int
159         },
160
161 /***************************************
162      dojo.data.api.Read API
163 ***************************************/
164         
165         getValue: function(     /* item */ item, 
166                                                 /* attribute-name-string */ attribute, 
167                                                 /* value? */ defaultValue){
168                 //      summary: 
169                 //      See dojo.data.api.Read.getValue()
170                 var values = this.getValues(item, attribute);
171                 return (values.length > 0)?values[0]:defaultValue; //Object || int || Boolean
172         },
173
174         getValues: function(/* item */ item, 
175                                                 /* attribute-name-string */ attribute){
176                 //      summary: 
177                 //              See dojo.data.api.Read.getValues()
178
179                 this._assertIsItem(item);
180                 var index = this._assertIsAttribute(attribute);
181
182                 if(index>-1){
183                         if (item.cells){
184                           return [dojox.data.dom.textContent(item.cells[index])];
185                         }else{//return Value for lists
186                             return [dojox.data.dom.textContent(item)];
187                         }
188                 }
189                 return []; //Array
190         },
191
192         getAttributes: function(/* item */ item){
193                 //      summary: 
194                 //              See dojo.data.api.Read.getAttributes()
195                 this._assertIsItem(item);
196                 var attributes = [];
197                 for(var i=0; i<this._headings.length; i++){
198                         if(this.hasAttribute(item, this._headings[i]))
199                                 attributes.push(this._headings[i]);
200                 }
201                 return attributes; //Array
202         },
203
204         hasAttribute: function( /* item */ item,
205                                                         /* attribute-name-string */ attribute){
206                 //      summary: 
207                 //              See dojo.data.api.Read.hasAttribute()
208                 return this.getValues(item, attribute).length > 0;
209         },
210
211         containsValue: function(/* item */ item, 
212                                                         /* attribute-name-string */ attribute, 
213                                                         /* anything */ value){
214                 //      summary: 
215                 //              See dojo.data.api.Read.containsValue()
216                 var regexp = undefined;
217                 if(typeof value === "string"){
218                    regexp = dojo.data.util.filter.patternToRegExp(value, false);
219                 }
220                 return this._containsValue(item, attribute, value, regexp); //boolean.
221         },
222
223         _containsValue: function(       /* item */ item, 
224                                                                 /* attribute-name-string */ attribute, 
225                                                                 /* anything */ value,
226                                                                 /* RegExp?*/ regexp){
227                 //      summary: 
228                 //              Internal function for looking at the values contained by the item.
229                 //      description: 
230                 //              Internal function for looking at the values contained by the item.  This 
231                 //              function allows for denoting if the comparison should be case sensitive for
232                 //              strings or not (for handling filtering cases where string case should not matter)
233                 //      
234                 //      item:
235                 //              The data item to examine for attribute values.
236                 //      attribute:
237                 //              The attribute to inspect.
238                 //      value:  
239                 //              The value to match.
240                 //      regexp:
241                 //              Optional regular expression generated off value if value was of string type to handle wildcarding.
242                 //              If present and attribute values are string, then it can be used for comparison instead of 'value'
243                 var values = this.getValues(item, attribute);
244                 for(var i = 0; i < values.length; ++i){
245                         var possibleValue = values[i];
246                         if(typeof possibleValue === "string" && regexp){
247                                 return (possibleValue.match(regexp) !== null);
248                         }else{
249                                 //Non-string matching.
250                                 if(value === possibleValue){
251                                         return true; // Boolean
252                                 }
253                         }
254                 }
255                 return false; // Boolean
256         },
257
258         isItem: function(/* anything */ something){
259                 //      summary: 
260                 //              See dojo.data.api.Read.isItem()
261                 if(something && something.store && something.store === this){
262                         return true; //boolean
263                 }
264                 return false; //boolean
265         },
266
267         isItemLoaded: function(/* anything */ something){
268                 //      summary: 
269                 //              See dojo.data.api.Read.isItemLoaded()
270                 return this.isItem(something);
271         },
272
273         loadItem: function(/* Object */ keywordArgs){
274                 //      summary: 
275                 //              See dojo.data.api.Read.loadItem()
276                 this._assertIsItem(keywordArgs.item);
277         },
278         
279         _fetchItems: function(request, fetchHandler, errorHandler){
280                 //      summary:
281                 //              Fetch items (XML elements) that match to a query
282                 //      description:
283                 //              If '_fetchUrl' is specified, it is used to load an XML document
284                 //              with a query string.
285                 //              Otherwise and if 'url' is specified, the XML document is
286                 //              loaded and list XML elements that match to a query (set of element
287                 //              names and their text attribute values that the items to contain).
288                 //              A wildcard, "*" can be used to query values to match all
289                 //              occurrences.
290                 //              If '_rootItem' is specified, it is used to fetch items.
291                 //      request:
292                 //              A request object
293                 //      fetchHandler:
294                 //              A function to call for fetched items
295                 //      errorHandler:
296                 //              A function to call on error
297                 
298                 if(this._rootNode){
299                         this._finishFetchItems(request, fetchHandler, errorHandler);
300                 }else{
301                         if(!this.url){
302                                 this._rootNode = dojo.byId(this.dataId);
303                         }else{
304                                 var getArgs = {
305                                                 url: this.url,
306                                                 handleAs: "text"
307                                         };
308                                 var self = this;
309                                 var getHandler = dojo.xhrGet(getArgs);
310                                 getHandler.addCallback(function(data){
311                                         var findNode = function(node, id){
312                                                 if(node.id == id){
313                                                         return node; //object
314                                                 }
315                                                 if(node.childNodes){
316                                                         for(var i=0; i<node.childNodes.length; i++){
317                                                                 var returnNode = findNode(node.childNodes[i], id);
318                                                                 if(returnNode){
319                                                                         return returnNode; //object
320                                                                 }
321                                                         }
322                                                 }
323                                                 return null; //null
324                                         }
325
326                                         var d = document.createElement("div");
327                                         d.innerHTML = data;
328                                         self._rootNode = findNode(d, self.dataId);
329                                         self._indexItems();
330                                         self._finishFetchItems(request, fetchHandler, errorHandler);
331                                 });
332                                 getHandler.addErrback(function(error){
333                                         errorHandler(error, request);
334                                 });
335                         }
336                 }
337         },
338         
339         _finishFetchItems: function(request, fetchHandler, errorHandler){
340                 //      summary:
341                 //              Internal function for processing the passed in request and locating the requested items.
342                 var items = null;
343                 var arrayOfAllItems = this._getAllItems();
344                 if(request.query){
345                         var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false; 
346                         items = [];
347
348                         //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
349                         //same value for each item examined.  Much more efficient.
350                         var regexpList = {};
351                         var key;
352                         var value;
353                         for(key in request.query){
354                                 value = request.query[key]+'';
355                                 if(typeof value === "string"){
356                                         regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
357                                 }
358                         }
359
360                         for(var i = 0; i < arrayOfAllItems.length; ++i){
361                                 var match = true;
362                                 var candidateItem = arrayOfAllItems[i];
363                                 for(key in request.query){
364                                         value = request.query[key]+'';
365                                         if (!this._containsValue(candidateItem, key, value, regexpList[key])){
366                                                 match = false;
367                                         }
368                                 }
369                                 if(match){
370                                         items.push(candidateItem);
371                                 }
372                         }
373                         fetchHandler(items, request);
374                 }else{
375                         // We want a copy to pass back in case the parent wishes to sort the array.  We shouldn't allow resort 
376                         // of the internal list so that multiple callers can get listsand sort without affecting each other.
377                         if(arrayOfAllItems.length> 0){
378                                 items = arrayOfAllItems.slice(0,arrayOfAllItems.length); 
379                         }
380                         fetchHandler(items, request);
381                 }
382         },
383
384         getFeatures: function(){
385                 //      summary: 
386                 //              See dojo.data.api.Read.getFeatures()
387                 return {
388                         'dojo.data.api.Read': true,
389                         'dojo.data.api.Identity': true
390                 };
391         },
392         
393         close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
394                 //      summary:
395                 //              See dojo.data.api.Read.close()
396                 // nothing to do here!
397         },
398
399         getLabel: function(/* item */ item){
400                 //      summary: 
401                 //              See dojo.data.api.Read.getLabel()
402                 if(this.isItem(item)){
403                         if(item.cells){
404                                 return "Item #" + this.getIdentity(item);
405                         }else{
406                                 return this.getValue(item,"name");
407                         }
408                 }
409                 return undefined;
410         },
411
412         getLabelAttributes: function(/* item */ item){
413                 //      summary: 
414                 //              See dojo.data.api.Read.getLabelAttributes()
415                 if(item.cells){
416                         return null;
417                 }else{
418                         return ["name"];
419                 }
420         },
421
422 /***************************************
423      dojo.data.api.Identity API
424 ***************************************/
425
426         getIdentity: function(/* item */ item){
427                 //      summary: 
428                 //              See dojo.data.api.Identity.getIdentity()
429                 this._assertIsItem(item);
430                 if(this.hasAttribute(item, "name")){
431                         return this.getValue(item,"name");
432                 }else{
433                         return item._ident;
434                 }
435         },
436
437         getIdentityAttributes: function(/* item */ item){
438                  //     summary: 
439                  //             See dojo.data.api.Identity.getIdentityAttributes()
440                  //Identity isn't taken from a public attribute.
441                  return null;
442         },
443
444         fetchItemByIdentity: function(keywordArgs){
445                 //      summary: 
446                 //              See dojo.data.api.Identity.fetchItemByIdentity()
447                 var identity = keywordArgs.identity;
448                 var self = this;
449                 var item = null;
450                 var scope = null;
451
452                 if(!this._rootNode){
453                         if(!this.url){
454                                 this._rootNode = dojo.byId(this.dataId);
455                                 this._indexItems();
456                                 if(self._rootNode.rows){ //Table
457                                         item = this._rootNode.rows[identity + 1];
458                                 }else{ //Lists
459                                         for(var i = 0; i < self._rootNode.childNodes.length; i++){
460                                                 if(self._rootNode.childNodes[i].nodeType === 1 && identity === dojox.data.dom.textContent(self._rootNode.childNodes[i])) {
461                                                                 item = self._rootNode.childNodes[i];
462                                                 }
463                                         }
464                                 }
465                                 if(keywordArgs.onItem){
466                                         scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
467                                         keywordArgs.onItem.call(scope, item);
468                                 }
469
470                         }else{
471                                 var getArgs = {
472                                                 url: this.url,
473                                                 handleAs: "text"
474                                         };
475                                 var getHandler = dojo.xhrGet(getArgs);
476                                 getHandler.addCallback(function(data){
477                                         var findNode = function(node, id){
478                                                 if(node.id == id){
479                                                         return node; //object
480                                                 }
481                                                 if(node.childNodes){
482                                                         for(var i=0; i<node.childNodes.length; i++){
483                                                                 var returnNode = findNode(node.childNodes[i], id);
484                                                                 if(returnNode){
485                                                                         return returnNode; //object
486                                                                 }
487                                                         }
488                                                 }
489                                                 return null; //null
490                                         }
491                                         var d = document.createElement("div");
492                                         d.innerHTML = data;
493                                         self._rootNode = findNode(d, self.dataId);
494                                         self._indexItems();
495                                         if(self._rootNode.rows && identity <= self._rootNode.rows.length){ //Table
496                                                 item = self._rootNode.rows[identity-1];
497                                         }else{ //List
498                                                 for(var i = 0; i < self._rootNode.childNodes.length; i++){
499                                                         if(self._rootNode.childNodes[i].nodeType === 1 && identity === dojox.data.dom.textContent(self._rootNode.childNodes[i])) {
500                                                                         item = self._rootNode.childNodes[i];
501                                                                         break;
502                                                         }
503                                                 }
504                                         }
505                                         if(keywordArgs.onItem){
506                                                 scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
507                                                 keywordArgs.onItem.call(scope, item);
508                                         }
509                                 });
510                                 getHandler.addErrback(function(error){
511                                         if(keywordArgs.onError){
512                                                 scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
513                                                 keywordArgs.onError.call(scope, error);
514
515                                         }
516                                 });
517                         }
518                 }else{
519                         if(this._rootNode.rows[identity+1]){
520                                 item = this._rootNode.rows[identity+1];
521                                 if(keywordArgs.onItem){
522                                         scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
523                                         keywordArgs.onItem.call(scope, item);
524                                 }
525                         }
526                 }
527         }
528 });
529 dojo.extend(dojox.data.HtmlStore,dojo.data.util.simpleFetch);
530
531 }