/** * @protected * @class Ext.app.BaseController * Base class for Controllers. * */Ext.define('Ext.app.BaseController', { requires: [ 'Ext.app.EventBus', 'Ext.app.domain.Global' ], uses: [ 'Ext.app.domain.Controller' ], mixins: [ 'Ext.mixin.Observable', 'Ext.route.Mixin' ], isController: true, config: { /** * @cfg {String} id The id of this controller. You can use this id when dispatching. * * For an example of dispatching, see the examples under the * {@link Ext.app.Controller#cfg-listen listen} config. * * If an id is not explicitly set, it will default to the controller's full classname. * * @accessor */ id: undefined, /** * @cfg {Object} control * @accessor * * Adds listeners to components selected via {@link Ext.ComponentQuery}. Accepts an * object containing component paths mapped to a hash of listener functions. * The function value may also be a string matching the name of a method on the * controller. * * In the following example the `updateUser` function is mapped to to the `click` * event on a button component, which is a child of the `useredit` component. * * Ext.define('MyApp.controller.Users', { * extend: 'Ext.app.Controller', * * control: { * 'useredit button[action=save]': { * click: 'updateUser' * } * }, * * updateUser: function(button) { * console.log('clicked the Save button'); * } * }); * * The method you pass to the listener will automatically be resolved on the controller. * In this case, the `updateUser` method that will get executed on the `button` `click` * event will resolve to the `updateUser` method on the controller, * * See {@link Ext.ComponentQuery} for more information on component selectors. */ control: null, /** * @cfg {Object} listen * @accessor * * Adds listeners to different event sources (also called "event domains"). The * primary event domain is that of components, but there are also other event domains: * {@link Ext.app.domain.Global Global} domain that intercepts events fired from * {@link Ext.GlobalEvents} Observable instance, * {@link Ext.app.domain.Controller Controller} domain can be used to listen to events * fired by other Controllers, {@link Ext.app.domain.Store Store} domain gives access to * Store events, and {@link Ext.app.domain.Direct Direct} domain can be used with * Ext Direct Providers to listen to their events. * * To listen to "bar" events fired by a controller with id="foo": * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * listen: { * controller: { * '#foo': { * bar: 'onFooBar' * } * } * } * }); * * To listen to "bar" events fired by any controller, and "baz" events * fired by Store with storeId="baz": * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * listen: { * controller: { * '*': { * bar: 'onAnyControllerBar' * } * }, * store: { * '#baz': { * baz: 'onStoreBaz' * } * } * } * }); * * To listen to "idle" events fired by {@link Ext.GlobalEvents} when other event * processing is complete and Ext JS is about to return control to the browser: * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * listen: { * global: { // Global events are always fired * idle: 'onIdle' // from the same object, so there * } // are no selectors * } * }); * * As this relates to components, the following example: * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * listen: { * component: { * 'useredit button[action=save]': { * click: 'updateUser' * } * } * } * }); * * Is equivalent to: * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * control: { * 'useredit button[action=save]': { * click: 'updateUser' * } * } * }); * * Of course, these can all be combined in a single call and used instead of * `control`, like so: * * Ext.define('AM.controller.Users', { * extend: 'Ext.app.Controller', * * listen: { * global: { * idle: 'onIdle' * }, * controller: { * '*': { * foobar: 'onAnyFooBar' * }, * '#foo': { * bar: 'onFooBar' * } * }, * component: { * 'useredit button[action=save]': { * click: 'updateUser' * } * }, * store: { * '#qux': { * load: 'onQuxLoad' * } * } * } * }); */ listen: null }, /** * Creates new Controller. * * @param {Object} [config] Configuration object. */ constructor: function(config) { var me = this; // In versions prior to 5.1, this constructor used to call the Ext.util.Observable // constructor (which applied the config properties directly to the instance) // AND it used to call initConfig as well. Since the constructor of // Ext.mixin.Observable calls initConfig, but does not apply the properties to // the instance, we do that here for backward compatibility. Ext.apply(me, config); // The control and listen properties are also methods so we need to delete them // from the instance after applying the config object. delete me.control; delete me.listen; me.eventbus = Ext.app.EventBus; // need to have eventbus property set before we initialize the config me.mixins.observable.constructor.call(me, config); }, updateId: function(id) { this.id = id; }, applyListen: function(listen) { if (Ext.isObject(listen)) { listen = Ext.clone(listen); } return listen; }, applyControl: function(control) { if (Ext.isObject(control)) { control = Ext.clone(control); } return control; }, /** * @param {Object} control The object to pass to the {@link #method-control} method * @private */ updateControl: function(control) { this.getId(); if (control) { this.control(control); } }, /** * @param {Object} listen The object to pass to the {@link #method-listen} method * @private */ updateListen: function(listen) { this.getId(); if (listen) { this.listen(listen); } }, isActive: function() { return true; }, /** * Adds listeners to components selected via {@link Ext.ComponentQuery}. Accepts an * object containing component paths mapped to a hash of listener functions. * * In the following example the `updateUser` function is mapped to to the `click` * event on a button component, which is a child of the `useredit` component. * * Ext.define('AM.controller.Users', { * init: function() { * this.control({ * 'useredit button[action=save]': { * click: this.updateUser * } * }); * }, * * updateUser: function(button) { * console.log('clicked the Save button'); * } * }); * * Or alternatively one call `control` with two arguments: * * this.control('useredit button[action=save]', { * click: this.updateUser * }); * * See {@link Ext.ComponentQuery} for more information on component selectors. * * @param {String/Object} selectors If a String, the second argument is used as the * listeners, otherwise an object of selectors -> listeners is assumed * @param {Object} [listeners] Config for listeners. * @param {Ext.app.BaseController} [controller] (private) */ control: function(selectors, listeners, controller) { var me = this, ctrl = controller, obj; if (Ext.isString(selectors)) { obj = {}; obj[selectors] = listeners; } else { obj = selectors; ctrl = listeners; } me.eventbus.control(obj, ctrl || me); }, /** * Adds listeners to different event sources (also called "event domains"). The * primary event domain is that of components, but there are also other event domains: * {@link Ext.app.domain.Global Global} domain that intercepts events fired from * {@link Ext.GlobalEvents} Observable instance, {@link Ext.app.domain.Controller Controller} * domain can be used to listen to events fired by other Controllers, * {@link Ext.app.domain.Store Store} domain gives access to Store events, and * {@link Ext.app.domain.Direct Direct} domain can be used with Ext Direct Providers * to listen to their events. * * To listen to "bar" events fired by a controller with id="foo": * * Ext.define('AM.controller.Users', { * init: function() { * this.listen({ * controller: { * '#foo': { * bar: this.onFooBar * } * } * }); * }, * ... * }); * * To listen to "bar" events fired by any controller, and "baz" events * fired by Store with storeId="baz": * * Ext.define('AM.controller.Users', { * init: function() { * this.listen({ * controller: { * '*': { * bar: this.onAnyControllerBar * } * }, * store: { * '#baz': { * baz: this.onStoreBaz * } * } * }); * }, * ... * }); * * To listen to "idle" events fired by {@link Ext.GlobalEvents} when other event * processing is complete and Ext JS is about to return control to the browser: * * Ext.define('AM.controller.Users', { * init: function() { * this.listen({ * global: { // Global events are always fired * idle: this.onIdle // from the same object, so there * } // are no selectors * }); * } * }); * * As this relates to components, the following example: * * Ext.define('AM.controller.Users', { * init: function() { * this.listen({ * component: { * 'useredit button[action=save]': { * click: this.updateUser * } * } * }); * }, * ... * }); * * Is equivalent to: * * Ext.define('AM.controller.Users', { * init: function() { * this.control({ * 'useredit button[action=save]': { * click: this.updateUser * } * }); * }, * ... * }); * * Of course, these can all be combined in a single call and used instead of * `control`, like so: * * Ext.define('AM.controller.Users', { * init: function() { * this.listen({ * global: { * idle: this.onIdle * }, * controller: { * '*': { * foobar: this.onAnyFooBar * }, * '#foo': { * bar: this.onFooBar * } * }, * component: { * 'useredit button[action=save]': { * click: this.updateUser * } * }, * store: { * '#qux': { * load: this.onQuxLoad * } * } * }); * }, * ... * }); * * @param {Object} to Config object containing domains, selectors and listeners. * @param {Ext.app.Controller} [controller] The controller to add the listeners to. Defaults * to the current controller. */ listen: function(to, controller) { this.eventbus.listen(to, controller || this); }, destroy: function() { var me = this, bus = me.eventbus; if (bus) { bus.unlisten(me); me.eventbus = null; } me.callParent(); }});