facebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskype
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
10 KiB
278 lines
10 KiB
/** |
|
* A Profile represents a range of devices that fall under a common category. For the vast majority of apps that use |
|
* device profiles, the app defines a Phone profile and a Tablet profile. Doing this enables you to easily customize |
|
* the experience for the different sized screens offered by those device types. |
|
* |
|
* Only one Profile can be active at a time, and each Profile defines a simple {@link #isActive} function that should |
|
* return either true or false. The first Profile to return true from its isActive function is set as your Application's |
|
* {@link Ext.app.Application#currentProfile current profile}. |
|
* |
|
* A Profile can define any number of {@link #models}, {@link #views}, {@link #controllers} and {@link #stores} which |
|
* will be loaded if the Profile is activated. It can also define a {@link #launch} function that will be called after |
|
* all of its dependencies have been loaded, just before the {@link Ext.app.Application#launch application launch} |
|
* function is called. |
|
* |
|
* ## Sample Usage |
|
* |
|
* First you need to tell your Application about your Profile(s): |
|
* |
|
* Ext.application({ |
|
* name: 'MyApp', |
|
* profiles: ['Phone', 'Tablet'] |
|
* }); |
|
* |
|
* This will load app/profile/Phone.js and app/profile/Tablet.js. Here's how we might define the Phone profile: |
|
* |
|
* Ext.define('MyApp.profile.Phone', { |
|
* extend: 'Ext.app.Profile', |
|
* |
|
* views: ['Main'], |
|
* |
|
* isActive: function() { |
|
* return Ext.os.is('Phone'); |
|
* } |
|
* }); |
|
* |
|
* The isActive function returns true if we detect that we are running on a phone device. If that is the case the |
|
* Application will set this Profile active and load the 'Main' view specified in the Profile's {@link #views} config. |
|
* |
|
* ## Class Specializations |
|
* |
|
* Because Profiles are specializations of an application, all of the models, views, controllers and stores defined |
|
* in a Profile are expected to be namespaced under the name of the Profile. Here's an expanded form of the example |
|
* above: |
|
* |
|
* Ext.define('MyApp.profile.Phone', { |
|
* extend: 'Ext.app.Profile', |
|
* |
|
* views: ['Main'], |
|
* controllers: ['Signup'], |
|
* models: ['MyApp.model.Group'], |
|
* |
|
* isActive: function() { |
|
* return Ext.os.is('Phone'); |
|
* } |
|
* }); |
|
* |
|
* In this case, the Profile is going to load *app/view/phone/Main.js*, *app/controller/phone/Signup.js* and |
|
* *app/model/Group.js*. Notice that in each of the first two cases the name of the profile ('phone' in this case) was |
|
* injected into the class names. In the third case we specified the full Model name (for Group) so the Profile name |
|
* was not injected. |
|
* |
|
* For a fuller understanding of the ideas behind Profiles and how best to use them in your app, we suggest you read |
|
* the [device profiles guide](/touch/2.4/core_concepts/device_profiles.html). |
|
* |
|
*/ |
|
Ext.define('Ext.app.Profile', { |
|
mixins: { |
|
observable: "Ext.mixin.Observable" |
|
}, |
|
|
|
config: { |
|
/** |
|
* @cfg {String} namespace The namespace that this Profile's classes can be found in. Defaults to the lowercased |
|
* Profile {@link #name}, for example a Profile called MyApp.profile.Phone will by default have a 'phone' |
|
* namespace, which means that this Profile's additional models, stores, views and controllers will be loaded |
|
* from the MyApp.model.phone.*, MyApp.store.phone.*, MyApp.view.phone.* and MyApp.controller.phone.* namespaces |
|
* respectively. |
|
* @accessor |
|
*/ |
|
namespace: 'auto', |
|
|
|
/** |
|
* @cfg {String} name The name of this Profile. Defaults to the last section of the class name (e.g. a profile |
|
* called MyApp.profile.Phone will default the name to 'Phone'). |
|
* @accessor |
|
*/ |
|
name: 'auto', |
|
|
|
/** |
|
* @cfg {String} mainView |
|
*/ |
|
mainView: { |
|
$value: null, |
|
lazy: true |
|
}, |
|
|
|
/** |
|
* @cfg {Ext.app.Application} application The {@link Ext.app.Application Application} instance that this |
|
* Profile is bound to. This is set automatically. |
|
* @accessor |
|
* @readonly |
|
*/ |
|
application: null, |
|
|
|
// @cmd-auto-dependency {aliasPrefix: "controller.", profile: true, blame: "all"} |
|
/** |
|
* @cfg {Array} controllers Any additional {@link Ext.app.Controller Controllers} to load for this |
|
* profile. Note that each item here will be prepended with the Profile namespace when loaded. Example usage: |
|
* |
|
* controllers: [ |
|
* 'Users', |
|
* 'MyApp.controller.Products' |
|
* ] |
|
* |
|
* This will load *MyApp.controller.tablet.Users* and *MyApp.controller.Products*. |
|
* @accessor |
|
*/ |
|
controllers: [], |
|
|
|
// @cmd-auto-dependency {aliasPrefix : "model.", profile: true, blame: "all"} |
|
/** |
|
* @cfg {Array} models Any additional {@link Ext.app.Application#models Models} to load for this profile. Note |
|
* that each item here will be prepended with the Profile namespace when loaded. Example usage: |
|
* |
|
* models: [ |
|
* 'Group', |
|
* 'MyApp.model.User' |
|
* ] |
|
* |
|
* This will load *MyApp.model.tablet.Group* and *MyApp.model.User*. |
|
* @accessor |
|
*/ |
|
models: [], |
|
|
|
// @cmd-auto-dependency {aliasPrefix: "view.", profile: true, blame: "all"} |
|
/** |
|
* @cfg {Array} views Any additional {@link Ext.app.Application#views views} to load for this profile. Note |
|
* that each item here will be prepended with the Profile namespace when loaded. Example usage: |
|
* |
|
* views: [ |
|
* 'Main', |
|
* 'MyApp.view.Login' |
|
* ] |
|
* |
|
* This will load *MyApp.view.tablet.Main* and *MyApp.view.Login*. |
|
* @accessor |
|
*/ |
|
views: [], |
|
|
|
// @cmd-auto-dependency {aliasPrefix: "store.", profile: true, blame: "all"} |
|
/** |
|
* @cfg {Array} stores Any additional {@link Ext.app.Application#stores Stores} to load for this profile. Note |
|
* that each item here will be prepended with the Profile namespace when loaded. Example usage: |
|
* |
|
* stores: [ |
|
* 'Users', |
|
* 'MyApp.store.Products' |
|
* ] |
|
* |
|
* This will load *MyApp.store.tablet.Users* and *MyApp.store.Products*. |
|
* @accessor |
|
*/ |
|
stores: [] |
|
}, |
|
|
|
/** |
|
* Creates a new Profile instance |
|
*/ |
|
constructor: function(config) { |
|
this.initConfig(config); |
|
|
|
this.mixins.observable.constructor.apply(this, arguments); |
|
}, |
|
|
|
/** |
|
* Determines whether or not this Profile is active on the device isActive is executed on. Should return true if |
|
* this profile is meant to be active on this device, false otherwise. Each Profile should implement this function |
|
* (the default implementation just returns false). |
|
* @return {Boolean} True if this Profile should be activated on the device it is running on, false otherwise |
|
*/ |
|
isActive: function() { |
|
return false; |
|
}, |
|
|
|
/** |
|
* @method |
|
* The launch function is called by the {@link Ext.app.Application Application} if this Profile's {@link #isActive} |
|
* function returned true. This is typically the best place to run any profile-specific app launch code. Example |
|
* usage: |
|
* |
|
* launch: function() { |
|
* Ext.create('MyApp.view.tablet.Main'); |
|
* } |
|
*/ |
|
launch: Ext.emptyFn, |
|
|
|
/** |
|
* @private |
|
*/ |
|
applyNamespace: function(name) { |
|
if (name == 'auto') { |
|
name = this.getName(); |
|
} |
|
|
|
return name.toLowerCase(); |
|
}, |
|
|
|
/** |
|
* @private |
|
*/ |
|
applyName: function(name) { |
|
if (name == 'auto') { |
|
var pieces = this.$className.split('.'); |
|
name = pieces[pieces.length - 1]; |
|
} |
|
|
|
return name; |
|
}, |
|
onClassExtended: function(cls, data, hooks) { |
|
var onBeforeClassCreated = hooks.onBeforeCreated; |
|
|
|
hooks.onBeforeCreated = function(cls, data) { |
|
var Controller = Ext.app.Controller, |
|
requires = [], |
|
proto = cls.prototype, |
|
namespace; |
|
|
|
namespace = Controller.resolveNamespace(cls, data); |
|
|
|
Controller.processDependencies(proto, requires, namespace, 'model', data.models); |
|
Controller.processDependencies(proto, requires, namespace, 'view', data.views); |
|
Controller.processDependencies(proto, requires, namespace, 'store', data.stores); |
|
Controller.processDependencies(proto, requires, namespace, 'controller', data.controllers); |
|
|
|
Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this)); |
|
}; |
|
}, |
|
|
|
/** |
|
* @private |
|
* Computes the full class names of any specified model, view, controller and store dependencies, returns them in |
|
* an object map for easy loading |
|
*/ |
|
getDependencies: function() { |
|
var allClasses = [], |
|
appName = this.getApplication().getName(), |
|
namespace = this.getNamespace(), |
|
map = { |
|
model: this.getModels(), |
|
view: this.getViews(), |
|
controller: this.getControllers(), |
|
store: this.getStores() |
|
}, |
|
classType, classNames; |
|
|
|
for (classType in map) { |
|
classNames = []; |
|
|
|
Ext.each(map[classType], function(className) { |
|
if (Ext.isString(className)) { |
|
//we check name === appName to allow MyApp.profile.MyApp to exist |
|
if (Ext.isString(className) && (Ext.ClassManager.getPrefix(className) === "" || className === appName)) { |
|
className = appName + '.' + classType + '.' + namespace + '.' + className; |
|
} |
|
|
|
classNames.push(className); |
|
allClasses.push(className); |
|
} |
|
}, this); |
|
|
|
map[classType] = classNames; |
|
} |
|
|
|
map.all = allClasses; |
|
|
|
return map; |
|
} |
|
}); |