netzke-core 0.6.7 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG.rdoc +36 -1
  2. data/{README.markdown → README.md} +17 -15
  3. data/Rakefile +1 -1
  4. data/TODO +4 -4
  5. data/app/controllers/netzke_controller.rb +8 -3
  6. data/javascripts/base.js +71 -68
  7. data/javascripts/ext.js +182 -111
  8. data/lib/netzke/actions.rb +2 -1
  9. data/lib/netzke/base.rb +5 -1
  10. data/lib/netzke/composition.rb +2 -2
  11. data/lib/netzke/configuration.rb +1 -1
  12. data/lib/netzke/core/dynamic_assets.rb +7 -7
  13. data/lib/netzke/core/session.rb +4 -0
  14. data/lib/netzke/core/version.rb +2 -2
  15. data/lib/netzke/core.rb +23 -30
  16. data/lib/netzke/core_ext/symbol.rb +1 -1
  17. data/lib/netzke/embedding.rb +1 -1
  18. data/lib/netzke/ext_component.rb +2 -2
  19. data/lib/netzke/javascript.rb +70 -39
  20. data/lib/netzke/plugin.rb +15 -0
  21. data/lib/netzke/plugins.rb +29 -0
  22. data/lib/netzke/railz/action_view_ext/ext.rb +13 -16
  23. data/lib/netzke/railz/action_view_ext/touch.rb +3 -3
  24. data/lib/netzke/railz/action_view_ext.rb +0 -3
  25. data/lib/netzke/railz/engine.rb +34 -29
  26. data/lib/netzke/services.rb +1 -1
  27. data/lib/netzke/state.rb +2 -2
  28. data/lib/netzke-core.rb +1 -0
  29. data/netzke-core.gemspec +108 -9
  30. data/stylesheets/core.css +25 -5
  31. data/test/rails_app/Gemfile +1 -1
  32. data/test/rails_app/Gemfile.lock +37 -36
  33. data/test/rails_app/app/components/component_loader.rb +36 -24
  34. data/test/rails_app/app/components/component_with_js_mixin/javascripts/component_with_js_mixin.js +5 -0
  35. data/test/rails_app/app/components/component_with_js_mixin.rb +3 -1
  36. data/test/rails_app/app/components/component_with_nested_through.rb +28 -0
  37. data/test/rails_app/app/components/component_with_session_persistence.rb +7 -5
  38. data/test/rails_app/app/components/dynamic_tab_panel/javascripts/dynamic_tab_panel.js +9 -0
  39. data/test/rails_app/app/components/dynamic_tab_panel.rb +19 -0
  40. data/test/rails_app/app/components/extended_server_caller.rb +6 -5
  41. data/test/rails_app/app/components/loader_of_component_with_custom_css.rb +7 -8
  42. data/test/rails_app/app/components/localized_panel.rb +10 -1
  43. data/test/rails_app/app/components/nested_component.rb +18 -0
  44. data/test/rails_app/app/components/panel_with_plugin.rb +4 -0
  45. data/test/rails_app/app/components/panel_with_tools.rb +19 -0
  46. data/test/rails_app/app/components/plugin_with_components.rb +14 -0
  47. data/test/rails_app/app/components/server_caller.rb +1 -1
  48. data/test/rails_app/app/components/server_counter.rb +1 -1
  49. data/test/rails_app/app/components/simple_component.rb +2 -0
  50. data/test/rails_app/app/components/simple_tab_panel.rb +21 -21
  51. data/test/rails_app/app/components/simple_window.rb +1 -1
  52. data/test/rails_app/app/components/some_composite.rb +3 -2
  53. data/test/rails_app/app/components/some_plugin.rb +39 -0
  54. data/test/rails_app/app/controllers/application_controller.rb +1 -1
  55. data/test/rails_app/app/controllers/components_controller.rb +1 -1
  56. data/test/rails_app/app/views/layouts/touch.html.erb +1 -1
  57. data/test/rails_app/config/application.rb +0 -2
  58. data/test/rails_app/config/initializers/netzke.rb +2 -1
  59. data/test/rails_app/config/locales/es.yml +1 -0
  60. data/test/rails_app/features/{actions.feature → actions_and_tools.feature} +8 -0
  61. data/test/rails_app/features/client-server.feature +0 -1
  62. data/test/rails_app/features/complex_component.feature +1 -1
  63. data/test/rails_app/features/component_loader.feature +7 -0
  64. data/test/rails_app/features/composition.feature +2 -2
  65. data/test/rails_app/features/custom_css.feature +1 -1
  66. data/test/rails_app/features/i18n.feature +3 -0
  67. data/test/rails_app/features/js_include.feature +2 -0
  68. data/test/rails_app/features/nested_views.feature +5 -4
  69. data/test/rails_app/features/plugin.feature +16 -0
  70. data/test/rails_app/features/step_definitions/generic_steps.rb +21 -2
  71. data/test/rails_app/features/touch.feature +10 -10
  72. data/test/rails_app/spec/component/component_spec.rb +20 -0
  73. metadata +106 -10
  74. data/app/models/netzke_preference.rb +0 -170
