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.
Files changed (41) hide show
  1. data/CHANGELOG.md +65 -607
  2. data/Gemfile +1 -1
  3. data/LICENSE +2 -6
  4. data/README.md +77 -145
  5. data/javascripts/base.js +582 -96
  6. data/javascripts/core.js +62 -0
  7. data/javascripts/notifications.js +43 -0
  8. data/javascripts/remoting_provider.js +29 -0
  9. data/javascripts/routing.js +63 -0
  10. data/lib/netzke/base.rb +16 -83
  11. data/lib/netzke/core/action_config.rb +1 -5
  12. data/lib/netzke/core/actions.rb +59 -21
  13. data/lib/netzke/core/{client_class.rb → client_class_config.rb} +81 -73
  14. data/lib/netzke/core/client_code.rb +157 -0
  15. data/lib/netzke/core/component_config.rb +2 -2
  16. data/lib/netzke/core/composition.rb +85 -65
  17. data/lib/netzke/core/configuration.rb +26 -14
  18. data/lib/netzke/core/core_i18n.rb +17 -0
  19. data/lib/netzke/core/css_config.rb +6 -6
  20. data/lib/netzke/core/dynamic_assets.rb +17 -24
  21. data/lib/netzke/core/embedding.rb +2 -2
  22. data/lib/netzke/core/endpoint_response.rb +8 -2
  23. data/lib/netzke/core/inheritance.rb +33 -0
  24. data/lib/netzke/core/plugins.rb +1 -4
  25. data/lib/netzke/core/railz/action_view_ext.rb +1 -1
  26. data/lib/netzke/core/railz/controller_extensions.rb +21 -15
  27. data/lib/netzke/core/services.rb +61 -48
  28. data/lib/netzke/core/session.rb +0 -2
  29. data/lib/netzke/core/state.rb +11 -9
  30. data/lib/netzke/core/stylesheets.rb +3 -3
  31. data/lib/netzke/core/version.rb +1 -1
  32. data/lib/netzke/core.rb +3 -3
  33. data/lib/netzke/plugin.rb +2 -6
  34. data/stylesheets/core.css +2 -2
  35. metadata +11 -10
  36. data/TODO.md +0 -9
  37. data/javascripts/ext.js +0 -518
  38. data/lib/netzke/core/config_to_dsl_delegator.rb +0 -62
  39. data/lib/netzke/core/dsl_support.rb +0 -70
  40. data/lib/netzke/core/html.rb +0 -29
  41. data/lib/netzke/core/javascript.rb +0 -123
