/**
* @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();
}
});