forked from extmvc/extmvc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.js
219 lines (193 loc) · 6.89 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
* @class ExtMVC.App
* @extends Ext.util.Observable
* @cfg {Boolean} usesHistory True to automatically create required DOM elements for Ext.History,
* sets up a listener on Ext.History's change event to fire this.onHistoryChange. False by default
*/
ExtMVC.App = Ext.extend(Ext.util.Observable, {
/**
* @constructor
* Sets up the Application - adds events, sets up namespaces, optionally sets up history.
* Fires the 'before-launch' event before initializing router, viewport and history.
* Calls this.launch() once everything else is set up (override the 'launch' method to provide your own logic).
* Fires the 'launched' event after calling this.launch()
*/
constructor: function(config) {
ExtMVC.App.superclass.constructor.apply(this, arguments);
//apply configuration object and set up namespaces
Ext.apply(this, config || {});
window[this.name] = this;
this.initializeNamespaces();
// Ext.onReady(this.onReady, this);
this.on('launched', function() {
/**
* TODO: This used to reside in initializeHistory but this.launch() needs to be
* called before this dispatches so it is temporarily here... ugly though
*/
if (this.usesHistory) {
if (this.dispatchHistoryOnLoad === true) {
Ext.History.init(function(history) {
var hash = document.location.hash.replace("#", "");
var params = this.router.recognise(hash);
if (params) {this.dispatch(params);}
}, this);
} else {
Ext.History.init();
}
}
}, this);
},
/**
* @private
* Called when Ext.onReady fires
*/
onReady: function() {
if (this.fireEvent('before-launch', this)) {
this.initializeRouter();
// this.initializeViewport();
this.initializeEvents();
if (this.usesHistory === true) this.initializeHistory();
this.launch();
}
},
/**
* @property name
* @type String
* The application's name. This is used when creating namespaces for models, views and controllers,
* and automatically set up as a global variable reference to this application. Read only.
*/
name: 'MyApp',
/**
* @property usesHistory
* @type Boolean
* True to automatically create required DOM elements for Ext.History,
* sets up a listener on Ext.History's change event to fire this.onHistoryChange.
* False by default
*/
usesHistory: false,
/**
* @prop dispatchHistoryOnLoad
* @type Boolean
* If usesHistory is true and dispatchHistoryOnLoad is also true, the OS will attempt to match
* any string currently after the # in the url and dispatch to it
*/
dispatchHistoryOnLoad: true,
/**
* Called when the application is booted up. Override this to provide your own startup logic (defaults to Ext.emptyFn)
*/
launch: function() {
this.fireEvent('launched', this);
},
/**
* @property params
* @type Object
* An object containing the most current parameters (usually decoded from a url using this.router)
* e.g. {controller: 'index', action: 'welcome', id: 10}
*/
params: {},
/**
* Dispatches a request to a registered controller.
* @param {Object} dispatchConfig A config object which should look something like this:
* {controller: 'MyController', action: 'index'}, where 'MyController' is the key for a controller
* which has been registered to the controller. If action is not specified, it defaults to 'index'
* @param {Object} scope The scope in which to fire the event (defaults to the controller)
* @param {Array} args An array of arguments which are passed to the controller action.
*/
dispatch: function dispatch(dispatchConfig, scope, args) {
var dispatchConfig = dispatchConfig || {};
Ext.applyIf(dispatchConfig, {
action: 'index'
});
this.params = dispatchConfig;
var c = ExtMVC.getController(dispatchConfig.controller);
if (c != undefined) {
var action = c[dispatchConfig.action];
if (typeof action == "function") action.apply(scope || c, args || []);
else throw new Error(String.format("Action '{0}' not found on Controller '{1}'", dispatchConfig.action, dispatchConfig.controller));
}
},
/**
* Sets up a Router instance. This is called automatically before onLaunch()
* Add routes using this.router.connect
*/
initializeRouter: function() {
if (this.router == undefined) {
this.router = new ExtMVC.router.Router();
ExtMVC.router.Router.defineRoutes(this.router);
}
},
/**
* Uses Ext.namespace to create packages view controllers, models and views
* E.g. if name = 'Blog' or this.name = 'Blog', this is the same as:
* Ext.ns('Blog', 'Blog.controllers', 'Blog.models', 'Blog.views')
*/
initializeNamespaces: function initializeNamespaces(name) {
var name = name || this.name;
if (name) {
Ext.ns(name, name + '.controllers', name + '.models', name + '.views');
};
},
/**
* Creates the necessary DOM elements required for Ext.History to manage state
* Sets up listeners on Ext.History's change event to fire the dispatch() action in the normal way.
* This is not called automatically as not all applications will need it
*/
initializeHistory: function initializeHistory() {
this.historyForm = Ext.getBody().createChild({
tag: 'form',
action: '#',
cls: 'x-hidden',
id: 'history-form',
children: [
{
tag: 'div',
children: [
{
tag: 'input',
id: 'x-history-field',
type: 'hidden'
},
{
tag: 'iframe',
id: 'x-history-frame'
}
]
}
]
});
Ext.History.on('change', this.onHistoryChange, this);
},
/**
* Takes a history token (anything after the # in the url), consults the router and dispatches
* to the appropriate controller and action if a match was found
* @param {String} token The url token (e.g. the token would be cont/act/id for a url like mydomain.com/#cont/act/id)
*/
onHistoryChange: function onHistoryChange(token) {
var match = this.router.recognise(token);
if (match) {
this.dispatch(match, null, [{url: token}]);
};
},
/**
* Sets up events emitted by the Application
*/
initializeEvents: function initializeEvents() {
this.addEvents(
/**
* @event before-launch
* Fires before this application launches
* @param {ExtMVC.App} this The application about to be launched
*/
'before-launch',
/**
* @event launched
* Fires once the application has been launched
* @param {ExtMVC.App} this The application which has been launched
*/
'launched'
);
}
});
ExtMVC.App.define = function(config) {
ExtMVC.app = new ExtMVC.App(config);
};