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.
Files changed (76) hide show
  1. data/CHANGELOG.rdoc +19 -0
  2. data/README.markdown +43 -0
  3. data/TODO +1 -5
  4. data/app/controllers/netzke_controller.rb +47 -15
  5. data/config/database.yml +2 -0
  6. data/features/component_loader.feature +6 -1
  7. data/features/composition.feature +2 -0
  8. data/features/js_include.feature +18 -0
  9. data/features/nested_views.feature +9 -0
  10. data/features/persistence.feature +6 -4
  11. data/features/support/paths.rb +3 -0
  12. data/javascripts/core.js +166 -519
  13. data/javascripts/ext.js +355 -0
  14. data/javascripts/touch.js +47 -0
  15. data/lib/netzke/actions.rb +31 -38
  16. data/lib/netzke/base.rb +48 -6
  17. data/lib/netzke/composition.rb +52 -63
  18. data/lib/netzke/configuration.rb +6 -2
  19. data/lib/netzke/core/version.rb +2 -2
  20. data/lib/netzke/core.rb +22 -15
  21. data/lib/netzke/javascript/scopes.rb +39 -0
  22. data/lib/netzke/javascript.rb +145 -114
  23. data/lib/netzke/railz/action_view_ext/ext.rb +59 -0
  24. data/lib/netzke/railz/action_view_ext/touch.rb +50 -0
  25. data/lib/netzke/railz/action_view_ext.rb +86 -0
  26. data/lib/netzke/railz/controller_extensions.rb +33 -0
  27. data/lib/netzke/{rails → railz}/routes.rb +0 -0
  28. data/lib/netzke/railz.rb +3 -0
  29. data/lib/netzke/session.rb +18 -3
  30. data/lib/netzke/state.rb +42 -15
  31. data/lib/netzke/stylesheets.rb +23 -8
  32. data/lib/netzke-core.rb +23 -16
  33. data/netzke-core.gemspec +52 -10
  34. data/spec/component/base_spec.rb +11 -0
  35. data/spec/component/javascript_spec.rb +3 -2
  36. data/spec/component/state_spec.rb +18 -0
  37. data/spec/spec_helper.rb +1 -1
  38. data/test/rails_app/Gemfile +3 -2
  39. data/test/rails_app/Gemfile.lock +73 -71
  40. data/test/rails_app/app/components/component_loader.rb +39 -4
  41. data/test/rails_app/app/components/{custom.css → component_with_custom_css/stylesheets/custom.css} +0 -0
  42. data/test/rails_app/app/components/component_with_custom_css.rb +2 -2
  43. data/test/rails_app/app/components/component_with_js_mixin/javascripts/extra_one.js +2 -0
  44. data/test/rails_app/app/components/component_with_js_mixin/javascripts/extra_two.js +2 -0
  45. data/test/rails_app/app/components/component_with_js_mixin/javascripts/method_set_one.js +6 -0
  46. data/test/rails_app/app/components/component_with_js_mixin/javascripts/method_set_two.js +5 -0
  47. data/test/rails_app/app/components/component_with_js_mixin.rb +8 -0
  48. data/test/rails_app/app/components/component_with_session_persistence.rb +10 -3
  49. data/test/rails_app/app/components/extended_component_with_js_mixin/javascripts/some_method_set.js +5 -0
  50. data/test/rails_app/app/components/extended_component_with_js_mixin.rb +7 -0
  51. data/test/rails_app/app/components/hello_world_component.rb +31 -0
  52. data/test/rails_app/app/components/server_caller.rb +1 -1
  53. data/test/rails_app/app/components/simple_panel.rb +2 -0
  54. data/test/rails_app/app/components/touch/hello_world_component.rb +25 -0
  55. data/test/rails_app/app/components/touch/server_caller.rb +28 -0
  56. data/test/rails_app/app/components/touch/simple_carousel.rb +17 -0
  57. data/test/rails_app/app/controllers/components_controller.rb +6 -1
  58. data/test/rails_app/app/controllers/touch_controller.rb +6 -0
  59. data/test/rails_app/app/helpers/touch_helper.rb +2 -0
  60. data/test/rails_app/app/views/components/panel_with_autoload.html.erb +2 -0
  61. data/test/rails_app/app/views/components/some_tab_panel.html.erb +11 -0
  62. data/test/rails_app/app/views/layouts/nested.html.erb +5 -0
  63. data/test/rails_app/app/views/layouts/touch.html.erb +13 -0
  64. data/test/rails_app/config/initializers/netzke.rb +1 -1
  65. data/test/rails_app/config/locales/en.yml +7 -1
  66. data/test/rails_app/config/routes.rb +10 -1
  67. data/test/rails_app/db/migrate/20110110132720_create_netzke_component_states.rb +20 -0
  68. data/test/rails_app/db/schema.rb +14 -1
  69. data/test/rails_app/spec/controllers/touch_controller_spec.rb +5 -0
  70. data/test/rails_app/spec/helpers/touch_helper_spec.rb +15 -0
  71. data/test/unit/netzke_core_test.rb +2 -6
  72. metadata +53 -11
  73. data/README.rdoc +0 -136
  74. data/lib/netzke/rails/action_view_ext.rb +0 -103
  75. data/lib/netzke/rails/controller_extensions.rb +0 -31
  76. data/test/rails_app/db/migrate/20100905214933_create_netzke_preferences.rb +0 -16
