netzke-core 0.3.1 → 0.4.2
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/.autotest +1 -0
- data/.gitignore +4 -0
- data/CHANGELOG +21 -0
- data/Manifest +9 -11
- data/README.rdoc +12 -0
- data/Rakefile +17 -13
- data/TODO +2 -1
- data/VERSION +1 -0
- data/generators/netzke_core/templates/create_netzke_preferences.rb +1 -1
- data/javascripts/core.js +271 -113
- data/lib/app/controllers/netzke_controller.rb +66 -9
- data/lib/app/models/netzke_preference.rb +39 -32
- data/lib/netzke-core.rb +0 -3
- data/lib/netzke/base.rb +318 -140
- data/lib/netzke/base_js.rb +249 -0
- data/lib/netzke/controller_extensions.rb +29 -40
- data/lib/netzke/core_ext.rb +40 -18
- data/lib/netzke/feedback_ghost.rb +2 -2
- data/netzke-core.gemspec +90 -11
- data/test/unit/core_ext_test.rb +28 -7
- data/test/unit/netzke_core_test.rb +57 -29
- data/test/unit/netzke_preference_test.rb +7 -7
- metadata +35 -38
- data/README.mdown +0 -15
- data/lib/netzke/base_extras/interface.rb +0 -20
- data/lib/netzke/base_extras/js_builder.rb +0 -271
- data/lib/vendor/facets/hash/recursive_merge.rb +0 -28
data/README.mdown
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# netzke-core
|
2
|
-
Create Ext JS + Rails reusable components (widgets) with minimum effort.
|
3
|
-
|
4
|
-
Note that if you would like to modify this code or experiment with it, you may be better off cloning this project into your app's vendor/plugin directory - it will then behave as a Rails plugin.
|
5
|
-
|
6
|
-
# Example
|
7
|
-
See the introduction to the Netzke framework at http://github.com/skozlov/netzke/tree/master
|
8
|
-
|
9
|
-
The tutorials: http://blog.writelesscode.com
|
10
|
-
|
11
|
-
Live-demo: http://netzke-demo.writelesscode.com
|
12
|
-
|
13
|
-
Also see the netzke-basepack project: http://github.com/skozlov/netzke-basepack/tree/master
|
14
|
-
|
15
|
-
Copyright (c) 2008-2009 Sergei Kozlov, released under LGPL 3.0
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Netzke
|
2
|
-
module BaseExtras
|
3
|
-
module Interface
|
4
|
-
def get_widget(params = {})
|
5
|
-
components_cache = (ActiveSupport::JSON.decode(params[:components_cache]) if params[:components_cache]) || []
|
6
|
-
|
7
|
-
js = js_missing_code(components_cache)
|
8
|
-
css = css_missing_code(components_cache)
|
9
|
-
|
10
|
-
css = nil if css.blank?
|
11
|
-
|
12
|
-
# if browser does not have our widget's (and all its dependencies') class and styles, send it over
|
13
|
-
{ :config => js_config,
|
14
|
-
:js => js,
|
15
|
-
:css => css
|
16
|
-
}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,271 +0,0 @@
|
|
1
|
-
module Netzke
|
2
|
-
module BaseExtras
|
3
|
-
#
|
4
|
-
# Module which provides JS-class generation functionality for the widgets ("client-side"). This code is executed only once per widget class, and the results are cached at the server.
|
5
|
-
# Included into Netzke::Base class.
|
6
|
-
# Most of the methods below are meant to be overwritten.
|
7
|
-
#
|
8
|
-
module JsBuilder
|
9
|
-
def self.included(base)
|
10
|
-
base.extend ClassMethods
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
# Instance methods
|
15
|
-
#
|
16
|
-
|
17
|
-
# The config that is sent from the server and is used for instantiating a widget
|
18
|
-
def js_config
|
19
|
-
res = {}
|
20
|
-
|
21
|
-
# Unique id of the widget
|
22
|
-
res.merge!(:id => @id_name)
|
23
|
-
|
24
|
-
# Recursively include configs of all non-late aggregatees, so that the widget can instantiate them in
|
25
|
-
# in the browser immediately.
|
26
|
-
aggregatees.each_pair do |aggr_name, aggr_config|
|
27
|
-
next if aggr_config[:late_aggregation]
|
28
|
-
res["#{aggr_name}_config".to_sym] = aggregatee_instance(aggr_name.to_sym).js_config
|
29
|
-
end
|
30
|
-
|
31
|
-
# Interface
|
32
|
-
interface = self.class.interface_points.inject({}){|h,interfacep| h.merge(interfacep => widget_action(interfacep))}
|
33
|
-
res.merge!(:interface => interface)
|
34
|
-
|
35
|
-
# Widget class name
|
36
|
-
res.merge!(:widget_class_name => short_widget_class_name)
|
37
|
-
|
38
|
-
# Include
|
39
|
-
res.merge!(js_ext_config)
|
40
|
-
|
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)
|
47
|
-
|
48
|
-
# Permissions
|
49
|
-
res.merge!(:permissions => permissions) unless available_permissions.empty?
|
50
|
-
|
51
|
-
res
|
52
|
-
end
|
53
|
-
|
54
|
-
def js_ext_config
|
55
|
-
config[:ext_config] || {}
|
56
|
-
end
|
57
|
-
|
58
|
-
# All the JS-code required by this instance of the widget to be instantiated in the browser.
|
59
|
-
# It includes the JS-class for the widget itself, as well as JS-classes for all widgets' (non-late) aggregatees.
|
60
|
-
def js_missing_code(cached_dependencies = [])
|
61
|
-
dependency_classes.inject("") do |r,k|
|
62
|
-
cached_dependencies.include?(k) ? r : r + "Netzke::#{k}".constantize.js_code(cached_dependencies).strip_js_comments
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def css_missing_code(cached_dependencies = [])
|
67
|
-
dependency_classes.inject("") do |r,k|
|
68
|
-
cached_dependencies.include?(k) ? r : r + "Netzke::#{k}".constantize.css_code(cached_dependencies)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# The following methods are used when a widget is generated stand-alone (as a part of a HTML page)
|
74
|
-
#
|
75
|
-
|
76
|
-
# instantiating
|
77
|
-
def js_widget_instance
|
78
|
-
%Q{var #{config[:name].to_js} = new Ext.netzke.cache.#{short_widget_class_name}(#{js_config.to_js});}
|
79
|
-
end
|
80
|
-
|
81
|
-
# rendering
|
82
|
-
def js_widget_render
|
83
|
-
%Q{#{config[:name].to_js}.render("#{config[:name].to_s.split('_').join('-')}");}
|
84
|
-
end
|
85
|
-
|
86
|
-
# container for rendering
|
87
|
-
def js_widget_html
|
88
|
-
%Q{<div id="#{config[:name].to_s.split('_').join('-')}"></div>}
|
89
|
-
end
|
90
|
-
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
|
95
|
-
# widget's actions, tools and toolbars that are loaded at the moment of instantiating a widget
|
96
|
-
def actions; nil; end
|
97
|
-
def tbar; nil; end
|
98
|
-
def bbar; nil; end
|
99
|
-
def menu; nil; end
|
100
|
-
def tools; nil; end
|
101
|
-
|
102
|
-
# little helpers
|
103
|
-
def this; "this".l; end
|
104
|
-
def null; "null".l; end
|
105
|
-
|
106
|
-
|
107
|
-
# Methods used to create the javascript class (only once per widget class).
|
108
|
-
# The generated code gets cached at the browser, and the widget intstances (at the browser side)
|
109
|
-
# get instantiated from it.
|
110
|
-
# All these methods can be overwritten in case you want to extend the functionality of some pre-built widget
|
111
|
-
# instead of using it as is (using both would cause JS-code duplication)
|
112
|
-
module ClassMethods
|
113
|
-
# the JS (Ext) class that we inherit from on JS-level
|
114
|
-
def js_base_class; "Ext.Panel"; end
|
115
|
-
|
116
|
-
# default config that gets merged with Base#js_config
|
117
|
-
def js_default_config
|
118
|
-
{
|
119
|
-
# :header => user_has_role?(:configurator) ? true : nil,
|
120
|
-
:title => "config.id.humanize()".l,
|
121
|
-
:listeners => js_listeners,
|
122
|
-
:tools => "config.tools".l,
|
123
|
-
:actions => "config.actions".l,
|
124
|
-
:tbar => "config.tbar".l,
|
125
|
-
:bbar => "config.bbar".l,
|
126
|
-
# :items => "config.items".l,
|
127
|
-
# :items => js_items,
|
128
|
-
:height => 400,
|
129
|
-
:width => 800,
|
130
|
-
:border => false,
|
131
|
-
:is_netzke => true # to distinguish a Netzke widget from regular Ext components
|
132
|
-
}
|
133
|
-
end
|
134
|
-
|
135
|
-
# functions and properties that will be used to extend the functionality of (Ext) JS-class specified in js_base_class
|
136
|
-
def js_extend_properties; {}; end
|
137
|
-
|
138
|
-
# code executed before and after the constructor
|
139
|
-
def js_before_constructor; ""; end
|
140
|
-
def js_after_constructor; ""; end
|
141
|
-
|
142
|
-
# widget's listeners
|
143
|
-
def js_listeners; {}; end
|
144
|
-
|
145
|
-
# widget's menus
|
146
|
-
def js_menus; []; end
|
147
|
-
|
148
|
-
# items
|
149
|
-
def js_items; null; end
|
150
|
-
|
151
|
-
# are we using JS inheritance? for now, if js_base_class is a Netzke class - yes
|
152
|
-
def js_inheritance
|
153
|
-
js_base_class.is_a?(Class)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Declaration of widget's class (stored in the cache storage (Ext.netzke.cache) at the client side
|
157
|
-
# to be reused at the moment of widget instantiation)
|
158
|
-
def js_class
|
159
|
-
if js_inheritance
|
160
|
-
<<-JS
|
161
|
-
Ext.netzke.cache.#{short_widget_class_name} = function(config){
|
162
|
-
Ext.netzke.cache.#{short_widget_class_name}.superclass.constructor.call(this, config);
|
163
|
-
};
|
164
|
-
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));
|
165
|
-
|
166
|
-
JS
|
167
|
-
else
|
168
|
-
js_add_menus = "this.addMenus(#{js_menus.to_js});" unless js_menus.empty?
|
169
|
-
<<-JS
|
170
|
-
Ext.netzke.cache.#{short_widget_class_name} = function(config){
|
171
|
-
this.beforeConstructor(config);
|
172
|
-
#{js_before_constructor}
|
173
|
-
Ext.netzke.cache.#{short_widget_class_name}.superclass.constructor.call(this, Ext.apply(#{js_default_config.to_js}, config));
|
174
|
-
this.afterConstructor(config);
|
175
|
-
#{js_after_constructor}
|
176
|
-
#{js_add_menus}
|
177
|
-
};
|
178
|
-
Ext.extend(Ext.netzke.cache.#{short_widget_class_name}, #{js_base_class}, Ext.applyIf(#{js_extend_properties.to_js}, Ext.widgetMixIn));
|
179
|
-
JS
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
#
|
184
|
-
# Include extra code from Ext js library (e.g. examples)
|
185
|
-
#
|
186
|
-
def ext_js_include(*args)
|
187
|
-
included_ext_js = read_inheritable_attribute(:included_ext_js) || []
|
188
|
-
args.each {|f| included_ext_js << f}
|
189
|
-
write_inheritable_attribute(:included_ext_js, included_ext_js)
|
190
|
-
end
|
191
|
-
|
192
|
-
#
|
193
|
-
# Include extra Javascript code. This code will be loaded along with the widget's class and in front of it.
|
194
|
-
#
|
195
|
-
# Example usage:
|
196
|
-
# js_include "File.dirname(__FILE__)/form_panel_extras/javascripts/xdatetime.js",
|
197
|
-
# :ext_examples => ["grid-filtering/menu/EditableItem.js", "grid-filtering/menu/RangeMenu.js"],
|
198
|
-
# "File.dirname(__FILE__)/form_panel_extras/javascripts/xcheckbox.js"
|
199
|
-
#
|
200
|
-
def js_include(*args)
|
201
|
-
included_js = read_inheritable_attribute(:included_js) || []
|
202
|
-
args.each do |inclusion|
|
203
|
-
if inclusion.is_a?(Hash)
|
204
|
-
# we are signalized a non-default file location (e.g. Ext examples)
|
205
|
-
case inclusion.keys.first
|
206
|
-
when :ext_examples
|
207
|
-
location = Netzke::Base.config[:ext_location] + "/examples/"
|
208
|
-
end
|
209
|
-
files = inclusion.values.first
|
210
|
-
else
|
211
|
-
location = ""
|
212
|
-
files = inclusion
|
213
|
-
end
|
214
|
-
|
215
|
-
files = [files] if files.is_a?(String)
|
216
|
-
|
217
|
-
for f in files
|
218
|
-
included_js << location + f
|
219
|
-
end
|
220
|
-
end
|
221
|
-
write_inheritable_attribute(:included_js, included_js)
|
222
|
-
end
|
223
|
-
|
224
|
-
# returns all extra js-code (as string) required by this widget's class
|
225
|
-
def js_included
|
226
|
-
res = ""
|
227
|
-
|
228
|
-
included_js = read_inheritable_attribute(:included_js) || []
|
229
|
-
res << included_js.inject("") do |r, path|
|
230
|
-
f = File.new(path)
|
231
|
-
r << f.read
|
232
|
-
end
|
233
|
-
|
234
|
-
res
|
235
|
-
end
|
236
|
-
|
237
|
-
# all JS code needed for this class, including one from the ancestor widget
|
238
|
-
def js_code(cached_dependencies = [])
|
239
|
-
res = ""
|
240
|
-
|
241
|
-
# include the base-class javascript if doing JS inheritance
|
242
|
-
res << js_base_class.js_code << "\n" if js_inheritance && !cached_dependencies.include?(js_base_class.short_widget_class_name)
|
243
|
-
|
244
|
-
# include static javascripts
|
245
|
-
res << js_included << "\n"
|
246
|
-
|
247
|
-
# our own JS class definition
|
248
|
-
res << js_class
|
249
|
-
res
|
250
|
-
end
|
251
|
-
|
252
|
-
# all JS code needed for this class including the one from the ancestor widget
|
253
|
-
def css_code(cached_dependencies = [])
|
254
|
-
res = ""
|
255
|
-
|
256
|
-
# include the base-class javascript if doing JS inheritance
|
257
|
-
res << js_base_class.css_code << "\n" if js_inheritance && !cached_dependencies.include?(js_base_class.short_widget_class_name)
|
258
|
-
|
259
|
-
# res << css_included << "\n"
|
260
|
-
|
261
|
-
res
|
262
|
-
end
|
263
|
-
|
264
|
-
def this; "this".l; end
|
265
|
-
def null; "null".l; end
|
266
|
-
|
267
|
-
end
|
268
|
-
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
class Hash
|
2
|
-
# Same as Hash#merge but recursively merges sub-hashes.
|
3
|
-
def recursive_merge(other)
|
4
|
-
hash = self.dup
|
5
|
-
other.each do |key, value|
|
6
|
-
myval = self[key]
|
7
|
-
if value.is_a?(Hash) && myval.is_a?(Hash)
|
8
|
-
hash[key] = myval.recursive_merge(value)
|
9
|
-
else
|
10
|
-
hash[key] = value
|
11
|
-
end
|
12
|
-
end
|
13
|
-
hash
|
14
|
-
end
|
15
|
-
|
16
|
-
# Same as Hash#merge! but recursively merges sub-hashes.
|
17
|
-
def recursive_merge!(other)
|
18
|
-
other.each do |key, value|
|
19
|
-
myval = self[key]
|
20
|
-
if value.is_a?(Hash) && myval.is_a?(Hash)
|
21
|
-
myval.recursive_merge!(value)
|
22
|
-
else
|
23
|
-
self[key] = value
|
24
|
-
end
|
25
|
-
end
|
26
|
-
self
|
27
|
-
end
|
28
|
-
end
|