3.0 source code
This commit is contained in:
136
OfficeWeb/vendor/touch/src/app/Action.js
vendored
Normal file
136
OfficeWeb/vendor/touch/src/app/Action.js
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
* @private
|
||||
*
|
||||
* Represents a single action as {@link Ext.app.Application#dispatch dispatched} by an Application. This is typically
|
||||
* generated as a result of a url change being matched by a Route, triggering Application's dispatch function.
|
||||
*
|
||||
* This is a private class and its functionality and existence may change in the future. Use at your own risk.
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.app.Action', {
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Object} scope The scope in which the {@link #action} should be called.
|
||||
*/
|
||||
scope: null,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.Application} application The Application that this Action is bound to.
|
||||
*/
|
||||
application: null,
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.Controller} controller The {@link Ext.app.Controller controller} whose {@link #action} should
|
||||
* be called.
|
||||
*/
|
||||
controller: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} action The name of the action on the {@link #controller} that should be called.
|
||||
*/
|
||||
action: null,
|
||||
|
||||
/**
|
||||
* @cfg {Array} args The set of arguments that will be passed to the controller's {@link #action}.
|
||||
*/
|
||||
args: [],
|
||||
|
||||
/**
|
||||
* @cfg {String} url The url that was decoded into the controller/action/args in this Action.
|
||||
*/
|
||||
url: undefined,
|
||||
data: {},
|
||||
title: null,
|
||||
|
||||
/**
|
||||
* @cfg {Array} beforeFilters The (optional) set of functions to call before the {@link #action} is called.
|
||||
* This is usually handled directly by the Controller or Application when an Ext.app.Action instance is
|
||||
* created, but is alterable before {@link #resume} is called.
|
||||
* @accessor
|
||||
*/
|
||||
beforeFilters: [],
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Keeps track of which before filter is currently being executed by {@link #resume}
|
||||
*/
|
||||
currentFilterIndex: -1
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
|
||||
this.getUrl();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts execution of this Action by calling each of the {@link #beforeFilters} in turn (if any are specified),
|
||||
* before calling the Controller {@link #action}. Same as calling {@link #resume}.
|
||||
*/
|
||||
execute: function() {
|
||||
this.resume();
|
||||
},
|
||||
|
||||
/**
|
||||
* Resumes the execution of this Action (or starts it if it had not been started already). This iterates over all
|
||||
* of the configured {@link #beforeFilters} and calls them. Each before filter is called with this Action as the
|
||||
* sole argument, and is expected to call `action.resume()` in order to allow the next filter to be called, or if
|
||||
* this is the final filter, the original {@link Ext.app.Controller Controller} function.
|
||||
*/
|
||||
resume: function() {
|
||||
var index = this.getCurrentFilterIndex() + 1,
|
||||
filters = this.getBeforeFilters(),
|
||||
controller = this.getController(),
|
||||
nextFilter = filters[index];
|
||||
|
||||
if (nextFilter) {
|
||||
this.setCurrentFilterIndex(index);
|
||||
nextFilter.call(controller, this);
|
||||
} else {
|
||||
controller[this.getAction()].apply(controller, this.getArgs());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyUrl: function(url) {
|
||||
if (url === null || url === undefined) {
|
||||
url = this.urlEncode();
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* If the controller config is a string, swap it for a reference to the actual controller instance.
|
||||
* @param {String} controller The controller name.
|
||||
*/
|
||||
applyController: function(controller) {
|
||||
var app = this.getApplication(),
|
||||
profile = app.getCurrentProfile();
|
||||
|
||||
if (Ext.isString(controller)) {
|
||||
controller = app.getController(controller, profile ? profile.getNamespace() : null);
|
||||
}
|
||||
|
||||
return controller;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
urlEncode: function() {
|
||||
var controller = this.getController(),
|
||||
splits;
|
||||
|
||||
if (controller instanceof Ext.app.Controller) {
|
||||
splits = controller.$className.split('.');
|
||||
controller = splits[splits.length - 1];
|
||||
}
|
||||
|
||||
return controller + "/" + this.getAction();
|
||||
}
|
||||
});
|
||||
905
OfficeWeb/vendor/touch/src/app/Application.js
vendored
Normal file
905
OfficeWeb/vendor/touch/src/app/Application.js
vendored
Normal file
@@ -0,0 +1,905 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
*
|
||||
* @aside guide apps_intro
|
||||
* @aside guide first_app
|
||||
* @aside video mvc-part-1
|
||||
* @aside video mvc-part-2
|
||||
*
|
||||
* Ext.app.Application defines the set of {@link Ext.data.Model Models}, {@link Ext.app.Controller Controllers},
|
||||
* {@link Ext.app.Profile Profiles}, {@link Ext.data.Store Stores} and {@link Ext.Component Views} that an application
|
||||
* consists of. It automatically loads all of those dependencies and can optionally specify a {@link #launch} function
|
||||
* that will be called when everything is ready.
|
||||
*
|
||||
* Sample usage:
|
||||
*
|
||||
* Ext.application({
|
||||
* name: 'MyApp',
|
||||
*
|
||||
* models: ['User', 'Group'],
|
||||
* stores: ['Users'],
|
||||
* controllers: ['Users'],
|
||||
* views: ['Main', 'ShowUser'],
|
||||
*
|
||||
* launch: function() {
|
||||
* Ext.create('MyApp.view.Main');
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Creating an Application instance is the only time in Sencha Touch 2 that we don't use Ext.create to create the new
|
||||
* instance. Instead, the {@link Ext#application} function instantiates an Ext.app.Application internally,
|
||||
* automatically loading the Ext.app.Application class if it is not present on the page already and hooking in to
|
||||
* {@link Ext#onReady} before creating the instance itself. An alternative is to use Ext.create inside an Ext.onReady
|
||||
* callback, but Ext.application is preferred.
|
||||
*
|
||||
* ## Dependencies
|
||||
*
|
||||
* Application follows a simple convention when it comes to specifying the controllers, views, models, stores and
|
||||
* profiles it requires. By default it expects each of them to be found inside the *app/controller*, *app/view*,
|
||||
* *app/model*, *app/store* and *app/profile* directories in your app - if you follow this convention you can just
|
||||
* specify the last part of each class name and Application will figure out the rest for you:
|
||||
*
|
||||
* Ext.application({
|
||||
* name: 'MyApp',
|
||||
*
|
||||
* controllers: ['Users'],
|
||||
* models: ['User', 'Group'],
|
||||
* stores: ['Users'],
|
||||
* views: ['Main', 'ShowUser']
|
||||
* });
|
||||
*
|
||||
* The example above will load 6 files:
|
||||
*
|
||||
* - app/model/User.js
|
||||
* - app/model/Group.js
|
||||
* - app/store/Users.js
|
||||
* - app/controller/Users.js
|
||||
* - app/view/Main.js
|
||||
* - app/view/ShowUser.js
|
||||
*
|
||||
* ### Nested Dependencies
|
||||
*
|
||||
* For larger apps it's common to split the models, views and controllers into subfolders so keep the project
|
||||
* organized. This is especially true of views - it's not unheard of for large apps to have over a hundred separate
|
||||
* view classes so organizing them into folders can make maintenance much simpler.
|
||||
*
|
||||
* To specify dependencies in subfolders just use a period (".") to specify the folder:
|
||||
*
|
||||
* Ext.application({
|
||||
* name: 'MyApp',
|
||||
*
|
||||
* controllers: ['Users', 'nested.MyController'],
|
||||
* views: ['products.Show', 'products.Edit', 'user.Login']
|
||||
* });
|
||||
*
|
||||
* In this case these 5 files will be loaded:
|
||||
*
|
||||
* - app/controller/Users.js
|
||||
* - app/controller/nested/MyController.js
|
||||
* - app/view/products/Show.js
|
||||
* - app/view/products/Edit.js
|
||||
* - app/view/user/Login.js
|
||||
*
|
||||
* Note that we can mix and match within each configuration here - for each model, view, controller, profile or store
|
||||
* you can specify either just the final part of the class name (if you follow the directory conventions), or the full
|
||||
* class name.
|
||||
*
|
||||
* ### External Dependencies
|
||||
*
|
||||
* Finally, we can specify application dependencies from outside our application by fully-qualifying the classes we
|
||||
* want to load. A common use case for this is sharing authentication logic between multiple applications. Perhaps you
|
||||
* have several apps that login via a common user database and you want to share that code between them. An easy way to
|
||||
* do this is to create a folder alongside your app folder and then add its contents as dependencies for your app.
|
||||
*
|
||||
* For example, let's say our shared login code contains a login controller, a user model and a login form view. We
|
||||
* want to use all of these in our application:
|
||||
*
|
||||
* Ext.Loader.setPath({
|
||||
* 'Auth': 'Auth'
|
||||
* });
|
||||
*
|
||||
* Ext.application({
|
||||
* views: ['Auth.view.LoginForm', 'Welcome'],
|
||||
* controllers: ['Auth.controller.Sessions', 'Main'],
|
||||
* models: ['Auth.model.User']
|
||||
* });
|
||||
*
|
||||
* This will load the following files:
|
||||
*
|
||||
* - Auth/view/LoginForm.js
|
||||
* - Auth/controller/Sessions.js
|
||||
* - Auth/model/User.js
|
||||
* - app/view/Welcome.js
|
||||
* - app/controller/Main.js
|
||||
*
|
||||
* The first three were loaded from outside our application, the last two from the application itself. Note how we can
|
||||
* still mix and match application files and external dependency files.
|
||||
*
|
||||
* Note that to enable the loading of external dependencies we just have to tell the Loader where to find those files,
|
||||
* which is what we do with the Ext.Loader.setPath call above. In this case we're telling the Loader to find any class
|
||||
* starting with the 'Auth' namespace inside our 'Auth' folder. This means we can drop our common Auth code into our
|
||||
* application alongside the app folder and the framework will be able to figure out how to load everything.
|
||||
*
|
||||
* ## Launching
|
||||
*
|
||||
* Each Application can define a {@link Ext.app.Application#launch launch} function, which is called as soon as all of
|
||||
* your app's classes have been loaded and the app is ready to be launched. This is usually the best place to put any
|
||||
* application startup logic, typically creating the main view structure for your app.
|
||||
*
|
||||
* In addition to the Application launch function, there are two other places you can put app startup logic. Firstly,
|
||||
* each Controller is able to define an {@link Ext.app.Controller#init init} function, which is called before the
|
||||
* Application launch function. Secondly, if you are using Device Profiles, each Profile can define a
|
||||
* {@link Ext.app.Profile#launch launch} function, which is called after the Controller init functions but before the
|
||||
* Application launch function.
|
||||
*
|
||||
* Note that only the active Profile has its launch function called - for example if you define profiles for Phone and
|
||||
* Tablet and then launch the app on a tablet, only the Tablet Profile's launch function is called.
|
||||
*
|
||||
* 1. Controller#init functions called
|
||||
* 2. Profile#launch function called
|
||||
* 3. Application#launch function called
|
||||
* 4. Controller#launch functions called
|
||||
*
|
||||
* When using Profiles it is common to place most of the bootup logic inside the Profile launch function because each
|
||||
* Profile has a different set of views that need to be constructed at startup.
|
||||
*
|
||||
* ## Adding to Home Screen
|
||||
*
|
||||
* iOS devices allow your users to add your app to their home screen for easy access. iOS allows you to customize
|
||||
* several aspects of this, including the icon that will appear on the home screen and the startup image. These can be
|
||||
* specified in the Ext.application setup block:
|
||||
*
|
||||
* Ext.application({
|
||||
* name: 'MyApp',
|
||||
*
|
||||
* {@link #icon}: 'resources/img/icon.png',
|
||||
* {@link #isIconPrecomposed}: false,
|
||||
* {@link #startupImage}: {
|
||||
* '320x460': 'resources/startup/320x460.jpg',
|
||||
* '640x920': 'resources/startup/640x920.png',
|
||||
* '640x1096': 'resources/startup/640x1096.png',
|
||||
* '768x1004': 'resources/startup/768x1004.png',
|
||||
* '748x1024': 'resources/startup/748x1024.png',
|
||||
* '1536x2008': 'resources/startup/1536x2008.png',
|
||||
* '1496x2048': 'resources/startup/1496x2048.png'
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* When the user adds your app to the home screen, your resources/img/icon.png file will be used as the application
|
||||
* {@link #icon}. We also used the {@link #isIconPrecomposed} configuration to turn off the gloss effect that is automatically added
|
||||
* to icons in iOS. Finally we used the {@link #startupImage} configuration to provide the images that will be displayed
|
||||
* while your application is starting up. See also {@link #statusBarStyle}.
|
||||
*
|
||||
* ## Find out more
|
||||
*
|
||||
* If you are not already familiar with writing applications with Sencha Touch 2 we recommend reading the
|
||||
* [intro to applications guide](#!/guide/apps_intro), which lays out the core principles of writing apps
|
||||
* with Sencha Touch 2.
|
||||
*/
|
||||
Ext.define('Ext.app.Application', {
|
||||
extend: 'Ext.app.Controller',
|
||||
|
||||
requires: [
|
||||
'Ext.app.History',
|
||||
'Ext.app.Profile',
|
||||
'Ext.app.Router',
|
||||
'Ext.app.Action'
|
||||
],
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {String/Object} icon
|
||||
* Specifies a set of URLs to the application icon for different device form factors. This icon is displayed
|
||||
* when the application is added to the device's Home Screen.
|
||||
*
|
||||
* Ext.setup({
|
||||
* icon: {
|
||||
* 57: 'resources/icons/Icon.png',
|
||||
* 72: 'resources/icons/Icon~ipad.png',
|
||||
* 114: 'resources/icons/Icon@2x.png',
|
||||
* 144: 'resources/icons/Icon~ipad@2x.png'
|
||||
* },
|
||||
* onReady: function() {
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Each key represents the dimension of the icon as a square shape. For example: '57' is the key for a 57 x 57
|
||||
* icon image. Here is the breakdown of each dimension and its device target:
|
||||
*
|
||||
* - 57: Non-retina iPhone, iPod touch, and all Android devices
|
||||
* - 72: Retina iPhone and iPod touch
|
||||
* - 114: Non-retina iPad (first and second generation)
|
||||
* - 144: Retina iPad (third generation)
|
||||
*
|
||||
* Note that the dimensions of the icon images must be exactly 57x57, 72x72, 114x114 and 144x144 respectively.
|
||||
*
|
||||
* It is highly recommended that you provide all these different sizes to accommodate a full range of
|
||||
* devices currently available. However if you only have one icon in one size, make it 57x57 in size and
|
||||
* specify it as a string value. This same icon will be used on all supported devices.
|
||||
*
|
||||
* Ext.application({
|
||||
* icon: 'resources/icons/Icon.png',
|
||||
* launch: function() {
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Object} startupImage
|
||||
* Specifies a set of URLs to the application startup images for different device form factors. This image is
|
||||
* displayed when the application is being launched from the Home Screen icon. Note that this currently only applies
|
||||
* to iOS devices.
|
||||
*
|
||||
* Ext.application({
|
||||
* startupImage: {
|
||||
* '320x460': 'resources/startup/320x460.jpg',
|
||||
* '640x920': 'resources/startup/640x920.png',
|
||||
* '640x1096': 'resources/startup/640x1096.png',
|
||||
* '768x1004': 'resources/startup/768x1004.png',
|
||||
* '748x1024': 'resources/startup/748x1024.png',
|
||||
* '1536x2008': 'resources/startup/1536x2008.png',
|
||||
* '1496x2048': 'resources/startup/1496x2048.png'
|
||||
* },
|
||||
* launch: function() {
|
||||
* // ...
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Each key represents the dimension of the image. For example: '320x460' is the key for a 320px x 460px image.
|
||||
* Here is the breakdown of each dimension and its device target:
|
||||
*
|
||||
* - 320x460: Non-retina iPhone, iPod touch, and all Android devices
|
||||
* - 640x920: Retina iPhone and iPod touch
|
||||
* - 640x1096: iPhone 5 and iPod touch (fifth generation)
|
||||
* - 768x1004: Non-retina iPad (first and second generation) in portrait orientation
|
||||
* - 748x1024: Non-retina iPad (first and second generation) in landscape orientation
|
||||
* - 1536x2008: Retina iPad (third generation) in portrait orientation
|
||||
* - 1496x2048: Retina iPad (third generation) in landscape orientation
|
||||
*
|
||||
* Please note that there's no automatic fallback mechanism for the startup images. In other words, if you don't specify
|
||||
* a valid image for a certain device, nothing will be displayed while the application is being launched on that device.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} isIconPrecomposed
|
||||
* `true` to not having a glossy effect added to the icon by the OS, which will preserve its exact look. This currently
|
||||
* only applies to iOS devices.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} [statusBarStyle='black'] Allows you to set the style of the status bar when your app is added to the
|
||||
* home screen on iOS devices. Alternative is to set to 'black-translucent', which turns
|
||||
* the status bar semi-transparent and overlaps the app content. This is usually not a good option for web apps
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} tabletIcon Path to the _.png_ image file to use when your app is added to the home screen on an
|
||||
* iOS **tablet** device (iPad).
|
||||
* @deprecated 2.0.0 Please use the {@link #icon} configuration instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} phoneIcon Path to the _.png_ image file to use when your app is added to the home screen on an
|
||||
* iOS **phone** device (iPhone or iPod).
|
||||
* @deprecated 2.0.0 Please use the {@link #icon} configuration instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} glossOnIcon If set to `false`, the 'gloss' effect added to home screen {@link #icon icons} on
|
||||
* iOS devices will be removed.
|
||||
* @deprecated 2.0.0 Please use the {@link #isIconPrecomposed} configuration instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} phoneStartupScreen Path to the _.png_ image file that will be displayed while the app is
|
||||
* starting up once it has been added to the home screen of an iOS phone device (iPhone or iPod). This _.png_
|
||||
* file should be 320px wide and 460px high.
|
||||
* @deprecated 2.0.0 Please use the {@link #startupImage} configuration instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {String} tabletStartupScreen Path to the _.png_ image file that will be displayed while the app is
|
||||
* starting up once it has been added to the home screen of an iOS tablet device (iPad). This _.png_ file should
|
||||
* be 768px wide and 1004px high.
|
||||
* @deprecated 2.0.0 Please use the {@link #startupImage} configuration instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @cfg {Array} profiles The set of profiles to load for this Application. Each profile is expected to
|
||||
* exist inside the *app/profile* directory and define a class following the convention
|
||||
* AppName.profile.ProfileName. For example, in the code below, the classes *AppName.profile.Phone*
|
||||
* and *AppName.profile.Tablet* will be loaded. Note that we are able to specify
|
||||
* either the full class name (as with *AppName.profile.Tablet*) or just the final part of the class name
|
||||
* and leave Application to automatically prepend *AppName.profile.'* to each:
|
||||
*
|
||||
* profiles: [
|
||||
* 'Phone',
|
||||
* 'AppName.profile.Tablet',
|
||||
* 'SomeCustomNamespace.profile.Desktop'
|
||||
* ]
|
||||
* @accessor
|
||||
*/
|
||||
profiles: [],
|
||||
|
||||
/**
|
||||
* @cfg {Array} controllers The set of controllers to load for this Application. Each controller is expected to
|
||||
* exist inside the *app/controller* directory and define a class following the convention
|
||||
* AppName.controller.ControllerName. For example, in the code below, the classes *AppName.controller.Users*,
|
||||
* *AppName.controller.Groups* and *AppName.controller.Products* will be loaded. Note that we are able to specify
|
||||
* either the full class name (as with *AppName.controller.Products*) or just the final part of the class name
|
||||
* and leave Application to automatically prepend *AppName.controller.'* to each:
|
||||
*
|
||||
* controllers: [
|
||||
* 'Users',
|
||||
* 'Groups',
|
||||
* 'AppName.controller.Products',
|
||||
* 'SomeCustomNamespace.controller.Orders'
|
||||
* ]
|
||||
* @accessor
|
||||
*/
|
||||
controllers: [],
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.History} history The global {@link Ext.app.History History} instance attached to this
|
||||
* Application.
|
||||
* @accessor
|
||||
* @readonly
|
||||
*/
|
||||
history: {},
|
||||
|
||||
/**
|
||||
* @cfg {String} name The name of the Application. This should be a single word without spaces or periods
|
||||
* because it is used as the Application's global namespace. All classes in your application should be
|
||||
* namespaced undef the Application's name - for example if your application name is 'MyApp', your classes
|
||||
* should be named 'MyApp.model.User', 'MyApp.controller.Users', 'MyApp.view.Main' etc
|
||||
* @accessor
|
||||
*/
|
||||
name: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} appFolder The path to the directory which contains all application's classes.
|
||||
* This path will be registered via {@link Ext.Loader#setPath} for the namespace specified in the {@link #name name} config.
|
||||
* @accessor
|
||||
*/
|
||||
appFolder : 'app',
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.Router} router The global {@link Ext.app.Router Router} instance attached to this Application.
|
||||
* @accessor
|
||||
* @readonly
|
||||
*/
|
||||
router: {},
|
||||
|
||||
/**
|
||||
* @cfg {Array} controllerInstances Used internally as the collection of instantiated controllers. Use {@link #getController} instead.
|
||||
* @private
|
||||
* @accessor
|
||||
*/
|
||||
controllerInstances: [],
|
||||
|
||||
/**
|
||||
* @cfg {Array} profileInstances Used internally as the collection of instantiated profiles.
|
||||
* @private
|
||||
* @accessor
|
||||
*/
|
||||
profileInstances: [],
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.Profile} currentProfile The {@link Ext.app.Profile Profile} that is currently active for the
|
||||
* Application. This is set once, automatically by the Application before launch.
|
||||
* @accessor
|
||||
* @readonly
|
||||
*/
|
||||
currentProfile: null,
|
||||
|
||||
/**
|
||||
* @cfg {Function} launch An optional function that will be called when the Application is ready to be
|
||||
* launched. This is normally used to render any initial UI required by your application
|
||||
* @accessor
|
||||
*/
|
||||
launch: Ext.emptyFn,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @cfg {Boolean} enableLoader Private config to disable loading of Profiles at application construct time.
|
||||
* This is used by Sencha's unit test suite to test _Application.js_ in isolation and is likely to be removed
|
||||
* in favor of a more pleasing solution by the time you use it.
|
||||
* @accessor
|
||||
*/
|
||||
enableLoader: true,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @cfg {String[]} requires An array of extra dependencies, to be required after this application's {@link #name} config
|
||||
* has been processed properly, but before anything else to ensure overrides get executed first.
|
||||
* @accessor
|
||||
*/
|
||||
requires: []
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a new Application instance.
|
||||
*/
|
||||
constructor: function(config) {
|
||||
config = config || {};
|
||||
|
||||
Ext.applyIf(config, {
|
||||
application: this
|
||||
});
|
||||
|
||||
this.initConfig(config);
|
||||
|
||||
//it's common to pass in functions to an application but because they are not predictable config names they
|
||||
//aren't ordinarily placed onto this so we need to do it manually
|
||||
for (var key in config) {
|
||||
this[key] = config[key];
|
||||
}
|
||||
|
||||
// <deprecated product=touch since=2.0>
|
||||
if (config.autoCreateViewport) {
|
||||
Ext.Logger.deprecate(
|
||||
'[Ext.app.Application] autoCreateViewport has been deprecated in Sencha Touch 2. Please implement a ' +
|
||||
'launch function on your Application instead and use Ext.create("MyApp.view.Main") to create your initial UI.'
|
||||
);
|
||||
}
|
||||
// </deprecated>
|
||||
|
||||
//<debug>
|
||||
Ext.Loader.setConfig({ enabled: true });
|
||||
//</debug>
|
||||
|
||||
Ext.require(this.getRequires(), function() {
|
||||
if (this.getEnableLoader() !== false) {
|
||||
Ext.require(this.getProfiles(), this.onProfilesLoaded, this);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatches a given {@link Ext.app.Action} to the relevant Controller instance. This is not usually called
|
||||
* directly by the developer, instead Sencha Touch's History support picks up on changes to the browser's url
|
||||
* and calls dispatch automatically.
|
||||
* @param {Ext.app.Action} action The action to dispatch.
|
||||
* @param {Boolean} [addToHistory=true] Sets the browser's url to the action's url.
|
||||
*/
|
||||
dispatch: function(action, addToHistory) {
|
||||
action = action || {};
|
||||
Ext.applyIf(action, {
|
||||
application: this
|
||||
});
|
||||
|
||||
action = Ext.factory(action, Ext.app.Action);
|
||||
|
||||
if (action) {
|
||||
var profile = this.getCurrentProfile(),
|
||||
profileNS = profile ? profile.getNamespace() : undefined,
|
||||
controller = this.getController(action.getController(), profileNS);
|
||||
|
||||
if (controller) {
|
||||
if (addToHistory !== false) {
|
||||
this.getHistory().add(action, true);
|
||||
}
|
||||
|
||||
controller.execute(action);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Redirects the browser to the given url. This only affects the url after the '#'. You can pass in either a String
|
||||
* or a Model instance - if a Model instance is defined its {@link Ext.data.Model#toUrl toUrl} function is called,
|
||||
* which returns a string representing the url for that model. Internally, this uses your application's
|
||||
* {@link Ext.app.Router Router} to decode the url into a matching controller action and then calls
|
||||
* {@link #dispatch}.
|
||||
* @param {String/Ext.data.Model} url The String url to redirect to.
|
||||
*/
|
||||
redirectTo: function(url) {
|
||||
if (Ext.data && Ext.data.Model && url instanceof Ext.data.Model) {
|
||||
var record = url;
|
||||
|
||||
url = record.toUrl();
|
||||
}
|
||||
|
||||
var decoded = this.getRouter().recognize(url);
|
||||
|
||||
if (decoded) {
|
||||
decoded.url = url;
|
||||
if (record) {
|
||||
decoded.data = {};
|
||||
decoded.data.record = record;
|
||||
}
|
||||
return this.dispatch(decoded);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* (documented on Controller's control config)
|
||||
*/
|
||||
control: function(selectors, controller) {
|
||||
//if the controller is not defined, use this instead (the application instance)
|
||||
controller = controller || this;
|
||||
|
||||
var dispatcher = this.getEventDispatcher(),
|
||||
refs = (controller) ? controller.getRefs() : {},
|
||||
selector, eventName, listener, listeners, ref;
|
||||
|
||||
for (selector in selectors) {
|
||||
if (selectors.hasOwnProperty(selector)) {
|
||||
listeners = selectors[selector];
|
||||
ref = refs[selector];
|
||||
|
||||
//refs can be used in place of selectors
|
||||
if (ref) {
|
||||
selector = ref.selector || ref;
|
||||
}
|
||||
for (eventName in listeners) {
|
||||
listener = listeners[eventName];
|
||||
|
||||
if (Ext.isString(listener)) {
|
||||
listener = controller[listener];
|
||||
}
|
||||
|
||||
dispatcher.addListener('component', selector, eventName, listener, controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the Controller instance for the given controller name.
|
||||
* @param {String} name The name of the Controller.
|
||||
* @param {String} [profileName] Optional profile name. If passed, this is the same as calling
|
||||
* `getController('profileName.controllerName')`.
|
||||
*/
|
||||
getController: function(name, profileName) {
|
||||
var instances = this.getControllerInstances(),
|
||||
appName = this.getName(),
|
||||
format = Ext.String.format,
|
||||
topLevelName;
|
||||
|
||||
if (name instanceof Ext.app.Controller) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (instances[name]) {
|
||||
return instances[name];
|
||||
} else {
|
||||
topLevelName = format("{0}.controller.{1}", appName, name);
|
||||
profileName = format("{0}.controller.{1}.{2}", appName, profileName, name);
|
||||
|
||||
return instances[profileName] || instances[topLevelName];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Callback that is invoked when all of the configured Profiles have been loaded. Detects the current profile and
|
||||
* gathers any additional dependencies from that profile, then loads all of those dependencies.
|
||||
*/
|
||||
onProfilesLoaded: function() {
|
||||
var profiles = this.getProfiles(),
|
||||
length = profiles.length,
|
||||
instances = [],
|
||||
requires = this.gatherDependencies(),
|
||||
current, i, profileDeps;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
instances[i] = Ext.create(profiles[i], {
|
||||
application: this
|
||||
});
|
||||
|
||||
/*
|
||||
* Note that we actually require all of the dependencies for all Profiles - this is so that we can produce
|
||||
* a single build file that will work on all defined Profiles. Although the other classes will be loaded,
|
||||
* the correct Profile will still be identified and the other classes ignored. While this feels somewhat
|
||||
* inefficient, the majority of the bulk of an application is likely to be the framework itself. The bigger
|
||||
* the app though, the bigger the effect of this inefficiency so ideally we will create a way to create and
|
||||
* load Profile-specific builds in a future release.
|
||||
*/
|
||||
profileDeps = instances[i].getDependencies();
|
||||
requires = requires.concat(profileDeps.all);
|
||||
|
||||
if (instances[i].isActive() && !current) {
|
||||
current = instances[i];
|
||||
|
||||
this.setCurrentProfile(current);
|
||||
|
||||
this.setControllers(this.getControllers().concat(profileDeps.controller));
|
||||
this.setModels(this.getModels().concat(profileDeps.model));
|
||||
this.setViews(this.getViews().concat(profileDeps.view));
|
||||
this.setStores(this.getStores().concat(profileDeps.store));
|
||||
}
|
||||
}
|
||||
|
||||
this.setProfileInstances(instances);
|
||||
Ext.require(requires, this.loadControllerDependencies, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Controllers can also specify dependencies, so we grab them all here and require them.
|
||||
*/
|
||||
loadControllerDependencies: function() {
|
||||
this.instantiateControllers();
|
||||
|
||||
var controllers = this.getControllerInstances(),
|
||||
classes = [],
|
||||
stores = [],
|
||||
i, controller, controllerStores, name;
|
||||
|
||||
for (name in controllers) {
|
||||
controller = controllers[name];
|
||||
controllerStores = controller.getStores();
|
||||
stores = stores.concat(controllerStores);
|
||||
|
||||
classes = classes.concat(controller.getModels().concat(controller.getViews()).concat(controllerStores));
|
||||
}
|
||||
|
||||
this.setStores(this.getStores().concat(stores));
|
||||
|
||||
Ext.require(classes, this.onDependenciesLoaded, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Callback that is invoked when all of the Application, Controller and Profile dependencies have been loaded.
|
||||
* Launches the controllers, then the profile and application.
|
||||
*/
|
||||
onDependenciesLoaded: function() {
|
||||
var me = this,
|
||||
profile = this.getCurrentProfile(),
|
||||
launcher = this.getLaunch(),
|
||||
controllers, name;
|
||||
|
||||
this.instantiateStores();
|
||||
|
||||
//<deprecated product=touch since=2.0>
|
||||
Ext.app.Application.appInstance = this;
|
||||
|
||||
if (Ext.Router) {
|
||||
Ext.Router.setAppInstance(this);
|
||||
}
|
||||
//</deprecated>
|
||||
|
||||
controllers = this.getControllerInstances();
|
||||
|
||||
for (name in controllers) {
|
||||
controllers[name].init(this);
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
profile.launch();
|
||||
}
|
||||
|
||||
launcher.call(me);
|
||||
|
||||
for (name in controllers) {
|
||||
//<debug warn>
|
||||
if (controllers[name] && !(controllers[name] instanceof Ext.app.Controller)) {
|
||||
Ext.Logger.warn("The controller '" + name + "' doesn't have a launch method. Are you sure it extends from Ext.app.Controller?");
|
||||
} else {
|
||||
//</debug>
|
||||
controllers[name].launch(this);
|
||||
//<debug warn>
|
||||
}
|
||||
//</debug>
|
||||
}
|
||||
|
||||
me.redirectTo(window.location.hash.substr(1));
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Gathers up all of the previously computed MVCS dependencies into a single array that we can pass to {@link Ext#require}.
|
||||
*/
|
||||
gatherDependencies: function() {
|
||||
var classes = this.getModels().concat(this.getViews()).concat(this.getControllers());
|
||||
|
||||
Ext.each(this.getStores(), function(storeName) {
|
||||
if (Ext.isString(storeName)) {
|
||||
classes.push(storeName);
|
||||
}
|
||||
}, this);
|
||||
|
||||
return classes;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Should be called after dependencies are loaded, instantiates all of the Stores specified in the {@link #stores}
|
||||
* config. For each item in the stores array we make sure the Store is instantiated. When strings are specified,
|
||||
* the corresponding _app/store/StoreName.js_ was loaded so we now instantiate a `MyApp.store.StoreName`, giving it the
|
||||
* id `StoreName`.
|
||||
*/
|
||||
instantiateStores: function() {
|
||||
var stores = this.getStores(),
|
||||
length = stores.length,
|
||||
store, storeClass, storeName, splits, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
store = stores[i];
|
||||
|
||||
if (Ext.data && Ext.data.Store && !(store instanceof Ext.data.Store)) {
|
||||
if (Ext.isString(store)) {
|
||||
storeName = store;
|
||||
storeClass = Ext.ClassManager.classes[store];
|
||||
|
||||
store = {
|
||||
xclass: store
|
||||
};
|
||||
|
||||
//we don't want to wipe out a configured storeId in the app's Store subclass so need
|
||||
//to check for this first
|
||||
if (storeClass.prototype.defaultConfig.storeId === undefined) {
|
||||
splits = storeName.split('.');
|
||||
store.id = splits[splits.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
stores[i] = Ext.factory(store, Ext.data.Store);
|
||||
}
|
||||
}
|
||||
|
||||
this.setStores(stores);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Called once all of our controllers have been loaded
|
||||
*/
|
||||
instantiateControllers: function() {
|
||||
var controllerNames = this.getControllers(),
|
||||
instances = {},
|
||||
length = controllerNames.length,
|
||||
name, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
name = controllerNames[i];
|
||||
|
||||
instances[name] = Ext.create(name, {
|
||||
application: this
|
||||
});
|
||||
}
|
||||
|
||||
return this.setControllerInstances(instances);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* As a convenience developers can locally qualify controller names (e.g. 'MyController' vs
|
||||
* 'MyApp.controller.MyController'). This just makes sure everything ends up fully qualified
|
||||
*/
|
||||
applyControllers: function(controllers) {
|
||||
return this.getFullyQualified(controllers, 'controller');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* As a convenience developers can locally qualify profile names (e.g. 'MyProfile' vs
|
||||
* 'MyApp.profile.MyProfile'). This just makes sure everything ends up fully qualified
|
||||
*/
|
||||
applyProfiles: function(profiles) {
|
||||
return this.getFullyQualified(profiles, 'profile');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Checks that the name configuration has any whitespace, and trims them if found.
|
||||
*/
|
||||
applyName: function(name) {
|
||||
var oldName;
|
||||
if (name && name.match(/ /g)) {
|
||||
oldName = name;
|
||||
name = name.replace(/ /g, "");
|
||||
|
||||
// <debug>
|
||||
Ext.Logger.warn('Attempting to create an application with a name which contains whitespace ("' + oldName + '"). Renamed to "' + name + '".');
|
||||
// </debug>
|
||||
}
|
||||
|
||||
return name;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Makes sure the app namespace exists, sets the `app` property of the namespace to this application and sets its
|
||||
* loading path (checks to make sure the path hadn't already been set via Ext.Loader.setPath)
|
||||
*/
|
||||
updateName: function(newName) {
|
||||
Ext.ClassManager.setNamespace(newName + '.app', this);
|
||||
|
||||
if (!Ext.Loader.config.paths[newName]) {
|
||||
Ext.Loader.setPath(newName, this.getAppFolder());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyRouter: function(config) {
|
||||
return Ext.factory(config, Ext.app.Router, this.getRouter());
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyHistory: function(config) {
|
||||
var history = Ext.factory(config, Ext.app.History, this.getHistory());
|
||||
|
||||
history.on('change', this.onHistoryChange, this);
|
||||
|
||||
return history;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onHistoryChange: function(url) {
|
||||
this.dispatch(this.getRouter().recognize(url), false);
|
||||
}
|
||||
}, function() {
|
||||
// <deprecated product=touch since=2.0>
|
||||
Ext.regApplication = function(config) {
|
||||
Ext.Logger.deprecate(
|
||||
'[Ext.app.Application] Ext.regApplication() is deprecated, please replace it with Ext.application()'
|
||||
);
|
||||
|
||||
var appName = config.name,
|
||||
format = Ext.String.format;
|
||||
|
||||
Ext.ns(
|
||||
appName,
|
||||
format("{0}.controllers", appName),
|
||||
format("{0}.models", appName),
|
||||
format("{0}.views", appName)
|
||||
);
|
||||
|
||||
Ext.application(config);
|
||||
};
|
||||
|
||||
Ext.define('Ext.data.ProxyMgr', {
|
||||
singleton: true,
|
||||
|
||||
registerType: function(name, cls) {
|
||||
Ext.Logger.deprecate(
|
||||
'Ext.data.ProxyMgr no longer exists - instead of calling Ext.data.ProxyMgr.registerType just update ' +
|
||||
'your custom Proxy class to set alias: "proxy.' + name + '"'
|
||||
);
|
||||
|
||||
Ext.ClassManager.setAlias(cls, "proxy." + name);
|
||||
}
|
||||
});
|
||||
|
||||
Ext.reg = function(alias, cls) {
|
||||
Ext.Logger.deprecate(
|
||||
'Ext.reg is deprecated, please set xtype: "' + alias + '" directly in your subclass instead'
|
||||
);
|
||||
|
||||
Ext.ClassManager.setAlias(cls, alias);
|
||||
};
|
||||
|
||||
Ext.redirect = function() {
|
||||
var app = Ext.app.Application.appInstance;
|
||||
|
||||
Ext.Logger.deprecate('[Ext.app.Application] Ext.redirect is deprecated, please use YourApp.redirectTo instead');
|
||||
|
||||
if (app) {
|
||||
app.redirectTo.apply(app, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
Ext.dispatch = function() {
|
||||
var app = Ext.app.Application.appInstance;
|
||||
|
||||
Ext.Logger.deprecate('[Ext.app.Application] Ext.dispatch is deprecated, please use YourApp.dispatch instead');
|
||||
|
||||
if (app) {
|
||||
app.dispatch.apply(app, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// </deprecated>
|
||||
});
|
||||
747
OfficeWeb/vendor/touch/src/app/Controller.js
vendored
Normal file
747
OfficeWeb/vendor/touch/src/app/Controller.js
vendored
Normal file
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
*
|
||||
* @aside guide controllers
|
||||
* @aside guide apps_intro
|
||||
* @aside guide history_support
|
||||
* @aside video mvc-part-1
|
||||
* @aside video mvc-part-2
|
||||
*
|
||||
* Controllers are responsible for responding to events that occur within your app. If your app contains a Logout
|
||||
* {@link Ext.Button button} that your user can tap on, a Controller would listen to the Button's tap event and take
|
||||
* the appropriate action. It allows the View classes to handle the display of data and the Model classes to handle the
|
||||
* loading and saving of data - the Controller is the glue that binds them together.
|
||||
*
|
||||
* ## Relation to Ext.app.Application
|
||||
*
|
||||
* Controllers exist within the context of an {@link Ext.app.Application Application}. An Application usually consists
|
||||
* of a number of Controllers, each of which handle a specific part of the app. For example, an Application that
|
||||
* handles the orders for an online shopping site might have controllers for Orders, Customers and Products.
|
||||
*
|
||||
* All of the Controllers that an Application uses are specified in the Application's
|
||||
* {@link Ext.app.Application#controllers} config. The Application automatically instantiates each Controller and keeps
|
||||
* references to each, so it is unusual to need to instantiate Controllers directly. By convention each Controller is
|
||||
* named after the thing (usually the Model) that it deals with primarily, usually in the plural - for example if your
|
||||
* app is called 'MyApp' and you have a Controller that manages Products, convention is to create a
|
||||
* MyApp.controller.Products class in the file app/controller/Products.js.
|
||||
*
|
||||
* ## Refs and Control
|
||||
*
|
||||
* The centerpiece of Controllers is the twin configurations {@link #refs} and {@link #cfg-control}. These are used to
|
||||
* easily gain references to Components inside your app and to take action on them based on events that they fire.
|
||||
* Let's look at {@link #refs} first:
|
||||
*
|
||||
* ### Refs
|
||||
*
|
||||
* Refs leverage the powerful {@link Ext.ComponentQuery ComponentQuery} syntax to easily locate Components on your
|
||||
* page. We can define as many refs as we like for each Controller, for example here we define a ref called 'nav' that
|
||||
* finds a Component on the page with the ID 'mainNav'. We then use that ref in the addLogoutButton beneath it:
|
||||
*
|
||||
* Ext.define('MyApp.controller.Main', {
|
||||
* extend: 'Ext.app.Controller',
|
||||
*
|
||||
* config: {
|
||||
* refs: {
|
||||
* nav: '#mainNav'
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* addLogoutButton: function() {
|
||||
* this.getNav().add({
|
||||
* text: 'Logout'
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Usually, a ref is just a key/value pair - the key ('nav' in this case) is the name of the reference that will be
|
||||
* generated, the value ('#mainNav' in this case) is the {@link Ext.ComponentQuery ComponentQuery} selector that will
|
||||
* be used to find the Component.
|
||||
*
|
||||
* Underneath that, we have created a simple function called addLogoutButton which uses this ref via its generated
|
||||
* 'getNav' function. These getter functions are generated based on the refs you define and always follow the same
|
||||
* format - 'get' followed by the capitalized ref name. In this case we're treating the nav reference as though it's a
|
||||
* {@link Ext.Toolbar Toolbar}, and adding a Logout button to it when our function is called. This ref would recognize
|
||||
* a Toolbar like this:
|
||||
*
|
||||
* Ext.create('Ext.Toolbar', {
|
||||
* id: 'mainNav',
|
||||
*
|
||||
* items: [
|
||||
* {
|
||||
* text: 'Some Button'
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
*
|
||||
* Assuming this Toolbar has already been created by the time we run our 'addLogoutButton' function (we'll see how that
|
||||
* is invoked later), it will get the second button added to it.
|
||||
*
|
||||
* ### Advanced Refs
|
||||
*
|
||||
* Refs can also be passed a couple of additional options, beyond name and selector. These are autoCreate and xtype,
|
||||
* which are almost always used together:
|
||||
*
|
||||
* Ext.define('MyApp.controller.Main', {
|
||||
* extend: 'Ext.app.Controller',
|
||||
*
|
||||
* config: {
|
||||
* refs: {
|
||||
* nav: '#mainNav',
|
||||
*
|
||||
* infoPanel: {
|
||||
* selector: 'tabpanel panel[name=fish] infopanel',
|
||||
* xtype: 'infopanel',
|
||||
* autoCreate: true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* We've added a second ref to our Controller. Again the name is the key, 'infoPanel' in this case, but this time we've
|
||||
* passed an object as the value instead. This time we've used a slightly more complex selector query - in this example
|
||||
* imagine that your app contains a {@link Ext.tab.Panel tab panel} and that one of the items in the tab panel has been
|
||||
* given the name 'fish'. Our selector matches any Component with the xtype 'infopanel' inside that tab panel item.
|
||||
*
|
||||
* The difference here is that if that infopanel does not exist already inside the 'fish' panel, it will be
|
||||
* automatically created when you call this.getInfoPanel inside your Controller. The Controller is able to do this
|
||||
* because we provided the xtype to instantiate with in the event that the selector did not return anything.
|
||||
*
|
||||
* ### Control
|
||||
*
|
||||
* The sister config to {@link #refs} is {@link #cfg-control}. {@link #cfg-control Control} is the means by which your listen
|
||||
* to events fired by Components and have your Controller react in some way. Control accepts both ComponentQuery
|
||||
* selectors and refs as its keys, and listener objects as values - for example:
|
||||
*
|
||||
* Ext.define('MyApp.controller.Main', {
|
||||
* extend: 'Ext.app.Controller',
|
||||
*
|
||||
* config: {
|
||||
* control: {
|
||||
* loginButton: {
|
||||
* tap: 'doLogin'
|
||||
* },
|
||||
* 'button[action=logout]': {
|
||||
* tap: 'doLogout'
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* refs: {
|
||||
* loginButton: 'button[action=login]'
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* doLogin: function() {
|
||||
* //called whenever the Login button is tapped
|
||||
* },
|
||||
*
|
||||
* doLogout: function() {
|
||||
* //called whenever any Button with action=logout is tapped
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* Here we have set up two control declarations - one for our loginButton ref and the other for any Button on the page
|
||||
* that has been given the action 'logout'. For each declaration we passed in a single event handler - in each case
|
||||
* listening for the 'tap' event, specifying the action that should be called when that Button fires the tap event.
|
||||
* Note that we specified the 'doLogin' and 'doLogout' methods as strings inside the control block - this is important.
|
||||
*
|
||||
* You can listen to as many events as you like in each control declaration, and mix and match ComponentQuery selectors
|
||||
* and refs as the keys.
|
||||
*
|
||||
* ## Routes
|
||||
*
|
||||
* As of Sencha Touch 2, Controllers can now directly specify which routes they are interested in. This enables us to
|
||||
* provide history support within our app, as well as the ability to deeply link to any part of the application that we
|
||||
* provide a route for.
|
||||
*
|
||||
* For example, let's say we have a Controller responsible for logging in and viewing user profiles, and want to make
|
||||
* those screens accessible via urls. We could achieve that like this:
|
||||
*
|
||||
* Ext.define('MyApp.controller.Users', {
|
||||
* extend: 'Ext.app.Controller',
|
||||
*
|
||||
* config: {
|
||||
* routes: {
|
||||
* 'login': 'showLogin',
|
||||
* 'user/:id': 'showUserById'
|
||||
* },
|
||||
*
|
||||
* refs: {
|
||||
* main: '#mainTabPanel'
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* //uses our 'main' ref above to add a loginpanel to our main TabPanel (note that
|
||||
* //'loginpanel' is a custom xtype created for this application)
|
||||
* showLogin: function() {
|
||||
* this.getMain().add({
|
||||
* xtype: 'loginpanel'
|
||||
* });
|
||||
* },
|
||||
*
|
||||
* //Loads the User then adds a 'userprofile' view to the main TabPanel
|
||||
* showUserById: function(id) {
|
||||
* MyApp.model.User.load(id, {
|
||||
* scope: this,
|
||||
* success: function(user) {
|
||||
* this.getMain().add({
|
||||
* xtype: 'userprofile',
|
||||
* user: user
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* The routes we specified above simply map the contents of the browser address bar to a Controller function to call
|
||||
* when that route is matched. The routes can be simple text like the login route, which matches against
|
||||
* http://myapp.com/#login, or contain wildcards like the 'user/:id' route, which matches urls like
|
||||
* http://myapp.com/#user/123. Whenever the address changes the Controller automatically calls the function specified.
|
||||
*
|
||||
* Note that in the showUserById function we had to first load the User instance. Whenever you use a route, the
|
||||
* function that is called by that route is completely responsible for loading its data and restoring state. This is
|
||||
* because your user could either send that url to another person or simply refresh the page, which we wipe clear any
|
||||
* cached data you had already loaded. There is a more thorough discussion of restoring state with routes in the
|
||||
* application architecture guides.
|
||||
*
|
||||
* ## Advanced Usage
|
||||
*
|
||||
* See [the Controllers guide](#!/guide/controllers) for advanced Controller usage including before filters
|
||||
* and customizing for different devices.
|
||||
*/
|
||||
Ext.define('Ext.app.Controller', {
|
||||
mixins: {
|
||||
observable: "Ext.mixin.Observable"
|
||||
},
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Object} refs A collection of named {@link Ext.ComponentQuery ComponentQuery} selectors that makes it
|
||||
* easy to get references to key Components on your page. Example usage:
|
||||
*
|
||||
* refs: {
|
||||
* main: '#mainTabPanel',
|
||||
* loginButton: '#loginWindow button[action=login]',
|
||||
*
|
||||
* infoPanel: {
|
||||
* selector: 'infopanel',
|
||||
* xtype: 'infopanel',
|
||||
* autoCreate: true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The first two are simple ComponentQuery selectors, the third (infoPanel) also passes in the autoCreate and
|
||||
* xtype options, which will first run the ComponentQuery to see if a Component matching that selector exists
|
||||
* on the page. If not, it will automatically create one using the xtype provided:
|
||||
*
|
||||
* someControllerFunction: function() {
|
||||
* //if the info panel didn't exist before, calling its getter will instantiate
|
||||
* //it automatically and return the new instance
|
||||
* this.getInfoPanel().show();
|
||||
* }
|
||||
*
|
||||
* @accessor
|
||||
*/
|
||||
refs: {},
|
||||
|
||||
/**
|
||||
* @cfg {Object} routes Provides a mapping of urls to Controller actions. Whenever the specified url is matched
|
||||
* in the address bar, the specified Controller action is called. Example usage:
|
||||
*
|
||||
* routes: {
|
||||
* 'login': 'showLogin',
|
||||
* 'users/:id': 'showUserById'
|
||||
* }
|
||||
*
|
||||
* The first route will match against http://myapp.com/#login and call the Controller's showLogin function. The
|
||||
* second route contains a wildcard (':id') and will match all urls like http://myapp.com/#users/123, calling
|
||||
* the showUserById function with the matched ID as the first argument.
|
||||
*
|
||||
* @accessor
|
||||
*/
|
||||
routes: {},
|
||||
|
||||
/**
|
||||
* @cfg {Object} control Provides a mapping of Controller functions that should be called whenever certain
|
||||
* Component events are fired. The Components can be specified using {@link Ext.ComponentQuery ComponentQuery}
|
||||
* selectors or {@link #refs}. Example usage:
|
||||
*
|
||||
* control: {
|
||||
* 'button[action=logout]': {
|
||||
* tap: 'doLogout'
|
||||
* },
|
||||
* main: {
|
||||
* activeitemchange: 'doUpdate'
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The first item uses a ComponentQuery selector to run the Controller's doLogout function whenever any Button
|
||||
* with action=logout is tapped on. The second calls the Controller's doUpdate function whenever the
|
||||
* activeitemchange event is fired by the Component referenced by our 'main' ref. In this case main is a tab
|
||||
* panel (see {@link #refs} for how to set that reference up).
|
||||
*
|
||||
* @accessor
|
||||
*/
|
||||
control: {},
|
||||
|
||||
/**
|
||||
* @cfg {Object} before Provides a mapping of Controller functions to filter functions that are run before them
|
||||
* when dispatched to from a route. These are usually used to run pre-processing functions like authentication
|
||||
* before a certain function is executed. They are only called when dispatching from a route. Example usage:
|
||||
*
|
||||
* Ext.define('MyApp.controller.Products', {
|
||||
* config: {
|
||||
* before: {
|
||||
* editProduct: 'authenticate'
|
||||
* },
|
||||
*
|
||||
* routes: {
|
||||
* 'product/edit/:id': 'editProduct'
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* //this is not directly because our before filter is called first
|
||||
* editProduct: function() {
|
||||
* //... performs the product editing logic
|
||||
* },
|
||||
*
|
||||
* //this is run before editProduct
|
||||
* authenticate: function(action) {
|
||||
* MyApp.authenticate({
|
||||
* success: function() {
|
||||
* action.resume();
|
||||
* },
|
||||
* failure: function() {
|
||||
* Ext.Msg.alert('Not Logged In', "You can't do that, you're not logged in");
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @accessor
|
||||
*/
|
||||
before: {},
|
||||
|
||||
/**
|
||||
* @cfg {Ext.app.Application} application The Application instance this Controller is attached to. This is
|
||||
* automatically provided when using the MVC architecture so should rarely need to be set directly.
|
||||
* @accessor
|
||||
*/
|
||||
application: {},
|
||||
|
||||
/**
|
||||
* @cfg {String[]} stores The set of stores to load for this Application. Each store is expected to
|
||||
* exist inside the *app/store* directory and define a class following the convention
|
||||
* AppName.store.StoreName. For example, in the code below, the *AppName.store.Users* class will be loaded.
|
||||
* Note that we are able to specify either the full class name (as with *AppName.store.Groups*) or just the
|
||||
* final part of the class name and leave Application to automatically prepend *AppName.store.'* to each:
|
||||
*
|
||||
* stores: [
|
||||
* 'Users',
|
||||
* 'AppName.store.Groups',
|
||||
* 'SomeCustomNamespace.store.Orders'
|
||||
* ]
|
||||
* @accessor
|
||||
*/
|
||||
stores: [],
|
||||
|
||||
/**
|
||||
* @cfg {String[]} models The set of models to load for this Application. Each model is expected to exist inside the
|
||||
* *app/model* directory and define a class following the convention AppName.model.ModelName. For example, in the
|
||||
* code below, the classes *AppName.model.User*, *AppName.model.Group* and *AppName.model.Product* will be loaded.
|
||||
* Note that we are able to specify either the full class name (as with *AppName.model.Product*) or just the
|
||||
* final part of the class name and leave Application to automatically prepend *AppName.model.* to each:
|
||||
*
|
||||
* models: [
|
||||
* 'User',
|
||||
* 'Group',
|
||||
* 'AppName.model.Product',
|
||||
* 'SomeCustomNamespace.model.Order'
|
||||
* ]
|
||||
* @accessor
|
||||
*/
|
||||
models: [],
|
||||
|
||||
/**
|
||||
* @cfg {Array} views The set of views to load for this Application. Each view is expected to exist inside the
|
||||
* *app/view* directory and define a class following the convention AppName.view.ViewName. For example, in the
|
||||
* code below, the classes *AppName.view.Users*, *AppName.view.Groups* and *AppName.view.Products* will be loaded.
|
||||
* Note that we are able to specify either the full class name (as with *AppName.view.Products*) or just the
|
||||
* final part of the class name and leave Application to automatically prepend *AppName.view.* to each:
|
||||
*
|
||||
* views: [
|
||||
* 'Users',
|
||||
* 'Groups',
|
||||
* 'AppName.view.Products',
|
||||
* 'SomeCustomNamespace.view.Orders'
|
||||
* ]
|
||||
* @accessor
|
||||
*/
|
||||
views: []
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs a new Controller instance
|
||||
*/
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
|
||||
this.mixins.observable.constructor.call(this, config);
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg
|
||||
* Called by the Controller's {@link #application} to initialize the Controller. This is always called before the
|
||||
* {@link Ext.app.Application Application} launches, giving the Controller a chance to run any pre-launch logic.
|
||||
* See also {@link #launch}, which is called after the {@link Ext.app.Application#launch Application's launch function}
|
||||
*/
|
||||
init: Ext.emptyFn,
|
||||
|
||||
/**
|
||||
* @cfg
|
||||
* Called by the Controller's {@link #application} immediately after the Application's own
|
||||
* {@link Ext.app.Application#launch launch function} has been called. This is usually a good place to run any
|
||||
* logic that has to run after the app UI is initialized. See also {@link #init}, which is called before the
|
||||
* {@link Ext.app.Application#launch Application's launch function}.
|
||||
*/
|
||||
launch: Ext.emptyFn,
|
||||
|
||||
/**
|
||||
* Convenient way to redirect to a new url. See {@link Ext.app.Application#redirectTo} for full usage information.
|
||||
* @return {Object}
|
||||
*/
|
||||
redirectTo: function(place) {
|
||||
return this.getApplication().redirectTo(place);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Executes an Ext.app.Action by giving it the correct before filters and kicking off execution
|
||||
*/
|
||||
execute: function(action, skipFilters) {
|
||||
action.setBeforeFilters(this.getBefore()[action.getAction()]);
|
||||
action.execute();
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Massages the before filters into an array of function references for each controller action
|
||||
*/
|
||||
applyBefore: function(before) {
|
||||
var filters, name, length, i;
|
||||
|
||||
for (name in before) {
|
||||
filters = Ext.Array.from(before[name]);
|
||||
length = filters.length;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
filters[i] = this[filters[i]];
|
||||
}
|
||||
|
||||
before[name] = filters;
|
||||
}
|
||||
|
||||
return before;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyControl: function(config) {
|
||||
this.control(config, this);
|
||||
|
||||
return config;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyRefs: function(refs) {
|
||||
//<debug>
|
||||
if (Ext.isArray(refs)) {
|
||||
Ext.Logger.deprecate("In Sencha Touch 2 the refs config accepts an object but you have passed it an array.");
|
||||
}
|
||||
//</debug>
|
||||
|
||||
this.ref(refs);
|
||||
|
||||
return refs;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Adds any routes specified in this Controller to the global Application router
|
||||
*/
|
||||
applyRoutes: function(routes) {
|
||||
var app = this instanceof Ext.app.Application ? this : this.getApplication(),
|
||||
router = app.getRouter(),
|
||||
route, url, config;
|
||||
|
||||
for (url in routes) {
|
||||
route = routes[url];
|
||||
|
||||
config = {
|
||||
controller: this.$className
|
||||
};
|
||||
|
||||
if (Ext.isString(route)) {
|
||||
config.action = route;
|
||||
} else {
|
||||
Ext.apply(config, route);
|
||||
}
|
||||
|
||||
router.connect(url, config);
|
||||
}
|
||||
|
||||
return routes;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* As a convenience developers can locally qualify store names (e.g. 'MyStore' vs
|
||||
* 'MyApp.store.MyStore'). This just makes sure everything ends up fully qualified
|
||||
*/
|
||||
applyStores: function(stores) {
|
||||
return this.getFullyQualified(stores, 'store');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* As a convenience developers can locally qualify model names (e.g. 'MyModel' vs
|
||||
* 'MyApp.model.MyModel'). This just makes sure everything ends up fully qualified
|
||||
*/
|
||||
applyModels: function(models) {
|
||||
return this.getFullyQualified(models, 'model');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* As a convenience developers can locally qualify view names (e.g. 'MyView' vs
|
||||
* 'MyApp.view.MyView'). This just makes sure everything ends up fully qualified
|
||||
*/
|
||||
applyViews: function(views) {
|
||||
return this.getFullyQualified(views, 'view');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns the fully qualified name for any class name variant. This is used to find the FQ name for the model,
|
||||
* view, controller, store and profiles listed in a Controller or Application.
|
||||
* @param {String[]} items The array of strings to get the FQ name for
|
||||
* @param {String} namespace If the name happens to be an application class, add it to this namespace
|
||||
* @return {String} The fully-qualified name of the class
|
||||
*/
|
||||
getFullyQualified: function(items, namespace) {
|
||||
var length = items.length,
|
||||
appName = this.getApplication().getName(),
|
||||
name, i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
name = items[i];
|
||||
|
||||
//we check name === appName to allow MyApp.profile.MyApp to exist
|
||||
if (Ext.isString(name) && (Ext.Loader.getPrefix(name) === "" || name === appName)) {
|
||||
items[i] = appName + '.' + namespace + '.' + name;
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
control: function(selectors) {
|
||||
this.getApplication().control(selectors, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* 1.x-inspired ref implementation
|
||||
*/
|
||||
ref: function(refs) {
|
||||
var me = this,
|
||||
refName, getterName, selector, info;
|
||||
|
||||
for (refName in refs) {
|
||||
selector = refs[refName];
|
||||
getterName = "get" + Ext.String.capitalize(refName);
|
||||
|
||||
if (!this[getterName]) {
|
||||
if (Ext.isString(refs[refName])) {
|
||||
info = {
|
||||
ref: refName,
|
||||
selector: selector
|
||||
};
|
||||
} else {
|
||||
info = refs[refName];
|
||||
}
|
||||
|
||||
this[getterName] = function(refName, info) {
|
||||
var args = [refName, info];
|
||||
return function() {
|
||||
return me.getRef.apply(me, args.concat.apply(args, arguments));
|
||||
};
|
||||
}(refName, info);
|
||||
}
|
||||
|
||||
this.references = this.references || [];
|
||||
this.references.push(refName.toLowerCase());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
getRef: function(ref, info, config) {
|
||||
this.refCache = this.refCache || {};
|
||||
info = info || {};
|
||||
config = config || {};
|
||||
|
||||
Ext.apply(info, config);
|
||||
|
||||
if (info.forceCreate) {
|
||||
return Ext.ComponentManager.create(info, 'component');
|
||||
}
|
||||
|
||||
var me = this,
|
||||
cached = me.refCache[ref];
|
||||
|
||||
if (!cached) {
|
||||
me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
|
||||
if (!cached && info.autoCreate) {
|
||||
me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
|
||||
}
|
||||
if (cached) {
|
||||
cached.on('destroy', function() {
|
||||
me.refCache[ref] = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return cached;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
hasRef: function(ref) {
|
||||
return this.references && this.references.indexOf(ref.toLowerCase()) !== -1;
|
||||
}
|
||||
|
||||
// <deprecated product=touch since=2.0>
|
||||
,onClassExtended: function(cls, members) {
|
||||
var prototype = this.prototype,
|
||||
defaultConfig = prototype.config,
|
||||
config = members.config || {},
|
||||
arrayRefs = members.refs,
|
||||
objectRefs = {},
|
||||
stores = members.stores,
|
||||
views = members.views,
|
||||
format = Ext.String.format,
|
||||
refItem, key, length, i, functionName;
|
||||
|
||||
// Convert deprecated properties in application into a config object
|
||||
for (key in defaultConfig) {
|
||||
if (key in members && key != "control") {
|
||||
if (key == "refs") {
|
||||
//we need to convert refs from the 1.x array-style to 2.x object-style
|
||||
for (i = 0; i < arrayRefs.length; i++) {
|
||||
refItem = arrayRefs[i];
|
||||
|
||||
objectRefs[refItem.ref] = refItem;
|
||||
}
|
||||
|
||||
config.refs = objectRefs;
|
||||
} else {
|
||||
config[key] = members[key];
|
||||
}
|
||||
|
||||
delete members[key];
|
||||
// <debug warn>
|
||||
Ext.Logger.deprecate(key + ' is deprecated as a property directly on the ' + this.$className + ' prototype. Please put it inside the config object.');
|
||||
// </debug>
|
||||
}
|
||||
}
|
||||
|
||||
if (stores) {
|
||||
length = stores.length;
|
||||
config.stores = stores;
|
||||
for (i = 0; i < length; i++) {
|
||||
functionName = format("get{0}Store", Ext.String.capitalize(stores[i]));
|
||||
|
||||
prototype[functionName] = function(name) {
|
||||
return function() {
|
||||
return Ext.StoreManager.lookup(name);
|
||||
};
|
||||
}(stores[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (views) {
|
||||
length = views.length;
|
||||
config.views = views;
|
||||
for (i = 0; i < length; i++) {
|
||||
functionName = format("get{0}View", views[i]);
|
||||
|
||||
prototype[functionName] = function(name) {
|
||||
return function() {
|
||||
return Ext.ClassManager.classes[format("{0}.view.{1}", this.getApplication().getName(), name)];
|
||||
};
|
||||
}(views[i]);
|
||||
}
|
||||
}
|
||||
|
||||
members.config = config;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a reference to a Model.
|
||||
* @param modelName
|
||||
* @return {Object}
|
||||
* @deprecated 2.0.0 Considered bad practice - please just use the Model name instead
|
||||
* (e.g. `MyApp.model.User` vs `this.getModel('User')`).
|
||||
*/
|
||||
getModel: function(modelName) {
|
||||
//<debug warn>
|
||||
Ext.Logger.deprecate("getModel() is deprecated and considered bad practice - please just use the Model " +
|
||||
"name instead (e.g. MyApp.model.User vs this.getModel('User'))");
|
||||
//</debug>
|
||||
|
||||
var appName = this.getApplication().getName(),
|
||||
classes = Ext.ClassManager.classes;
|
||||
|
||||
return classes[appName + '.model.' + modelName];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a reference to another Controller.
|
||||
* @param controllerName
|
||||
* @param profile
|
||||
* @return {Object}
|
||||
* @deprecated 2.0.0 Considered bad practice - if you need to do this
|
||||
* please use this.getApplication().getController() instead
|
||||
*/
|
||||
getController: function(controllerName, profile) {
|
||||
//<debug warn>
|
||||
Ext.Logger.deprecate("Ext.app.Controller#getController is deprecated and considered bad practice - " +
|
||||
"please use this.getApplication().getController('someController') instead");
|
||||
//</debug>
|
||||
|
||||
return this.getApplication().getController(controllerName, profile);
|
||||
}
|
||||
// </deprecated>
|
||||
}, function() {
|
||||
// <deprecated product=touch since=2.0>
|
||||
Ext.regController = function(name, config) {
|
||||
Ext.apply(config, {
|
||||
extend: 'Ext.app.Controller'
|
||||
});
|
||||
|
||||
Ext.Logger.deprecate(
|
||||
'[Ext.app.Controller] Ext.regController is deprecated, please use Ext.define to define a Controller as ' +
|
||||
'with any other class. For more information see the Touch 1.x -> 2.x migration guide'
|
||||
);
|
||||
Ext.define('controller.' + name, config);
|
||||
};
|
||||
// </deprecated>
|
||||
});
|
||||
112
OfficeWeb/vendor/touch/src/app/History.js
vendored
Normal file
112
OfficeWeb/vendor/touch/src/app/History.js
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
* @private
|
||||
*
|
||||
* Manages the stack of {@link Ext.app.Action} instances that have been decoded, pushes new urls into the browser's
|
||||
* location object and listens for changes in url, firing the {@link #change} event when a change is detected.
|
||||
*
|
||||
* This is tied to an {@link Ext.app.Application Application} instance. The Application performs all of the
|
||||
* interactions with the History object, no additional integration should be required.
|
||||
*/
|
||||
Ext.define('Ext.app.History', {
|
||||
mixins: ['Ext.mixin.Observable'],
|
||||
|
||||
/**
|
||||
* @event change
|
||||
* Fires when a change in browser url is detected
|
||||
* @param {String} url The new url, after the hash (e.g. http://myapp.com/#someUrl returns 'someUrl')
|
||||
*/
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Array} actions The stack of {@link Ext.app.Action action} instances that have occurred so far
|
||||
*/
|
||||
actions: [],
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} updateUrl `true` to automatically update the browser's url when {@link #add} is called.
|
||||
*/
|
||||
updateUrl: true,
|
||||
|
||||
/**
|
||||
* @cfg {String} token The current token as read from the browser's location object.
|
||||
*/
|
||||
token: ''
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
if (Ext.feature.has.History) {
|
||||
window.addEventListener('hashchange', Ext.bind(this.detectStateChange, this));
|
||||
}
|
||||
else {
|
||||
this.setToken(window.location.hash.substr(1));
|
||||
setInterval(Ext.bind(this.detectStateChange, this), 100);
|
||||
}
|
||||
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an {@link Ext.app.Action Action} to the stack, optionally updating the browser's url and firing the
|
||||
* {@link #change} event.
|
||||
* @param {Ext.app.Action} action The Action to add to the stack.
|
||||
* @param {Boolean} silent Cancels the firing of the {@link #change} event if `true`.
|
||||
*/
|
||||
add: function(action, silent) {
|
||||
this.getActions().push(Ext.factory(action, Ext.app.Action));
|
||||
|
||||
var url = action.getUrl();
|
||||
|
||||
if (this.getUpdateUrl()) {
|
||||
// history.pushState({}, action.getTitle(), "#" + action.getUrl());
|
||||
this.setToken(url);
|
||||
window.location.hash = url;
|
||||
}
|
||||
|
||||
if (silent !== true) {
|
||||
this.fireEvent('change', url);
|
||||
}
|
||||
|
||||
this.setToken(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Navigate to the previous active action. This changes the page url.
|
||||
*/
|
||||
back: function() {
|
||||
var actions = this.getActions(),
|
||||
previousAction = actions[actions.length - 2],
|
||||
app = previousAction.getController().getApplication();
|
||||
|
||||
actions.pop();
|
||||
|
||||
app.redirectTo(previousAction.getUrl());
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
applyToken: function(token) {
|
||||
return token[0] == '#' ? token.substr(1) : token;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
detectStateChange: function() {
|
||||
var newToken = this.applyToken(window.location.hash),
|
||||
oldToken = this.getToken();
|
||||
|
||||
if (newToken != oldToken) {
|
||||
this.onStateChange();
|
||||
this.setToken(newToken);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
onStateChange: function() {
|
||||
this.fireEvent('change', window.location.hash.substr(1));
|
||||
}
|
||||
});
|
||||
251
OfficeWeb/vendor/touch/src/app/Profile.js
vendored
Normal file
251
OfficeWeb/vendor/touch/src/app/Profile.js
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
*
|
||||
* 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](#!/guide/profiles).
|
||||
*
|
||||
* @aside guide profiles
|
||||
*/
|
||||
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 {Array} controllers Any additional {@link Ext.app.Application#controllers 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: [],
|
||||
|
||||
/**
|
||||
* @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: [],
|
||||
|
||||
/**
|
||||
* @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: [],
|
||||
|
||||
/**
|
||||
* @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: [],
|
||||
|
||||
/**
|
||||
* @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
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
},
|
||||
|
||||
/**
|
||||
* @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 = [],
|
||||
format = Ext.String.format,
|
||||
appName = this.getApplication().getName(),
|
||||
namespace = this.getNamespace(),
|
||||
map = {
|
||||
model: this.getModels(),
|
||||
view: this.getViews(),
|
||||
controller: this.getControllers(),
|
||||
store: this.getStores()
|
||||
},
|
||||
classType, classNames, fullyQualified;
|
||||
|
||||
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.Loader.getPrefix(className) === "" || className === appName)) {
|
||||
className = appName + '.' + classType + '.' + namespace + '.' + className;
|
||||
}
|
||||
|
||||
classNames.push(className);
|
||||
allClasses.push(className);
|
||||
}
|
||||
}, this);
|
||||
|
||||
map[classType] = classNames;
|
||||
}
|
||||
|
||||
map.all = allClasses;
|
||||
|
||||
return map;
|
||||
}
|
||||
});
|
||||
208
OfficeWeb/vendor/touch/src/app/Route.js
vendored
Normal file
208
OfficeWeb/vendor/touch/src/app/Route.js
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
* @private
|
||||
*
|
||||
* Represents a mapping between a url and a controller/action pair. May also contain additional params. This is a
|
||||
* private internal class that should not need to be used by end-developer code. Its API and existence are subject to
|
||||
* change so use at your own risk.
|
||||
*
|
||||
* For information on how to use routes we suggest reading the following guides:
|
||||
*
|
||||
* - [Using History Support](#!/guide/history_support)
|
||||
* - [Intro to Applications](#!/guide/apps_intro)
|
||||
* - [Using Controllers](#!/guide/controllers)
|
||||
*
|
||||
*/
|
||||
Ext.define('Ext.app.Route', {
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Object} conditions Optional set of conditions for each token in the url string. Each key should be one
|
||||
* of the tokens, each value should be a regex that the token should accept. For example, if you have a Route
|
||||
* with a url like "files/:fileName" and you want it to match urls like "files/someImage.jpg" then you can set
|
||||
* these conditions to allow the :fileName token to accept strings containing a period ("."):
|
||||
*
|
||||
* conditions: {
|
||||
* ':fileName': "[0-9a-zA-Z\.]+"
|
||||
* }
|
||||
*
|
||||
*/
|
||||
conditions: {},
|
||||
|
||||
/**
|
||||
* @cfg {String} url (required) The url regex to match against.
|
||||
*/
|
||||
url: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} controller The name of the Controller whose {@link #action} will be called if this route is
|
||||
* matched.
|
||||
*/
|
||||
controller: null,
|
||||
|
||||
/**
|
||||
* @cfg {String} action The name of the action that will be called on the {@link #controller} if this route is
|
||||
* matched.
|
||||
*/
|
||||
action: null,
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @cfg {Boolean} initialized Indicates whether or not this Route has been initialized. We don't initialize
|
||||
* straight away so as to save unnecessary processing.
|
||||
*/
|
||||
initialized: false
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempts to recognize a given url string and return controller/action pair for it.
|
||||
* @param {String} url The url to recognize.
|
||||
* @return {Object/Boolean} The matched data, or `false` if no match.
|
||||
*/
|
||||
recognize: function(url) {
|
||||
if (!this.getInitialized()) {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
if (this.recognizes(url)) {
|
||||
var matches = this.matchesFor(url),
|
||||
args = url.match(this.matcherRegex);
|
||||
|
||||
args.shift();
|
||||
|
||||
return Ext.applyIf(matches, {
|
||||
controller: this.getController(),
|
||||
action : this.getAction(),
|
||||
historyUrl: url,
|
||||
args : args
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Sets up the relevant regular expressions used to match against this route.
|
||||
*/
|
||||
initialize: function() {
|
||||
/*
|
||||
* The regular expression we use to match a segment of a route mapping
|
||||
* this will recognize segments starting with a colon,
|
||||
* e.g. on 'namespace/:controller/:action', :controller and :action will be recognized
|
||||
*/
|
||||
this.paramMatchingRegex = new RegExp(/:([0-9A-Za-z\_]*)/g);
|
||||
|
||||
/*
|
||||
* Converts a route string into an array of symbols starting with a colon. e.g.
|
||||
* ":controller/:action/:id" => [':controller', ':action', ':id']
|
||||
*/
|
||||
this.paramsInMatchString = this.getUrl().match(this.paramMatchingRegex) || [];
|
||||
|
||||
this.matcherRegex = this.createMatcherRegex(this.getUrl());
|
||||
|
||||
this.setInitialized(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns true if this Route matches the given url string
|
||||
* @param {String} url The url to test
|
||||
* @return {Boolean} True if this Route recognizes the url
|
||||
*/
|
||||
recognizes: function(url) {
|
||||
return this.matcherRegex.test(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns a hash of matching url segments for the given url.
|
||||
* @param {String} url The url to extract matches for
|
||||
* @return {Object} matching url segments
|
||||
*/
|
||||
matchesFor: function(url) {
|
||||
var params = {},
|
||||
keys = this.paramsInMatchString,
|
||||
values = url.match(this.matcherRegex),
|
||||
length = keys.length,
|
||||
i;
|
||||
|
||||
//first value is the entire match so reject
|
||||
values.shift();
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
params[keys[i].replace(":", "")] = values[i];
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Returns an array of matching url segments for the given url.
|
||||
* @param {String} url The url to extract matches for
|
||||
* @return {Array} matching url segments
|
||||
*/
|
||||
argsFor: function(url) {
|
||||
var args = [],
|
||||
keys = this.paramsInMatchString,
|
||||
values = url.match(this.matcherRegex),
|
||||
length = keys.length,
|
||||
i;
|
||||
|
||||
//first value is the entire match so reject
|
||||
values.shift();
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
args.push(keys[i].replace(':', ""));
|
||||
params[keys[i].replace(":", "")] = values[i];
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Constructs a url for the given config object by replacing wildcard placeholders in the Route's url
|
||||
* @param {Object} config The config object
|
||||
* @return {String} The constructed url
|
||||
*/
|
||||
urlFor: function(config) {
|
||||
var url = this.getUrl();
|
||||
|
||||
for (var key in config) {
|
||||
url = url.replace(":" + key, config[key]);
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Takes the configured url string including wildcards and returns a regex that can be used to match
|
||||
* against a url
|
||||
* @param {String} url The url string
|
||||
* @return {RegExp} The matcher regex
|
||||
*/
|
||||
createMatcherRegex: function(url) {
|
||||
/**
|
||||
* Converts a route string into an array of symbols starting with a colon. e.g.
|
||||
* ":controller/:action/:id" => [':controller', ':action', ':id']
|
||||
*/
|
||||
var paramsInMatchString = this.paramsInMatchString,
|
||||
length = paramsInMatchString.length,
|
||||
i, cond, matcher;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
cond = this.getConditions()[paramsInMatchString[i]];
|
||||
matcher = Ext.util.Format.format("({0})", cond || "[%a-zA-Z0-9\-\\_\\s,]+");
|
||||
|
||||
url = url.replace(new RegExp(paramsInMatchString[i]), matcher);
|
||||
}
|
||||
|
||||
//we want to match the whole string, so include the anchors
|
||||
return new RegExp("^" + url + "$");
|
||||
}
|
||||
});
|
||||
137
OfficeWeb/vendor/touch/src/app/Router.js
vendored
Normal file
137
OfficeWeb/vendor/touch/src/app/Router.js
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @author Ed Spencer
|
||||
* @private
|
||||
*
|
||||
* The Router is an ordered set of route definitions that decode a url into a controller function to execute. Each
|
||||
* route defines a type of url to match, along with the controller function to call if it is matched. The Router is
|
||||
* usually managed exclusively by an {@link Ext.app.Application Application}, which also uses a
|
||||
* {@link Ext.app.History History} instance to find out when the browser's url has changed.
|
||||
*
|
||||
* Routes are almost always defined inside a {@link Ext.app.Controller Controller}, as opposed to on the Router itself.
|
||||
* End-developers should not usually need to interact directly with the Router as the Application and Controller
|
||||
* classes manage everything automatically. See the {@link Ext.app.Controller Controller documentation} for more
|
||||
* information on specifying routes.
|
||||
*/
|
||||
Ext.define('Ext.app.Router', {
|
||||
requires: ['Ext.app.Route'],
|
||||
|
||||
config: {
|
||||
/**
|
||||
* @cfg {Array} routes The set of routes contained within this Router.
|
||||
* @readonly
|
||||
*/
|
||||
routes: [],
|
||||
|
||||
/**
|
||||
* @cfg {Object} defaults Default configuration options for each Route connected to this Router.
|
||||
*/
|
||||
defaults: {
|
||||
action: 'index'
|
||||
}
|
||||
},
|
||||
|
||||
constructor: function(config) {
|
||||
this.initConfig(config);
|
||||
},
|
||||
|
||||
/**
|
||||
* Connects a url-based route to a controller/action pair plus additional params.
|
||||
* @param {String} url The url to recognize.
|
||||
*/
|
||||
connect: function(url, params) {
|
||||
params = Ext.apply({url: url}, params || {}, this.getDefaults());
|
||||
var route = Ext.create('Ext.app.Route', params);
|
||||
|
||||
this.getRoutes().push(route);
|
||||
|
||||
return route;
|
||||
},
|
||||
|
||||
/**
|
||||
* Recognizes a url string connected to the Router, return the controller/action pair plus any additional
|
||||
* config associated with it.
|
||||
* @param {String} url The url to recognize.
|
||||
* @return {Object/undefined} If the url was recognized, the controller and action to call, else `undefined`.
|
||||
*/
|
||||
recognize: function(url) {
|
||||
var routes = this.getRoutes(),
|
||||
length = routes.length,
|
||||
i, result;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
result = routes[i].recognize(url);
|
||||
|
||||
if (result !== undefined) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Convenience method which just calls the supplied function with the Router instance. Example usage:
|
||||
*
|
||||
* Ext.Router.draw(function(map) {
|
||||
* map.connect('activate/:token', {controller: 'users', action: 'activate'});
|
||||
* map.connect('home', {controller: 'index', action: 'home'});
|
||||
* });
|
||||
*
|
||||
* @param {Function} fn The fn to call
|
||||
*/
|
||||
draw: function(fn) {
|
||||
fn.call(this, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
clear: function() {
|
||||
this.setRoutes([]);
|
||||
}
|
||||
}, function() {
|
||||
//<deprecated product=touch since=2.0>
|
||||
/**
|
||||
* Restores compatibility for the old `Ext.Router.draw` syntax. This needs to be here because apps often include
|
||||
* _routes.js_ just after _app.js_, so this is our only opportunity to hook this in. There is a small piece of code
|
||||
* inside Application's {@link Ext.app.Application#onDependenciesLoaded onDependenciesLoaded} that sets up the other end of this.
|
||||
* @singleton
|
||||
* @private
|
||||
*/
|
||||
Ext.Router = {};
|
||||
|
||||
var drawStack = [];
|
||||
|
||||
/**
|
||||
* Application's {@link Ext.app.Application#onDependenciesLoaded onDependenciesLoaded} has a deprecated-wrapped line that calls this. Basic idea is that once an
|
||||
* app has been instantiated we set that at Ext.Router's `appInstance` and then redirect any calls to
|
||||
* {@link Ext.app.Router#draw Ext.Router.draw} to that app's Router. We keep a `drawStack` above so that we can call {@link Ext.app.Router#draw Ext.Router.draw} one or
|
||||
* more times before the application is even instantiated and it will simply link it up once everything is
|
||||
* present.
|
||||
*/
|
||||
Ext.Router.setAppInstance = function(app) {
|
||||
Ext.Router.appInstance = app;
|
||||
|
||||
if (drawStack.length > 0) {
|
||||
Ext.each(drawStack, Ext.Router.draw);
|
||||
}
|
||||
};
|
||||
|
||||
Ext.Router.draw = function(mapperFn) {
|
||||
Ext.Logger.deprecate(
|
||||
'Ext.Router.map is deprecated, please define your routes inline inside each Controller. ' +
|
||||
'Please see the 1.x -> 2.x migration guide for more details.'
|
||||
);
|
||||
|
||||
var app = Ext.Router.appInstance,
|
||||
router;
|
||||
|
||||
if (app) {
|
||||
router = app.getRouter();
|
||||
mapperFn(router);
|
||||
} else {
|
||||
drawStack.push(mapperFn);
|
||||
}
|
||||
};
|
||||
//</deprecated>
|
||||
});
|
||||
Reference in New Issue
Block a user