@@ -1,3 +1,4 @@
1
+ require "netzke/javascript/scopes"
1
2
  module Netzke
2
3
  # == Component javascript code
3
4
  # Here's a brief explanation on how a javascript class for a component gets built.
@@ -10,23 +11,34 @@ module Netzke
10
11
  extend ActiveSupport::Concern
11
12
 
12
13
  included do
14
+ include Scopes
15
+
13
16
  class_attribute :js_included_files
14
17
  self.js_included_files = []
15
18
  end
16
19
 
17
20
  module ClassMethods
18
21
 
19
- # The JS (Ext) class that we inherit from on the JS level
22
+ # Used it to specify what JavaScript class this component's JavaScript class will be extending, e.g.:
23
+ #
24
+ # js_base_class "Ext.TabPanel"
25
+ #
26
+ # By default, "Ext.Panel" is assumed.
27
+ #
28
+ # If called without parameters, returns the JS base class declared for the component.
20
29
  def js_base_class(class_name = nil)
21
30
  class_name.nil? ? (read_inheritable_attribute(:js_base_class) || "Ext.Panel") : write_inheritable_attribute(:js_base_class, class_name)
22
31
  end
23
32
 
24
- # Definition of a public JS method, e.g.:
25
- # js_method :on_call_server, <<-JS
26
- # function(){
27
- # this.whatsUp();
33
+ # Use it to define a public method of the component's JavaScript class, e.g.:
34
+ #
35
+ # js_method :do_something, <<-JS
36
+ # function(params){
37
+ # // implementation, maybe dynamically generated
28
38
  # }
29
39
  # JS
40
+ #
41
+ # This will effectively result in definition of a public method called +doSomething+ in the JavaScript class (note the conversion from underscore_name to camelCaseName).
30
42
  def js_method(name, definition = nil)
31
43
  definition = yield.l if block_given?
32
44
  current_js_methods = read_clean_inheritable_hash(:js_methods)
@@ -39,30 +51,35 @@ module Netzke
39
51
  read_clean_inheritable_hash(:js_methods)
40
52
  end
41
53
 
42
- # Definition of JS files which will be dynamically loaded together with this component, e.g.:
43
- # js_include "#{File.dirname(__FILE__)}/my_component/static.js"
44
- # or
54
+ # Use it to specify JS files to be loaded before this component's JS code. Useful when using external extensions required by this component.
55
+ # It may accept one or more symbols or strings. Strings will be interpreted as full paths to included JS file:
56
+ #
45
57
  # js_include "#{File.dirname(__FILE__)}/my_component/one.js","#{File.dirname(__FILE__)}/my_component/two.js"
46
- # This is alternative to defining self.include_js
58
+ #
59
+ # Symbols will be expanded following a convention, e.g.:
60
+ #
61
+ # class MyComponent < Netzke::Base
62
+ # js_include :some_library
63
+ # # ...
64
+ # end
65
+ #
66
+ # This will "include" a JavaScript file +{component_location}/my_component/javascripts/some_library.js+
47
67
  def js_include(*args)
48
- self.js_included_files += args
49
- end
68
+ callr = caller.first
50
69
 
