summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/charting/DataSeries.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/charting/DataSeries.js')
-rw-r--r--js/dojo/dojox/charting/DataSeries.js184
1 files changed, 184 insertions, 0 deletions
diff --git a/js/dojo/dojox/charting/DataSeries.js b/js/dojo/dojox/charting/DataSeries.js
new file mode 100644
index 0000000..190a264
--- /dev/null
+++ b/js/dojo/dojox/charting/DataSeries.js
@@ -0,0 +1,184 @@
+//>>built
+define("dojox/charting/DataSeries", ["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/array", "dojo/_base/connect", "dojox/lang/functional"],
+ function(Lang, declare, ArrayUtil, Hub, df){
+
+ return declare("dojox.charting.DataSeries", null, {
+ constructor: function(store, kwArgs, value){
+ // summary:
+ // Series adapter for dojo.data stores.
+ // store: Object:
+ // A dojo.data store object.
+ // kwArgs: Object:
+ // A store-specific keyword parameters used for fetching items.
+ // See dojo.data.api.Read.fetch().
+ // value: Function|Object|String|Null:
+ // Function, which takes a store, and an object handle, and
+ // produces an output possibly inspecting the store's item. Or
+ // a dictionary object, which tells what names to extract from
+ // an object and how to map them to an output. Or a string, which
+ // is a numeric field name to use for plotting. If undefined, null
+ // or empty string (the default), "value" field is extracted.
+ this.store = store;
+ this.kwArgs = kwArgs;
+
+ if(value){
+ if(Lang.isFunction(value)){
+ this.value = value;
+ }else if(Lang.isObject(value)){
+ this.value = Lang.hitch(this, "_dictValue",
+ df.keys(value), value);
+ }else{
+ this.value = Lang.hitch(this, "_fieldValue", value);
+ }
+ }else{
+ this.value = Lang.hitch(this, "_defaultValue");
+ }
+
+ this.data = [];
+
+ this._events = [];
+
+ if(this.store.getFeatures()["dojo.data.api.Notification"]){
+ this._events.push(
+ Hub.connect(this.store, "onNew", this, "_onStoreNew"),
+ Hub.connect(this.store, "onDelete", this, "_onStoreDelete"),
+ Hub.connect(this.store, "onSet", this, "_onStoreSet")
+ );
+ }
+
+ this.fetch();
+ },
+
+ destroy: function(){
+ // summary:
+ // Clean up before GC.
+ ArrayUtil.forEach(this._events, Hub.disconnect);
+ },
+
+ setSeriesObject: function(series){
+ // summary:
+ // Sets a dojox.charting.Series object we will be working with.
+ // series: dojox.charting.Series:
+ // Our interface to the chart.
+ this.series = series;
+ },
+
+ // value transformers
+
+ _dictValue: function(keys, dict, store, item){
+ var o = {};
+ ArrayUtil.forEach(keys, function(key){
+ o[key] = store.getValue(item, dict[key]);
+ });
+ return o;
+ },
+
+ _fieldValue: function(field, store, item){
+ return store.getValue(item, field);
+ },
+
+ _defaultValue: function(store, item){
+ return store.getValue(item, "value");
+ },
+
+ // store fetch loop
+
+ fetch: function(){
+ // summary:
+ // Fetches data from the store and updates a chart.
+ if(!this._inFlight){
+ this._inFlight = true;
+ var kwArgs = Lang.delegate(this.kwArgs);
+ kwArgs.onComplete = Lang.hitch(this, "_onFetchComplete");
+ kwArgs.onError = Lang.hitch(this, "onFetchError");
+ this.store.fetch(kwArgs);
+ }
+ },
+
+ _onFetchComplete: function(items, request){
+ this.items = items;
+ this._buildItemMap();
+ this.data = ArrayUtil.map(this.items, function(item){
+ return this.value(this.store, item);
+ }, this);
+ this._pushDataChanges();
+ this._inFlight = false;
+ },
+
+ onFetchError: function(errorData, request){
+ // summary:
+ // As stub to process fetch errors. Provide so user can attach to
+ // it with dojo.connect(). See dojo.data.api.Read fetch() for
+ // details: onError property.
+ this._inFlight = false;
+ },
+
+ _buildItemMap: function(){
+ if(this.store.getFeatures()["dojo.data.api.Identity"]){
+ var itemMap = {};
+ ArrayUtil.forEach(this.items, function(item, index){
+ itemMap[this.store.getIdentity(item)] = index;
+ }, this);
+ this.itemMap = itemMap;
+ }
+ },
+
+ _pushDataChanges: function(){
+ if(this.series){
+ this.series.chart.updateSeries(this.series.name, this);
+ this.series.chart.delayedRender();
+ }
+ },
+
+ // store notification handlers
+
+ _onStoreNew: function(){
+ // the only thing we can do is to re-fetch items
+ this.fetch();
+ },
+
+ _onStoreDelete: function(item){
+ // we cannot do anything with deleted item, the only way is to compare
+ // items for equality
+ if(this.items){
+ var flag = ArrayUtil.some(this.items, function(it, index){
+ if(it === item){
+ this.items.splice(index, 1);
+ this._buildItemMap();
+ this.data.splice(index, 1);
+ return true;
+ }
+ return false;
+ }, this);
+ if(flag){
+ this._pushDataChanges();
+ }
+ }
+ },
+
+ _onStoreSet: function(item){
+ if(this.itemMap){
+ // we can use our handy item map, if the store supports Identity
+ var id = this.store.getIdentity(item), index = this.itemMap[id];
+ if(typeof index == "number"){
+ this.data[index] = this.value(this.store, this.items[index]);
+ this._pushDataChanges();
+ }
+ }else{
+ // otherwise we have to rely on item's equality
+ if(this.items){
+ var flag = ArrayUtil.some(this.items, function(it, index){
+ if(it === item){
+ this.data[index] = this.value(this.store, it);
+ return true;
+ }
+ return false;
+ }, this);
+ if(flag){
+ this._pushDataChanges();
+ }
+ }
+ }
+ }
+ });
+});