Ext.BLANK_IMAGE_URL = '<%= image_path("ext/default/s.gif") %>'; Ext.Updater.defaults.showLoadIndicator = false; Ext.namespace('Admin'); // This is our event manager Admin.events = new Ext.util.Observable(); // That is the main app Admin.app = function(){ return { // Init our app init: function(){ // Cookie provider Ext.state.Manager.setProvider( new Ext.state.CookieProvider({ expires: new Date(new Date().getTime()+(1000*60*60*24*365)) }) ); // We want save cookies only for grids Ext.override(Ext.Component, { stateful:false }); // Ext.override(Ext.grid.GridPanel, { stateful:true }); Ext.QuickTips.init(); // Used for direclty load some specific page var loadUrl = undefined; if (window.location.search){ loadUrl = Ext.urlDecode(window.location.search.substring(1)).load; } else if (window.location.href.split('#')[1]) { loadUrl = window.location.href.split('#')[1]; } // Used for history the browsing Ext.History.init(); Ext.History.on('change', function(token){ Admin.app.load(token) }); // Build some events Admin.events.addEvents('itemAdded', 'contentLoaded'); // Our header var header = new Ext.Panel({ contentEl: 'header', region: 'north', border: false, bbar: <%= admin_menu %> }); // Our main container this.contentDynamic = new Ext.Panel({ id:'dynamic', region:'center', activeItem: 0, border:false, frame: true, bodyCssClass: 'dynamic', buttonAlign: 'left', buttons: [{ id:'back', text: Admin.locale.buttons.back, cls: 'x-btn-text-icon back', handler: this.back },'->',{ id:'save', text: Admin.locale.buttons.save, hidden: true, cls: 'x-btn-text-icon save' }], layout:'card' }); // Our viewport this.viewport = new Ext.Viewport({ layout:'border', items: [header, this.contentDynamic] }); loadUrl ? this.load(loadUrl) : this.loadPage('<%= url(:dashboard) %>'); setTimeout(function(){ Ext.get('loading').remove(); Ext.get('loading-mask').fadeOut({remove:true}); }, 250); }, // init load: function(url){ var ext = (/[.]/.exec(url)) ? /[^.]+$/.exec(url) : 'html'; // Now give a reply based on request if (ext.length == 1 && ext[0].toLowerCase() == 'js') { // Clean the html and scripts this.cleanScripts(); this.clean(); Ext.History.add(url, true); // Enable this for debug errors: // // We append the js into the head so we can easy inspect errors // var hd = document.getElementsByTagName("head")[0]; // var s = document.createElement("script"); // s.src = url; // s.type = 'text/javascript'; // // Now we can append the child. // hd.appendChild(s); Admin.app.mask(); Ext.Ajax.request({ url: url, nocache:true, callback:this.unmask, scope:this }); } else if (ext == 'html'){ this.loadWidget(url); } else { Admin.showAlert(Admin.locale.messages.alert.message); } }, // load loadPage: function(url){ // Clean the html and scripts this.cleanScripts(); this.clean(); this.contentDynamic.load({ url: url, scripts: true, callback:this.inspectContent, scope:this, nocache:true }); }, // loadPage loadWidget: function(url, id){ var win = undefined; if (id) { Ext.WindowMgr.each(function(w) { if (w.id == id) { win = w; return false } }, this) }; if (win){ win.toFront(); } else { Admin.app.mask(); var win = new Admin.window({ id: id }); win.show(); win.hide(); win.load({ url: url, scripts: true, callback: Admin.app.inspectContent, scope: win, nocache: true }); } }, back: function(){ Ext.History.back(); }, // back update: function(html){ this.cleanScripts(); this.clean(); var el = this.contentDynamic.body.update(html); this.inspectContent(el, html); }, // update cleanScripts: function(){ Ext.select('head > script').each(function(el){ el.remove(); }); }, // cleanScripts clean: function(){ this.saveButtons(false); this.contentDynamic.items.each(function(item){ item.destroy }); this.contentDynamic.removeAll(true); this.contentDynamic.body.update(''); }, // clean saveButtons: function(show, id){ var btns = this.contentDynamic.fbar.items.map; if (show){ btns.save.show(); btns.save.handler = function(){ Admin.app.submitForm(id) }; } else { btns.save.hide(); btns.save.handler = undefined; } }, // saveButtons addItem: function(item, small){ // If we are loading a small item we don't need to add them to our container if (small && small!=''){ Admin.events.fireEvent('customItemAdded', item); } else { this.contentDynamic.add(item); this.contentDynamic.layout.setActiveItem(0); this.contentDynamic.doLayout(true, true); } Admin.events.fireEvent('itemAdded', item) }, // addItem submitForm: function(id){ var form = Ext.fly(id); form.mask(Admin.locale.messages.wait.message); Ext.Ajax.request({ form: form, callback: function(){ Ext.fly(id).unmask() } }); }, // submitForms setTitle: function(title){ this.contentDynamic.setTitle(title); }, // setTitle inspectContent: function(el, success, response){ // Go away if no success if (!success) return; // Reformat ajax forms el.select('form[data-remote=true]').each(function(form){ var id = Ext.id(form, 'ajax-form-'); form.dom.onsubmit = function(){ Admin.app.submitForm(id); return false }; }); // Search for tabs in the page var tabs = el.select('div[tabbed=true]'); // We select the first form in the dom var form = el.select('form[data-remote=true]').first(); // We need to parse our title var title = el.select('span[title]').first(); if (title) this.setTitle(title.getAttribute("title")); // If we have a form we need some save buttons if (form) this.saveButtons(true, form.id); // Build our tab panel if we have a form and tabs if (tabs.elements.length > 0 && form){ // Build Tabs var items = [] Ext.each(tabs.elements, function(tab){ tab.id = Ext.id('', tab.id +'-tab-'); items.push({ id: tab.id + '-tab-id-', contentEl: tab.id, title: tab.title }); }); // We can build the tabPanel this.tabPanel = new Ext.TabPanel({ applyTo: form, activeTab: 0, border:false, items: items, layoutOnTabChange: true, enableTabScroll: true, defaults: { autoScroll:true, layout:'fit' } }); this.addItem(this.tabPanel); } Admin.app.unmask(); this.fireEvent('contentLoaded'); },//inspectContent fireEvent: function(event){ Admin.events.fireEvent(event); }, // fireEvent error: function(e){ (typeof console != 'undefined') ? console.error(e) : Admin.showAlert(e) }, // error doLayout: function(){ this.contentDynamic.doLayout(true, true); }, //doLayout mask: function(text){ if (text == null || text.length == 0) { text = Ext.LoadMask.prototype.msg; } this.contentDynamic.el.mask(text); }, // mask unmask: function(){ this.contentDynamic.el.unmask(); }, // unmask collapseBoxes: function(current){ var el = current.up().down('div.x-box-collapsible'); var currentEl = Ext.get(el); currentEl.isDisplayed() ? currentEl.slideOut('t', {duration:.2, useDisplay:true}) : currentEl.slideIn('t', {duration:.2, useDisplay:true}); Ext.select('div.x-box-collapsible').each(function(el){ if (el.isDisplayed() && el.dom.id!=currentEl.id){ el.slideOut('t', {duration:.2, useDisplay:true}); } }); } //collapseBoxes } // return }(); Admin.grid = Ext.extend(Ext.grid.GridPanel, { title: 'Grid', baseUrl: '', region: "center", border: false, buttons: ['add', 'edit', 'remove'], search: true, plugins: [], column_fields: [], store_fields: [], window: undefined, initComponent: function(){ // Prepare our View/Cm/Sm this.view = new Ext.grid.GroupingView({ forceFit: true }); this.selModel = new Ext.grid.CheckboxSelectionModel(); this.column_fields.unshift(this.selModel); this.colModel = new Ext.grid.ColumnModel({ columns: this.column_fields }); // Toolbar if (this.buttons.length > 0 || this.search){ this.tbar = new Ext.Toolbar() }; // Add Buttons Ext.each(this.buttons, function(button){ switch(button){ case 'add': this.btnAdd = this.tbar.addButton({ handler: this.addRecord, text: Admin.locale.buttons.add, disabled: false, scope: this, cls: "x-btn-text-icon add", name: "add" }); break; case 'edit': this.btnEdit = this.tbar.addButton({ handler: this.editRecord, text: Admin.locale.buttons.edit, disabled: true, scope: this, cls: "x-btn-text-icon edit", name: "edit" }); break; case 'remove': this.btnRemove = this.tbar.addButton({ handler: this.removeRecord, text: Admin.locale.buttons.remove, disabled: true, scope: this, cls: "x-btn-text-icon remove", name: "remove" }); break; } }, this); this.buttons = undefined; // Remove all bbar buttons, we don't want them in the bottom of grid. // Add search functions if (this.search){ this.plugins = [new Ext.grid.Search()] }; // Build our store this.store = new Ext.data.GroupingStore({ remoteSort: true, proxy: new Ext.data.HttpProxy({ url: this.baseUrl +'.json' }), baseParams: {"_method":"GET"}, reader: new Ext.data.JsonReader({ fields: this.store_fields, root: "results", totalProperty: "count", id: "id" }) }); // Build bbar this.bbar = new Ext.PagingToolbar({ pageSize: 50, displayInfo: true, store: this.store }); // Call our superclass Admin.grid.superclass.initComponent.call(this); // Now we need to add some handlers for activate/deactivate buttons this.on('render', function(){ this.store.load() }, this); this.selModel.on('selectionchange', function(){ var n = this.selModel.getSelected(); if(!n){ if (this.btnRemove){ this.btnRemove.disable() }; if (this.btnEdit){ this.btnEdit.disable() }; } else { if (this.btnRemove){ this.btnRemove.enable() }; if (this.btnEdit){ this.btnEdit.enable() }; } }, this); this.on("dblclick", function() { if (this.btnEdit){ this.editRecord() } }, this); this.store.on('beforeload', function(){ this.el.mask(); }, this); this.store.on('load', function(){ this.el.unmask(); }, this); }, // initComponent addRecord: function(){ Admin.app.loadWidget(this.baseUrl + '/new'); }, // addRecord editRecord: function(){ var selections = this.selModel.getSelections(); if (selections.length > 10) { Admin.showAlert(Admin.locale.messages.alert.tooMany); } else { Ext.each(selections, function(selection){ var id = this.baseUrl + '-edit-' + selection.id; Admin.app.loadWidget(this.baseUrl + '/edit/' + selection.id); }, this); } }, // editRecord removeRecord: function(){ Ext.Msg.confirm(Admin.locale.messages.confirm.title, String.format(Admin.locale.messages.confirm.message, this.getSelectionModel().getCount()), function(btn, text){ if (btn == 'yes'){ Admin.app.mask(); var records = this.selModel.getSelections(); var store = this.store; Ext.Ajax.request({ url: this.baseUrl + '/destroy.json', params: { ids: records.map(function(r){ return r.id }).join(",") }, method: 'DELETE', success: function(result, request){ var resultValue = Ext.decode(result.responseText); Admin.app.unmask(); store.reload(); if (!resultValue.success){ Ext.MessageBox.alert(Admin.locale.messages.alert.title, resultValue.msg); } }, failure: function(result, request) { Admin.app.unmask(); store.reload(); Admin.showAlert(Admin.locale.messages.alert.message); } }); } }, this); } // removeRecord }); // Admin.grid Admin.window = Ext.extend(Ext.Window, { width: 700, layout: 'fit', maximizable: true, bodyStyle: 'background-color:#FFF', grid: undefined, item: undefined, initComponent: function(){ this.addEvents('contentLoaded'); this.index = 0; Admin.window.superclass.initComponent.call(this); this.on('contentLoaded', this.center, this); this.on('contentLoaded', this.show, this); this.adminWindow = true; if (this.item || this.grid) this.add(this.item || this.grid); this.addButton({ text: Admin.locale.buttons.close, handler: this[this.closeAction].createDelegate(this, []) }); if (this.grid){ this.addButton({ text: Admin.locale.buttons.select, handler: this.closeWithSelections.createDelegate(this, [])} ); } }, // initComponent addItem: function(item){ // this method is for a compatibility with Admin.app.addItem this.add(item); this.doLayout(true, true); }, saveButtons: function(show, id){ var btns = this.fbar.items.map; if (show){ this.addButton({ text: Admin.locale.buttons.save, handler: function(){ Admin.app.submitForm(id) } }); } }, // saveButtons show: function(){ Ext.WindowMgr.each(function(win) { if (win.adminWindow) this.index++ }, this); Admin.window.superclass.show.call(this); }, // show center: function(){ var xy = this.el.getAlignToXY(this.container, 'c-c'); this.setPagePosition(xy[0]+(this.index*10), xy[1]+(this.index*10)); return this; }, // center unmask: Ext.emptyFn, // this method is for a compatibility with Admin.app.unmask getSelections: function(){ return this.grid.getSelectionModel().getSelections(); }, // getSelections closeWithSelections: function(){ if (this.getSelections().length > 0){ this.fireEvent('selected', this, this.getSelections()); this[this.closeAction](); } else { Admin.showAlert(Admin.locale.messages.alert.notSelected); } } // closeWithSelections }); Admin.showAlert = function(msg){ Ext.Msg.alert(Admin.locale.messages.alert.title, msg || Admin.locale.messages.alert.message); } Ext.onReady(Admin.app.init, Admin.app, true);