51
- # Definition of a public JS property, e.g.:
52
- # js_property :title, "My Netzke Component"
53
- def js_property(name, value = nil)
54
- name = name.to_sym
55
- if value.nil?
56
- (read_inheritable_attribute(:js_properties) || {})[name]
57
- else
58
- current_js_properties = read_clean_inheritable_hash(:js_properties)
59
- current_js_properties[name] = value
60
- write_inheritable_attribute(:js_properties, current_js_properties)
61
- end
70
+ self.js_included_files += args.map{ |a| a.is_a?(Symbol) ? expand_js_include_path(a, callr) : a }
62
71
  end
63
72
 
64
- # Assignment of multiple public JS properties in a bunch, e.g.:
65
- # js_properties :title => "My Component", :border => true, :html => "Inner HTML"
73
+ # Used to define default properties of the JavaScript class, e.g.:
74
+ #
75
+ # js_properties :collapsible => true, :hide_collapse_tool => true
76
+ #
77
+ # (this will result in the definition of the following properties in the JavaScript class's prototype: +collapsible+ and +hideCollapseTool+ (note the automatic conversion from underscore to camelcase))
78
+ #
79
+ # Also, +js_property+ can be used to define properties one by one.
80
+ #
81
+ # For the complete list of available options refer to the Ext documentation, the "Config Options" section of a the component specified with +js_base_class+.
82
+ # Note, that not all the configuration options can be defined on the prototype of the class. For example, defining +items+ on the prototype won't take any effect, so, +items+ should be passed as a configuration option at the moment of instantiation (see Netzke::Base#configuration and Netzke::Base#default_config).
66
83
  def js_properties(hsh = nil)
67
84
  if hsh.nil?
68
85
  read_clean_inheritable_hash(:js_properties)
@@ -73,49 +90,49 @@ module Netzke
73
90
  end
74
91
  end
75
92
 
76
- # JS properties and methods merged together
77
- def js_extend_properties
78
- @_js_extend_properties ||= js_properties.merge(js_methods)
79
- # res = js_properties.merge(js_methods)
80
- # extracted_actions = extract_actions(res)
81
- # res.merge!(:actions => extracted_actions) if !extracted_actions.empty?
82
- # res
83
- # end
84
- end
85
-
86
- # TODO: the code below needs refactoring and cleaning-up
87
-
88
- # component's menus
89
- # def js_menus; []; end
90
-
91
- # Given class name, e.g. GridPanelLib::Components::RecordFormWindow,
92
- # returns its scope: "Components.RecordFormWindow"
93
- def js_class_name_to_scope(name)
94
- name.split("::")[0..-2].join(".")
95
- end
96
-
97
- # Top level scope which will be used to scope out Netzke classes
98
- def js_default_scope
99
- "Netzke.classes"
100
- end
101
-
102
- # Scope of this component without default scope
103
- # e.g.: GridPanelLib.Components
104
- def js_scope
105
- js_class_name_to_scope(short_component_class_name)
93
+ # Used to define a single JS class property, e.g.:
94
+ # js_property :title, "My Netzke Component"
95
+ def js_property(name, value = nil)
96
+ name = name.to_sym
97
+ if value.nil?
98
+ (read_inheritable_attribute(:js_properties) || {})[name]
99
+ else
100
+ current_js_properties = read_clean_inheritable_hash(:js_properties)
101
+ current_js_properties[name] = value
102
+ write_inheritable_attribute(:js_properties, current_js_properties)
103
+ end
106
104
  end
107
105
 
108
- # Returns the scope of this component
109
- # e.g. "Netzke.classes.GridPanelLib"
110
- def js_full_scope
111
- js_scope.empty? ? js_default_scope : [js_default_scope, js_scope].join(".")
106
+ # Use it to "mixin" JavaScript objects defined in a separate file.
107
+ #
108
+ # You do not _have_ to use +js_method+ or +js_properties+ if those methods or properties are not supposed to be changed _dynamically_ (by means of configuring the component on the class level). Instead, you may "mixin" a JavaScript object defined in the JavaScript file named following a certain convention. This way static JavaScript code will rest in a corresponding .js file, not in the Ruby class. E.g.:
109
+ #
110
+ # class MyComponent < Netzke::Base
111
+ # js_mixin :some_functionality
112
+ # #...
113
+ # end
114
+ #
115
+ # This will "mixin" a JavaScript object defined in a file called +{component_location}/my_component/javascripts/some_functionality.js+, which way contain something like this:
116
+ #
117
+ # {
118
+ # someProperty: 100,
119
+ #
120
+ # someMethod: function(params){
121
+ # // ...
122
+ # }
123
+ # }
124
+ #
125
+ # Also accepts a string, which will be interpreted as a full path to the file (useful for sharing mixins between classes).
126
+ def js_mixin(*args)
127
+ current_mixins = read_clean_inheritable_array(:js_mixins) || []
128
+ callr = caller.first
129
+ args.each{ |a| current_mixins << (a.is_a?(Symbol) ? File.read(expand_js_include_path(a, callr)) : File.read(a))}
130
+ write_inheritable_attribute(:js_mixins, current_mixins)
112
131
  end
