source: Dev/trunk/src/client/dojox/grid/enhanced/_PluginManager.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 7.7 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/lang",
4        "dojo/_base/declare",
5        "dojo/_base/array",
6        "dojo/_base/connect",
7        "./_Events",
8        "./_FocusManager",
9        "../util"
10], function(dojo, lang, declare, array, connect, _Events, _FocusManager, util){
11
12var _PluginManager = declare("dojox.grid.enhanced._PluginManager", null, {
13        // summary:
14        //              Singleton plugin manager
15        // description:
16        //              Plugin manager is responsible for:
17        //
18        //              1. Loading required plugins
19        //              2. Handling collaboration and dependencies among plugins
20        //
21        //              Some plugin dependencies:
22        //
23        //              - "columnReordering" attribute won't work when either DnD or Indirect Selections plugin is on.
24               
25        // _options: Object
26        //              Normalized plugin options
27        _options: null,
28
29        // _plugins: Array
30        //              Plugin list
31        _plugins: null,
32
33        // _connects: Array
34        //              Connection list
35        _connects: null,
36
37        constructor: function(inGrid){
38                this.grid = inGrid;
39                this._store = inGrid.store;
40                this._options = {};
41                this._plugins = [];
42                this._connects = [];
43                this._parseProps(this.grid.plugins);
44               
45                inGrid.connect(inGrid, "_setStore", lang.hitch(this, function(store){
46                        if(this._store !== store){
47                                this.forEach('onSetStore', [store, this._store]);
48                                this._store = store;
49                        }
50                }));
51        },
52        startup: function(){
53                this.forEach('onStartUp');
54        },
55        preInit: function(){
56                // summary:
57                //              Load appropriate plugins before DataGrid.postCreate().
58                //              See EnhancedGrid.postCreate()
59                this.grid.focus.destroy();
60                this.grid.focus = new _FocusManager(this.grid);
61                new _Events(this.grid);//overwrite some default events of DataGrid
62                this._init(true);
63                this.forEach('onPreInit');
64        },
65        postInit: function(){
66                // summary:
67                //              Load plugins after DataGrid.postCreate() - the default phase when plugins are created
68                //              See EnhancedGrid.postCreate()
69                this._init(false);
70               
71                array.forEach(this.grid.views.views, this._initView, this);
72                this._connects.push(connect.connect(this.grid.views, 'addView', lang.hitch(this, this._initView)));
73                       
74                if(this._plugins.length > 0){
75                        var edit = this.grid.edit;
76                        if(edit){ edit.styleRow = function(inRow){}; }
77                }
78                this.forEach('onPostInit');
79        },
80        forEach: function(func, args){
81                array.forEach(this._plugins, function(p){
82                        if(!p || !p[func]){ return; }
83                        p[func].apply(p, args ? args : []);
84                });
85        },
86        _parseProps: function(plugins){
87                // summary:
88                //              Parse plugins properties
89                // plugins: Object
90                //              Plugin properties defined by user
91                if(!plugins){ return; }
92               
93                var p, loading = {}, options = this._options, grid = this.grid;
94                var registry = _PluginManager.registry;//global plugin registry
95                for(p in plugins){
96                        if(plugins[p]){//filter out boolean false e.g. {p:false}
97                                this._normalize(p, plugins, registry, loading);
98                        }
99                }
100                //"columnReordering" attribute won't work when DnD plugin is turned on.
101                if(options.dnd){
102                        options.columnReordering = false;
103                }
104               
105                //mixin all plugin properties into Grid
106                lang.mixin(grid, options);
107        },
108        _normalize: function(p, plugins, registry, loading){
109                // summary:
110                //              Normalize plugin properties especially the dependency chain
111                // p: String
112                //              Plugin name
113                // plugins: Object
114                //              Plugin properties set by user
115                // registry: Object
116                //              The global plugin registry
117                // loading: Object
118                //              Map for checking process state
119                if(!registry[p]){ throw new Error('Plugin ' + p + ' is required.');}
120               
121                if(loading[p]){ throw new Error('Recursive cycle dependency is not supported.'); }
122               
123                var options = this._options;
124                if(options[p]){ return options[p]; }
125               
126                loading[p] = true;
127                //TBD - more strict conditions?
128                options[p] = lang.mixin({}, registry[p], lang.isObject(plugins[p]) ? plugins[p] : {});
129               
130                var dependencies = options[p]['dependency'];
131                if(dependencies){
132                        if(!lang.isArray(dependencies)){
133                                dependencies = options[p]['dependency'] = [dependencies];
134                        }
135                        array.forEach(dependencies, function(dependency){
136                                if(!this._normalize(dependency, plugins, registry, loading)){
137                                        throw new Error('Plugin ' + dependency + ' is required.');
138                                }
139                        }, this);
140                }
141                delete loading[p];
142                return options[p];
143        },
144        _init: function(pre){
145                // summary:
146                //              Find appropriate plugins and load them
147                // pre: Boolean
148                //              True - preInit | False - postInit(by default)
149                var p, preInit, options = this._options;
150                for(p in options){
151                        preInit = options[p]['preInit'];
152                        if((pre ? preInit : !preInit) && options[p]['class'] && !this.pluginExisted(p)){
153                                this.loadPlugin(p);
154                        }
155                }
156        },
157        loadPlugin: function(name){
158                // summary:
159                //              Load required plugin("name")
160                // name: String
161                //              Plugin name
162                // returns: Object
163                //              The newly loaded plugin
164                var option = this._options[name];
165                if(!option){ return null; } //return if no plugin option
166               
167                var plugin = this.getPlugin(name);
168                if(plugin){ return plugin; } //return if plugin("name") already existed
169               
170                var dependencies = option['dependency'];
171                array.forEach(dependencies, function(dependency){
172                        if(!this.loadPlugin(dependency)){
173                                throw new Error('Plugin ' + dependency + ' is required.');
174                        }
175                }, this);
176                var cls = option['class'];
177                delete option['class'];//remove it for safety
178                plugin = new this.getPluginClazz(cls)(this.grid, option);
179                this._plugins.push(plugin);
180                return plugin;
181        },
182        _initView: function(view){
183                // summary:
184                //              Overwrite several default behavior for each views(including _RowSelector view)
185                if(!view){ return; }
186                //add more events handler - _View
187                util.funnelEvents(view.contentNode, view, "doContentEvent", ['mouseup', 'mousemove']);
188                util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']);
189        },
190        pluginExisted: function(name){
191                // summary:
192                //              Check if plugin("name") existed
193                // name: String
194                //              Plugin name
195                // returns: Boolean
196                //              True - existed | False - not existed
197                return !!this.getPlugin(name);
198        },
199        getPlugin: function(name){
200                // summary:
201                //              Get plugin("name")
202                // name: String
203                //              Plugin name
204                // returns: Object
205                //              Plugin instance
206                var plugins = this._plugins;
207                name = name.toLowerCase();
208                for(var i = 0, len = plugins.length; i < len; i++){
209                        if(name == plugins[i]['name'].toLowerCase()){
210                                return plugins[i];
211                        }
212                }
213                return null;
214        },
215        getPluginClazz: function(clazz){
216                // summary:
217                //              Load target plugin which must be already required (require(..))
218                // clazz: Class|String
219                //              Plugin class
220                if(lang.isFunction(clazz)){
221                        return clazz;//return if it's already a clazz
222                }
223                var errorMsg = 'Please make sure Plugin "' + clazz + '" is existed.';
224                try{
225                        var cls = lang.getObject(clazz);
226                        if(!cls){ throw new Error(errorMsg); }
227                        return cls;
228                }catch(e){
229                        throw new Error(errorMsg);
230                }
231        },
232        isFixedCell: function(cell){
233                // summary:
234                //              See if target cell(column) is fixed or not.
235                // cell: Object
236                //              Target cell(column)
237                // returns: Boolean
238                //              True - fixed| False - not fixed
239
240                //target cell can use Boolean attributes named "isRowSelector" or "fixedPos" to mark it's a fixed cell(column)
241                return cell && (cell.isRowSelector || cell.fixedPos);
242        },
243        destroy: function(){
244                // summary:
245                //              Destroy all resources
246                array.forEach(this._connects, connect.disconnect);
247                this.forEach('destroy');
248                if(this.grid.unwrap){
249                        this.grid.unwrap();
250                }
251                delete this._connects;
252                delete this._plugins;
253                delete this._options;
254        }
255});
256
257_PluginManager.registerPlugin = function(clazz, props){
258                // summary:
259                //              Register plugins - TODO, a better way rather than global registry?
260                // clazz: String
261                //              Full class name, e.g. "dojox.grid.enhanced.plugins.DnD"
262                // props: Object?
263                //              Plugin properties e.g. {"dependency": ["nestedSorting"], ...}
264        if(!clazz){
265                console.warn("Failed to register plugin, class missed!");
266                return;
267        }
268        var cls = _PluginManager;
269        cls.registry = cls.registry || {};
270        cls.registry[clazz.prototype.name]/*plugin name*/ = lang.mixin({"class": clazz}, (props ? props : {}));
271};
272
273return _PluginManager;
274
275});
Note: See TracBrowser for help on using the repository browser.