josh wrote:So it is 1 class or or not?
Well, the Application class depends on several classes:
[js]Ext.dependencies ={ application : [ 'ex/app/CurrentUser', 'ex/app/CurrentSettings', 'desktop/AppWatch', 'desktop/StartMenu', 'desktop/TaskBar', 'desktop/Desktop', 'desktop/Module', 'desktop/MRTGModule', 'desktop/ReportModule', 'desktop/Shortcut', 'desktop/Notification', 'desktop/App', 'ex/Sound', 'ex/Image', 'ex/Printer' ],.... [/js]
But there are no classes not related to the framework itself loaded. See what I meant by "meta data" below.
josh wrote:You said 1 main application class but what is a module meta data?
You know that JS classes are prototype based, so you can extend them and their instances at runtime. So ... this is a "meta-class" (see below its "real" class):
personnelview-launcher.js
[js](function (){ return ( { translationContext : 'ledger', translationSource : null, dependencies : null, create : function () { Ext.namespace('Ext.Module'); Ext.Module.Ledger = Ext.extend(Ext.app.Module, { moduleId : 'mod-ledger', menuPath : 'StartMenu/' + Ext.Translation.get('menu', 'ledger_menu'), launcher : { iconCls : 'ledger-icon', shortcutIconCls : 'ledger-shortcut', text : Ext.Translation.get('ledger', 'title'), tooltip : Ext.Translation.get('ledger', 'module_description', true) } }); return new Ext.Module.Ledger(); } })})();[/js]
josh wrote:Is all your code abstracted and your modules are simply listings of fields to render in a grid? and things like that?
I didn't get this one ... Are you talking about the JS "modules" or for PHP modules?
If you are talking about JS modules - well, they are not so thin:
[js](function (){ return ( { translationContext : 'ledger', translationSource : null, dependencies : Ext.dependencies.singleEditGrid, create : function () { Ext.namespace('Ext.Module'); Ext.override(Ext.Module.Ledger, { init : function () { /* ** ledger JsonStore extended ** */ var ledgerDataStore = new Ext.data.JsonStore( { proxy: new Ext.data.HttpProxy( { url : '/ledger/personnelView', method : 'POST' }), root : 'response', totalProperty : 'totalCount', recordModel : Ext.data.Record.create( [ {name: 'id', type: 'int', defaultValue: 0}, {name: 'operation_id', type: 'int', defaultValue: ''}, {name: 'value', type: 'int', defaultValue: ''}, {name: 'notice', type: 'string', defaultValue: ''} ]), fields : [ {name: 'id', type: 'int' }, {name: 'time', type: 'date', dateFormat : 'Y-m-d H:i:s' }, {name: 'operation_id', type: 'int' }, {name: 'operation_sign',type: 'int'}, {name: 'value', type: 'float' }, {name: 'notice', type: 'string' }, {name: 'username', type: 'string' }, {name: 'fullname', type: 'string' } ], sortInfo : {field: 'time', direction: 'ASC'}, remoteSort : true, autoLoad : true, listeners : { loadexception : { fn : function () { Ext.Msg.error(Ext.Translation.get('common', 'load_data_failure')); } } } }); ledgerDataStore.setDefaultSort('time', 'asc'); this.ledgerOperationDataStore = new Ext.data.JsonStore( { proxy: new Ext.data.HttpProxy( { url : '/ledgeroperation/load', method : 'POST' }), root : 'response', fields : [ {name: 'id', type: 'int'}, {name: 'sign', type: 'int'}, {name: 'visible', type: 'int'}, {name: 'notice', type: 'string'} ], sortInfo : {field: 'notice', direction: 'ASC'}, remoteSort : false, autoLoad : true, listeners : { loadexception : { fn : function () { Ext.Msg.error(Ext.Translation.get('common', 'load_data_failure')); } }, load : { fn : function () { ledgerDataStore.fireEvent('datachanged', ledgerDataStore); } } } }); this.ledgerSignedOperationDataStore = new Ext.data.JsonStore( { proxy: new Ext.data.HttpProxy( { url : '/ledgeroperation/load', method : 'POST' }), root : 'response', fields : [ {name: 'id', type: 'int'}, {name: 'sign', type: 'int'}, {name: 'visible', type: 'int'}, {name: 'notice', type: 'string'} ], sortInfo : {field: 'notice', direction: 'ASC'}, remoteSort : false, autoLoad : true, listeners : { loadexception : { fn : function () { Ext.Msg.error(Ext.Translation.get('common', 'load_data_failure')); } }, load : { scope : this, fn : function () { var sign_income = Ext.Translation.get('ledger', 'sign_income'); var sign_outgo = Ext.Translation.get('ledger', 'sign_outgo'); this.ledgerSignedOperationDataStore.each(function (record) { if (record.get('sign') == 1) record.set('notice', sign_income + ' - ' + record.get('notice')); else record.set('notice', sign_outgo + ' - ' + record.get('notice')); }); this.ledgerSignedOperationDataStore.fireEvent('datachanged', this.ledgerSignedOperationDataStore); } } } }); this.totalsDataStore = new Ext.data.JsonStore( { proxy: new Ext.data.HttpProxy( { url : '/ledger/currentCash', method : 'POST' }), root : 'response', fields : [ {name: 'id', type: 'int'}, {name: 'profit', type: 'int'}, {name: 'income', type: 'int'}, {name: 'outgo', type: 'int'} ], sortInfo : {field: 'id', direction: 'ASC'}, remoteSort : false, autoLoad : true, listeners : { loadexception : { fn : function () { Ext.Msg.error(Ext.Translation.get('common', 'load_data_failure')); } } } }); var totalsColumnModel = new Ext.grid.ColumnModel( { columns: [ { id : 'profit', dataIndex : 'profit', header : Ext.Translation.get('ledger', 'totals_profit_header_text'), renderer : function (val, meta) { if (val.toFixed) { if (val < 0) meta.attr = 'style="color:red;"'; return val.toFixed(2); } else return val; } }, { dataIndex : 'income', header : Ext.Translation.get('ledger', 'totals_income_header_text'), renderer : function (val) { if (val.toFixed) return val.toFixed(2); else return val; } }, { dataIndex : 'outgo', header : Ext.Translation.get('ledger', 'totals_outgo_header_text'), renderer : function (val) { if (val.toFixed) return val.toFixed(2); else return val; } } ] }); totalsColumnModel.defaultSortable = false; var totalsGrid = new Ext.grid.GridPanel( { store : this.totalsDataStore, colModel : totalsColumnModel, loadMask : true, enableColLock : true, enableColumnHide: false, enableHdMenu : false, viewConfig : { forceFit : true }, autoExpandColumn: 'profit' }); /* ** Column model ** */ var expander = new Ext.grid.RowExpander( { tpl : new Ext.Template( '<pre class="expander">{notice}</pre>' ) }); var cm = new Ext.grid.ColumnModel( { columns: [ expander, { dataIndex : 'time', header : Ext.Translation.get('ledger', 'time_header_text'), renderer : function (val) { if (val.format) return val.format('Y-m-d H:i:s'); else return val; } }, { dataIndex : 'username', header : Ext.Translation.get('ledger', 'username_header_text'), renderer : function (val, meta, rec) { return rec.get('fullname') + ' (' + val + ')'; } }, { dataIndex : 'operation_sign', header : Ext.Translation.get('ledger', 'operation_sign_header_text'), renderer : function (val, meta) { if (val > 0) { meta.attr = 'style="color:green"'; return Ext.Translation.get('ledger', 'sign_income'); } else { meta.attr = 'style="color:red"'; return Ext.Translation.get('ledger', 'sign_outgo'); } } }, { dataIndex : 'operation_id', header : Ext.Translation.get('ledger', 'operation_header_text'), id : 'operation_id', store : this.ledgerOperationDataStore, displayField: 'notice', valueField : 'id' }, { dataIndex : 'value', header : Ext.Translation.get('ledger', 'value_header_text'), renderer : function (val) { if (val.toFixed) return val.toFixed(2); else return val; } } ] }); cm.defaultSortable = true; /* ** Grid ** */ var grid = new Ext.ex.grid.SingleEditGridPanel( { scope : this, baseUrl : 'ledger', toolButtons : + Ext.ex.grid.SingleEditGridPanel.constant.hasAddButton, store : ledgerDataStore, colModel : cm, enableColLock : false, plugins : [ new Ext.ex.grid.ComboField(), expander ], autoExpandColumn: 'notice', getEditWindowConfig : function () { return ( { title : Ext.Translation.get('ledger', 'ledger_properties_window_title') }); }, getEditFormConfig : function (record, self) { return ( { items : [ { name : 'operation_id', xtype : 'combo', fieldLabel : Ext.Translation.get('ledger', 'operation_header_text'), mode : 'local', autoWidth : true, store : self.ledgerSignedOperationDataStore, editable : false, allowBlank : false, triggerAction: 'all', displayField: 'notice', valueField : 'id', listClass : 'x-combo-list-small' }, { name : 'notice', xtype : 'textarea', maxLength : 500, fieldLabel : Ext.Translation.get('ledger', 'notice_header_text'), allowBlank : false }, { name : 'value', vtype : 'money', minValue : 0.01, xtype : 'numberfield', fieldLabel : Ext.Translation.get('ledger', 'value_header_text'), allowBlank : false } ] }); } }); this.winConfig = { items : { xtype : 'panel', layout : 'border', items : [ { xtype : 'panel', layout : 'fit', items : grid, region : 'center' }, { xtype : 'panel', layout : 'fit', items : totalsGrid, height : 70, region : 'south' } ] }, title : Ext.Translation.get('ledger', 'title') }; } }); } })})(); [/js]
While most of the back office modules are grid based, front office modules are much more complex:
[js]... this.tabPanel = new Ext.TabPanel( { resizeTabs : true, minTabWidth : 115, tabWidth : 135, autoWidth : true, enableTabScroll : true, activeTab : 0, defaults : { autoScroll : true, labelWidth : 120 }, bbar : [ this.resetButton ], items : [ this.personalDataForm, this.internetDataForm ] }); this.searchPanel = new Ext.Panel( { region : 'west', width : 320, layout : 'fit', items : this.tabPanel }); this.resultsPanel = new Ext.Panel( { region : 'center', width : 400, items : this.userGrid }); this.container = new Ext.Panel( { layout : 'border', frame : true, defaults : { layout : 'fit' }, items : [ this.searchPanel, this.resultsPanel ] }); this.winConfig = { items : this.container, title : Ext.Translation.get('payment', 'title') }; }[/js]
It's just the visual layout ...