113
132
 
114
- # Returns the full name of the JavaScript class, including the scopes *and* the common scope, which is
115
- # Netzke.classes.
116
- # E.g.: "Netzke.classes.Netzke.GridPanelLib.RecordFormWindow"
117
- def js_full_class_name
118
- [js_full_scope, short_component_class_name.split("::").last].join(".")
133
+ # Returns all objects to be mixed in (as array of strings)
134
+ def js_mixins
135
+ read_clean_inheritable_array(:js_mixins) || []
119
136
  end
120
137
 
121
138
  # Builds this component's xtype
@@ -124,48 +141,22 @@ module Netzke
124
141
  name.gsub("::", "").downcase
125
142
  end
126
143
 
127
- # are we using JS inheritance? for now, if js_base_class is a Netzke class - yes
128
- def extends_netzke_component?
129
- superclass != Netzke::Base
130
- end
131
-
132
- # Declaration of component's class (stored in the cache storage (Ext.netzke.cache) at the client side
133
- # to be reused at the moment of component instantiation)
134
- def js_class(cached = [])
144
+ # Component's JavaScript class declaration.
145
+ # It gets stored in the JS class cache storage (Netzke.classes) at the client side to be reused at the moment of component instantiation.
146
+ def js_class
135
147
  res = []
136
148
  # Defining the scope if it isn't known yet
137
149
  res << %{Ext.ns("#{js_full_scope}");} unless js_full_scope == js_default_scope
138
150
 
139
151
  res << (extends_netzke_component? ? js_class_declaration_extending_component : js_class_declaration_new_component)
140
152
 
