netzke-core 0.6.4 → 0.6.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +19 -0
- data/README.markdown +43 -0
- data/TODO +1 -5
- data/app/controllers/netzke_controller.rb +47 -15
- data/config/database.yml +2 -0
- data/features/component_loader.feature +6 -1
- data/features/composition.feature +2 -0
- data/features/js_include.feature +18 -0
- data/features/nested_views.feature +9 -0
- data/features/persistence.feature +6 -4
- data/features/support/paths.rb +3 -0
- data/javascripts/core.js +166 -519
- data/javascripts/ext.js +355 -0
- data/javascripts/touch.js +47 -0
- data/lib/netzke/actions.rb +31 -38
- data/lib/netzke/base.rb +48 -6
- data/lib/netzke/composition.rb +52 -63
- data/lib/netzke/configuration.rb +6 -2
- data/lib/netzke/core/version.rb +2 -2
- data/lib/netzke/core.rb +22 -15
- data/lib/netzke/javascript/scopes.rb +39 -0
- data/lib/netzke/javascript.rb +145 -114
- data/lib/netzke/railz/action_view_ext/ext.rb +59 -0
- data/lib/netzke/railz/action_view_ext/touch.rb +50 -0
- data/lib/netzke/railz/action_view_ext.rb +86 -0
- data/lib/netzke/railz/controller_extensions.rb +33 -0
- data/lib/netzke/{rails → railz}/routes.rb +0 -0
- data/lib/netzke/railz.rb +3 -0
- data/lib/netzke/session.rb +18 -3
- data/lib/netzke/state.rb +42 -15
- data/lib/netzke/stylesheets.rb +23 -8
- data/lib/netzke-core.rb +23 -16
- data/netzke-core.gemspec +52 -10
- data/spec/component/base_spec.rb +11 -0
- data/spec/component/javascript_spec.rb +3 -2
- data/spec/component/state_spec.rb +18 -0
- data/spec/spec_helper.rb +1 -1
- data/test/rails_app/Gemfile +3 -2
- data/test/rails_app/Gemfile.lock +73 -71
- data/test/rails_app/app/components/component_loader.rb +39 -4
- data/test/rails_app/app/components/{custom.css → component_with_custom_css/stylesheets/custom.css} +0 -0
- data/test/rails_app/app/components/component_with_custom_css.rb +2 -2
- data/test/rails_app/app/components/component_with_js_mixin/javascripts/extra_one.js +2 -0
- data/test/rails_app/app/components/component_with_js_mixin/javascripts/extra_two.js +2 -0
- data/test/rails_app/app/components/component_with_js_mixin/javascripts/method_set_one.js +6 -0
- data/test/rails_app/app/components/component_with_js_mixin/javascripts/method_set_two.js +5 -0
- data/test/rails_app/app/components/component_with_js_mixin.rb +8 -0
- data/test/rails_app/app/components/component_with_session_persistence.rb +10 -3
- data/test/rails_app/app/components/extended_component_with_js_mixin/javascripts/some_method_set.js +5 -0
- data/test/rails_app/app/components/extended_component_with_js_mixin.rb +7 -0
- data/test/rails_app/app/components/hello_world_component.rb +31 -0
- data/test/rails_app/app/components/server_caller.rb +1 -1
- data/test/rails_app/app/components/simple_panel.rb +2 -0
- data/test/rails_app/app/components/touch/hello_world_component.rb +25 -0
- data/test/rails_app/app/components/touch/server_caller.rb +28 -0
- data/test/rails_app/app/components/touch/simple_carousel.rb +17 -0
- data/test/rails_app/app/controllers/components_controller.rb +6 -1
- data/test/rails_app/app/controllers/touch_controller.rb +6 -0
- data/test/rails_app/app/helpers/touch_helper.rb +2 -0
- data/test/rails_app/app/views/components/panel_with_autoload.html.erb +2 -0
- data/test/rails_app/app/views/components/some_tab_panel.html.erb +11 -0
- data/test/rails_app/app/views/layouts/nested.html.erb +5 -0
- data/test/rails_app/app/views/layouts/touch.html.erb +13 -0
- data/test/rails_app/config/initializers/netzke.rb +1 -1
- data/test/rails_app/config/locales/en.yml +7 -1
- data/test/rails_app/config/routes.rb +10 -1
- data/test/rails_app/db/migrate/20110110132720_create_netzke_component_states.rb +20 -0
- data/test/rails_app/db/schema.rb +14 -1
- data/test/rails_app/spec/controllers/touch_controller_spec.rb +5 -0
- data/test/rails_app/spec/helpers/touch_helper_spec.rb +15 -0
- data/test/unit/netzke_core_test.rb +2 -6
- metadata +53 -11
- data/README.rdoc +0 -136
- data/lib/netzke/rails/action_view_ext.rb +0 -103
- data/lib/netzke/rails/controller_extensions.rb +0 -31
- data/test/rails_app/db/migrate/20100905214933_create_netzke_preferences.rb +0 -16
data/lib/netzke/base.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext'
|
2
|
+
require 'active_support/memoizable'
|
2
3
|
require 'netzke/core_ext'
|
3
4
|
require 'netzke/javascript'
|
4
5
|
require 'netzke/stylesheets'
|
@@ -47,20 +48,29 @@ module Netzke
|
|
47
48
|
attr_reader :global_id
|
48
49
|
|
49
50
|
class << self
|
51
|
+
extend ActiveSupport::Memoizable
|
52
|
+
|
50
53
|
# Component's short class name, e.g.:
|
51
54
|
# "Netzke::Module::SomeComponent" => "Module::SomeComponent"
|
52
55
|
def short_component_class_name
|
53
56
|
self.name.sub(/^Netzke::/, "")
|
54
57
|
end
|
55
58
|
|
56
|
-
# Component's class, given its name
|
59
|
+
# Component's class, given its name.
|
60
|
+
# Note: this method will be memoized if Rails.configuration.cache_classes is true.
|
57
61
|
def constantize_class_name(class_name)
|
58
|
-
"#{class_name}".constantize
|
62
|
+
"#{class_name}".constantize
|
63
|
+
rescue NameError
|
64
|
+
begin
|
65
|
+
"Netzke::#{class_name}".constantize
|
66
|
+
rescue NameError
|
67
|
+
nil
|
68
|
+
end
|
59
69
|
end
|
60
70
|
|
61
71
|
# Instance of component by config
|
62
72
|
def instance_by_config(config)
|
63
|
-
constantize_class_name(config[:class_name]).new(config)
|
73
|
+
(config[:klass] || constantize_class_name(config[:class_name])).new(config)
|
64
74
|
end
|
65
75
|
|
66
76
|
# All ancestor classes in the Netzke class hierarchy (i.e. up to Netzke::Base)
|
@@ -78,6 +88,27 @@ module Netzke
|
|
78
88
|
# We don't want here any values from the superclass (which is the consequence of using inheritable attributes).
|
79
89
|
res == self.superclass.read_inheritable_attribute(attr_name) ? {} : res
|
80
90
|
end
|
91
|
+
|
92
|
+
# Same as +read_inheritable_attribute+ returning a hash, but returns empty hash when it's equal to superclass's
|
93
|
+
def read_clean_inheritable_array(attr_name)
|
94
|
+
res = read_inheritable_attribute(attr_name) || []
|
95
|
+
# We don't want here any values from the superclass (which is the consequence of using inheritable attributes).
|
96
|
+
res == self.superclass.read_inheritable_attribute(attr_name) ? [] : res
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def self.total_instances
|
102
|
+
@@instances || 0
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.reset_total_instances
|
106
|
+
@@instances = 0
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.increase_total_instances
|
110
|
+
@@instances ||= 0
|
111
|
+
@@instances += 1
|
81
112
|
end
|
82
113
|
|
83
114
|
# Instantiates a component instance. A parent can optionally be provided.
|
@@ -92,6 +123,8 @@ module Netzke
|
|
92
123
|
# initialize @components and @items
|
93
124
|
normalize_components_in_items
|
94
125
|
# auto_collect_actions_from_config_and_js_properties
|
126
|
+
|
127
|
+
self.class.increase_total_instances
|
95
128
|
end
|
96
129
|
|
97
130
|
# Proxy to the equally named class method
|
@@ -108,11 +141,20 @@ module Netzke
|
|
108
141
|
def before_load
|
109
142
|
end
|
110
143
|
|
144
|
+
def clean_up
|
145
|
+
component_session.clear
|
146
|
+
components.keys.each { |k| component_instance(k).clean_up }
|
147
|
+
end
|
148
|
+
|
149
|
+
def i18n_id
|
150
|
+
self.class.name.split("::").map{|c| c.underscore}.join(".")
|
151
|
+
end
|
152
|
+
|
111
153
|
private
|
112
154
|
|
113
155
|
def logger #:nodoc:
|
114
|
-
if defined?(Rails)
|
115
|
-
Rails.logger
|
156
|
+
if defined?(::Rails)
|
157
|
+
::Rails.logger
|
116
158
|
else
|
117
159
|
require 'logger'
|
118
160
|
Logger.new(STDOUT)
|
@@ -126,4 +168,4 @@ module Netzke
|
|
126
168
|
end
|
127
169
|
|
128
170
|
end
|
129
|
-
end
|
171
|
+
end
|
data/lib/netzke/composition.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# require 'active_support/core_ext/class/inheritable_attributes'
|
2
2
|
|
3
3
|
module Netzke
|
4
|
+
# You can define a nested components by calling the class method +component+:
|
5
|
+
#
|
6
|
+
# component :users, :data_class => "GridPanel", :model => "User"
|
7
|
+
#
|
8
|
+
# The method also accepts a block in case you want access to the component's instance:
|
9
|
+
#
|
10
|
+
# component :books do
|
11
|
+
# {:data_class => "Book", :title => build_title}
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# To override a component, define a method {component_name}_component, e.g.:
|
15
|
+
#
|
16
|
+
# def books_component
|
17
|
+
# super.merge(:title => "Modified Title")
|
18
|
+
# end
|
4
19
|
module Composition
|
5
20
|
extend ActiveSupport::Concern
|
6
21
|
|
@@ -14,8 +29,8 @@ module Netzke
|
|
14
29
|
# * <tt>:id</tt> - reference to the component
|
15
30
|
# * <tt>:container</tt> - Ext id of the container where in which the component will be rendered
|
16
31
|
endpoint :deliver_component do |params|
|
17
|
-
cache = params[:cache].
|
18
|
-
component_name = params
|
32
|
+
cache = params[:cache].split(",") # array of cached xtypes
|
33
|
+
component_name = params[:name].underscore.to_sym
|
19
34
|
component = components[component_name] && component_instance(component_name)
|
20
35
|
|
21
36
|
if component
|
@@ -38,15 +53,6 @@ module Netzke
|
|
38
53
|
module ClassMethods
|
39
54
|
|
40
55
|
# Defines a nested component.
|
41
|
-
# For example:
|
42
|
-
#
|
43
|
-
# component :users, :data_class => "GridPanel", :model => "User"
|
44
|
-
#
|
45
|
-
# It can also accept a block (receiving as parameter the eventual definition from super class):
|
46
|
-
#
|
47
|
-
# component :books do |orig|
|
48
|
-
# {:data_class => "Book", :title => orig[:title] + ", extended"}
|
49
|
-
# end
|
50
56
|
def component(name, config = {}, &block)
|
51
57
|
register_component(name)
|
52
58
|
config = config.dup
|
@@ -69,6 +75,7 @@ module Netzke
|
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
78
|
+
# DEPRECATED in favor of Symbol#component
|
72
79
|
# Component's js config used when embedding components as Container's items
|
73
80
|
# (see some_composite.rb for an example)
|
74
81
|
def js_component(name, config = {})
|
@@ -91,11 +98,13 @@ module Netzke
|
|
91
98
|
end
|
92
99
|
|
93
100
|
module InstanceMethods
|
101
|
+
extend ActiveSupport::Memoizable
|
94
102
|
|
95
|
-
def items
|
103
|
+
def items #:nodoc:
|
96
104
|
@items_with_normalized_components
|
97
105
|
end
|
98
106
|
|
107
|
+
# DEPRECATED in favor of Base.component
|
99
108
|
def initial_components
|
100
109
|
{}
|
101
110
|
end
|
@@ -105,14 +114,16 @@ module Netzke
|
|
105
114
|
@components ||= self.class.registered_components.inject({}){ |res, name| res.merge(name.to_sym => send(COMPONENT_METHOD_NAME % name)) }
|
106
115
|
end
|
107
116
|
|
108
|
-
def
|
117
|
+
def eager_loaded_components
|
109
118
|
components.reject{|k,v| v[:lazy_loading]}
|
110
119
|
end
|
111
120
|
|
121
|
+
# DEPRECATED
|
112
122
|
def add_component(aggr)
|
113
123
|
components.merge!(aggr)
|
114
124
|
end
|
115
125
|
|
126
|
+
# DEPRECATED
|
116
127
|
def remove_component(aggr)
|
117
128
|
if config[:persistent_config]
|
118
129
|
persistence_manager_class.delete_all_for_component("#{global_id}__#{aggr}")
|
@@ -120,51 +131,41 @@ module Netzke
|
|
120
131
|
components[aggr] = nil
|
121
132
|
end
|
122
133
|
|
123
|
-
#
|
124
|
-
def initial_late_components
|
125
|
-
{}
|
126
|
-
end
|
127
|
-
|
128
|
-
def add_late_component(aggr)
|
129
|
-
components.merge!(aggr.merge(:lazy_loading => true))
|
130
|
-
end
|
131
|
-
|
132
|
-
# called when the method_missing tries to processes a non-existing component
|
134
|
+
# Called when the method_missing tries to processes a non-existing component
|
133
135
|
def component_missing(aggr)
|
134
136
|
flash :error => "Unknown component #{aggr} for component #{name}"
|
135
137
|
{:feedback => @flash}.to_nifty_json
|
136
138
|
end
|
137
139
|
|
138
|
-
#
|
140
|
+
# Recursively instantiates a component based on its "path": e.g. if we have component :component1 which in its turn has component :component2, the path to the latter would be "component1__component2"
|
139
141
|
def component_instance(name, strong_config = {})
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
composite = component_class.new(conf, composite) # params: config, parent
|
157
|
-
# composite.weak_children_config = weak_children_config
|
158
|
-
# composite.strong_children_config = strong_children_config
|
159
|
-
end
|
160
|
-
composite
|
142
|
+
composite = self
|
143
|
+
name.to_s.split('__').each do |cmp|
|
144
|
+
cmp = cmp.to_sym
|
145
|
+
|
146
|
+
component_config = composite.components[cmp]
|
147
|
+
raise ArgumentError, "No child component '#{cmp}' defined for component '#{composite.global_id}'" if component_config.nil?
|
148
|
+
|
149
|
+
component_class_name = component_config[:class_name]
|
150
|
+
raise ArgumentError, "No class_name specified for component #{cmp} of #{composite.global_id}" if component_class_name.nil?
|
151
|
+
|
152
|
+
component_class = constantize_class_name(component_class_name)
|
153
|
+
raise ArgumentError, "Unknown constant #{component_class_name}" if component_class.nil?
|
154
|
+
|
155
|
+
instance_config = weak_children_config.merge(component_config).merge(strong_config).merge(:name => cmp)
|
156
|
+
|
157
|
+
composite = component_class.new(instance_config, composite) # params: config, parent
|
161
158
|
end
|
159
|
+
composite
|
162
160
|
end
|
163
161
|
|
162
|
+
memoize :component_instance # for performance
|
163
|
+
|
164
|
+
# All components that we depend on (used to render all necessary JavaScript and stylesheets)
|
164
165
|
def dependency_classes
|
165
166
|
res = []
|
166
167
|
|
167
|
-
|
168
|
+
eager_loaded_components.keys.each do |aggr|
|
168
169
|
res += component_instance(aggr).dependency_classes
|
169
170
|
end
|
170
171
|
|
@@ -174,19 +175,7 @@ module Netzke
|
|
174
175
|
res.uniq
|
175
176
|
end
|
176
177
|
|
177
|
-
|
178
|
-
# def dependencies
|
179
|
-
# @dependencies ||= begin
|
180
|
-
# non_late_components_component_classes = non_late_components.values.map{|v| v[:class_name]}
|
181
|
-
# (initial_dependencies + non_late_components_component_classes << self.class.short_component_class_name).uniq
|
182
|
-
# end
|
183
|
-
# end
|
184
|
-
|
185
|
-
# override this method if you need some extra dependencies, which are not the components
|
186
|
-
def initial_dependencies
|
187
|
-
[]
|
188
|
-
end
|
189
|
-
|
178
|
+
# DEPRECATED
|
190
179
|
def js_component(*args)
|
191
180
|
self.class.js_component(*args)
|
192
181
|
end
|
@@ -233,9 +222,9 @@ module Netzke
|
|
233
222
|
end
|
234
223
|
end
|
235
224
|
|
236
|
-
|
225
|
+
protected
|
237
226
|
|
238
|
-
def normalize_components(items)
|
227
|
+
def normalize_components(items) #:nodoc:
|
239
228
|
@component_index ||= 0
|
240
229
|
@items_with_normalized_components = items.each_with_index.map do |item, i|
|
241
230
|
if is_component_config?(item)
|
@@ -251,11 +240,11 @@ module Netzke
|
|
251
240
|
end
|
252
241
|
end
|
253
242
|
|
254
|
-
def normalize_components_in_items
|
243
|
+
def normalize_components_in_items #:nodoc:
|
255
244
|
normalize_components(config[:items]) if config[:items]
|
256
245
|
end
|
257
246
|
|
258
|
-
def is_component_config?(c)
|
247
|
+
def is_component_config?(c) #:nodoc:
|
259
248
|
!!(c.is_a?(Hash) && c[:class_name])
|
260
249
|
end
|
261
250
|
end
|
data/lib/netzke/configuration.rb
CHANGED
@@ -60,6 +60,10 @@ module Netzke
|
|
60
60
|
@strong_config ||= session_config.merge(weak_final_options).merge(strong_parent_config)
|
61
61
|
end
|
62
62
|
|
63
|
+
def configuration
|
64
|
+
final_config
|
65
|
+
end
|
66
|
+
|
63
67
|
# Resulting config that takes into account all possible ways to configure a component. *Read only*.
|
64
68
|
# Translates into something like this:
|
65
69
|
#
|
@@ -72,7 +76,7 @@ module Netzke
|
|
72
76
|
# Moved out to a separate method in order to provide for easy caching.
|
73
77
|
# *Do not override this method*, use +Base.config+ instead.
|
74
78
|
def config
|
75
|
-
@config ||=
|
79
|
+
@config ||= configuration
|
76
80
|
end
|
77
81
|
|
78
82
|
def flat_config(key = nil)
|
@@ -131,4 +135,4 @@ module Netzke
|
|
131
135
|
|
132
136
|
end
|
133
137
|
end
|
134
|
-
end
|
138
|
+
end
|
data/lib/netzke/core/version.rb
CHANGED
data/lib/netzke/core.rb
CHANGED
@@ -15,41 +15,48 @@ module Netzke
|
|
15
15
|
# The following configuration options are available:
|
16
16
|
# * ext_location - absolute path to your Ext code root
|
17
17
|
# * icons_uri - relative URI to the icons
|
18
|
-
# * javascript_on_main_page (true/false, defaults to false) - if you want the JS classes to be inserted into the code of the page,
|
19
|
-
# rather than into netzke.js (setting to true can be handy for debugging)
|
20
18
|
module Core
|
21
19
|
extend Session
|
22
20
|
extend Masquerading
|
23
21
|
|
22
|
+
# Ext or Touch
|
23
|
+
mattr_accessor :platform
|
24
|
+
@@platform = :ext
|
25
|
+
|
24
26
|
# set in Netzke::ControllerExtensions
|
25
27
|
mattr_accessor :controller
|
26
|
-
|
28
|
+
|
27
29
|
# set in Netzke::ControllerExtensions
|
28
30
|
mattr_accessor :session
|
29
31
|
@@session = {}
|
30
32
|
|
31
|
-
mattr_accessor :
|
32
|
-
@@
|
33
|
+
mattr_accessor :ext_javascripts
|
34
|
+
@@ext_javascripts = []
|
35
|
+
|
36
|
+
mattr_accessor :ext_stylesheets
|
37
|
+
@@ext_stylesheets = []
|
33
38
|
|
34
|
-
mattr_accessor :
|
35
|
-
@@
|
39
|
+
mattr_accessor :touch_javascripts
|
40
|
+
@@touch_javascripts = []
|
36
41
|
|
37
|
-
mattr_accessor :
|
38
|
-
@@
|
42
|
+
mattr_accessor :touch_stylesheets
|
43
|
+
@@touch_stylesheets = []
|
44
|
+
|
45
|
+
# Stylesheets that cannot be loaded dynamically along with the rest of the component, e.g. due to that relative paths are used in them
|
46
|
+
mattr_accessor :external_ext_css
|
47
|
+
@@external_ext_css = []
|
39
48
|
|
40
49
|
# Set in the Engine after_initialize callback
|
41
|
-
mattr_accessor :ext_location
|
50
|
+
mattr_accessor :ext_location # TODO: rename to ext_path
|
51
|
+
mattr_accessor :touch_location # TODO: rename to touch_path
|
42
52
|
mattr_accessor :with_icons
|
43
53
|
|
44
54
|
mattr_accessor :icons_uri
|
45
55
|
@@icons_uri = "/images/icons"
|
46
56
|
|
47
|
-
mattr_accessor :javascript_on_main_page
|
48
|
-
@@javascript_on_main_page = true
|
49
|
-
|
50
57
|
mattr_accessor :persistence_manager
|
51
58
|
@@persistence_manager = "NetzkeComponentState"
|
52
|
-
|
59
|
+
|
53
60
|
# Set in the Engine after_initialize callback
|
54
61
|
mattr_accessor :persistence_manager_class
|
55
62
|
|
@@ -61,4 +68,4 @@ module Netzke
|
|
61
68
|
Netzke::Core.session[:netzke_components].try(:clear)
|
62
69
|
end
|
63
70
|
end
|
64
|
-
end
|
71
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Javascript
|
3
|
+
module Scopes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
# Given class name, e.g. GridPanelLib::Components::RecordFormWindow,
|
8
|
+
# returns its scope: "Components.RecordFormWindow"
|
9
|
+
def js_class_name_to_scope(name)
|
10
|
+
name.split("::")[0..-2].join(".")
|
11
|
+
end
|
12
|
+
|
13
|
+
# Top level scope which will be used to scope out Netzke classes
|
14
|
+
def js_default_scope
|
15
|
+
"Netzke.classes"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Scope of this component without default scope
|
19
|
+
# e.g.: GridPanelLib.Components
|
20
|
+
def js_scope
|
21
|
+
js_class_name_to_scope(short_component_class_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the scope of this component
|
25
|
+
# e.g. "Netzke.classes.GridPanelLib"
|
26
|
+
def js_full_scope
|
27
|
+
js_scope.empty? ? js_default_scope : [js_default_scope, js_scope].join(".")
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the full name of the JavaScript class, including the scopes *and* the common scope, which is
|
31
|
+
# Netzke.classes.
|
32
|
+
# E.g.: "Netzke.classes.Netzke.GridPanelLib.RecordFormWindow"
|
33
|
+
def js_full_class_name
|
34
|
+
[js_full_scope, short_component_class_name.split("::").last].join(".")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|