define([ "../lib/object", "./Selector", "dijit/layout/ContentPane", "dijit/layout/TabContainer", "dojo/_base/array", "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/window", "dojo/when", "dojox/widget/Standby" ], function(objectFuns, Selector, ContentPane, TabContainer, array, declare, lang, win, when, Standby) { return declare([TabContainer],{ tabPosition: 'left-h', // interface the client must implement getCategories: function(){ return []; }, getCategoryName: function(category){ return ""; }, getCategoryCount: function(category){ return 0; }, getTopics: function(category){ return []; }, getTopicName: function(topic){ return "";}, getTopicCount: function(topic){ return 0; }, getItems: function(category,topic){ return []; }, getItemName: function(item){ return ""; }, getItemActions: function(item){ return {}; }, // {name:{'callback'(item,sel),'icon','description'}} getSelectedItemActions: function(){ return {}; }, // {name:{'callback'(item,sel),'icon','description'}} areItemsEqual: function(i1,i2){ return i1 === i2; }, dndType: "", _dataMap: null, _busyCount: 0, constructor: function() { this._dataMap = {}; }, startup: function() { if ( this._started ){ return; } this.inherited(arguments); this._busyWidget = new Standby({ target: this.domNode, duration: 200 }).placeAt(win.body()); this._busyWidget.startup(); this.watch("selectedChildWidget",lang.hitch(this,'_handleChangeTab')); when(this.getCategories()) .then(lang.hitch(this,'_addCategories')); }, _addCategories: function(categories) { array.forEach(categories, function(category) { this._addCategory(category); }, this); }, _handleChangeTab: function(name,oldTab,newTab) { this._fillCategory(newTab.__category); }, _addCategory: function(category) { var name = this.getCategoryName(category); var count = this.getCategoryCount(category); if (this._dataMap[name] === undefined) { var tab = new ContentPane({ __category: category, title: (name||'[No category]')+(count&&' ('+count+')') }); tab.startup(); this._dataMap[name] = { _widget: tab }; this.addChild(tab); } }, _fillCategory: function(category) { var name = this.getCategoryName(category); var map = this._dataMap[name]; if (!map._filled) { this._busy(); map._filled = true; when(this.getTopics(category)) .then(lang.hitch(this,'_addTopicsToCategory',category)) .always(lang.hitch(this,'_done')); } }, _addTopicsToCategory: function(category,topics) { array.forEach(topics, function(topic) { var cname = this.getCategoryName(category); var tname = this.getTopicName(topic); this._addTopicToCategory(category,topic); }, this); }, _addTopicToCategory: function(category,topic) { var map = this._dataMap[this.getCategoryName(category)]; var name = this.getTopicName(topic); var count = this.getTopicCount(topic); if (map[name] === undefined) { var w = new Selector({ __category: category, __topic: topic, dndType: this.dndType, title: (name||'[No topic]')+(count&&" ("+count+")"), selectedActions: lang.hitch(this,'getSelectedItemActions'), itemActions: lang.hitch(this,'getItemActions'), itemTitle: lang.hitch(this,'getItemName'), itemEquals: lang.hitch(this,'areItemsEqual') }).placeAt(map._widget.containerNode); w.startup(); map[name] = { _widget: w }; this._fillTopicInCategory(category,topic); } }, _fillTopicInCategory: function(category,topic) { var map = this._dataMap[this.getCategoryName(category)][this.getTopicName(topic)]; if (!map._filled) { map._filled = true; this._busy(); when(this.getItems(category,topic)) .then(lang.hitch(this,function(items){ array.forEach(items,map._widget.addItem,map._widget); })).always(lang.hitch(this,'_done')); } }, removeItem: function(item) { var cmap = this._dataMap; objectFuns.forEach(cmap,function(tmap,cat){ objectFuns.forEach(tmap,function(topObj,top){ var widget = topObj._widget; if ( widget ) { widget.removeItem(item); } },this); },this); }, _busy: function() { if ( this._busyCount === 0 ) { this._busyWidget.show(); } this._busyCount++; }, _done: function() { if ( this._busyCount > 0 ) { this._busyCount--; if ( this._busyCount === 0 ) { this._busyWidget.hide(); } } else { console.warn('_done() was called more times than _busy().'); } }, destroy: function() { this._busyWidget.destroyRecursive(); this.inherited(arguments); } }); });