141
- res << %(Ext.reg("#{js_xtype}", #{js_full_class_name});)
153
+ res << %(Netzke.reg("#{js_xtype}", #{js_full_class_name});)
142
154
 
143
155
  res.join("\n")
144
156
  end
145
157
 
146
158
 
147
- def js_extra_code
148
- ""
149
- end
150
-
151
- # Generates declaration of the JS class as direct extension of a Ext component
152
- def js_class_declaration_new_component
153
- %(#{js_full_class_name} = Ext.extend(#{js_base_class}, Ext.apply(Netzke.componentMixin(#{js_base_class}),
154
- #{js_extend_properties.to_nifty_json}));)
155
- end
156
-
157
- # Generates declaration of the JS class as extension of another Netzke component
158
- def js_class_declaration_extending_component
159
- base_class = superclass.js_full_class_name
160
-
161
- # Do we specify our own extend properties?
162
- # If so, include them, if not - don't re-include those from the parent.
163
- js_extend_properties.empty? ? \
164
- %{#{js_full_class_name} = #{base_class};} :
165
- %{#{js_full_class_name} = Ext.extend(#{base_class}, #{js_extend_properties.to_nifty_json});}
166
- end
167
-
168
- # Returns all extra JavaScript-code (as string) required by this component's class
159
+ # Returns all included JavaScript files as a string
169
160
  def js_included
170
161
  res = ""
171
162
 
@@ -179,34 +170,73 @@ module Netzke
179
170
  res
180
171
  end
181
172
 
173
+ # DEPRECATED. Returns an array of included files. Made to be overridden. +js_include+ is preferred way.
182
174
  def include_js
183
175
  []
184
176
  end
185
177
 
186
178
  # JavaScript code needed for this particulaer class. Includes external JS code and the JS class definition for self.
187
- def js_code(cached = [])
188
- [js_included, js_class(cached)].join("\n")
179
+ def js_code
180
+ [js_included, js_class].join("\n")
189
181
  end
190
182
 
191
- # Little helper
192
- def this; "this".l; end
183
+ protected
184
+
185
+ # Little helper
186
+ def this; "this".l; end
187
+
188
+ # Little helper. E.g.:
189
+ #
190
+ # js_property :load_mask, null
191
+ def null; "null".l; end
192
+
193
+ # JS properties and methods merged together
194
+ def js_extend_properties
195
+ @js_extend_properties ||= js_properties.merge(js_methods)
196
+ end
197
+
198
+ # Generates declaration of the JS class as direct extension of a Ext component
199
+ def js_class_declaration_new_component
200
+ mixins = js_mixins.empty? ? "" : %(#{js_mixins.join(", \n")}, )
201
+ %(#{js_full_class_name} = function(config){
202
+ Netzke.aliasMethodChain(this, "initComponent", "netzke");
203
+ #{js_full_class_name}.superclass.constructor.call(this, config);
204
+ };
205
+
206
+ Ext.extend(#{js_full_class_name}, #{js_base_class}, Netzke.chainApply(Netzke.componentMixin, #{mixins}
207
+ #{js_extend_properties.to_nifty_json}));)
208
+ end
209
+
210
+ # Generates declaration of the JS class as extension of another Netzke component
211
+ def js_class_declaration_extending_component
212
+ base_class = superclass.js_full_class_name
193
213
 
194
- # Little helper
195
- def null; "null".l; end
214
+ mixins = js_mixins.empty? ? "" : %(#{js_mixins.join(", \n")}, )
215
+
216
+ %{#{js_full_class_name} = Ext.extend(#{base_class}, Netzke.chainApply(#{mixins}#{js_extend_properties.to_nifty_json}));}
217
+ end
218
+
219
+ def expand_js_include_path(sym, callr) # :nodoc:
220
+ %Q(#{callr.split(".rb:").first}/javascripts/#{sym}.js)
221
+ end
222
+
223
+ def extends_netzke_component? # :nodoc:
224
+ superclass != Netzke::Base
225
+ end
196
226
 
197
227
  end
198
228
 
199
229
  module InstanceMethods
200
- # Config that is used for instantiating the component in javascript
230
+ # Config that, after being converted to JSON, is used for instantiating the component in JavaScript.
201
231
  def js_config
202
232
  res = {}
203
233
 
204
234
  # Unique id of the component
205
- res.merge!(:id => global_id)
235
+ res[:id] = global_id
206
236
 
207
- # Non-late components
237
+ # Non-lazy-loaded components
208
238
  comp_hash = {}
209
- non_late_components.each_pair do |comp_name, comp_config|
239
+ eager_loaded_components.each_pair do |comp_name, comp_config|
210
240
  comp_instance = component_instance(comp_name.to_sym)
211
241
  comp_instance.before_load
212
242
  comp_hash[comp_name] = comp_instance.js_config
@@ -216,9 +246,9 @@ module Netzke
216
246
  # +items+, generally, only contain a subset of all non-lazy-loaded children.
217
247
  res[:components] = comp_hash unless comp_hash.empty?
218
248
 
219
- # Api (besides the default "deliver_component" - JavaScript side already knows about it)
249
+ # Endpoints (besides the default "deliver_component" - JavaScript side already knows about it)
220
250
  endpoints = self.class.registered_endpoints - [:deliver_component]
221
- res.merge!(:endpoints => endpoints) unless endpoints.empty?
251
+ res[:endpoints] = endpoints unless endpoints.empty?
222
252
 
223
253
  # Inform the JavaScript side if persistent_config is enabled
224
254
  # res[:persistent_config] = persistence_enabled?
@@ -234,26 +264,27 @@ module Netzke
234
264
  res.merge!(config[:ext_config])
235
265
  end
236
266
 
267
+ # Items (nested Ext/Netzke components)
237
268
  res[:items] = items unless items.blank?
238
269
 
239
270
  res
240
271
  end
241
-
242
- # Helper to access config[:ext_config] - DEPRECATED
243
- def ext_config
244
- ::ActiveSupport::Deprecation.warn("Using ext_config is deprecated. All config options must be specified at the same level in the hash.", caller)
245
- config[:ext_config] || {}
246
- end
247
272
 
248
273
  # All the JS-code required by this instance of the component to be instantiated in the browser.
249
274
  # It includes JS-classes for the parents, non-lazy-loaded child components, and itself.
250
275
  def js_missing_code(cached = [])
251
276
  code = dependency_classes.inject("") do |r,k|
252
- cached.include?(k.to_s) ? r : r + k.js_code(cached)#.strip_js_comments
277
+ cached.include?(k.js_xtype) ? r : r + k.js_code#.strip_js_comments
253
278
  end
254
279
  code.blank? ? nil : code
255
280
  end
256
281
 
282
+ # DEPRECATED. Helper to access config[:ext_config].
283
+ def ext_config
284
+ ::ActiveSupport::Deprecation.warn("Using ext_config is deprecated. All config options must be specified at the same level in the hash.", caller)
285
+ config[:ext_config] || {}
286
+ end
287
+
257
288
  end
258
289
  end
259
- end
290
+ end
@@ -0,0 +1,59 @@
1
+ module Netzke
2
+ module Railz
3
+ module ActionViewExt
4
+ # Implementation of Ext-specific helpers
5
+ module Ext #:nodoc:
6
+
7
+ protected
8
+
9
+ def netzke_ext_css_include(theme)
10
+ # ExtJS base
11
+ res = stylesheet_link_tag("/extjs/resources/css/ext-all")
12
+
13
+ # ExtJS theming
14
+ res << "\n" << stylesheet_link_tag("/extjs/resources/css/xtheme-#{theme}") unless theme.to_sym == :default
15
+
16
+ # Netzke-related (dynamically generated by NetzkeController)
17
+ res << "\n" << stylesheet_link_tag("/netzke/ext")
18
+
19
+ res << "\n" << stylesheet_link_tag(Netzke::Core.external_ext_css)
20
+
21
+ res
22
+ end
23
+
24
+ def netzke_ext_js_include
25
+ res = []
26
+
27
+ # ExtJS
28
+ res << (ENV['RAILS_ENV'] == 'development' ? javascript_include_tag("/extjs/adapter/ext/ext-base-debug", "/extjs/ext-all-debug") : javascript_include_tag("/extjs/adapter/ext/ext-base", "/extjs/ext-all"))
29
+
30
+ # Netzke (dynamically generated)
31
+ res << javascript_include_tag("/netzke/ext")
32
+
33
+ res.join("\n")
34
+ end
35
+
36
+ def netzke_ext_js
37
+ res = []
38
+ res << content_for(:netzke_js_classes)
39
+ res << "\n"
40
+
41
+ res << "Ext.onReady(function(){"
42
+ res << content_for(:netzke_on_ready)
43
+ res << "});"
44
+
45
+ javascript_tag res.join("\n")
46
+ end
47
+
48
+ # (Experimental) Embeds a "pure" (non-Netzke) Ext component into the view, e.g.:
49
+ # <%= ext :my_panel, :xtype => :panel, :html => "Simple Panel"
50
+ def ext(name, config = {}) #:doc:
51
+ comp = Netzke::ExtComponent.new(name, config)
52
+ content_for :netzke_on_ready, raw("#{comp.js_component_render}")
53
+ raw(comp.js_component_html)
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,50 @@
1
+ module Netzke
2
+ module Railz
3
+ module ActionViewExt
4
+ # Implementation of Touch-specific helpers
5
+ module Touch #:nodoc:
6
+
7
+ protected
8
+
9
+ def netzke_touch_css_include(theme)
10
+ # theme is not used for now
11
+
12
+ res = stylesheet_link_tag("/sencha-touch/resources/css/sencha-touch")
13
+
14
+ # Netzke-related (dynamically generated by NetzkeController)
15
+ res << "\n" << stylesheet_link_tag("/netzke/touch")
16
+
17
+ res
18
+ end
19
+
20
+ def netzke_touch_js
21
+ res = []
22
+ res << content_for(:netzke_js_classes)
23
+ res << "\n"
24
+
25
+ res << "Ext.setup({"
26
+ res << "onReady: function(){"
27
+ res << content_for(:netzke_on_ready)
28
+ res << "}"
29
+ res << "});"
30
+
31
+ javascript_tag res.join("\n")
32
+ end
33
+
34
+
35
+ def netzke_touch_js_include
36
+ res = []
37
+
38
+ # ExtJS
39
+ res << (ENV['RAILS_ENV'] == 'development' ? javascript_include_tag("/sencha-touch/sencha-touch-debug.js") : javascript_include_tag("/sencha-touch/sencha-touch"))
40
+
41
+ # Netzke (dynamically generated)
42
+ res << javascript_include_tag("/netzke/touch")
43
+
44
+ res.join("\n")
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end