data/javascripts/ext.js CHANGED
@@ -1,83 +1,109 @@
1
+ // Enable Ext 4 migration errors traceback display
2
+ if (Ext.Compat) Ext.Compat.showErrors = true;
3
+
1
4
  // Because of Netzke's double-underscore notation, Ext.TabPanel should have a different id-delimiter (yes, this should be in netzke-core)
2
5
  Ext.TabPanel.prototype.idDelimiter = "___";
3
6
 
4
7
  Ext.QuickTips.init();
5
8
 
6
9
  // We don't want no state managment by default, thank you!
7
- Ext.state.Provider.prototype.set = function(){};
10
+ Ext.state.Provider.prototype.set = Ext.emptyFn;
8
11
 
9
- // Check Ext JS version
12
+ // Checking Ext JS version: both major and minor versions must be the same
10
13
  (function(){
11
- var requiredExtVersion = "3.3.1";
12
- var currentExtVersion = Ext.version;
13
- if (requiredExtVersion !== currentExtVersion) {
14
- Netzke.deprecationWarning("Need Ext " + requiredExtVersion + ". You have " + currentExtVersion + ".");
14
+ var requiredVersionMajor = 4,
15
+ requiredVersionMinor = 0,
16
+ extVersion = Ext.getVersion('extjs'),
17
+ currentVersionMajor = extVersion.getMajor(),
18
+ currentVersionMinor = extVersion.getMinor(),
19
+ requiredString = "" + requiredVersionMajor + "." + requiredVersionMinor + ".x",
20
+ currentString = "" + currentVersionMajor + "." + currentVersionMinor + ".x";
21
+
22
+ if (requiredVersionMajor != currentVersionMajor || requiredVersionMinor != currentVersionMinor) {
23
+ Netzke.warning("Ext " + requiredString + " required. You have " + currentString + ".");
15
24
  }
16
25
  })();
17
26
 
18
- Netzke.classes.NetzkeRemotingProvider = Ext.extend(Ext.direct.RemotingProvider, {
27
+ // FeedbackGhost is a little class that displays unified feedback from Netzke components.
28
+ Ext.define('Netzke.FeedbackGhost', {
29
+ showFeedback: function(msg){
30
+ if (!msg) Netzke.exception("Netzke.FeedbackGhost#showFeedback: wrong number of arguments (0 for 1)");
31
+ if (Ext.isObject(msg)) {
32
+ this.msg(msg.level.camelize(), msg.msg);
33
+ } else if (Ext.isArray(msg)) {
34
+ Ext.each(msg, function(m) { this.showFeedback(m); }, this);
35
+ } else {
36
+ this.msg(null, msg); // no header for now
37
+ }
38
+ },
39
+
40
+ msg: function(title, format){
41
+ if(!this.msgCt){
42
+ this.msgCt = Ext.core.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
43
+ }
44
+ var s = Ext.String.format.apply(String, Array.prototype.slice.call(arguments, 1));
45
+ var m = Ext.core.DomHelper.append(this.msgCt, this.createBox(title, s), true);
46
+ m.hide();
47
+ m.slideIn('t').ghost("t", { delay: 1000, remove: true});
48
+ },
49
+
50
+ createBox: function(t, s){
51
+ if (t) {
52
+ return '<div class="msg"><h3>' + t + '</h3><p>' + s + '</p></div>';
53
+ } else {
54
+ return '<div class="msg"><p>' + s + '</p></div>';
55
+ }
56
+ }
57
+ });
58
+
59
+ // Mix it into every Netzke component as feedbackGhost
60
+ Netzke.componentMixin.feedbackGhost = Ext.create("Netzke.FeedbackGhost");
61
+
62
+ Ext.define('Netzke.classes.NetzkeRemotingProvider', {
63
+ extend: 'Ext.direct.RemotingProvider',
64
+
19
65
  getCallData: function(t){
20
66
  return {
21
67
  act: t.action, // rails doesn't really support having a parameter named "action"
22
68
  method: t.method,
23
69
  data: t.data,
24
70
  type: 'rpc',
25
- tid: t.tid
71
+ tid: t.id
26
72
  }
27
73
  },
28
74
 
29
75
  addAction: function(action, methods) {
30
76
  var cls = this.namespace[action] || (this.namespace[action] = {});
31
77
  for(var i = 0, len = methods.length; i < len; i++){
32
- var m = methods[i];
33
- cls[m.name] = this.createMethod(action, m);
34
- }
78
+ method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
79
+ cls[method.name] = this.createHandler(action, method);
80
+ }
35
81
  },
36
82
 
37
- // process response regardess of status
38
- // i.e. in a batch request,
39
- // - we request tids 1,2,3.
40
- // - server is able to process 1 but not 2
41
- // - server will stop and *not* process 3, because it could be dependant on 2 (this best possible approach to this
42
- // situation, as we don't have transactions)
43
- // - server will respond with status 500, indicating a fault
44
- // - in the response, server will respond with the result from tid 1
45
- // - client marks tid 1 as success (deletes the transaction from pending), and will retry 2 and 3 - this is the
46
- // change in Ext.direct.RemotingProvider's default behaviour
47
- onData: function(opt, success, xhr){
48
- var events=this.getEvents(xhr);
49
-
50
- for(var i = 0, len = events.length; i < len; i++){
51
- var e = events[i],
52
- t = this.getTransaction(e);
53
- this.fireEvent('data', this, e);
54
- if(t){
55
- this.doCallback(t, e, true);
56
- Ext.Direct.removeTransaction(t);
57
- }
83
+ // HACK: Ext JS 4.0.0 retry mechanism is broken
84
+ getTransaction: function(opt) {
85
+ if (opt.$className == "Ext.direct.Transaction") {
86
+ return opt;
87
+ } else {
88
+ return this.callParent([opt]);
58
89
  }
59
-
60
- Netzke.classes.NetzkeRemotingProvider.superclass.onData.call(this, opt, success, xhr);
61
90
  }
62
-
63
91
  });
64
92
 
65
93
  Netzke.directProvider = new Netzke.classes.NetzkeRemotingProvider({
66
- "type": "remoting", // create a Ext.direct.RemotingProvider
67
- "url": Netzke.RelativeUrlRoot + "/netzke/direct/", // url to connect to the Ext.Direct server-side router.
68
- "namespace": "Netzke.providers", // namespace to create the Remoting Provider in
69
- "actions": {},
70
- "maxRetries": Netzke.core.directMaxRetries,
71
- "enableBuffer": true, // buffer/batch requests within 10ms timeframe
72
- "timeout": 30000 // 30s timeout per request
94
+ type: "remoting", // create a Ext.direct.RemotingProvider
95
+ url: Netzke.RelativeUrlRoot + "/netzke/direct/", // url to connect to the Ext.Direct server-side router.
96
+ namespace: "Netzke.providers", // namespace to create the Remoting Provider in
97
+ actions: {},
98
+ maxRetries: Netzke.core.directMaxRetries,
99
+ enableBuffer: true, // buffer/batch requests within 10ms timeframe
100
+ timeout: 30000 // 30s timeout per request
73
101
  });
74
102
 
75
103
  Ext.Direct.addProvider(Netzke.directProvider);
76
104
 
105
+ // Methods/properties that each and every Netzke component will have
77
106
  Ext.apply(Netzke.classes.Core.Mixin, {
78
- height: 400,
79
- border: false,
80
-
81
107
  /*
82
108
  Mask shown during loading of a component. Set to false to not mask. Pass config for Ext.LoadMask for configuring msg/cls, etc.
83
109
  Set msg to null if mask without any msg is desirable.
@@ -90,12 +116,17 @@ Ext.apply(Netzke.classes.Core.Mixin, {
90
116
 
91
117
  this.detectActions(this);
92
118
 
119
+ // Detects component placeholders in the passed object (typically, "items"),
120
+ // and merges them with the corresponding config from this.netzkeComponents.
121
+ // This way it becomes ready to be instantiated properly by Ext.
93
122
  this.detectComponents(this.items);
94
123
 
95
124
  this.normalizeTools();
96
125
 
97
126
  this.processEndpoints();
98
127
 
128
+ this.processPlugins();
129
+
99
130
  // This is where the references to different callback functions will be stored
100
131
  this.callbackHash = {};
101
132
 
@@ -120,20 +151,21 @@ Ext.apply(Netzke.classes.Core.Mixin, {
120
151
  },
121
152
 
122
153
  /*
123
- Dynamically creates methods for endpoints, so that we could later call them like: this.myEndpointMethod() (using Ext.Direct)
154
+ Dynamically creates methods for endpoints, so that we could later call them like: this.myEndpointMethod()
124
155
  */
125
156
  processEndpoints: function(){
126
157
  var endpoints = this.endpoints || [];
127
158
  endpoints.push('deliver_component'); // all Netzke components get this endpoint
128
159
  var directActions = [];
129
- var that=this;
160
+ var that = this;
130
161
 
131
162
  Ext.each(endpoints, function(intp){
132
163
  directActions.push({"name":intp.camelize(true), "len":1});
133
164
  this[intp.camelize(true)] = function(arg, callback, scope) {
134
165
  Netzke.runningRequests++;
135
- scope=scope || that;
136
- Netzke.providers[this.id][intp.camelize(true)].call(typeof scope != 'undefined' ? scope : that, arg, function(result, remotingEvent) {
166
+
167
+ scope = scope || that;
168
+ Netzke.providers[this.id][intp.camelize(true)].call(scope, arg, function(result, remotingEvent) {
137
169
  if(remotingEvent.message) {
138
170
  console.error("RPC event indicates an error: ", remotingEvent);
139
171
  throw new Error(remotingEvent.message);
@@ -157,8 +189,8 @@ Ext.apply(Netzke.classes.Core.Mixin, {
157
189
  // Create an event for each action (so that higher-level components could interfere)
158
190
  this.addEvents(tool.id+'click');
159
191
 
160
- var handler = this.toolActionHandler.createDelegate(this, [tool]);
161
- normTools.push({id : tool, handler : handler, scope : this});
192
+ var handler = Ext.Function.bind(this.toolActionHandler, this, [tool]);
193
+ normTools.push({type : tool, handler : handler, scope : this});
162
194
  }, this);
163
195
  this.tools = normTools;
164
196
  }
@@ -176,7 +208,7 @@ Ext.apply(Netzke.classes.Core.Mixin, {
176
208
  // Configure the action
177
209
  var actionConfig = Ext.apply({}, this.actions[name]); // do not modify original this.actions
178
210
  actionConfig.customHandler = actionConfig.handler;
179
- actionConfig.handler = this.actionHandler.createDelegate(this); // handler common for all actions
211
+ actionConfig.handler = Ext.Function.bind(this.actionHandler, this); // handler common for all actions
180
212
  actionConfig.name = name;
181
213
  normActions[name] = new Ext.Action(actionConfig);
182
214
  }
@@ -195,7 +227,7 @@ Ext.apply(Netzke.classes.Core.Mixin, {
195
227
  o.handler = this[o.handler.camelize(true)].createDelegate(this);
196
228
  }
197
229
  // TODO: this should be configurable!
198
- Ext.each(["bbar", "tbar", "fbar", "menu", "items", "contextMenu", "buttons"], function(key){
230
+ Ext.each(["bbar", "tbar", "fbar", "menu", "items", "contextMenu", "buttons", "dockedItems"], function(key){
199
231
  if (o[key]) {
200
232
  var items = [].concat(o[key]); // we need to do it in order to esure that this instance has a separate bbar/tbar/etc, NOT shared via class' prototype
201
233
  delete(o[key]);
@@ -220,13 +252,14 @@ Ext.apply(Netzke.classes.Core.Mixin, {
220
252
  },
221
253
 
222
254
  /*
223
- Loads a component. Config options:
255
+ Dynamically loads a Netzke component.
256
+ Config options:
224
257
  'name' (required) - the name of the child component to load
225
- 'container' - the id of a panel with the 'fit' layout where the loaded component will be instantiated
226
- 'callback' - function that gets called after the component is loaded. It receives the component's instance as parameter.
227
- 'scope' - scope for the callback.
258
+ 'container' - if specified, the id (or instance) of a panel with the 'fit' layout where the loaded component will be added to; the previously existing component will be destroyed
259
+ 'callback' - function that gets called after the component is loaded; it receives the component's instance as parameter
260
+ 'scope' - scope for the callback
228
261
  */
229
- loadComponent: function(params){
262
+ loadNetzkeComponent: function(params){
230
263
  if (params.id) {
231
264
  params.name = params.id;
232
265
  Netzke.deprecationWarning("Using 'id' in loadComponent is deprecated. Use 'name' instead.");
@@ -272,10 +305,17 @@ Ext.apply(Netzke.classes.Core.Mixin, {
272
305
  this.deliverComponent(serverParams);
273
306
  },
274
307
 
308
+ // DEPRECATED in favor or loadNetzkeComponent
309
+ loadComponent: function(params) {
310
+ Netzke.deprecationWarning("loadComponent is deprecated in favor of loadNetzkeComponent");
311
+ params.container = params.container || this.getId(); // for backward compatibility
312
+ this.loadNetzkeComponent(params);
313
+ },
314
+
275
315
  /*
276
316
  Called by the server after we ask him to load a component
277
317
  */
278
- componentDelivered : function(config){
318
+ componentDelivered: function(config){
279
319
  // retrieve the loading config for this component
280
320
  var storedConfig = this.componentsBeingLoaded[config.name] || {};
281
321
  delete this.componentsBeingLoaded[config.name];
@@ -285,8 +325,21 @@ Ext.apply(Netzke.classes.Core.Mixin, {
285
325
  storedConfig.loadMaskCmp.destroy();
286
326
  }
287
327
 
288
- // instantiate and render it
289
- var componentInstance = this.instantiateAndRenderComponent(config, storedConfig.container);
328
+ var componentInstance = Ext.createByAlias(config.alias, config);
329
+
330
+ if (storedConfig.container) {
331
+ var containerCmp = Ext.isString(storedConfig.container) ? Ext.getCmp(storedConfig.container) : storedConfig.container;
332
+ // containerCmp.insertNetzkeComponent(componentInstance);
333
+ containerCmp.removeAll();
334
+ containerCmp.add(componentInstance);
335
+
336
+ if (containerCmp.isVisible()) {
337
+ containerCmp.doLayout();
338
+ } else {
339
+ // if loaded into a hidden container, we need a little trick
340
+ containerCmp.on('show', function(cmp){ cmp.doLayout(); }, {single: true});
341
+ }
342
+ }
290
343
 
291
344
  if (storedConfig.callback) {
292
345
  storedConfig.callback.call(storedConfig.scope || this, componentInstance);
@@ -295,10 +348,22 @@ Ext.apply(Netzke.classes.Core.Mixin, {
295
348
  this.fireEvent('componentload', componentInstance);
296
349
  },
297
350
 
351
+ componentDeliveryFailed: function(params) {
352
+ var storedConfig = this.componentsBeingLoaded[params.componentName] || {};
353
+ delete this.componentsBeingLoaded[params.componentName];
354
+
355
+ if (storedConfig.loadMaskCmp) {
356
+ storedConfig.loadMaskCmp.hide();
357
+ storedConfig.loadMaskCmp.destroy();
358
+ }
359
+
360
+ this.netzkeFeedback({msg: params.msg, level: "Error"});
361
+ },
362
+
298
363
  /*
299
- Instantiates and renders a component with given config and container
364
+ DEPRECATED. Instantiates and renders a component with given config and container.
300
365
  */
301
- instantiateAndRenderComponent : function(config, containerId){
366
+ instantiateAndRenderComponent: function(config, containerId){
302
367
  var componentInstance;
303
368
  if (containerId) {
304
369
  var container = Ext.getCmp(containerId);
@@ -310,24 +375,9 @@ Ext.apply(Netzke.classes.Core.Mixin, {
310
375
  },
311
376
 
312
377
  /*
313
- Instantiates and inserts a component into a container with layout 'fit'.
314
- Arg: an JS object with the following keys:
315
- - id: id of the receiving container
316
- - config: configuration of the component to be instantiated and inserted into the container
378
+ Returns parent Netzke component
317
379
  */
318
- // renderComponentInContainer : function(params){
319
- // var cont = Ext.getCmp(params.container);
320
- // if (cont) {
321
- // cont.instantiateChild(params.config);
322
- // } else {
323
- // this.instantiateChild(params.config);
324
- // }
325
- // },
326
-
327
- /*
328
- Returns the parent component
329
- */
330
- getParent: function(){
380
+ getParentNetzkeComponent: function(){
331
381
  // simply cutting the last part of the id: some_parent__a_kid__a_great_kid => some_parent__a_kid
332
382
  var idSplit = this.id.split("__");
333
383
  idSplit.pop();
@@ -336,61 +386,65 @@ Ext.apply(Netzke.classes.Core.Mixin, {
336
386
  return parentId === "" ? null : Ext.getCmp(parentId);
337
387
  },
338
388
 
389
+ // DEPRECATED
390
+ getParent: function() {
391
+ Netzke.deprecationWarning("getParent is deprecated in favor of getParentNetzkeComponent");
392
+ return this.getParentNetzkeComponent();
393
+ },
394
+
339
395
  /*
340
- Reloads current component (calls the parent to reload it as its component)
396
+ Reloads current component (calls the parent to reload us as its component)
341
397
  */
342
- reload : function(){
343
- var parent = this.getParent();
398
+ reload: function(){
399
+ var parent = this.getParentNetzkeComponent();
344
400
  if (parent) {
345
- parent.loadComponent({id:this.localId(parent), container:this.ownerCt.id});
401
+ parent.loadNetzkeComponent({id:this.localId(parent), container:this.ownerCt.id});
346
402
  } else {
347
403
  window.location.reload();
348
404
  }
349
405
  },
350
406
 
351
407
  /*
352
- Reconfigures the component
408
+ DEPRECATED: Reconfigures the component
353
409
  */
354
410
  reconfigure: function(config){
355
411
  this.ownerCt.instantiateChild(config)
356
412
  },
357
413
 
358
- // Get the child component
359
- getChildComponent : function(id){
414
+ /*
415
+ Instantiates and returns a Netzke component by its name.
416
+ */
417
+ instantiateChildNetzkeComponent: function(name) {
418
+ name = name.camelize(true);
419
+ return Ext.createByAlias(this.netzkeComponents[name].alias, this.netzkeComponents[name])
420
+ },
421
+
422
+ /*
423
+ Returns *instantiated* child component by its relative id, which may contain the 'parent' part to walk _up_ the hierarchy
424
+ */
425
+ getChildNetzkeComponent: function(id){
360
426
  if (id === "") {return this};
361
427
  id = id.underscore();
362
428
  var split = id.split("__");
363
429
  if (split[0] === 'parent') {
364
430
  split.shift();
365
431
  var childInParentScope = split.join("__");
366
- return this.getParent().getChildComponent(childInParentScope);
432
+ return this.getParentNetzkeComponent().getChildNetzkeComponent(childInParentScope);
367
433
  } else {
368
434
  return Ext.getCmp(this.id+"__"+id);
369
435
  }
370
436
  },
371
437
 
372
- // At this moment component is fully initializied
373
- commonAfterConstructor : function(config){
374
-
375
- // Add the menus
376
- if (this.initialConfig.menu) {this.addMenu(this.initialConfig.menu, this);}
377
-
378
- // generic events
379
- this.addEvents(
380
- 'componentload' // fired when a child is dynamically loaded
381
- );
382
-
383
- // Cleaning up on destroy
384
- this.on('beforedestroy', function(){
385
- this.cleanUpMenu();
386
- }, this);
387
-
388
- this.callbackHash = {};
389
-
390
- if (this.afterConstructor) this.afterConstructor(config);
438
+ // DEPRECATED
439
+ getChildComponent: function(id) {
440
+ Netzke.deprecationWarning("getChildComponent is deprecated in favor of getChildNetzkeComponent");
441
+ return this.getChildNetzkeComponent(id);
391
442
  },
392
443
 
393
- feedback:function(msg){
444
+ /*
445
+ Provides a visual feedback. TODO: refactor
446
+ */
447
+ netzkeFeedback: function(msg){
394
448
  if (this.initialConfig && this.initialConfig.quiet) {
395
449
  return false;
396
450
  }
@@ -413,8 +467,16 @@ Ext.apply(Netzke.classes.Core.Mixin, {
413
467
  }
414
468
  },
415
469
 
416
- // Common handler for all component's actions. <tt>comp</tt> is the Component that triggered the action (e.g. button or menu item)
417
- actionHandler : function(comp){
470
+ // DEPRECATED in favor of netzkeFeedback
471
+ feedback: function(msg) {
472
+ Netzke.deprecationWarning("feedback is deprecated in favor of netzkeFeedback");
473
+ this.netzkeFeedback(msg);
474
+ },
475
+
476
+ /*
477
+ Common handler for all netzke's actions. <tt>comp</tt> is the Component that triggered the action (e.g. button or menu item)
478
+ */
479
+ actionHandler: function(comp){
418
480
  var actionName = comp.name;
419
481
  // If firing corresponding event doesn't return false, call the handler
420
482
  if (this.fireEvent(actionName+'click', comp)) {
@@ -429,7 +491,7 @@ Ext.apply(Netzke.classes.Core.Mixin, {
429
491
  },
430
492
 
431
493
  // Common handler for tools
432
- toolActionHandler : function(tool){
494
+ toolActionHandler: function(tool){
433
495
  // If firing corresponding event doesn't return false, call the handler
434
496
  if (this.fireEvent(tool.id+'click')) {
435
497
  var methodName = "on"+tool.camelize();
@@ -438,5 +500,14 @@ Ext.apply(Netzke.classes.Core.Mixin, {
438
500
  }
439
501
  },
440
502
 
503
+ processPlugins: function() {
504
+ if (this.netzkePlugins) {
505
+ if (!this.plugins) this.plugins = [];
506
+ Ext.each(this.netzkePlugins, function(p){
507
+ this.plugins.push(this.instantiateChildNetzkeComponent(p));
508
+ }, this);
509
+ }
510
+ },
511
+
441
512
  onComponentLoad:Ext.emptyFn // gets overridden
442
513
  });
@@ -103,7 +103,8 @@ module Netzke
103
103
  end
104
104
 
105
105
  def uri_to_icon(icon)
106
- Netzke::Core.with_icons ? Netzke::Core.icons_uri + "/" + icon.to_s + ".png" : nil
106
+ Netzke::Core.with_icons ? [Netzke::Core.controller.config.relative_url_root, Netzke::Core.icons_uri, '/', icon.to_s, ".png"].join : nil
107
107
  end
108
+
108
109
  end
109
110
  end
data/lib/netzke/base.rb CHANGED
@@ -6,6 +6,7 @@ require 'netzke/stylesheets'
6
6
  require 'netzke/inheritance'
7
7
  require 'netzke/services'
8
8
  require 'netzke/composition'
9
+ require 'netzke/plugins'
9
10
  require 'netzke/configuration'
10
11
  require 'netzke/state'
11
12
  require 'netzke/embedding'
@@ -36,6 +37,7 @@ module Netzke
36
37
  include Inheritance
37
38
  include Services
38
39
  include Composition
40
+ include Plugins
39
41
  include Stylesheets
40
42
  include Embedding
41
43
  include Actions
@@ -74,7 +76,9 @@ module Netzke
74
76
 
75
77
  # Instance of component by config
76
78
  def instance_by_config(config)
77
- (config[:klass] || constantize_class_name(config[:class_name])).new(config)
79
+ klass = config[:klass] || constantize_class_name(config[:class_name])
80
+ raise NameError, "Netzke: Unknown component #{config[:class_name]}" if klass.nil?
81
+ klass.new(config)
78
82
  end
79
83
 
80
84
  # The ID used to locate this component's block in locale files
@@ -46,7 +46,7 @@ module Netzke
46
46
  :component_delivered => component.js_config
47
47
  }]
48
48
  else
49
- {:feedback => "Couldn't load component '#{component_name}'"}
49
+ {:component_delivery_failed => {:component_name => component_name, :msg => "Couldn't load component '#{component_name}'"}}
50
50
  end
51
51
  end
52
52
 
@@ -113,7 +113,7 @@ module Netzke
113
113
 
114
114
  # All components for this instance, which includes components defined on class level, and components detected in :items
115
115
  def components
116
- @components ||= self.class.registered_components.inject({}){ |res, name| res.merge(name.to_sym => send(COMPONENT_METHOD_NAME % name)) }
116
+ @components ||= self.class.registered_components.inject({}){ |res, name| res.merge(name.to_sym => send(COMPONENT_METHOD_NAME % name)) }.merge(config[:components] || {})
117
117
  end
118
118
 
119
119
  def eager_loaded_components
@@ -17,7 +17,7 @@ module Netzke
17
17
 
18
18
  # Config options that should not go to the client side
19
19
  def server_side_config_options
20
- [:lazy_loading, :class_name]
20
+ [:lazy_loading, :class_name, :components]
21
21
  end
22
22
 
23
23
  def config(*args, &block)
@@ -30,8 +30,8 @@ module Netzke
30
30
  res
31
31
  end
32
32
 
33
- def ext_js
34
- res = initial_dynamic_javascript << "\n"
33
+ def ext_js(form_authenticity_token)
34
+ res = initial_dynamic_javascript(form_authenticity_token) << "\n"
35
35
 
36
36
  include_base_js(res)
37
37
 
@@ -61,16 +61,16 @@ module Netzke
61
61
 
62
62
  protected
63
63
 
64
- # Generates initial javascript code that is dependent on Rails environement
65
- def initial_dynamic_javascript
64
+ # Generates initial javascript code that is dependent on Rails settings
65
+ def initial_dynamic_javascript(form_authenticity_token)
66
66
  res = []
67
- # res << %(Ext.Ajax.extraParams = {authenticity_token: '#{form_authenticity_token}'}; // Rails' forgery protection)
67
+ res << %(Ext.Ajax.extraParams = {authenticity_token: '#{form_authenticity_token}'}; // Rails' forgery protection)
68
68
  res << %{Ext.ns('Netzke');}
69
69
  res << %{Ext.ns('Netzke.core');}
70
70
  res << %{Netzke.RelativeUrlRoot = '#{ActionController::Base.config.relative_url_root}';}
71
- res << %{Netzke.RelativeExtUrl = '#{ActionController::Base.config.relative_url_root}/extjs';}
71
+ res << %{Netzke.RelativeExtUrl = '#{ActionController::Base.config.relative_url_root}#{Netzke::Core.ext_uri}';}
72
72
 
73
- res << %{Netzke.core.directMaxRetries = '#{Netzke::Core.js_direct_max_retries}';}
73
+ res << %{Netzke.core.directMaxRetries = #{Netzke::Core.js_direct_max_retries};}
74
74
 
75
75
  res.join("\n")
76
76
  end
@@ -11,6 +11,10 @@ module Netzke
11
11
  session[:_netzke_next_request_is_first_after_logout] = true
12
12
  end
13
13
 
14
+ def current_user
15
+ Netzke::Core.controller.respond_to?(Netzke::Core.current_user_method) && Netzke::Core.controller.send(Netzke::Core.current_user_method) || nil
16
+ end
17
+
14
18
  # Register the configuration for the component in the session, and also remember that the code for it has been rendered
15
19
  def reg_component(config)
16
20
  session[:netzke_components] ||= {}
@@ -2,8 +2,8 @@ module Netzke
2
2
  module Core
3
3
  module Version
4
4
  MAJOR = 0
5
- MINOR = 6
6
- PATCH = 7
5
+ MINOR = 7
6
+ PATCH = 0
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
9
9
  end