diff options
Diffstat (limited to 'js/dojo/dojox/grid/enhanced/_PluginManager.js')
| -rw-r--r-- | js/dojo/dojox/grid/enhanced/_PluginManager.js | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/js/dojo/dojox/grid/enhanced/_PluginManager.js b/js/dojo/dojox/grid/enhanced/_PluginManager.js new file mode 100644 index 0000000..20e6e91 --- /dev/null +++ b/js/dojo/dojox/grid/enhanced/_PluginManager.js @@ -0,0 +1,275 @@ +//>>built +define("dojox/grid/enhanced/_PluginManager", [ + "dojo/_base/kernel", + "dojo/_base/lang", + "dojo/_base/declare", + "dojo/_base/array", + "dojo/_base/connect", + "./_Events", + "./_FocusManager", + "../util" +], function(dojo, lang, declare, array, connect, _Events, _FocusManager, util){ + +var _PluginManager = declare("dojox.grid.enhanced._PluginManager", null, { + // summary: + // Singleton plugin manager + // + // description: + // Plugin manager is responsible for + // 1. Loading required plugins + // 2. Handling collaborat ion and dependencies among plugins + // + // Some plugin dependencies: + // - "columnReordering" attribute won't work when either DnD or Indirect Selections plugin is on. + + //_options: Object + // Normalized plugin options + _options: null, + + //_plugins: Array + // Plugin list + _plugins: null, + + //_connects: Array + // Connection list + _connects: null, + + constructor: function(inGrid){ + this.grid = inGrid; + this._store = inGrid.store; + this._options = {}; + this._plugins = []; + this._connects = []; + this._parseProps(this.grid.plugins); + + inGrid.connect(inGrid, "_setStore", lang.hitch(this, function(store){ + if(this._store !== store){ + this.forEach('onSetStore', [store, this._store]); + this._store = store; + } + })); + }, + startup: function(){ + this.forEach('onStartUp'); + }, + preInit: function(){ + // summary: + // Load appropriate plugins before DataGrid.postCreate(). + // See EnhancedGrid.postCreate() + this.grid.focus.destroy(); + this.grid.focus = new _FocusManager(this.grid); + new _Events(this.grid);//overwrite some default events of DataGrid + this._init(true); + this.forEach('onPreInit'); + }, + postInit: function(){ + // summary: + // Load plugins after DataGrid.postCreate() - the default phase when plugins are created + // See EnhancedGrid.postCreate() + this._init(false); + + array.forEach(this.grid.views.views, this._initView, this); + this._connects.push(connect.connect(this.grid.views, 'addView', lang.hitch(this, this._initView))); + + if(this._plugins.length > 0){ + var edit = this.grid.edit; + if(edit){ edit.styleRow = function(inRow){}; } + } + this.forEach('onPostInit'); + }, + forEach: function(func, args){ + array.forEach(this._plugins, function(p){ + if(!p || !p[func]){ return; } + p[func].apply(p, args ? args : []); + }); + }, + _parseProps: function(plugins){ + // summary: + // Parse plugins properties + // plugins: Object + // Plugin properties defined by user + if(!plugins){ return; } + + var p, loading = {}, options = this._options, grid = this.grid; + var registry = _PluginManager.registry;//global plugin registry + for(p in plugins){ + if(plugins[p]){//filter out boolean false e.g. {p:false} + this._normalize(p, plugins, registry, loading); + } + } + //"columnReordering" attribute won't work when either DnD or Indirect Selections plugin is used. + if(options.dnd || options.indirectSelection){ + options.columnReordering = false; + } + + //mixin all plugin properties into Grid + lang.mixin(grid, options); + }, + _normalize: function(p, plugins, registry, loading){ + // summary: + // Normalize plugin properties especially the dependency chain + // p: String + // Plugin name + // plugins: Object + // Plugin properties set by user + // registry: Object + // The global plugin registry + // loading: Object + // Map for checking process state + if(!registry[p]){ throw new Error('Plugin ' + p + ' is required.');} + + if(loading[p]){ throw new Error('Recursive cycle dependency is not supported.'); } + + var options = this._options; + if(options[p]){ return options[p]; } + + loading[p] = true; + //TBD - more strict conditions? + options[p] = lang.mixin({}, registry[p], lang.isObject(plugins[p]) ? plugins[p] : {}); + + var dependencies = options[p]['dependency']; + if(dependencies){ + if(!lang.isArray(dependencies)){ + dependencies = options[p]['dependency'] = [dependencies]; + } + array.forEach(dependencies, function(dependency){ + if(!this._normalize(dependency, plugins, registry, loading)){ + throw new Error('Plugin ' + dependency + ' is required.'); + } + }, this); + } + delete loading[p]; + return options[p]; + }, + _init: function(pre){ + // summary: + // Find appropriate plugins and load them + // pre: Boolean + // True - preInit | False - postInit(by default) + var p, preInit, options = this._options; + for(p in options){ + preInit = options[p]['preInit']; + if((pre ? preInit : !preInit) && options[p]['class'] && !this.pluginExisted(p)){ + this.loadPlugin(p); + } + } + }, + loadPlugin: function(name){ + // summary: + // Load required plugin("name") + // name: String + // Plugin name + // return: Object + // The newly loaded plugin + var option = this._options[name]; + if(!option){ return null; } //return if no plugin option + + var plugin = this.getPlugin(name); + if(plugin){ return plugin; } //return if plugin("name") already existed + + var dependencies = option['dependency']; + array.forEach(dependencies, function(dependency){ + if(!this.loadPlugin(dependency)){ + throw new Error('Plugin ' + dependency + ' is required.'); + } + }, this); + var cls = option['class']; + delete option['class'];//remove it for safety + plugin = new this.getPluginClazz(cls)(this.grid, option); + this._plugins.push(plugin); + return plugin; + }, + _initView: function(view){ + // summary: + // Overwrite several default behavior for each views(including _RowSelector view) + if(!view){ return; } + //add more events handler - _View + util.funnelEvents(view.contentNode, view, "doContentEvent", ['mouseup', 'mousemove']); + util.funnelEvents(view.headerNode, view, "doHeaderEvent", ['mouseup']); + }, + pluginExisted: function(name){ + // summary: + // Check if plugin("name") existed + // name: String + // Plugin name + // return: Boolean + // True - existed | False - not existed + return !!this.getPlugin(name); + }, + getPlugin: function(name){ + // summary: + // Get plugin("name") + // name: String + // Plugin name + // return: Object + // Plugin instance + var plugins = this._plugins; + name = name.toLowerCase(); + for(var i = 0, len = plugins.length; i < len; i++){ + if(name == plugins[i]['name'].toLowerCase()){ + return plugins[i]; + } + } + return null; + }, + getPluginClazz: function(clazz){ + // summary: + // Load target plugin which must be already required (require(..)) + // clazz: class | String + // Plugin class + if(lang.isFunction(clazz)){ + return clazz;//return if it's already a clazz + } + var errorMsg = 'Please make sure Plugin "' + clazz + '" is existed.'; + try{ + var cls = lang.getObject(clazz); + if(!cls){ throw new Error(errorMsg); } + return cls; + }catch(e){ + throw new Error(errorMsg); + } + }, + isFixedCell: function(cell){ + // summary: + // See if target cell(column) is fixed or not. + // cell: Object + // Target cell(column) + // return: Boolean + // True - fixed| False - not fixed + + //target cell can use Boolean attributes named "isRowSelector" or "fixedPos" to mark it's a fixed cell(column) + return cell && (cell.isRowSelector || cell.fixedPos); + }, + destroy: function(){ + // summary: + // Destroy all resources + array.forEach(this._connects, connect.disconnect); + this.forEach('destroy'); + if(this.grid.unwrap){ + this.grid.unwrap(); + } + delete this._connects; + delete this._plugins; + delete this._options; + } +}); + +_PluginManager.registerPlugin = function(clazz, props){ + // summary: + // Register plugins - TODO, a better way rather than global registry? + // clazz: String + // Full class name, e.g. "dojox.grid.enhanced.plugins.DnD" + // props: Object - Optional + // Plugin properties e.g. {"dependency": ["nestedSorting"], ...} + if(!clazz){ + console.warn("Failed to register plugin, class missed!"); + return; + } + var cls = _PluginManager; + cls.registry = cls.registry || {}; + cls.registry[clazz.prototype.name]/*plugin name*/ = lang.mixin({"class": clazz}, (props ? props : {})); +}; + +return _PluginManager; + +});
\ No newline at end of file |
