netzke-core 0.6.7 → 0.7.0

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.
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