data/javascripts/ext.js DELETED
@@ -1,518 +0,0 @@
1
- // This file has stuff related to Ext JS (as apposed to Touch)
2
-
3
- // Because of Netzke's double-underscore notation, Ext.TabPanel should have a different id-delimiter (yes, this should be in netzke-core)
4
- Ext.TabPanel.prototype.idDelimiter = "___";
5
-
6
- // Enable quick tips
7
- Ext.QuickTips.init();
8
-
9
- // Checking Ext JS version: both major and minor versions must be the same
10
- (function(){
11
- var requiredVersionMajor = 5,
12
- requiredVersionMinor = 1,
13
- extVersion = Ext.getVersion('extjs'),
14
- currentVersionMajor = extVersion.getMajor(),
15
- currentVersionMinor = extVersion.getMinor(),
16
- requiredString = "" + requiredVersionMajor + "." + requiredVersionMinor + ".x";
17
-
18
- if (requiredVersionMajor != currentVersionMajor || requiredVersionMinor != currentVersionMinor) {
19
- Netzke.warning("Ext JS " + requiredString + " required (you have " + extVersion.toString() + ").");
20
- }
21
- })();
22
-
23
- // FeedbackGhost is a little class that displays unified feedback from Netzke components.
24
- Ext.define('Netzke.FeedbackGhost', {
25
- showFeedback: function(msg, options){
26
- options = options || {};
27
- options.delay = options.delay || Netzke.core.FeedbackDelay;
28
- if (Ext.isObject(msg)) {
29
- this.msg(msg.level.camelize(), msg.msg, options.delay);
30
- } else if (Ext.isArray(msg)) {
31
- Ext.each(msg, function(m) { this.showFeedback(m); }, this);
32
- } else {
33
- this.msg(null, msg, options.delay); // no header for now
34
- }
35
- },
36
-
37
- msg: function(title, format, delay){
38
- if(!this.msgCt){
39
- this.msgCt = Ext.core.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
40
- }
41
- var s = Ext.String.format.apply(String, Array.prototype.slice.call(arguments, 1));
42
- var m = Ext.core.DomHelper.append(this.msgCt, this.createBox(title, s), true);
43
- m.hide();
44
- m.slideIn('t').ghost("t", { delay: delay, remove: true});
45
- },
46
-
47
- createBox: function(t, s){
48
- if (t) {
49
- return '<div class="msg"><h3>' + t + '</h3><p>' + s + '</p></div>';
50
- } else {
51
- return '<div class="msg"><p>' + s + '</p></div>';
52
- }
53
- }
54
- });
55
-
56
- Ext.define('Netzke.classes.NetzkeRemotingProvider', {
57
- extend: 'Ext.direct.RemotingProvider',
58
-
59
- getPayload: function(t){
60
- return {
61
- path: t.action,
62
- endpoint: t.method,
63
- data: t.data,
64
- tid: t.id,
65
- type: 'rpc'
66
- }
67
- },
68
-
69
- addEndpointsForComponent: function(componentPath, componentId, endpoints) {
70
- var cls = this.namespace[componentId] || (this.namespace[componentId] = {});
71
-
72
- Ext.Array.each(endpoints, function(ep) {
73
- var methodName = ep.camelize(true),
74
- method = Ext.create('Ext.direct.RemotingMethod', {name: methodName, len: 1});
75
-
76
- cls[methodName] = this.createHandler(componentPath, method);
77
- }, this);
78
- }
79
- });
80
-
81
- Netzke.directProvider = new Netzke.classes.NetzkeRemotingProvider({
82
- type: "remoting", // create a Ext.direct.RemotingProvider
83
- url: Netzke.ControllerUrl + "direct/", // url to connect to the Ext.Direct server-side router.
84
- namespace: "Netzke.providers", // Netzke.providers will have a key per Netzke component, each mapped to a hash with a RemotingMethod per endpoint
85
- actions: {},
86
- maxRetries: Netzke.core.directMaxRetries,
87
- enableBuffer: true, // buffer/batch requests within 10ms timeframe
88
- timeout: 30000 // 30s timeout per request
89
- });
90
-
91
- Ext.Direct.addProvider(Netzke.directProvider);
92
-
93
- // Override Ext.Component's constructor to enable Netzke features
94
- Ext.define(null, {
95
- override: 'Ext.Component',
96
- constructor: function(config) {
97
- if (this.isNetzke) {
98
- // component loading index
99
- this.netzkeLoadingIndex = 0;
100
-
101
- this.netzkeComponents = config.netzkeComponents;
102
- this.passedConfig = config;
103
-
104
- // process and get rid of endpoints config
105
- this.netzkeProcessEndpoints(config);
106
-
107
- // process and get rid of plugins config
108
- this.netzkeProcessPlugins(config);
109
-
110
- this.netzkeNormalizeActions(config);
111
-
112
- this.netzkeNormalizeConfig(config);
113
-
114
- this.netzkeNormalizeTools(config);
115
-
116
- // This is where the references to different callback functions will be stored
117
- this.callbackHash = {};
118
-
119
- // This is where we store the information about components that are currently being loaded with this.loadComponent()
120
- this.componentsBeingLoaded = {};
121
-
122
- this.netzkeClientConfig = config.clientConfig || {};
123
- }
124
-
125
- this.callOverridden([config]);
126
- }
127
- });
128
-
129
- // Methods/properties that each and every Netzke component will have
130
- Ext.define(null, {
131
- override: 'Netzke.classes.Core.Mixin',
132
- feedbackGhost: Ext.create("Netzke.FeedbackGhost"),
133
-
134
- /*
135
- Mask shown during loading of a component. Set to false to not mask. Pass config for Ext.LoadMask for configuring msg/cls, etc.
136
- Set msg to null if mask without any msg is desirable.
137
- */
138
- netzkeLoadMask: false, // TODO: reenable
139
-
140
- /**
141
- * Runs through initial config options and does the following:
142
- *
143
- * * detects component placeholders and replaces them with full component config found in netzkeComponents
144
- * * detects action placeholders and replaces them with instances of Ext actions found in this.actions
145
- * @private
146
- */
147
- netzkeNormalizeConfig: function(config) {
148
- for (key in config) {
149
- if (Ext.isArray(config[key])) this.netzkeNormalizeConfigArray(config[key]);
150
- }
151
- },
152
-
153
- /**
154
- * Dynamically creates methods for endpoints, so that we could later call them like: this.myEndpointMethod()
155
- * @private
156
- */
157
- netzkeProcessEndpoints: function(config){
158
- var endpoints = config.endpoints || [];
159
- endpoints.push('deliver_component'); // all Netzke components get this endpoint
160
-
161
- Netzke.directProvider.addEndpointsForComponent(config.path, config.id, endpoints);
162
-
163
- var that = this;
164
-
165
- Ext.each(endpoints, function(ep){
166
- var methodName = ep.camelize(true);
167
-
168
- /* add endpoint method to `this` */
169
- this[methodName] = function(args, callback, scope) {
170
- Netzke.runningRequests++;
171
-
172
- scope = scope || that;
173
-
174
- var cfgs = this.buildParentClientConfigs();
175
- var remotingArgs = {args: args, configs: cfgs};
176
-
177
- // Calling Ext.Direct's function
178
- Netzke.providers[config.id][methodName].call(scope, remotingArgs, function(result, e) {
179
- var callbackParam = e;
180
-
181
- if (Ext.getClass(e) == Ext.direct.RemotingEvent) { // means we didn't get an exception
182
- that.netzkeBulkExecute(result); // invoke the endpoint result on the calling component
183
- callbackParam = that.latestResult;
184
- }
185
-
186
- if (typeof callback == "function" && !scope.netzkeSessionIsExpired) {
187
- callback.call(scope, callbackParam); // invoke the callback on the provided scope, or on the calling component if no scope set. Pass latestResult to callback in case of success, or the Ext.direct.ExceptionEvent otherwise
188
- }
189
-
190
- Netzke.runningRequests--;
191
- });
192
- }
193
- }, this);
194
-
195
- delete config.endpoints;
196
- },
197
-
198
- /**
199
- * Array of client configs for each parent down the tree
200
- * @private
201
- */
202
- buildParentClientConfigs: function() {
203
- this._parentClientConfig = [];
204
- var parent = this;
205
- while (parent) {
206
- var cfg = Ext.clone(parent.netzkeClientConfig);
207
- cfg.component_id = parent.id;
208
- this._parentClientConfig.unshift(cfg);
209
- parent = parent.netzkeGetParentComponent();
210
- }
211
- return this._parentClientConfig;
212
- },
213
-
214
- /**
215
- * @private
216
- * Handles endpoint exceptions. Ext.direct.ExceptionEvent gets passed as parameter. Override to handle server side exceptions.
217
- */
218
- onDirectException: function(e) {
219
- Netzke.warning("Server error. Override onDirectException to handle this.");
220
- },
221
-
222
- /**
223
- * @private
224
- */
225
- netzkeNormalizeTools: function(config) {
226
- if (config.tools) {
227
- var normTools = [];
228
- Ext.each(config.tools, function(tool){
229
- var handler = Ext.Function.bind(this.netzkeToolHandler, this, [tool]);
230
- normTools.push({type : tool, handler : handler, scope : this});
231
- }, this);
232
- this.tools = normTools;
233
- delete config.tools;
234
- }
235
- },
236
-
237
- /**
238
- * Replaces actions configs with Ext.Action instances, assigning default handler to them
239
- * @private
240
- */
241
- netzkeNormalizeActions : function(config){
242
- var normActions = {};
243
- for (var name in config.actions) {
244
- // Configure the action
245
- var actionConfig = Ext.apply({}, config.actions[name]); // do not modify original this.actions
246
- actionConfig.customHandler = actionConfig.handler;
247
- actionConfig.handler = Ext.Function.bind(this.netzkeActionHandler, this); // handler common for all actions
248
- actionConfig.name = name;
249
- normActions[name] = new Ext.Action(actionConfig);
250
- }
251
- this.actions = normActions;
252
- delete(config.actions);
253
- },
254
-
255
- /**
256
- * Dynamically loads a Netzke component.
257
- * @param {String} name
258
- * @param {Object} config Can contain the following keys:
259
- * 'container' - if specified, the instance (or id) of a panel with the 'fit' layout where the loaded component will be added to; the previously existing component will be destroyed
260
- * 'append' - if set to +true+, do not clear the container before adding the loaded component
261
- * 'clone' - if set to +true+, allows loading multiple instances of the same child component
262
- * 'callback' - function that gets called after the component is loaded; it receives the component's instance as parameter
263
- * 'configOnly' - if set to +true+, do not instantiate the component, instead pass its config to the callback function
264
- * 'params' - object passed to the endpoint, may be useful for extra configuration
265
- * 'scope' - scope for the callback
266
- *
267
- * Examples:
268
- *
269
- * this.netzkeLoadComponent('info');
270
- *
271
- * loads 'info' and adds it to +this+ container, removing anything from it first.
272
- *
273
- * this.netzkeLoadComponent('info', {container: win, callback: function(instance){}, scope: this});
274
- *
275
- * loads 'info' and adds it to +win+ container, envoking a callback in +this+ scope, passing it an instance of 'info'.
276
- *
277
- * this.netzkeLoadComponent('info', {configOnly: true, callback: function(config){}, scope: this});
278
- *
279
- * loads configuration for the 'info' component, envoking a callback in +this+ scope, passing it the loaded config for 'info'.
280
- */
281
- netzkeLoadComponent: function(){
282
- var params;
283
-
284
- // support 2 different signatures
285
- if (Ext.isString(arguments[0])) {
286
- params = arguments[1] || {};
287
- params.name = arguments[0];
288
- } else {
289
- params = arguments[0];
290
- }
291
-
292
- if (params.container == undefined) params.container = this;
293
- params.name = params.name.underscore();
294
-
295
- /* params that will be provided for the server API call (deliver_component); all what's passed in params.params is
296
- * merged in. This way we exclude from sending along such things as :scope and :callback */
297
- var serverParams = params.params || {};
298
- serverParams["name"] = params.name;
299
- serverParams["client_config"] = params.clientConfig;
300
-
301
- // by which the loaded component will be referred in +netzkeComponentDelivered+
302
- var itemId = params.name;
303
-
304
- // multi-instance loading
305
- if (params.clone) {
306
- serverParams["index"] = this.netzkeLoadingIndex;
307
- itemId += this.netzkeLoadingIndex; // << index
308
- this.netzkeLoadingIndex++;
309
- }
310
-
311
- // coma-separated list of xtypes of already loaded classes
312
- serverParams["cache"] = Netzke.cache.join();
313
-
314
- var storedConfig = this.componentsBeingLoaded[itemId] = params;
315
-
316
- // Remember where the loaded component should be inserted into
317
- var containerCmp = params.container && Ext.isString(params.container) ? Ext.getCmp(params.container) : params.container;
318
- storedConfig.container = containerCmp;
319
-
320
- // Show loading mask if possible
321
- var containerEl = (containerCmp || this).getEl();
322
- if (this.netzkeLoadMask && containerEl){
323
- storedConfig.loadMaskCmp = new Ext.LoadMask(containerEl, this.netzkeLoadMask);
324
- storedConfig.loadMaskCmp.show();
325
- }
326
-
327
- // Call the endpoint
328
- this.deliverComponent(serverParams, function(e) {
329
- if (Ext.getClass(e) == Ext.direct.ExceptionEvent) {
330
- this.netzkeUndoLoadingComponent(params.name);
331
- }
332
- }, this);
333
- },
334
-
335
- /**
336
- * Called by the server after we ask him to load a component
337
- * @private
338
- */
339
- netzkeComponentDelivered: function(config){
340
- var storedConfig = this.netzkeUndoLoadingComponent(config.itemId),
341
- callbackParam = Ext.apply(config, storedConfig);
342
-
343
- config.netzkeParent = this;
344
-
345
- if (!storedConfig.configOnly) {
346
- var currentCmp = Ext.ComponentManager.get(config.id);
347
- if (currentCmp) currentCmp.destroy();
348
-
349
- var componentInstance = Ext.ComponentManager.create(config);
350
-
351
- // there's no sense in adding a window-type components
352
- if (storedConfig.container && !componentInstance.isFloating()) {
353
- var containerCmp = storedConfig.container;
354
- if (!storedConfig.append) containerCmp.removeAll();
355
- containerCmp.add(componentInstance);
356
-
357
- if (containerCmp.isVisible()) {
358
- containerCmp.doLayout();
359
- } else {
360
- // if loaded into a hidden container, we need a little trick
361
- containerCmp.on('show', function(cmp){ cmp.doLayout(); }, {single: true});
362
- }
363
- }
364
- callbackParam = componentInstance;
365
- }
366
-
367
- if (storedConfig.callback) {
368
- storedConfig.callback.call(storedConfig.scope || this, callbackParam, storedConfig);
369
- }
370
- },
371
-
372
- /**
373
- * Destroys the loading mask and removes the component from componentsBeingLoaded
374
- * @private
375
- */
376
- netzkeUndoLoadingComponent: function(itemId) {
377
- var storedConfig = this.componentsBeingLoaded[itemId] || {};
378
- delete this.componentsBeingLoaded[itemId];
379
-
380
- if (storedConfig.loadMaskCmp) {
381
- storedConfig.loadMaskCmp.hide();
382
- storedConfig.loadMaskCmp.destroy();
383
- }
384
-
385
- return storedConfig;
386
- },
387
-
388
- /**
389
- * @private
390
- */
391
- netzkeComponentDeliveryFailed: function(params) {
392
- var storedConfig = this.componentsBeingLoaded[params.itemId] || {};
393
- delete this.componentsBeingLoaded[params.itemId];
394
-
395
- if (storedConfig.loadMaskCmp) {
396
- storedConfig.loadMaskCmp.hide();
397
- storedConfig.loadMaskCmp.destroy();
398
- }
399
-
400
- this.netzkeFeedback({msg: params.msg, level: "Error"});
401
- },
402
-
403
- /**
404
- * Returns parent Netzke component
405
- */
406
- netzkeGetParentComponent: function(){
407
- return this.netzkeParent;
408
- },
409
-
410
- /**
411
- * Reloads itself by instructing the parent to call `netzkeLoadComponent`.
412
- * Note: in order for this to work, the component must be nested in a container with the 'fit' layout.
413
- */
414
- netzkeReload: function(){
415
- var parent = this.netzkeGetParentComponent();
416
-
417
- if (parent) {
418
- var name = this.netzkeLocalId(parent);
419
- parent.netzkeLoadComponent(name, {container: this.getRefOwner().id});
420
- } else {
421
- window.location.reload();
422
- }
423
- },
424
-
425
- /**
426
- * Instantiates and returns a Netzke component by its name.
427
- * @private
428
- */
429
- netzkeInstantiateComponent: function(name) {
430
- name = name.camelize(true);
431
- var cfg = this.netzkeComponents[name];
432
- return Ext.createByAlias(this.netzkeComponents[name].alias, cfg)
433
- },
434
-
435
- /**
436
- * Returns *instantiated* child component by its relative id, which may contain the 'parent' part to walk _up_ the hierarchy
437
- * @private
438
- */
439
- netzkeGetComponent: function(id){
440
- if (id === "") {return this};
441
- id = id.underscore();
442
- var split = id.split("__"), res;
443
- if (split[0] === 'parent') {
444
- split.shift();
445
- var childInParentScope = split.join("__");
446
- res = this.netzkeGetParentComponent().netzkeGetComponent(childInParentScope);
447
- } else {
448
- res = Ext.getCmp(this.id+"__"+id);
449
- }
450
- return res;
451
- },
452
-
453
- /**
454
- * Provides a visual feedback. TODO: refactor
455
- * msg can be a string, an array of strings, an object in form {msg: 'Message'}, or an array of such objects.
456
- */
457
- netzkeFeedback: function(msg, options){
458
- if (this.initialConfig && this.initialConfig.quiet) return false;
459
-
460
- options = options || {};
461
-
462
- if (typeof msg == 'string'){ msg = [msg]; }
463
-
464
- var feedback = "";
465
-
466
- Ext.each(msg, function(m){
467
- feedback += (m.msg || m) + "<br/>"
468
- });
469
-
470
- if (feedback != "") {
471
- this.feedbackGhost.showFeedback(feedback, {delay: options.delay});
472
- }
473
- },
474
-
475
- /**
476
- * Common handler for all netzke's actions. <tt>comp</tt> is the Component that triggered the action (e.g. button or menu item)
477
- * @private
478
- */
479
- netzkeActionHandler: function(comp){
480
- var actionName = comp.name;
481
- // If firing corresponding event doesn't return false, call the handler
482
- if (this.fireEvent(actionName+'click', comp)) {
483
- var action = this.actions[actionName];
484
- var customHandler = action.initialConfig.customHandler;
485
- var methodName = (customHandler && customHandler.camelize(true)) || "on" + actionName.camelize();
486
- if (!this[methodName]) {throw "Netzke: handler '" + methodName + "' is undefined in '" + this.id + "'";}
487
-
488
- // call the handler passing it the triggering component
489
- this[methodName](comp);
490
- }
491
- },
492
-
493
- /**
494
- * Common handler for tools
495
- * @private
496
- */
497
- netzkeToolHandler: function(tool){
498
- // If firing corresponding event doesn't return false, call the handler
499
- if (this.fireEvent(tool.id+'click')) {
500
- var methodName = "on"+tool.camelize();
501
- if (!this[methodName]) {throw "Netzke: handler for tool '"+tool+"' is undefined"}
502
- this[methodName]();
503
- }
504
- },
505
-
506
- /**
507
- * @private
508
- */
509
- netzkeProcessPlugins: function(config) {
510
- if (config.netzkePlugins) {
511
- if (!this.plugins) this.plugins = [];
512
- Ext.each(config.netzkePlugins, function(p){
513
- this.plugins.push(this.netzkeInstantiateComponent(p));
514
- }, this);
515
- delete config.netzkePlugins;
516
- }
517
- }
518
- });
@@ -1,62 +0,0 @@
1
- module Netzke::Core
2
- # This module can be included in a component class to allows delegating the configuration options for a component into the level of the component's class.
3
- # For example:
4
- #
5
- # class SomeComponentBase < Netzke::Base
6
- # delegates_to_dsl :title, :html
7
- # end
8
- #
9
- # This will provide its children with class (DSL) methods +title+ and +html+:
10
- #
11
- # class SomeComponent < SomeComponentBase
12
- # title "Some component"
13
- # html "HTML set in DSL"
14
- # end
15
- #
16
- # ... which would be equivalent to:
17
- #
18
- # class SomeComponent < SomeComponentBase
19
- # def configure(c)
20
- # c.title = "Some component"
21
- # c.html = "HTML set in DSL"
22
- # super
23
- # end
24
- # end
25
- #
26
- # This may be handy when a frequently-inherited class implements some common options.
27
- module ConfigToDslDelegator
28
- extend ActiveSupport::Concern
29
-
30
- included do
31
- class_attribute :delegated_options
32
- self.delegated_options = []
33
-
34
- class_attribute :delegated_defaults
35
- self.delegated_defaults = {}
36
- end
37
-
38
- def configure(c)
39
- c.merge! delegated_defaults
40
- super
41
- end
42
-
43
- module ClassMethods
44
- # Delegates specified configuration options to the class level
45
- def delegates_to_dsl(*option_names)
46
- self.delegated_options |= option_names
47
- end
48
-
49
- def inherited(inherited_class)
50
- super
51
-
52
- properties = self.delegated_options
53
- properties.each do |property|
54
- inherited_class.class.send(:define_method, property, lambda { |value|
55
- self.delegated_defaults = self.delegated_defaults.dup if self.superclass.respond_to?(:delegated_defaults) && self.delegated_defaults == self.superclass.delegated_defaults
56
- self.delegated_defaults[property.to_sym] = value
57
- })
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,70 +0,0 @@
1
- module Netzke
2
- module Core
3
- module DslSupport
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- # It's the easiest to be explained by an example:
8
- #
9
- # declare_dsl_for :components
10
- #
11
- # This creates:
12
- #
13
- # 1) DSL method `component` for declaration of child component in a given class, e.g.:
14
- #
15
- # component :simple_panel do |c|
16
- # # ...
17
- # end
18
- #
19
- # Each call to the created `component` method results in an instance method:
20
- #
21
- # def simple_panel_component(c)
22
- # # ...
23
- # end
24
- #
25
- # 2) Instance method `components` that returns a hash of all components configs. This hash is built by passing a new instance of `Netzke::Core::ComponentConfig` to each of the methods described in 1). Presence of `Netzke::Core::ComponentConfig` is assumed.
26
- #
27
- # Besides components, this method is being used in Core for DSL for actions.
28
- def declare_dsl_for(things, options = {})
29
- things = things.to_s
30
- storage_attribute = :"_declared_#{things}"
31
-
32
- class_attribute storage_attribute
33
- send("#{storage_attribute}=", [])
34
-
35
- define_dsl_method(things, storage_attribute, options)
36
- define_collector_method(things, storage_attribute, options)
37
- end
38
-
39
- def define_dsl_method(things, storage_attribute, options)
40
- thing = things.singularize
41
-
42
- define_singleton_method thing do |name, &block|
43
- self.send("#{storage_attribute}=", self.send(storage_attribute) | [name])
44
- method_name = "#{name}_#{thing}"
45
- define_method(method_name, &(block || ->(c){c}))
46
- end
47
- end
48
-
49
- def define_collector_method(things, storage_attribute, options)
50
- thing = things.singularize
51
- config_class = options[:config_class] || Netzke::Core::DslConfigBase
52
-
53
- define_method things do
54
- # memoization
55
- return instance_variable_get("@#{things}") if instance_variable_get("@#{things}")
56
-
57
- config_hash = self.class.send(storage_attribute).inject({}) do |out, name|
58
- c = config_class.new(name, self)
59
- send("#{name}_#{thing}", c)
60
- c.set_defaults!
61
- out.merge(name.to_sym => c.excluded ? {excluded: true} : c)
62
- end
63
-
64
- instance_variable_set "@#{things}", config_hash
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,29 +0,0 @@
1
- module Netzke
2
- module Core
3
- # Provides support for HTML rendering (currently HAML only)
4
- module Html
5
- # Will render an HTML template found in +{component_location}/html/+ For example:
6
- #
7
- # class MyComponent < Netzke::Base
8
- # def js_configure(c)
9
- # super
10
- # c.html = render(:body)
11
- # end
12
- # end
13
- #
14
- # This will render the HAML file located in +app/components/my_component/html/body.html.haml
15
- # The implementation is very simplistic at the moment - e.g. no caching, no support for .erb
16
- def render(what)
17
- callr = caller.first
18
- engine = Haml::Engine.new(File.read(expand_html_path(what, callr)))
19
- engine.method(:render).call(self)
20
- end
21
-
22
- private
23
-
24
- def expand_html_path(sym, callr = nil)
25
- %Q(#{callr.split(".rb:").first}/html/#{sym}.html.haml)
26
- end
27
- end
28
- end
29
- end