| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| dojo.provide("dojo.collections.Store"); |
| dojo.require("dojo.lang.common"); |
| |
| /* Store |
| * Designed to be a simple store of data with access methods... |
| * specifically to be mixed into other objects (such as widgets). |
| */ |
| dojo.collections.Store = function(/* array? */jsonArray){ |
| // summary |
| // Data Store with accessor methods. |
| var data = []; |
| this.keyField = "Id"; |
| |
| this.get = function(){ |
| // summary |
| // Get the internal data array, should not be used. |
| return data; // array |
| }; |
| this.getByKey = function(/* string */key){ |
| // summary |
| // Find the internal data object by key. |
| for(var i=0; i<data.length; i++){ |
| if(data[i].key==key){ |
| return data[i]; // object |
| } |
| } |
| return null; // null |
| }; |
| this.getByIndex = function(/*number*/idx){ |
| // summary |
| // Get the internal data object by index. |
| return data[idx]; // object |
| }; |
| |
| this.getData = function(){ |
| // summary |
| // Get an array of source objects. |
| var arr = []; |
| for(var i=0; i<data.length; i++){ |
| arr.push(data[i].src); |
| } |
| return arr; // array |
| }; |
| this.getDataByKey = function(/*string*/key){ |
| // summary |
| // Get the source object by key. |
| for(var i=0; i<data.length; i++){ |
| if(data[i].key==key){ |
| return data[i].src; // object |
| } |
| } |
| return null; // null |
| }; |
| this.getDataByIndex = function(/*number*/idx){ |
| // summary |
| // Get the source object at index idx. |
| return data[idx].src; // object |
| }; |
| |
| this.update = function(/* Object */obj, /* string */fieldPath, /* Object */val){ |
| var parts=fieldPath.split("."), i=0, o=obj, field; |
| if(parts.length>1) { |
| field = parts.pop(); |
| do{ |
| if(parts[i].indexOf("()")>-1){ |
| var temp=parts[i++].split("()")[0]; |
| if(!o[temp]){ |
| dojo.raise("dojo.collections.Store.getField(obj, '" + field + "'): '" + temp + "' is not a property of the passed object."); |
| } else { |
| // this *will* throw an error if the method in question can't be invoked without arguments. |
| o = o[temp](); |
| } |
| } else { |
| o = o[parts[i++]]; |
| } |
| } while (i<parts.length && o != null); |
| } else { |
| field = parts[0]; |
| } |
| |
| obj[field] = val; |
| this.onUpdateField(obj, fieldPath, val); |
| }; |
| |
| this.forEach = function(/* function */fn){ |
| // summary |
| // Functional iteration directly on the internal data array. |
| if(Array.forEach){ |
| Array.forEach(data, fn, this); |
| }else{ |
| for(var i=0; i<data.length; i++){ |
| fn.call(this, data[i]); |
| } |
| } |
| }; |
| this.forEachData = function(/* function */fn){ |
| // summary |
| // Functional iteration on source objects in internal data array. |
| if(Array.forEach){ |
| Array.forEach(this.getData(), fn, this); |
| }else{ |
| var a=this.getData(); |
| for(var i=0; i<a.length; i++){ |
| fn.call(this, a[i]); |
| } |
| } |
| }; |
| |
| this.setData = function(/*array*/arr){ |
| // summary |
| // Set up the internal data. |
| data = []; // don't fire onClearData |
| for(var i=0; i<arr.length; i++){ |
| data.push({ |
| key:arr[i][this.keyField], |
| src:arr[i] |
| }); |
| } |
| this.onSetData(); |
| }; |
| |
| this.clearData = function(){ |
| // summary |
| // Clears the internal data array. |
| data = []; |
| this.onClearData(); |
| }; |
| |
| this.addData = function(/*obj*/obj,/*string?*/key){ |
| // summary |
| // Add an object with optional key to the internal data array. |
| var k = key || obj[this.keyField]; |
| if(this.getByKey(k)){ |
| var o = this.getByKey(k); |
| o.src = obj; |
| } else { |
| var o={ key:k, src:obj }; |
| data.push(o); |
| } |
| this.onAddData(o); |
| }; |
| this.addDataRange = function(/*array*/arr){ |
| // summary |
| // Add a range of objects to the internal data array. |
| var objects=[]; |
| for(var i=0; i<arr.length; i++){ |
| var k = arr[i][this.keyField]; |
| if(this.getByKey(k)){ |
| var o = this.getByKey(k); |
| o.src = obj; |
| } else { |
| var o = { key:k, src:arr[i] }; |
| data.push(o); |
| } |
| objects.push(o); |
| } |
| this.onAddDataRange(objects); |
| }; |
| |
| this.removeData = function(/*obj*/obj){ |
| // summary |
| // remove the passed object from the internal data array. |
| var idx=-1; |
| var o=null; |
| for(var i=0; i<data.length; i++){ |
| if(data[i].src==obj){ |
| idx=i; |
| o=data[i]; |
| break; |
| } |
| } |
| this.onRemoveData(o); |
| if(idx>-1){ |
| data.splice(idx,1); |
| } |
| }; |
| this.removeDataByKey = function(/*string*/key){ |
| // summary |
| // remove the object at key from the internal data array. |
| this.removeData(this.getDataByKey(key)); |
| }; |
| this.removeDataByIndex = function(/*number*/idx){ |
| // summary |
| // remove the object at idx from the internal data array. |
| this.removeData(this.getDataByIndex(idx)); |
| }; |
| |
| if(jsonArray && jsonArray.length && jsonArray[0]){ |
| this.setData(jsonArray); |
| } |
| }; |
| |
| dojo.extend(dojo.collections.Store, { |
| getField:function(/*object*/obj, /*string*/field){ |
| // helper to get the nested value if needed. |
| var parts=field.split("."), i=0, o=obj; |
| do{ |
| if(parts[i].indexOf("()")>-1){ |
| var temp=parts[i++].split("()")[0]; |
| if(!o[temp]){ |
| dojo.raise("dojo.collections.Store.getField(obj, '" + field + "'): '" + temp + "' is not a property of the passed object."); |
| } else { |
| // this *will* throw an error if the method in question can't be invoked without arguments. |
| o = o[temp](); |
| } |
| } else { |
| o = o[parts[i++]]; |
| } |
| } while (i<parts.length && o != null); |
| |
| if(i < parts.length){ |
| dojo.raise("dojo.collections.Store.getField(obj, '" + field + "'): '" + field + "' is not a property of the passed object."); |
| } |
| return o; // object |
| }, |
| getFromHtml:function(/* array */meta, /* HTMLTableBody */body, /* function? */fnMod){ |
| // summary |
| // Parse HTML data into native JSON structure for the store. |
| var rows = body.rows; |
| |
| // create a data constructor. |
| var ctor=function(row){ |
| var obj = {}; |
| for(var i=0; i<meta.length; i++){ |
| var o = obj; |
| var data = row.cells[i].innerHTML; |
| var p = meta[i].getField(); |
| if(p.indexOf(".") > -1){ |
| p = p.split("."); |
| while(p.length>1){ |
| var pr = p.shift(); |
| o[pr] = {}; |
| o = o[pr]; |
| } |
| p = p[0]; |
| } |
| |
| var type = meta[i].getType(); |
| if(type == String){ |
| o[p] = data; |
| } else { |
| if(data){ |
| o[p] = new type(data); |
| } else { |
| o[p] = new type(); |
| } |
| } |
| } |
| return obj; |
| }; |
| |
| // we have initialization data, let's parse it. |
| var arr=[]; |
| for(var i=0; i<rows.length; i++){ |
| var o = ctor(rows[i]); |
| if(fnMod){ |
| fnMod(o, rows[i]); // apply any modifiers. |
| } |
| arr.push(o); |
| } |
| return arr; // array |
| }, |
| onSetData:function(){ }, |
| onClearData:function(){ }, |
| onAddData:function(obj){ }, |
| onAddDataRange:function(arr){ }, |
| onRemoveData:function(obj){ }, |
| onUpdateField:function(obj, field, val){ } |
| }); |