netzke-core 0.12.3 → 1.0.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +65 -607
- data/Gemfile +1 -1
- data/LICENSE +2 -6
- data/README.md +77 -145
- data/javascripts/base.js +582 -96
- data/javascripts/core.js +62 -0
- data/javascripts/notifications.js +43 -0
- data/javascripts/remoting_provider.js +29 -0
- data/javascripts/routing.js +63 -0
- data/lib/netzke/base.rb +16 -83
- data/lib/netzke/core/action_config.rb +1 -5
- data/lib/netzke/core/actions.rb +59 -21
- data/lib/netzke/core/{client_class.rb → client_class_config.rb} +81 -73
- data/lib/netzke/core/client_code.rb +157 -0
- data/lib/netzke/core/component_config.rb +2 -2
- data/lib/netzke/core/composition.rb +85 -65
- data/lib/netzke/core/configuration.rb +26 -14
- data/lib/netzke/core/core_i18n.rb +17 -0
- data/lib/netzke/core/css_config.rb +6 -6
- data/lib/netzke/core/dynamic_assets.rb +17 -24
- data/lib/netzke/core/embedding.rb +2 -2
- data/lib/netzke/core/endpoint_response.rb +8 -2
- data/lib/netzke/core/inheritance.rb +33 -0
- data/lib/netzke/core/plugins.rb +1 -4
- data/lib/netzke/core/railz/action_view_ext.rb +1 -1
- data/lib/netzke/core/railz/controller_extensions.rb +21 -15
- data/lib/netzke/core/services.rb +61 -48
- data/lib/netzke/core/session.rb +0 -2
- data/lib/netzke/core/state.rb +11 -9
- data/lib/netzke/core/stylesheets.rb +3 -3
- data/lib/netzke/core/version.rb +1 -1
- data/lib/netzke/core.rb +3 -3
- data/lib/netzke/plugin.rb +2 -6
- data/stylesheets/core.css +2 -2
- metadata +11 -10
- data/TODO.md +0 -9
- data/javascripts/ext.js +0 -518
- data/lib/netzke/core/config_to_dsl_delegator.rb +0 -62
- data/lib/netzke/core/dsl_support.rb +0 -70
- data/lib/netzke/core/html.rb +0 -29
- data/lib/netzke/core/javascript.rb +0 -123
data/javascripts/base.js
CHANGED
@@ -1,58 +1,78 @@
|
|
1
1
|
/**
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Netzke.RelativeExtUrl - URL to ext files
|
8
|
-
Netzke.ControllerUrl - NetzkeController URL
|
9
|
-
*/
|
10
|
-
|
11
|
-
// Initial stuff
|
12
|
-
Netzke.classNamespace = 'Netzke.classes'; // TODO: pass from Ruby
|
13
|
-
Ext.ns('Ext.netzke'); // namespace for extensions that depend on Ext
|
14
|
-
Ext.ns('Netzke.page'); // namespace for all component instances on the page
|
15
|
-
Ext.ns(Netzke.classNamespace); // namespace for all component classes
|
16
|
-
Ext.ns('Netzke.classes.Core'); // namespace for Core mixins
|
17
|
-
|
18
|
-
Netzke.deprecationWarning = function(msg){
|
19
|
-
if (typeof console == 'undefined') {
|
20
|
-
// no console defined
|
21
|
-
} else {
|
22
|
-
console.info("Netzke: " + msg);
|
23
|
-
}
|
24
|
-
};
|
2
|
+
* Client-side code for [Netzke::Base](http://www.rubydoc.info/github/netzke/netzke-core/Netzke/Base)
|
3
|
+
* @class Netzke.Base
|
4
|
+
*/
|
5
|
+
Ext.define("Netzke.Base", {
|
6
|
+
extend: 'Ext.Mixin',
|
25
7
|
|
26
|
-
|
8
|
+
mixinConfig: {
|
9
|
+
before: {
|
10
|
+
constructor: 'netzkeBeforeConstructor',
|
11
|
+
initComponent: 'netzkeBeforeInitComponent'
|
12
|
+
},
|
27
13
|
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
after: {
|
15
|
+
constructor: 'netzkeAfterConstructor',
|
16
|
+
initComponent: 'netzkeAfterInitComponent'
|
17
|
+
}
|
18
|
+
},
|
31
19
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Netzke.ajaxIsLoading = function() { return Netzke.nLoadingFixRequests > 0; };
|
39
|
-
}
|
20
|
+
/**
|
21
|
+
* This is `true` for all Netzke components.
|
22
|
+
* @property isNetzke
|
23
|
+
* @type boolean
|
24
|
+
*/
|
25
|
+
isNetzke: true,
|
40
26
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
/**
|
28
|
+
* Override this property globally if you to use a custom notifier class.
|
29
|
+
* @property netzkeNotifier
|
30
|
+
* @type Netzke.Notifier
|
31
|
+
*/
|
32
|
+
netzkeNotifier: Ext.create('Netzke.Notifier'),
|
46
33
|
|
47
|
-
|
48
|
-
Netzke.
|
34
|
+
/**
|
35
|
+
* Called before constructor. Implements all kinds of Netzke component initializations. Override as needed.
|
36
|
+
* @method netzkeBeforeConstructor
|
37
|
+
* @param config {Object} Passed configuration
|
38
|
+
*/
|
39
|
+
netzkeBeforeConstructor: function(config){
|
40
|
+
this.server = {}; // namespace for endpoint functions
|
41
|
+
this.netzkeComponents = config.netzkeComponents;
|
42
|
+
this.passedConfig = config;
|
43
|
+
this.netzkeProcessEndpoints(config);
|
44
|
+
this.netzkeProcessPlugins(config);
|
45
|
+
this.netzkeNormalizeActions(config);
|
46
|
+
this.netzkeNormalizeConfig(config);
|
47
|
+
this.serverConfig = config.clientConfig || {};
|
48
|
+
},
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
/**
|
51
|
+
* Called after constructor. Override as needed.
|
52
|
+
* @method netzkeAfterConstructor
|
53
|
+
* @param config {Object} Passed configuration
|
54
|
+
*/
|
55
|
+
netzkeAfterConstructor: function(config){
|
56
|
+
},
|
52
57
|
|
53
58
|
/**
|
54
|
-
|
55
|
-
|
59
|
+
* Called before `initComponent`. Override as needed.
|
60
|
+
* @method netzkeBeforeInitComponent
|
61
|
+
*/
|
62
|
+
netzkeBeforeInitComponent: function(){
|
63
|
+
},
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Called after `initComponent`. Override as needed.
|
67
|
+
* @method netzkeAfterInitComponent
|
68
|
+
*/
|
69
|
+
netzkeAfterInitComponent: function(){
|
70
|
+
},
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Evaluates CSS passed from the server.
|
74
|
+
* @method netzkeEvalCss
|
75
|
+
* @param code {String} CSS code
|
56
76
|
*/
|
57
77
|
netzkeEvalCss : function(code){
|
58
78
|
var head = Ext.fly(document.getElementsByTagName('head')[0]);
|
@@ -64,42 +84,36 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
64
84
|
},
|
65
85
|
|
66
86
|
/**
|
67
|
-
* Evaluates
|
68
|
-
* @
|
87
|
+
* Evaluates Javascript passed from the server.
|
88
|
+
* @method netzkeEvalJs
|
89
|
+
* @param code {String} Javascript code
|
69
90
|
*/
|
70
91
|
netzkeEvalJs : function(code){
|
71
92
|
eval(code);
|
72
93
|
},
|
73
94
|
|
74
|
-
|
75
|
-
*
|
76
|
-
*
|
77
|
-
*
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
Thus the server side of a component can provide any set of commands to its client side.
|
86
|
-
Args:
|
87
|
-
- instructions: can be
|
88
|
-
1) a hash of instructions, where the key is the method name, and value - the argument that method will be called with (thus, these methods are expected to *only* receive 1 argument). In this case, the methods will be executed in no particular order.
|
89
|
-
2) an array of hashes of instructions. They will be executed in order.
|
90
|
-
Arrays and hashes may be nested at will.
|
91
|
-
If the key in the instructions hash refers to a child Netzke component, netzkeBulkExecute will be called on that component with the value passed as the argument.
|
95
|
+
/**
|
96
|
+
* Executes a bunch of methods. This method is called almost every time a communication to the server takes place.
|
97
|
+
* Thus the server side of a component can provide any set of commands to its client side.
|
98
|
+
*
|
99
|
+
* @method netzkeBulkExecute
|
100
|
+
*
|
101
|
+
* @param {Array|Object} instructions
|
102
|
+
* 1) a hash of instructions, where the key is the method name, and value - the argument that method will be called with (thus, these methods are expected to *only* receive 1 argument). In this case, the methods will be executed in no particular order.
|
103
|
+
* 2) an array of hashes of instructions. They will be executed in order.
|
104
|
+
* Arrays and hashes may be nested at will.
|
105
|
+
* If the key in the instructions hash refers to a child Netzke component, netzkeBulkExecute will be called on that component with the value passed as the argument.
|
92
106
|
|
93
|
-
|
94
|
-
|
95
|
-
|
107
|
+
* @example
|
108
|
+
*
|
109
|
+
* // executes as this.feedback("Your order is accepted");
|
110
|
+
* {feedback: "You order is accepted"}
|
96
111
|
|
97
|
-
//
|
98
|
-
[{setTitle:'Suprise!'}, {setDisabled:true}]
|
112
|
+
* // executes as: this.setTitle('Suprise!'); this.setDisabled(true);
|
113
|
+
* [{setTitle:'Suprise!'}, {setDisabled:true}]
|
99
114
|
|
100
|
-
//
|
101
|
-
{users: [{setTitle:'Suprise!'}, {setDisabled:true}] }
|
102
|
-
@private
|
115
|
+
* // executes as: this.netzkeGetComponent('users').netzkeBulkExecute([{setTitle:'Suprise!'}, {setDisabled:true}]);
|
116
|
+
* {users: [{setTitle:'Suprise!'}, {setDisabled:true}] }
|
103
117
|
*/
|
104
118
|
netzkeBulkExecute : function(instructions){
|
105
119
|
if (Ext.isArray(instructions)) {
|
@@ -118,7 +132,7 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
118
132
|
if (childComponent) {
|
119
133
|
childComponent.netzkeBulkExecute(args);
|
120
134
|
} else if (Ext.isArray(args)) { // only consider those calls that have arguments wrapped in an array; the only (probably) case when they are not, is with 'success' property set to true in a non-ajax form submit - silently ignore that
|
121
|
-
throw "Netzke: Unknown method or child component '" + instr + "' in component '" + this.
|
135
|
+
throw "Netzke: Unknown method or child component '" + instr + "' in component '" + this.path + "'"
|
122
136
|
}
|
123
137
|
}
|
124
138
|
}
|
@@ -126,6 +140,9 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
126
140
|
},
|
127
141
|
|
128
142
|
/**
|
143
|
+
* Called by the server side to set the return value of an endpoint call; to be reworked.
|
144
|
+
* @method netzkeSetResult
|
145
|
+
* @param result {Any}
|
129
146
|
* @private
|
130
147
|
*/
|
131
148
|
netzkeSetResult: function(result) {
|
@@ -133,31 +150,37 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
133
150
|
},
|
134
151
|
|
135
152
|
/**
|
136
|
-
*
|
153
|
+
* Called by the server when the component to which an endpoint call was directed to, is not in the session anymore.
|
154
|
+
* @method netzkeSessionExpired
|
137
155
|
* @private
|
138
156
|
*/
|
139
|
-
|
157
|
+
netzkeOnSessionExpired: function() {
|
140
158
|
this.netzkeSessionIsExpired = true;
|
141
|
-
this.
|
159
|
+
this.netzkeOnSessionExpired();
|
142
160
|
},
|
143
161
|
|
144
162
|
/**
|
145
163
|
* Override this method to handle session expiration. E.g. you may want to inform the user that they will be redirected to the login page.
|
164
|
+
* @method onSessionExpired
|
146
165
|
* @private
|
147
166
|
*/
|
148
|
-
|
149
|
-
Netzke.warning("Component not in session. Override `
|
167
|
+
netzkeOnSessionExpired: function() {
|
168
|
+
Netzke.warning("Component not in session. Override `netzkeOnSessionExpired` to handle this.");
|
150
169
|
},
|
151
170
|
|
152
171
|
/**
|
153
|
-
* Returns a URL for old-fashion requests (used at multi-part form non-AJAX submissions)
|
154
|
-
* @
|
172
|
+
* Returns a URL for old-fashion requests (used at multi-part form non-AJAX submissions).
|
173
|
+
* @method netzkeEndpointUrl
|
174
|
+
* @param endpoint {String}
|
155
175
|
*/
|
156
176
|
netzkeEndpointUrl: function(endpoint){
|
157
177
|
return Netzke.ControllerUrl + "dispatcher?address=" + this.id + "__" + endpoint;
|
158
178
|
},
|
159
179
|
|
160
180
|
/**
|
181
|
+
* Processes items.
|
182
|
+
* @method netzkeNormalizeConfigArray
|
183
|
+
* @param items {Array} Items
|
161
184
|
* @private
|
162
185
|
*/
|
163
186
|
netzkeNormalizeConfigArray: function(items){
|
@@ -166,19 +189,9 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
166
189
|
Ext.each(items, function(item, i){
|
167
190
|
cfg = item;
|
168
191
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
if ((this.netzkeComponents || {})[ref]) cfg = {netzkeComponent: ref};
|
173
|
-
else if ((this.actions || {})[ref]) cfg = {netzkeAction: ref};
|
174
|
-
}
|
175
|
-
|
176
|
-
if (cfg.netzkeAction) {
|
177
|
-
// replace with action instance
|
178
|
-
actName = cfg.netzkeAction.camelize(true);
|
179
|
-
if (!this.actions[actName]) throw "Netzke: unknown action " + cfg.netzkeAction;
|
180
|
-
items[i] = this.actions[actName];
|
181
|
-
delete(item);
|
192
|
+
if (cfg.action) {
|
193
|
+
if (!this.actions[cfg.action]) throw "Netzke: unknown action " + cfg.action;
|
194
|
+
items[i] = this.actions[cfg.action];
|
182
195
|
|
183
196
|
} else if (cfg.netzkeComponent) {
|
184
197
|
// replace with component config
|
@@ -187,7 +200,6 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
187
200
|
if (!cmpCfg) throw "Netzke: unknown component " + cmpName;
|
188
201
|
cmpCfg.netzkeParent = this;
|
189
202
|
items[i] = Ext.apply(cmpCfg, cfg);
|
190
|
-
delete(item);
|
191
203
|
|
192
204
|
} else if (Ext.isString(cfg) && Ext.isFunction(this[cfg.camelize(true)+"Config"])) { // replace with config referred to on the Ruby side as a symbol
|
193
205
|
// pre-built config
|
@@ -202,5 +214,479 @@ Ext.define("Netzke.classes.Core.Mixin", {
|
|
202
214
|
}
|
203
215
|
}
|
204
216
|
}, this);
|
217
|
+
},
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Runs through initial config options and does the following:
|
221
|
+
*
|
222
|
+
* * detects component placeholders and replaces them with full component config found in `netzkeComponents`
|
223
|
+
* * detects action placeholders and replaces them with instances of Ext actions found in `this.actions`
|
224
|
+
*
|
225
|
+
* @method netzkeNormalizeConfig
|
226
|
+
* @param config {Object}
|
227
|
+
*/
|
228
|
+
netzkeNormalizeConfig: function(config) {
|
229
|
+
for (key in config) {
|
230
|
+
if (Ext.isArray(config[key])) this.netzkeNormalizeConfigArray(config[key]);
|
231
|
+
}
|
232
|
+
},
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Dynamically creates methods for endpoints, so that we could later call them like: this.myEndpointMethod()
|
236
|
+
* @method netzkeProcessEndpoints
|
237
|
+
* @param config {Object}
|
238
|
+
*/
|
239
|
+
netzkeProcessEndpoints: function(config){
|
240
|
+
var endpoints = config.endpoints || [], that = this;
|
241
|
+
|
242
|
+
Ext.each(endpoints, function(methodName){
|
243
|
+
Netzke.directProvider.addRemotingMethodToComponent(config, methodName);
|
244
|
+
|
245
|
+
// define endpoint function
|
246
|
+
this.server[methodName] = function(){
|
247
|
+
var args = Array.prototype.slice.call(arguments), callback, serverConfigs, scope = that;
|
248
|
+
|
249
|
+
if (Ext.isFunction(args[args.length - 2])) {
|
250
|
+
scope = args.pop();
|
251
|
+
callback = args.pop();
|
252
|
+
}
|
253
|
+
|
254
|
+
if (Ext.isFunction(args[args.length - 1])) {
|
255
|
+
callback = args.pop();
|
256
|
+
}
|
257
|
+
|
258
|
+
var cfgs = that.netzkeBuildParentConfigs();
|
259
|
+
var remotingArgs = {args: args, configs: cfgs};
|
260
|
+
|
261
|
+
// call Direct function
|
262
|
+
that.netzkeGetDirectFunction(methodName).call(scope, remotingArgs, function(response, event) {
|
263
|
+
that.netzkeProcessDirectResponse(response, event, callback, scope);
|
264
|
+
}, that);
|
265
|
+
}
|
266
|
+
}, this);
|
267
|
+
},
|
268
|
+
|
269
|
+
/**
|
270
|
+
* TODO
|
271
|
+
* @method netzkeProcessDirectResponse
|
272
|
+
* @param response {Object}
|
273
|
+
* @param event {Object}
|
274
|
+
* @param callback {Function}
|
275
|
+
* @param scope {Object}
|
276
|
+
*/
|
277
|
+
netzkeProcessDirectResponse: function(response, event, callback, scope){
|
278
|
+
var callbackParams,
|
279
|
+
result; // endpoint response
|
280
|
+
|
281
|
+
// no server exception?
|
282
|
+
if (Ext.getClass(event) == Ext.direct.RemotingEvent) {
|
283
|
+
|
284
|
+
// process response and get endpoint return value
|
285
|
+
this.netzkeBulkExecute(response);
|
286
|
+
result = this.latestResult;
|
287
|
+
|
288
|
+
// endpoint returns an error?
|
289
|
+
if (result && result.error) {
|
290
|
+
this.netzkeHandleEndpointError(callback, result);
|
291
|
+
// no error
|
292
|
+
} else {
|
293
|
+
if (callback) callback.apply(scope, [result, true]) != false
|
294
|
+
}
|
295
|
+
|
296
|
+
// got Direct exception?
|
297
|
+
} else {
|
298
|
+
this.netzkeHandleDirectError(callback, event);
|
299
|
+
}
|
300
|
+
},
|
301
|
+
|
302
|
+
/**
|
303
|
+
* TODO
|
304
|
+
* @method netzkeHandleEndpointError
|
305
|
+
*/
|
306
|
+
netzkeHandleEndpointError: function(callback, result){
|
307
|
+
var shouldFireGlobalEvent = true;
|
308
|
+
|
309
|
+
if (callback) {
|
310
|
+
shouldFireGlobalEvent = callback.apply(this, [result.error, false]) != false;
|
311
|
+
}
|
312
|
+
|
313
|
+
if (shouldFireGlobalEvent) {
|
314
|
+
Netzke.GlobalEvents.fireEvent('endpointexception', result.error);
|
315
|
+
}
|
316
|
+
},
|
317
|
+
|
318
|
+
/**
|
319
|
+
* TODO
|
320
|
+
* @method netzkeHandleDirectError
|
321
|
+
* @param callback {Function}
|
322
|
+
* @param event {Object}
|
323
|
+
*/
|
324
|
+
netzkeHandleDirectError: function(callback, event){
|
325
|
+
var shouldFireGlobalEvent = true;
|
326
|
+
|
327
|
+
callbackParams = event;
|
328
|
+
callbackParams.type = 'DIRECT_EXCEPTION';
|
329
|
+
|
330
|
+
// First invoke the callback, and if that allows, call generic exception handler
|
331
|
+
if (callback) {
|
332
|
+
shouldFireGlobalEvent = callback.apply(this, [callbackParams, false]) != false;
|
333
|
+
}
|
334
|
+
if (shouldFireGlobalEvent) {
|
335
|
+
Netzke.GlobalEvents.fireEvent('endpointexception', callbackParams);
|
336
|
+
}
|
337
|
+
},
|
338
|
+
|
339
|
+
/**
|
340
|
+
* Returns direct function by endpoint name and optional component's config (if not provided, component's instance
|
341
|
+
* will be used instead)
|
342
|
+
* @method netzkeGetDirectFunction
|
343
|
+
* @param methodName {String}
|
344
|
+
* @param {Object} [config]
|
345
|
+
*/
|
346
|
+
netzkeGetDirectFunction: function(methodName, config) {
|
347
|
+
config = config || this;
|
348
|
+
return Netzke.remotingMethods[config.id][methodName];
|
349
|
+
},
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Reversed array of server configs for each parent component up the tree
|
353
|
+
* @method netzkeBuildParentConfigs
|
354
|
+
*/
|
355
|
+
netzkeBuildParentConfigs: function() {
|
356
|
+
var res = [],
|
357
|
+
parent = this;
|
358
|
+
while (parent) {
|
359
|
+
var cfg = Ext.clone(parent.serverConfig);
|
360
|
+
res.unshift(cfg);
|
361
|
+
parent = parent.netzkeGetParentComponent();
|
362
|
+
}
|
363
|
+
return res;
|
364
|
+
},
|
365
|
+
|
366
|
+
/**
|
367
|
+
* Replaces actions configs with Ext.Action instances, assigning default handler to them
|
368
|
+
* @method netzkeNormalizeActions
|
369
|
+
* @param config {Object}
|
370
|
+
*/
|
371
|
+
netzkeNormalizeActions : function(config){
|
372
|
+
var normActions = {};
|
373
|
+
for (var name in config.actions) {
|
374
|
+
// Configure the action
|
375
|
+
var actionConfig = Ext.apply({}, config.actions[name]); // do not modify original this.actions
|
376
|
+
actionConfig.customHandler = actionConfig.handler;
|
377
|
+
actionConfig.handler = Ext.Function.bind(this.netzkeActionHandler, this); // handler common for all actions
|
378
|
+
actionConfig.name = name;
|
379
|
+
|
380
|
+
// instantiate Ext.Action
|
381
|
+
normActions[name] = new Ext.Action(actionConfig);
|
382
|
+
}
|
383
|
+
this.actions = normActions;
|
384
|
+
delete(config.actions);
|
385
|
+
},
|
386
|
+
|
387
|
+
/**
|
388
|
+
* Dynamically loads child Netzke component
|
389
|
+
* @method netzkeLoadComponent
|
390
|
+
* @param {String} name Component name as declared in the Ruby class with `component` DSL
|
391
|
+
* @param {Object} [options] May contain the following optional keys:
|
392
|
+
* * **container** {Ext.container.Container|Integer}
|
393
|
+
*
|
394
|
+
* The instance (or id) of a container with the "fit" layout where the loaded component will be added to; the previously existing component will be destroyed
|
395
|
+
*
|
396
|
+
* * **append** {Boolean}
|
397
|
+
*
|
398
|
+
* If set to `true`, do not clear the container before adding the loaded component
|
399
|
+
*
|
400
|
+
* * **configOnly** {Boolean}
|
401
|
+
*
|
402
|
+
* If set to `true`, do not instantiate/insert the component, instead pass its config to the callback function
|
403
|
+
*
|
404
|
+
* * **serverConfig** {Object}
|
405
|
+
*
|
406
|
+
* Config accessible inside the `component` DSL block as `client_config`; this allows reconfiguring child components by the client-side code
|
407
|
+
*
|
408
|
+
* * **callback** {Function}
|
409
|
+
*
|
410
|
+
* Function that gets called after the component is loaded; it receives the component's instance (or component config if `configOnly` is set) as parameter; if the function returns `false`, the loaded component will not be automatically inserted or (in case of window) shown.
|
411
|
+
*
|
412
|
+
* * **scope** {Object}
|
413
|
+
*
|
414
|
+
* Scope for the callback; defaults to the instance of the component.
|
415
|
+
*
|
416
|
+
* @example
|
417
|
+
*
|
418
|
+
* Loads 'info' and adds it to `this` container, removing anything from it first:
|
419
|
+
*
|
420
|
+
* this.netzkeLoadComponent('info');
|
421
|
+
*
|
422
|
+
* Loads 'info' and adds it to `win` container, envoking a callback in `this` scope, passing it an instance of 'info':
|
423
|
+
*
|
424
|
+
* this.netzkeLoadComponent('info', { container: win, callback: function(instance){} });
|
425
|
+
*
|
426
|
+
* Loads configuration for the 'info' component, envoking a callback in `this` scope, passing it the loaded config for 'info'.
|
427
|
+
*
|
428
|
+
* this.netzkeLoadComponent('info', { configOnly: true, callback: function(config){} });
|
429
|
+
*
|
430
|
+
* Loads two 'info' instances in different containers and with different configurations:
|
431
|
+
*
|
432
|
+
* this.netzkeLoadComponent('info', {
|
433
|
+
* container: 'tab1',
|
434
|
+
* serverConfig: { user: 'john' } // on the server: client_config[:user] == 'john'
|
435
|
+
* });
|
436
|
+
*
|
437
|
+
* this.netzkeLoadComponent('info', {
|
438
|
+
* container: 'tab2',
|
439
|
+
* serverConfig: { user: 'bill' } // on the server: client_config[:user] == 'bill'
|
440
|
+
* });
|
441
|
+
*/
|
442
|
+
netzkeLoadComponent: function(name, options){
|
443
|
+
var container, serverParams, containerEl;
|
444
|
+
options = options || {};
|
445
|
+
|
446
|
+
container = this.netzkeChooseContainer(options);
|
447
|
+
serverParams = this.netzkeBuildServerLoadingParams(name, options);
|
448
|
+
|
449
|
+
this.netzkeShowLoadingMask(container);
|
450
|
+
|
451
|
+
// Call the endpoint
|
452
|
+
this.server.deliverComponent(serverParams, function(result, success) {
|
453
|
+
this.netzkeHideLoadingMask(container);
|
454
|
+
|
455
|
+
if (success) {
|
456
|
+
this.netzkeHandleLoadingResponse(container, result, options);
|
457
|
+
} else {
|
458
|
+
this.netzkeHandleLoadingError(result);
|
459
|
+
}
|
460
|
+
});
|
461
|
+
},
|
462
|
+
|
463
|
+
/**
|
464
|
+
* Handles loading error
|
465
|
+
* @method netzkeHandleLoadingError
|
466
|
+
*/
|
467
|
+
netzkeHandleLoadingError: function(error){
|
468
|
+
this.netzkeNotify(error);
|
469
|
+
},
|
470
|
+
|
471
|
+
/**
|
472
|
+
* TODO
|
473
|
+
* @method netzkeBuildServerLoadingParams
|
474
|
+
*/
|
475
|
+
netzkeBuildServerLoadingParams: function(name, params) {
|
476
|
+
return Ext.apply(params.serverParams || {}, {
|
477
|
+
name: name,
|
478
|
+
client_config: params.serverConfig,
|
479
|
+
item_id: params.itemId || name, // TODO: make optional
|
480
|
+
cache: Netzke.cache.join() // coma-separated list of xtypes of already loaded classes
|
481
|
+
});
|
482
|
+
},
|
483
|
+
|
484
|
+
/**
|
485
|
+
* Decides, based on params passed to `netzkeLoadComponent`, what container the component should be loaded into.
|
486
|
+
* @method netzkeChooseContainer
|
487
|
+
* @param params Object
|
488
|
+
*/
|
489
|
+
netzkeChooseContainer: function(params) {
|
490
|
+
if (!params.container) return this;
|
491
|
+
return Ext.isString(params.container) ? Ext.getCmp(params.container) : params.container;
|
492
|
+
},
|
493
|
+
|
494
|
+
/**
|
495
|
+
* Handles regular server response (may include error)
|
496
|
+
* @method netzkeHandleLoadingResponse
|
497
|
+
*/
|
498
|
+
netzkeHandleLoadingResponse: function(container, result, params){
|
499
|
+
if (result.error) {
|
500
|
+
this.netzkeNotify(result.error);
|
501
|
+
} else {
|
502
|
+
this.netzkeProcessDeliveredComponent(container, result, params);
|
503
|
+
}
|
504
|
+
},
|
505
|
+
|
506
|
+
/**
|
507
|
+
* Processes delivered component
|
508
|
+
* @method netzkeProcessDeliveredComponent
|
509
|
+
*/
|
510
|
+
netzkeProcessDeliveredComponent: function(container, result, params){
|
511
|
+
var config = result.config, instance, doNotInsert, currentInstance;
|
512
|
+
config.netzkeParent = this;
|
513
|
+
|
514
|
+
this.netzkeEvalJs(result.js);
|
515
|
+
this.netzkeEvalCss(result.css);
|
516
|
+
|
517
|
+
if (params.configOnly) {
|
518
|
+
if (params.callback) params.callback.apply((params.scope || this), [config, params]);
|
519
|
+
} else {
|
520
|
+
// we must destroy eventual existing component with the same ID
|
521
|
+
currentInstance = Ext.getCmp(config.id);
|
522
|
+
if (currentInstance) currentInstance.destroy();
|
523
|
+
|
524
|
+
instance = Ext.create(config);
|
525
|
+
|
526
|
+
if (params.callback) {
|
527
|
+
doNotInsert = params.callback.apply((params.scope || this), [instance, params]) == false;
|
528
|
+
}
|
529
|
+
|
530
|
+
if (doNotInsert) return;
|
531
|
+
|
532
|
+
if (instance.isFloating()) { // windows are not containable
|
533
|
+
instance.show();
|
534
|
+
} else {
|
535
|
+
if (params.replace) {
|
536
|
+
this.netzkeReplaceChild(params.replace, instance)
|
537
|
+
} else {
|
538
|
+
if (!params.append) container.removeAll();
|
539
|
+
container.add(instance);
|
540
|
+
}
|
541
|
+
}
|
542
|
+
}
|
543
|
+
},
|
544
|
+
|
545
|
+
/**
|
546
|
+
* Masks container in which a child component is being loaded
|
547
|
+
* @method netzkeShowLoadingMask
|
548
|
+
*/
|
549
|
+
netzkeShowLoadingMask: function(container){
|
550
|
+
if (container.rendered) container.mask();
|
551
|
+
},
|
552
|
+
|
553
|
+
/**
|
554
|
+
* Unmasks loading container
|
555
|
+
* @method netzkeHideLoadingMask
|
556
|
+
*/
|
557
|
+
netzkeHideLoadingMask: function(container){
|
558
|
+
if (container.rendered) container.unmask();
|
559
|
+
},
|
560
|
+
|
561
|
+
/**
|
562
|
+
* Returns parent Netzke component
|
563
|
+
* @method netzkeGetParentComponent
|
564
|
+
*/
|
565
|
+
netzkeGetParentComponent: function(){
|
566
|
+
return this.netzkeParent;
|
567
|
+
},
|
568
|
+
|
569
|
+
/**
|
570
|
+
* Reloads itself by instructing the parent to call `netzkeLoadComponent`.
|
571
|
+
* Note: in order for this to work, the component must be nested in a container with the 'fit' layout.
|
572
|
+
* @method netzkeReload
|
573
|
+
*/
|
574
|
+
netzkeReload: function(){
|
575
|
+
var parent = this.netzkeGetParentComponent();
|
576
|
+
|
577
|
+
if (parent) {
|
578
|
+
parent.netzkeReloadChild(this);
|
579
|
+
} else {
|
580
|
+
window.location.reload();
|
581
|
+
}
|
582
|
+
},
|
583
|
+
|
584
|
+
/**
|
585
|
+
* Given child component and new serverConfig, reloads the component
|
586
|
+
* @method netzkeReloadChild
|
587
|
+
* @param child Netzke.Base
|
588
|
+
* @param serverConfig Object
|
589
|
+
*/
|
590
|
+
netzkeReloadChild: function(child, serverConfig){
|
591
|
+
this.netzkeLoadComponent(child.name, {
|
592
|
+
configOnly: true,
|
593
|
+
serverConfig: serverConfig,
|
594
|
+
callback: function(cfg) {
|
595
|
+
this.netzkeReplaceChild(child, cfg);
|
596
|
+
}
|
597
|
+
});
|
598
|
+
},
|
599
|
+
|
600
|
+
/**
|
601
|
+
* Replaces given (Netzke or Ext JS) component and new config, replaces former with latter, by instructing the parent
|
602
|
+
* component to re-insert the component at the same index. Override if you need something more fancy (e.g. active tab
|
603
|
+
* when it gets re-inserted)
|
604
|
+
* @method netzkeReplaceChild
|
605
|
+
* @param child {Netzke.Base}
|
606
|
+
* @param config {Obect}
|
607
|
+
*/
|
608
|
+
netzkeReplaceChild: function(child, config){
|
609
|
+
var parent = child.up();
|
610
|
+
if (!parent) return;
|
611
|
+
var index = parent.items.indexOf(child);
|
612
|
+
Ext.suspendLayouts();
|
613
|
+
parent.remove(child);
|
614
|
+
var res = parent.insert(index, config);
|
615
|
+
Ext.resumeLayouts(true);
|
616
|
+
return res;
|
617
|
+
},
|
618
|
+
|
619
|
+
/**
|
620
|
+
* Instantiates and returns a Netzke component by its name.
|
621
|
+
* @method netzkeInstantiateComponent
|
622
|
+
* @param name {String} Child component's name/itemId
|
623
|
+
*/
|
624
|
+
netzkeInstantiateComponent: function(name) {
|
625
|
+
name = name.camelize(true);
|
626
|
+
var cfg = this.netzkeComponents[name];
|
627
|
+
return Ext.createByAlias(this.netzkeComponents[name].alias, cfg)
|
628
|
+
},
|
629
|
+
|
630
|
+
/**
|
631
|
+
* Returns *instantiated* child component by its relative path
|
632
|
+
* @method netzkeGetComponent
|
633
|
+
* @param path {String} Component path, which may contain the 'parent' for walking up the hierarchy, e.g.
|
634
|
+
* `parent__sibling`. If this is empty, the method will return `this`.
|
635
|
+
*/
|
636
|
+
netzkeGetComponent: function(path){
|
637
|
+
if (path === "") {return this};
|
638
|
+
path = path.underscore();
|
639
|
+
var split = path.split("__"), res;
|
640
|
+
if (split[0] === 'parent') {
|
641
|
+
split.shift();
|
642
|
+
var childInParentScope = split.join("__");
|
643
|
+
res = this.netzkeGetParentComponent().netzkeGetComponent(childInParentScope);
|
644
|
+
} else {
|
645
|
+
res = Ext.getCmp(this.id+"__"+path);
|
646
|
+
}
|
647
|
+
return res;
|
648
|
+
},
|
649
|
+
|
650
|
+
/**
|
651
|
+
* Triggers a notification unless `quiet` config option is `true`.
|
652
|
+
* @method netzkeNotify
|
653
|
+
* @param {String} msg Notification body
|
654
|
+
* @param {Object} options Notification options (such as `title`, `delay`)
|
655
|
+
*/
|
656
|
+
netzkeNotify: function(msg, options){
|
657
|
+
if (this.quiet !== true) this.netzkeNotifier.msg(msg, options);
|
658
|
+
},
|
659
|
+
|
660
|
+
/**
|
661
|
+
* Common handler for all netzke's actions.
|
662
|
+
* @method netzkeActionHandler
|
663
|
+
* @param {Ext.Component} comp Component that triggered the action (e.g. button or menu item)
|
664
|
+
*/
|
665
|
+
netzkeActionHandler: function(comp){
|
666
|
+
var actionName = comp.name;
|
667
|
+
// If firing corresponding event doesn't return false, call the handler
|
668
|
+
if (this.fireEvent(actionName+'click', comp)) {
|
669
|
+
var action = this.actions[actionName];
|
670
|
+
var customHandler = action.initialConfig.customHandler;
|
671
|
+
var methodName = (customHandler && customHandler.camelize(true)) || "netzkeOn" + actionName.camelize();
|
672
|
+
if (!this[methodName]) {throw "Netzke: handler '" + methodName + "' is undefined in '" + this.id + "'";}
|
673
|
+
|
674
|
+
// call the handler passing it the triggering component
|
675
|
+
this[methodName](comp);
|
676
|
+
}
|
677
|
+
},
|
678
|
+
|
679
|
+
/**
|
680
|
+
* TODO
|
681
|
+
* @method netzkeProcessPlugins
|
682
|
+
*/
|
683
|
+
netzkeProcessPlugins: function(config) {
|
684
|
+
if (config.netzkePlugins) {
|
685
|
+
if (!this.plugins) this.plugins = [];
|
686
|
+
Ext.each(config.netzkePlugins, function(p){
|
687
|
+
this.plugins.push(this.netzkeInstantiateComponent(p));
|
688
|
+
}, this);
|
689
|
+
delete config.netzkePlugins;
|
690
|
+
}
|
205
691
|
}
|
206
692
|
});
|