netzke-core 0.2.8 → 0.2.9
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 +7 -0
- data/Manifest +2 -1
- data/README.mdown +1 -1
- data/TODO +1 -0
- data/javascripts/core.js +174 -59
- data/lib/app/controllers/netzke_controller.rb +1 -1
- data/lib/app/models/netzke_layout.rb +2 -9
- data/lib/app/models/netzke_preference.rb +10 -12
- data/lib/netzke/base.rb +61 -66
- data/lib/netzke/base_extras/interface.rb +2 -0
- data/lib/netzke/base_extras/js_builder.rb +106 -52
- data/lib/netzke/controller_extensions.rb +1 -1
- data/lib/netzke/core_ext.rb +1 -1
- data/lib/netzke-core.rb +6 -2
- data/netzke-core.gemspec +4 -4
- data/{css → stylesheets}/core.css +4 -0
- data/test/netzke_core_test.rb +2 -2
- metadata +5 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
v0.2.9
|
2
|
+
Actions, toolbars and tools reworked for easier configuration.
|
3
|
+
Menus introduced (based on actions).
|
4
|
+
Significant code clean-up.
|
5
|
+
Bug fix (nasty one): Ext.widgetMixIn was getting messed up along with dynamic widget loading.
|
6
|
+
Must work in IE now.
|
7
|
+
|
1
8
|
v0.2.8
|
2
9
|
Support for extra javascripts and stylesheets per widget.
|
3
10
|
|
data/Manifest
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
CHANGELOG
|
2
|
-
css/core.css
|
3
2
|
generators/netzke_core/netzke_core_generator.rb
|
4
3
|
generators/netzke_core/templates/create_netzke_layouts.rb
|
5
4
|
generators/netzke_core/templates/create_netzke_preferences.rb
|
@@ -25,6 +24,7 @@ Manifest
|
|
25
24
|
netzke-core.gemspec
|
26
25
|
Rakefile
|
27
26
|
README.mdown
|
27
|
+
stylesheets/core.css
|
28
28
|
tasks/netzke_core_tasks.rake
|
29
29
|
test/app_root/app/controllers/application.rb
|
30
30
|
test/app_root/config/boot.rb
|
@@ -42,4 +42,5 @@ test/core_ext_test.rb
|
|
42
42
|
test/netzke_core_test.rb
|
43
43
|
test/netzke_preference_test.rb
|
44
44
|
test/test_helper.rb
|
45
|
+
TODO
|
45
46
|
uninstall.rb
|
data/README.mdown
CHANGED
@@ -10,4 +10,4 @@ The tutorials: http://blog.writelesscode.com
|
|
10
10
|
|
11
11
|
Also see the netzke-basepack project: http://github.com/skozlov/netzke-basepack/tree/master
|
12
12
|
|
13
|
-
Copyright (c) 2008-2009 Sergei Kozlov, released under
|
13
|
+
Copyright (c) 2008-2009 Sergei Kozlov, released under LGPL 3.0
|
data/javascripts/core.js
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
/*
|
2
|
+
This file gets loaded along with the rest of Ext library at the initial load
|
3
|
+
*/
|
4
|
+
|
1
5
|
Ext.BLANK_IMAGE_URL = "/extjs/resources/images/default/s.gif";
|
2
6
|
Ext.namespace('Ext.netzke');
|
3
7
|
Ext.netzke.cache = {};
|
4
8
|
|
5
|
-
Ext.QuickTips.init(); // seems obligatory in Ext v2.2.1, otherwise destroy() stops working properly
|
9
|
+
Ext.QuickTips.init(); // seems obligatory in Ext v2.2.1, otherwise Ext.Component#destroy() stops working properly
|
6
10
|
|
7
11
|
// to comply with Rails' forgery protection
|
8
12
|
Ext.Ajax.extraParams = {
|
@@ -16,7 +20,50 @@ Ext.chainApply = function(objectArray){
|
|
16
20
|
return res;
|
17
21
|
};
|
18
22
|
|
19
|
-
//
|
23
|
+
// Type detection functions
|
24
|
+
function isArray(o) {
|
25
|
+
return (o != null && typeof o == "object" && o.constructor.toString() == Array.toString());
|
26
|
+
}
|
27
|
+
|
28
|
+
function isObject(o) {
|
29
|
+
return (o != null && typeof o == "object" && o.constructor.toString() == Object.toString());
|
30
|
+
}
|
31
|
+
|
32
|
+
// Some Rubyish String extensions
|
33
|
+
// from http://code.google.com/p/inflection-js/
|
34
|
+
String.prototype.camelize=function(lowFirstLetter)
|
35
|
+
{
|
36
|
+
var str=this.toLowerCase();
|
37
|
+
var str_path=str.split('/');
|
38
|
+
for(var i=0;i<str_path.length;i++)
|
39
|
+
{
|
40
|
+
var str_arr=str_path[i].split('_');
|
41
|
+
var initX=((lowFirstLetter&&i+1==str_path.length)?(1):(0));
|
42
|
+
for(var x=initX;x<str_arr.length;x++)
|
43
|
+
str_arr[x]=str_arr[x].charAt(0).toUpperCase()+str_arr[x].substring(1);
|
44
|
+
str_path[i]=str_arr.join('');
|
45
|
+
}
|
46
|
+
str=str_path.join('::');
|
47
|
+
return str;
|
48
|
+
};
|
49
|
+
|
50
|
+
String.prototype.capitalize=function()
|
51
|
+
{
|
52
|
+
var str=this.toLowerCase();
|
53
|
+
str=str.substring(0,1).toUpperCase()+str.substring(1);
|
54
|
+
return str;
|
55
|
+
};
|
56
|
+
|
57
|
+
String.prototype.humanize=function(lowFirstLetter)
|
58
|
+
{
|
59
|
+
var str=this.toLowerCase();
|
60
|
+
str=str.replace(new RegExp('_id','g'),'');
|
61
|
+
str=str.replace(new RegExp('_','g'),' ');
|
62
|
+
if(!lowFirstLetter)str=str.capitalize();
|
63
|
+
return str;
|
64
|
+
};
|
65
|
+
|
66
|
+
// Implementation of totalProperty, successProperty and root configuration options for ArrayReader
|
20
67
|
Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
|
21
68
|
readRecords : function(o){
|
22
69
|
var sid = this.meta ? this.meta.id : null;
|
@@ -49,68 +96,151 @@ Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
|
|
49
96
|
|
50
97
|
// Methods common to all widget classes
|
51
98
|
Ext.widgetMixIn = {
|
99
|
+
// Common handler for actions
|
52
100
|
actionHandler : function(action){
|
53
|
-
|
101
|
+
// If firing corresponding event doesn't return false, call the handler
|
102
|
+
if (this.fireEvent(action.name+'click', action)) {
|
103
|
+
this[(action.fn || action.name)](action);
|
104
|
+
}
|
54
105
|
},
|
55
106
|
|
56
|
-
|
57
|
-
|
107
|
+
// Common handler for tools
|
108
|
+
toolActionHandler : function(tool){
|
109
|
+
// If firing corresponding event doesn't return false, call the handler
|
110
|
+
if (this.fireEvent(tool.id+'click')) {
|
111
|
+
this[tool]();
|
112
|
+
}
|
113
|
+
},
|
58
114
|
|
59
|
-
|
60
|
-
|
61
|
-
}, this);
|
115
|
+
beforeConstructor : function(config){
|
116
|
+
this.actions = {};
|
62
117
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
118
|
+
// Create Ext.Actions based on config.actions
|
119
|
+
if (config.actions) {
|
120
|
+
for (var name in config.actions) {
|
121
|
+
// Create an event for each action (so that higher-level widgets could interfere)
|
122
|
+
this.addEvents(name+'click');
|
67
123
|
|
68
|
-
|
69
|
-
|
70
|
-
|
124
|
+
// Configure the action
|
125
|
+
var actionConfig = config.actions[name];
|
126
|
+
actionConfig.handler = this.actionHandler.createDelegate(this);
|
127
|
+
actionConfig.name = name;
|
128
|
+
this.actions[name] = new Ext.Action(actionConfig);
|
129
|
+
}
|
71
130
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
131
|
+
/* Parse the bbar and tbar (both Arrays), replacing the strings with the corresponding methods. For example:
|
132
|
+
replaceStringsWithActions( ['add', {text:'Menu', menu:['edit', 'delete']}] )
|
133
|
+
=> [scope.actions['add'], {text:'Menu', menu:[scope.actions['edit'], scope.actions['delete']]}]
|
134
|
+
*/
|
135
|
+
var replaceStringsWithActions = function(arry, scope){
|
136
|
+
var res = []; // new array
|
137
|
+
Ext.each(arry, function(o){
|
138
|
+
if (typeof o === "string") {
|
139
|
+
var camelized = o.camelize(true);
|
140
|
+
if (scope.actions[camelized]){
|
141
|
+
res.push(scope.actions[camelized]);
|
142
|
+
} else {
|
143
|
+
// if there's no action with this name, maybe it's a separator or something
|
144
|
+
res.push(o);
|
145
|
+
}
|
146
|
+
} else if (isObject(o)) {
|
147
|
+
// look inside the objects...
|
148
|
+
for (var key in o) {
|
149
|
+
if (isArray(o[key])) {
|
150
|
+
// ... and recursively process inner arrays found
|
151
|
+
o[key] = replaceStringsWithActions(o[key], scope);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
res.push(o);
|
155
|
+
}
|
156
|
+
});
|
157
|
+
return res;
|
77
158
|
}
|
159
|
+
config.bbar = config.bbar && replaceStringsWithActions(config.bbar, this);
|
160
|
+
config.tbar = config.tbar && replaceStringsWithActions(config.tbar, this);
|
161
|
+
config.menu = config.menu && replaceStringsWithActions(config.menu, this);
|
162
|
+
|
163
|
+
}
|
164
|
+
|
165
|
+
// Normalize tools
|
166
|
+
if (config.tools) {
|
167
|
+
var normTools = [];
|
168
|
+
Ext.each(config.tools, function(tool){
|
169
|
+
// Create an event for each action (so that higher-level widgets could interfere)
|
170
|
+
this.addEvents(tool.id+'click');
|
171
|
+
|
172
|
+
var handler = this.toolActionHandler.createDelegate(this, [tool]);
|
173
|
+
normTools.push({id : tool, handler : handler, scope : this});
|
174
|
+
}, this);
|
175
|
+
config.tools = normTools;
|
176
|
+
}
|
177
|
+
|
178
|
+
},
|
179
|
+
|
180
|
+
afterConstructor : function(config){
|
181
|
+
this.feedbackGhost = Ext.getCmp('feedback_ghost');
|
182
|
+
|
183
|
+
// cleaning up
|
184
|
+
this.on('beforedestroy', function(){
|
185
|
+
this.cleanUpMenu(this);
|
78
186
|
}, this);
|
79
187
|
|
188
|
+
// After render, add the menus
|
189
|
+
this.on('render', function(){
|
190
|
+
if (this.initialConfig.menu) {this.addMenu(this.initialConfig.menu);}
|
191
|
+
}, this);
|
192
|
+
|
80
193
|
this.on('render', this.onWidgetLoad, this);
|
81
194
|
},
|
82
195
|
|
83
196
|
feedback:function(msg){
|
84
|
-
if (this.initialConfig && this.initialConfig.quiet)
|
85
|
-
|
86
|
-
|
197
|
+
if (this.initialConfig && this.initialConfig.quiet) {
|
198
|
+
return false;
|
199
|
+
}
|
200
|
+
|
201
|
+
if (this.feedbackGhost) {
|
202
|
+
this.feedbackGhost.showFeedback(msg);
|
87
203
|
} else {
|
88
204
|
// there's no application to show the feedback - so, we do it ourselves
|
89
205
|
if (typeof msg == 'string'){
|
90
|
-
alert(msg)
|
206
|
+
alert(msg);
|
91
207
|
} else {
|
92
|
-
var compoundResponse = ""
|
208
|
+
var compoundResponse = "";
|
93
209
|
Ext.each(msg, function(m){
|
94
210
|
compoundResponse += m.msg + "\n"
|
95
|
-
})
|
96
|
-
if (compoundResponse != "")
|
211
|
+
});
|
212
|
+
if (compoundResponse != "") {
|
213
|
+
alert(compoundResponse);
|
214
|
+
}
|
97
215
|
}
|
98
|
-
}
|
216
|
+
}
|
99
217
|
},
|
100
218
|
|
101
|
-
|
102
|
-
if (
|
103
|
-
|
219
|
+
addMenu : function(menu, owner){
|
220
|
+
if (!owner) {
|
221
|
+
owner = this;
|
222
|
+
}
|
223
|
+
|
224
|
+
if (!!this.hostMenu) {
|
225
|
+
this.hostMenu(menu, owner);
|
104
226
|
} else {
|
105
|
-
if (this.
|
106
|
-
this.
|
227
|
+
if (this.parent) {
|
228
|
+
this.parent.addMenu(menu, owner);
|
107
229
|
}
|
108
230
|
}
|
109
231
|
},
|
110
|
-
|
111
|
-
|
112
|
-
if (
|
113
|
-
|
232
|
+
|
233
|
+
cleanUpMenu : function(owner){
|
234
|
+
if (!owner) {
|
235
|
+
owner = this;
|
236
|
+
}
|
237
|
+
|
238
|
+
if (!!this.unhostMenu) {
|
239
|
+
this.unhostMenu(owner);
|
240
|
+
} else {
|
241
|
+
if (this.parent) {
|
242
|
+
this.parent.cleanUpMenu(owner);
|
243
|
+
}
|
114
244
|
}
|
115
245
|
},
|
116
246
|
|
@@ -120,11 +250,13 @@ Ext.widgetMixIn = {
|
|
120
250
|
// Make Panel with layout 'fit' capable to dynamically load widgets
|
121
251
|
Ext.override(Ext.Panel, {
|
122
252
|
getWidget: function(){
|
123
|
-
return this.items.get(0)
|
253
|
+
return this.items.get(0);
|
124
254
|
},
|
125
255
|
|
126
256
|
loadWidget: function(url, params){
|
127
|
-
if (!params)
|
257
|
+
if (!params) {
|
258
|
+
params = {};
|
259
|
+
}
|
128
260
|
|
129
261
|
this.remove(this.getWidget()); // first delete previous widget
|
130
262
|
|
@@ -149,7 +281,7 @@ Ext.override(Ext.Panel, {
|
|
149
281
|
|
150
282
|
// evaluate widget's stylesheets
|
151
283
|
if (responseObj.css){
|
152
|
-
var linkTag = document.createElement('style')
|
284
|
+
var linkTag = document.createElement('style');
|
153
285
|
linkTag.type = 'text/css';
|
154
286
|
linkTag.innerHTML = responseObj.css;
|
155
287
|
document.body.appendChild(linkTag);
|
@@ -160,14 +292,14 @@ Ext.override(Ext.Panel, {
|
|
160
292
|
eval(responseObj.js);
|
161
293
|
}
|
162
294
|
|
163
|
-
responseObj.config.parent = this // we might want to know the parent panel in advance (e.g. to know its size)
|
295
|
+
responseObj.config.parent = this.ownerCt; // we might want to know the parent panel in advance (e.g. to know its size)
|
164
296
|
var instance = new Ext.netzke.cache[responseObj.config.widgetClassName](responseObj.config)
|
165
297
|
|
166
298
|
this.add(instance);
|
167
299
|
this.doLayout();
|
168
300
|
} else {
|
169
301
|
// we didn't get normal response - desplay the flash with eventual errors
|
170
|
-
this.ownerCt.feedback(responseObj.flash)
|
302
|
+
this.ownerCt.feedback(responseObj.flash);
|
171
303
|
}
|
172
304
|
|
173
305
|
// reenable the panel
|
@@ -178,20 +310,3 @@ Ext.override(Ext.Panel, {
|
|
178
310
|
}
|
179
311
|
});
|
180
312
|
|
181
|
-
// Some Rubyish String extensions
|
182
|
-
// from http://code.google.com/p/inflection-js/
|
183
|
-
String.prototype.capitalize=function()
|
184
|
-
{
|
185
|
-
var str=this.toLowerCase();
|
186
|
-
str=str.substring(0,1).toUpperCase()+str.substring(1);
|
187
|
-
return str;
|
188
|
-
};
|
189
|
-
|
190
|
-
String.prototype.humanize=function(lowFirstLetter)
|
191
|
-
{
|
192
|
-
var str=this.toLowerCase();
|
193
|
-
str=str.replace(new RegExp('_id','g'),'');
|
194
|
-
str=str.replace(new RegExp('_','g'),' ');
|
195
|
-
if(!lowFirstLetter)str=str.capitalize();
|
196
|
-
return str;
|
197
|
-
};
|
@@ -1,16 +1,9 @@
|
|
1
1
|
class NetzkeLayout < ActiveRecord::Base
|
2
2
|
EXT_UNRELATED_ATTRIBUTES = %w{ id layout_id position created_at updated_at }
|
3
|
+
|
3
4
|
# Multi user support
|
4
|
-
def self.user
|
5
|
-
@@user ||= nil
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.user=(user)
|
9
|
-
@@user = user
|
10
|
-
end
|
11
|
-
|
12
5
|
def self.user_id
|
13
|
-
user && user.id
|
6
|
+
Netzke::Base.user && Netzke::Base.user.id
|
14
7
|
end
|
15
8
|
|
16
9
|
# normal create, but with a user_id merged-in
|
@@ -6,19 +6,12 @@
|
|
6
6
|
# etc
|
7
7
|
#
|
8
8
|
class NetzkePreference < ActiveRecord::Base
|
9
|
-
|
10
|
-
|
11
|
-
# Multi user support
|
12
|
-
def self.user
|
13
|
-
@@user ||= nil
|
14
|
-
end
|
9
|
+
named_scope :for_current_user, lambda { {:conditions => {:user_id => user_id}} }
|
15
10
|
|
16
|
-
|
17
|
-
@@user = user
|
18
|
-
end
|
11
|
+
ELEMENTARY_CONVERTION_METHODS= {'Fixnum' => 'to_i', 'String' => 'to_s', 'Float' => 'to_f', 'Symbol' => 'to_sym'}
|
19
12
|
|
20
13
|
def self.user_id
|
21
|
-
user && user.id
|
14
|
+
Netzke::Base.user && Netzke::Base.user.id
|
22
15
|
end
|
23
16
|
|
24
17
|
def self.widget_name=(value)
|
@@ -54,14 +47,14 @@ class NetzkePreference < ActiveRecord::Base
|
|
54
47
|
end
|
55
48
|
|
56
49
|
def self.[](pref_name)
|
57
|
-
pref_name = pref_name
|
50
|
+
pref_name = normalize_preference_name(pref_name)
|
58
51
|
conditions = {:name => pref_name, :user_id => user_id, :widget_name => self.widget_name}
|
59
52
|
pref = self.find(:first, :conditions => conditions)
|
60
53
|
pref && pref.normalized_value
|
61
54
|
end
|
62
55
|
|
63
56
|
def self.[]=(pref_name, new_value)
|
64
|
-
pref_name = pref_name
|
57
|
+
pref_name = normalize_preference_name(pref_name)
|
65
58
|
conditions = {:name => pref_name, :user_id => user_id, :widget_name => self.widget_name}
|
66
59
|
pref = self.find(:first, :conditions => conditions)
|
67
60
|
|
@@ -75,4 +68,9 @@ class NetzkePreference < ActiveRecord::Base
|
|
75
68
|
end
|
76
69
|
end
|
77
70
|
|
71
|
+
private
|
72
|
+
def self.normalize_preference_name(name)
|
73
|
+
name.to_s.gsub(".", "__").gsub("/", "__")
|
74
|
+
end
|
75
|
+
|
78
76
|
end
|
data/lib/netzke/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'netzke/base_extras/js_builder'
|
2
|
+
require 'netzke/base_extras/interface'
|
2
3
|
|
3
4
|
module Netzke
|
4
5
|
#
|
@@ -8,48 +9,38 @@ module Netzke
|
|
8
9
|
# should be aware of this constant.
|
9
10
|
#
|
10
11
|
class Base
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
12
|
+
|
13
|
+
# Class-level Netzke::Base configuration. The defaults also get specified here.
|
14
|
+
def self.config
|
15
|
+
set_default_config({
|
16
|
+
# which javascripts and stylesheets must get included at the initial load (see netzke-core.rb)
|
17
|
+
:javascripts => [],
|
18
|
+
:stylesheets => [],
|
19
|
+
|
20
|
+
:layout_manager => "NetzkeLayout",
|
21
|
+
:persistent_config_manager => "NetzkePreference",
|
22
|
+
|
23
|
+
:ext_location => defined?(RAILS_ROOT) && "#{RAILS_ROOT}/public/extjs"
|
24
|
+
})
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
:css => [],
|
30
|
-
:layout_manager => "NetzkeLayout",
|
31
|
-
:persistent_config_manager => "NetzkePreference"
|
32
|
-
})
|
33
|
-
end
|
27
|
+
include Netzke::BaseExtras::JsBuilder
|
28
|
+
include Netzke::BaseExtras::Interface
|
29
|
+
|
30
|
+
module ClassMethods
|
34
31
|
|
32
|
+
# "Netzke::SomeWidget" => "SomeWidget"
|
35
33
|
def short_widget_class_name
|
36
|
-
name.split("::").last
|
34
|
+
self.name.split("::").last
|
37
35
|
end
|
38
36
|
|
37
|
+
# Multi-user support
|
39
38
|
def user
|
40
39
|
@@user ||= nil
|
41
40
|
end
|
42
41
|
|
43
42
|
def user=(user)
|
44
43
|
@@user = user
|
45
|
-
|
46
|
-
# also set up the managers
|
47
|
-
persistent_config_manager_class && persistent_config_manager_class.user = user
|
48
|
-
layout_manager_class && layout_manager_class.user = user
|
49
|
-
end
|
50
|
-
|
51
|
-
def user_has_role?(role)
|
52
|
-
user.login == 'sergei' && role.to_s == 'configurator'
|
53
44
|
end
|
54
45
|
|
55
46
|
#
|
@@ -78,32 +69,6 @@ module Netzke
|
|
78
69
|
read_inheritable_attribute(:interface_points)
|
79
70
|
end
|
80
71
|
|
81
|
-
#
|
82
|
-
# Include extra code from Ext js library (e.g. examples)
|
83
|
-
#
|
84
|
-
def ext_js_include(*args)
|
85
|
-
included_ext_js = read_inheritable_attribute(:included_ext_js) || []
|
86
|
-
args.each {|f| included_ext_js << f}
|
87
|
-
write_inheritable_attribute(:included_ext_js, included_ext_js)
|
88
|
-
end
|
89
|
-
|
90
|
-
# def js_include(*args)
|
91
|
-
# included_js = read_inheritable_attribute(:included_js) || []
|
92
|
-
# args.each {|f| included_js << f}
|
93
|
-
# write_inheritable_attribute(:included_js, included_js)
|
94
|
-
# end
|
95
|
-
|
96
|
-
# include eventual extra modules
|
97
|
-
def include_extras
|
98
|
-
extras_dir = File.join(File.dirname(widget_file), short_widget_class_name.underscore + "_extras")
|
99
|
-
file_list = Dir.glob("#{extras_dir}/*.rb")
|
100
|
-
for file_name in file_list
|
101
|
-
require file_name
|
102
|
-
module_name = "#{self.name}Extras::#{File.basename(file_name, ".rb").classify}"
|
103
|
-
include module_name.constantize
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
72
|
# returns an instance of a widget defined in the config
|
108
73
|
def instance_by_config(config)
|
109
74
|
widget_class = "Netzke::#{config[:widget_class_name]}".constantize
|
@@ -123,7 +88,6 @@ module Netzke
|
|
123
88
|
nil
|
124
89
|
end
|
125
90
|
|
126
|
-
|
127
91
|
private
|
128
92
|
def set_default_config(default_config)
|
129
93
|
@@config ||= {}
|
@@ -134,9 +98,6 @@ module Netzke
|
|
134
98
|
end
|
135
99
|
extend ClassMethods
|
136
100
|
|
137
|
-
# include extra modules
|
138
|
-
include_extras
|
139
|
-
|
140
101
|
attr_accessor :config, :server_confg, :parent, :logger, :id_name, :permissions
|
141
102
|
attr_reader :pref
|
142
103
|
|
@@ -171,9 +132,14 @@ module Netzke
|
|
171
132
|
# persistent_config["window.size"] => 100
|
172
133
|
# This method is user-aware
|
173
134
|
def persistent_config
|
174
|
-
config_klass = self.class.persistent_config_manager_class
|
175
|
-
|
176
|
-
|
135
|
+
config_klass = config[:persistent_config] && self.class.persistent_config_manager_class
|
136
|
+
if config_klass
|
137
|
+
config_klass.widget_name = id_name # pass to the config class our unique name
|
138
|
+
config_klass
|
139
|
+
else
|
140
|
+
# if we can't use presistent config, all the calls to it will always return nil, and the "="-operation will be ignored
|
141
|
+
{}
|
142
|
+
end
|
177
143
|
end
|
178
144
|
|
179
145
|
def initial_config
|
@@ -272,7 +238,11 @@ module Netzke
|
|
272
238
|
|
273
239
|
# ... and then merge it with NetzkePreferences
|
274
240
|
available_permissions.each do |p|
|
275
|
-
|
241
|
+
# if nothing is stored in persistent_config, store the permission from the config; otherwise leave what's there
|
242
|
+
persistent_config["permissions/#{p}"].nil? && persistent_config["permissions/#{p}"] = @permissions[p.to_sym]
|
243
|
+
|
244
|
+
# what's stored in persistent_config has higher priority, so, if there's something there, use that
|
245
|
+
persistent_permisson = persistent_config["permissions/#{p}"]
|
276
246
|
@permissions[p.to_sym] = persistent_permisson unless persistent_permisson.nil?
|
277
247
|
end
|
278
248
|
end
|
@@ -303,5 +273,30 @@ module Netzke
|
|
303
273
|
{:success => false, :flash => @flash}.to_json
|
304
274
|
end
|
305
275
|
|
276
|
+
def tools
|
277
|
+
persistent_config[:tools] ||= config[:tools] == false ? nil : config[:tools]
|
278
|
+
end
|
279
|
+
|
280
|
+
def bbar
|
281
|
+
persistent_config[:bottom_bar] ||= config[:bbar] == false ? nil : config[:bbar]
|
282
|
+
end
|
283
|
+
|
284
|
+
def tbar
|
285
|
+
persistent_config[:top_bar] ||= config[:tbar] == false ? nil : config[:tbar]
|
286
|
+
end
|
287
|
+
|
288
|
+
def menu
|
289
|
+
persistent_config[:menu] ||= config[:menu] == false ? nil : config[:menu]
|
290
|
+
end
|
291
|
+
|
292
|
+
# some convenience for instances
|
293
|
+
def layout_manager_class
|
294
|
+
self.class.layout_manager_class
|
295
|
+
end
|
296
|
+
|
297
|
+
def persistent_config_manager_class
|
298
|
+
self.class.persistent_config_manager_class
|
299
|
+
end
|
300
|
+
|
306
301
|
end
|
307
302
|
end
|
@@ -17,29 +17,35 @@ module Netzke
|
|
17
17
|
# The config that is sent from the server and is used for instantiating a widget
|
18
18
|
def js_config
|
19
19
|
res = {}
|
20
|
+
|
21
|
+
# Unique id of the widget
|
22
|
+
res.merge!(:id => @id_name)
|
20
23
|
|
21
|
-
#
|
24
|
+
# Recursively include configs of all non-late aggregatees, so that the widget can instantiate them in
|
25
|
+
# in the browser immediately.
|
22
26
|
aggregatees.each_pair do |aggr_name, aggr_config|
|
23
27
|
next if aggr_config[:late_aggregation]
|
24
28
|
res["#{aggr_name}_config".to_sym] = aggregatee_instance(aggr_name.to_sym).js_config
|
25
29
|
end
|
26
30
|
|
27
|
-
#
|
31
|
+
# Interface
|
28
32
|
interface = self.class.interface_points.inject({}){|h,interfacep| h.merge(interfacep => widget_action(interfacep))}
|
29
33
|
res.merge!(:interface => interface)
|
30
34
|
|
35
|
+
# Widget class name
|
31
36
|
res.merge!(:widget_class_name => short_widget_class_name)
|
32
|
-
|
37
|
+
|
38
|
+
# Include
|
33
39
|
res.merge!(js_ext_config)
|
34
|
-
res.merge!(:id => @id_name)
|
35
40
|
|
36
|
-
#
|
37
|
-
res.merge!(:tools => tools)
|
38
|
-
res.merge!(:actions => actions)
|
39
|
-
res.merge!(:
|
40
|
-
res.merge!(:
|
41
|
+
# Actions, toolbars and menus
|
42
|
+
tools && res.merge!(:tools => tools)
|
43
|
+
actions && res.merge!(:actions => actions)
|
44
|
+
tbar && res.merge!(:tbar => tbar)
|
45
|
+
bbar && res.merge!(:bbar => bbar)
|
46
|
+
menu && res.merge!(:menu => menu)
|
41
47
|
|
42
|
-
#
|
48
|
+
# Permissions
|
43
49
|
res.merge!(:permissions => permissions) unless available_permissions.empty?
|
44
50
|
|
45
51
|
res
|
@@ -69,7 +75,7 @@ module Netzke
|
|
69
75
|
|
70
76
|
# instantiating
|
71
77
|
def js_widget_instance
|
72
|
-
%Q{var #{config[:name].to_js} = new Ext.netzke.cache
|
78
|
+
%Q{var #{config[:name].to_js} = new Ext.netzke.cache.#{short_widget_class_name}(#{js_config.to_js});}
|
73
79
|
end
|
74
80
|
|
75
81
|
# rendering
|
@@ -88,9 +94,10 @@ module Netzke
|
|
88
94
|
|
89
95
|
# widget's actions, tools and toolbars that are loaded at the moment of instantiating a widget
|
90
96
|
def actions; nil; end
|
91
|
-
def tools; nil; end
|
92
97
|
def tbar; nil; end
|
93
98
|
def bbar; nil; end
|
99
|
+
def menu; nil; end
|
100
|
+
def tools; nil; end
|
94
101
|
|
95
102
|
# little helpers
|
96
103
|
def this; "this".l; end
|
@@ -150,50 +157,97 @@ module Netzke
|
|
150
157
|
def js_class
|
151
158
|
if js_inheritance
|
152
159
|
<<-JS
|
153
|
-
Ext.netzke.cache
|
154
|
-
constructor
|
155
|
-
|
156
|
-
|
157
|
-
}, #{js_extend_properties.to_js}]))
|
160
|
+
Ext.netzke.cache.#{short_widget_class_name} = function(config){
|
161
|
+
Ext.netzke.cache.#{short_widget_class_name}.superclass.constructor.call(this, config);
|
162
|
+
};
|
163
|
+
Ext.extend(Ext.netzke.cache.#{short_widget_class_name}, Ext.netzke.cache.#{js_base_class.short_widget_class_name}, Ext.applyIf(#{js_extend_properties.to_js}, Ext.widgetMixIn));
|
158
164
|
|
159
165
|
JS
|
160
166
|
else
|
161
167
|
js_add_menus = "this.addMenus(#{js_menus.to_js});" unless js_menus.empty?
|
162
168
|
<<-JS
|
163
|
-
Ext.netzke.cache
|
164
|
-
|
165
|
-
// comment
|
169
|
+
Ext.netzke.cache.#{short_widget_class_name} = function(config){
|
170
|
+
this.beforeConstructor(config);
|
166
171
|
#{js_before_constructor}
|
167
|
-
Ext.netzke.cache
|
168
|
-
this.
|
172
|
+
Ext.netzke.cache.#{short_widget_class_name}.superclass.constructor.call(this, Ext.apply(#{js_default_config.to_js}, config));
|
173
|
+
this.afterConstructor(config);
|
169
174
|
#{js_after_constructor}
|
170
175
|
#{js_add_menus}
|
171
|
-
|
172
|
-
}, #{js_extend_properties.to_js}
|
176
|
+
};
|
177
|
+
Ext.extend(Ext.netzke.cache.#{short_widget_class_name}, #{js_base_class}, Ext.applyIf(#{js_extend_properties.to_js}, Ext.widgetMixIn));
|
173
178
|
JS
|
174
179
|
end
|
175
180
|
end
|
176
181
|
|
182
|
+
#
|
183
|
+
# Include extra code from Ext js library (e.g. examples)
|
184
|
+
#
|
185
|
+
def ext_js_include(*args)
|
186
|
+
included_ext_js = read_inheritable_attribute(:included_ext_js) || []
|
187
|
+
args.each {|f| included_ext_js << f}
|
188
|
+
write_inheritable_attribute(:included_ext_js, included_ext_js)
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Include extra Javascript code. This code will be loaded along with the widget's class and in front of it.
|
193
|
+
#
|
194
|
+
# Example usage:
|
195
|
+
# js_include "File.dirname(__FILE__)/form_panel_extras/javascripts/xdatetime.js",
|
196
|
+
# :ext_examples => ["grid-filtering/menu/EditableItem.js", "grid-filtering/menu/RangeMenu.js"],
|
197
|
+
# "File.dirname(__FILE__)/form_panel_extras/javascripts/xcheckbox.js"
|
198
|
+
#
|
199
|
+
def js_include(*args)
|
200
|
+
included_js = read_inheritable_attribute(:included_js) || []
|
201
|
+
args.each do |inclusion|
|
202
|
+
if inclusion.is_a?(Hash)
|
203
|
+
# we are signalized a non-default file location (e.g. Ext examples)
|
204
|
+
case inclusion.keys.first
|
205
|
+
when :ext_examples
|
206
|
+
location = Netzke::Base.config[:ext_location] + "/examples/"
|
207
|
+
end
|
208
|
+
files = inclusion.values.first
|
209
|
+
else
|
210
|
+
location = ""
|
211
|
+
files = inclusion
|
212
|
+
end
|
213
|
+
|
214
|
+
files = [files] if files.is_a?(String)
|
215
|
+
|
216
|
+
for f in files
|
217
|
+
included_js << location + f
|
218
|
+
end
|
219
|
+
end
|
220
|
+
write_inheritable_attribute(:included_js, included_js)
|
221
|
+
end
|
222
|
+
|
177
223
|
# returns all extra js-code (as string) required by this widget's class
|
178
224
|
def js_included
|
179
225
|
# from extjs - defined in the widget class with ext_js_include
|
180
|
-
extjs_dir = "#{RAILS_ROOT}/public/extjs" # TODO: make extjs location configurable
|
181
|
-
|
182
|
-
res =
|
183
|
-
|
184
|
-
|
185
|
-
end
|
226
|
+
# extjs_dir = "#{RAILS_ROOT}/public/extjs" # TODO: make extjs location configurable
|
227
|
+
# begin
|
228
|
+
# res = super
|
229
|
+
# rescue
|
230
|
+
# raise self.superclass.to_s
|
231
|
+
# end
|
186
232
|
|
187
|
-
res
|
233
|
+
res = ""
|
188
234
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
for file_name in file_list
|
194
|
-
f = File.new(file_name)
|
195
|
-
res << f.read
|
235
|
+
included_js = read_inheritable_attribute(:included_js) || []
|
236
|
+
res << included_js.inject("") do |r, path|
|
237
|
+
f = File.new(path)
|
238
|
+
r << f.read
|
196
239
|
end
|
240
|
+
|
241
|
+
# res << "\n"
|
242
|
+
#
|
243
|
+
# # from <widget_name>_extras/javascripts - all *.js files found there
|
244
|
+
# js_dir = File.join(File.dirname(widget_file), short_widget_class_name.underscore + "_extras", "javascripts")
|
245
|
+
# file_list = Dir.glob("#{js_dir}/*.js")
|
246
|
+
#
|
247
|
+
# for file_name in file_list
|
248
|
+
# f = File.new(file_name)
|
249
|
+
# res << f.read
|
250
|
+
# end
|
197
251
|
|
198
252
|
res
|
199
253
|
end
|
@@ -214,19 +268,19 @@ JS
|
|
214
268
|
end
|
215
269
|
|
216
270
|
# returns all css code require by this widget's class
|
217
|
-
def css_included
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
end
|
271
|
+
# def css_included
|
272
|
+
# res = ""
|
273
|
+
# # from <widget_name>_extras/stylesheets - all *.css files found there
|
274
|
+
# js_dir = File.join(File.dirname(widget_file), short_widget_class_name.underscore + "_extras", "stylesheets")
|
275
|
+
# file_list = Dir.glob("#{js_dir}/*.css")
|
276
|
+
#
|
277
|
+
# for file_name in file_list
|
278
|
+
# f = File.new(file_name)
|
279
|
+
# res << f.read
|
280
|
+
# end
|
281
|
+
#
|
282
|
+
# res
|
283
|
+
# end
|
230
284
|
|
231
285
|
# all JS code needed for this class including the one from the ancestor widget
|
232
286
|
def css_code(cached_dependencies = [])
|
@@ -235,7 +289,7 @@ JS
|
|
235
289
|
# include the base-class javascript if doing JS inheritance
|
236
290
|
res << js_base_class.css_code << "\n" if js_inheritance && !cached_dependencies.include?(js_base_class.short_widget_class_name)
|
237
291
|
|
238
|
-
res << css_included << "\n"
|
292
|
+
# res << css_included << "\n"
|
239
293
|
|
240
294
|
res
|
241
295
|
end
|
data/lib/netzke/core_ext.rb
CHANGED
@@ -12,7 +12,6 @@ class Hash
|
|
12
12
|
|
13
13
|
# First camelizes the keys, then convert the whole hash to JSON
|
14
14
|
def to_js
|
15
|
-
# self.delete_if{ |k,v| v.nil? } # we don't need to explicitely pass null values to javascript
|
16
15
|
self.recursive_delete_if_nil.convert_keys{|k| k.camelize(:lower)}.to_json
|
17
16
|
end
|
18
17
|
|
@@ -21,6 +20,7 @@ class Hash
|
|
21
20
|
self.each_pair{|k,v| self[k] = v.to_s if v.is_a?(Symbol)}
|
22
21
|
end
|
23
22
|
|
23
|
+
# We don't need to pass null values in JSON, they are null by simply being absent
|
24
24
|
def recursive_delete_if_nil
|
25
25
|
self.inject({}) do |h,(k,v)|
|
26
26
|
if !v.nil?
|
data/lib/netzke-core.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
1
3
|
# NetzkeCore
|
2
4
|
require 'netzke/base'
|
5
|
+
|
3
6
|
require 'netzke/action_view_ext'
|
4
7
|
require 'netzke/controller_extensions'
|
5
8
|
require 'netzke/core_ext'
|
@@ -34,6 +37,7 @@ end
|
|
34
37
|
# Make this plugin auto-reloadable for easier development
|
35
38
|
ActiveSupport::Dependencies.load_once_paths.delete(File.join(File.dirname(__FILE__)))
|
36
39
|
|
37
|
-
# Include javascript & styles
|
40
|
+
# Include javascript & styles required by all Netzke widgets.
|
41
|
+
# These files will get loaded at the initial load of the framework (along with Ext).
|
38
42
|
Netzke::Base.config[:javascripts] << "#{File.dirname(__FILE__)}/../javascripts/core.js"
|
39
|
-
Netzke::Base.config[:
|
43
|
+
Netzke::Base.config[:stylesheets] << "#{File.dirname(__FILE__)}/../stylesheets/core.css"
|
data/netzke-core.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{netzke-core}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.9"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Sergei Kozlov"]
|
9
|
-
s.date = %q{2009-03-
|
9
|
+
s.date = %q{2009-03-19}
|
10
10
|
s.description = %q{Build ExtJS/Rails widgets with minimum effort}
|
11
11
|
s.email = %q{sergei@writelesscode.com}
|
12
|
-
s.extra_rdoc_files = ["CHANGELOG", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/base_extras/interface.rb", "lib/netzke/base_extras/js_builder.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/feedback_ghost.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "README.mdown", "tasks/netzke_core_tasks.rake"]
|
13
|
-
s.files = ["CHANGELOG", "
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/base_extras/interface.rb", "lib/netzke/base_extras/js_builder.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/feedback_ghost.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "README.mdown", "tasks/netzke_core_tasks.rake", "TODO"]
|
13
|
+
s.files = ["CHANGELOG", "generators/netzke_core/netzke_core_generator.rb", "generators/netzke_core/templates/create_netzke_layouts.rb", "generators/netzke_core/templates/create_netzke_preferences.rb", "generators/netzke_core/USAGE", "init.rb", "install.rb", "javascripts/core.js", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/action_view_ext.rb", "lib/netzke/base.rb", "lib/netzke/base_extras/interface.rb", "lib/netzke/base_extras/js_builder.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/feedback_ghost.rb", "lib/netzke/routing.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "Manifest", "netzke-core.gemspec", "Rakefile", "README.mdown", "stylesheets/core.css", "tasks/netzke_core_tasks.rake", "test/app_root/app/controllers/application.rb", "test/app_root/config/boot.rb", "test/app_root/config/database.yml", "test/app_root/config/environment.rb", "test/app_root/config/environments/in_memory.rb", "test/app_root/config/environments/mysql.rb", "test/app_root/config/environments/postgresql.rb", "test/app_root/config/environments/sqlite.rb", "test/app_root/config/environments/sqlite3.rb", "test/app_root/config/routes.rb", "test/app_root/db/migrate/20081222035855_create_netzke_preferences.rb", "test/app_root/script/console", "test/core_ext_test.rb", "test/netzke_core_test.rb", "test/netzke_preference_test.rb", "test/test_helper.rb", "TODO", "uninstall.rb"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://writelesscode.com}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Netzke-core", "--main", "README.mdown"]
|
data/test/netzke_core_test.rb
CHANGED
@@ -160,8 +160,8 @@ class NetzkeCoreTest < ActiveSupport::TestCase
|
|
160
160
|
|
161
161
|
test "js inheritance" do
|
162
162
|
widget = JsInheritanceWidget.new
|
163
|
-
assert(widget.js_missing_code.index("Ext.netzke.cache
|
164
|
-
assert(widget.js_missing_code.index("Ext.netzke.cache
|
163
|
+
assert(widget.js_missing_code.index("Ext.netzke.cache.JsInheritanceWidget"))
|
164
|
+
assert(widget.js_missing_code.index("Ext.netzke.cache.Widget"))
|
165
165
|
end
|
166
166
|
# test "multiuser" do
|
167
167
|
# Netzke::Base.current_user = User.new(1)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: netzke-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergei Kozlov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-03-
|
12
|
+
date: 2009-03-19 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -37,9 +37,9 @@ extra_rdoc_files:
|
|
37
37
|
- LICENSE
|
38
38
|
- README.mdown
|
39
39
|
- tasks/netzke_core_tasks.rake
|
40
|
+
- TODO
|
40
41
|
files:
|
41
42
|
- CHANGELOG
|
42
|
-
- css/core.css
|
43
43
|
- generators/netzke_core/netzke_core_generator.rb
|
44
44
|
- generators/netzke_core/templates/create_netzke_layouts.rb
|
45
45
|
- generators/netzke_core/templates/create_netzke_preferences.rb
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- netzke-core.gemspec
|
66
66
|
- Rakefile
|
67
67
|
- README.mdown
|
68
|
+
- stylesheets/core.css
|
68
69
|
- tasks/netzke_core_tasks.rake
|
69
70
|
- test/app_root/app/controllers/application.rb
|
70
71
|
- test/app_root/config/boot.rb
|
@@ -82,6 +83,7 @@ files:
|
|
82
83
|
- test/netzke_core_test.rb
|
83
84
|
- test/netzke_preference_test.rb
|
84
85
|
- test/test_helper.rb
|
86
|
+
- TODO
|
85
87
|
- uninstall.rb
|
86
88
|
has_rdoc: true
|
87
89
|
homepage: http://writelesscode.com
|