apotomo 1.0.5 → 1.1.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/.gitignore +5 -0
  2. data/CHANGES.textile +35 -7
  3. data/Gemfile +0 -2
  4. data/README.rdoc +9 -9
  5. data/apotomo.gemspec +3 -3
  6. data/lib/apotomo.rb +4 -47
  7. data/lib/apotomo/event.rb +2 -0
  8. data/lib/apotomo/event_handler.rb +0 -3
  9. data/lib/apotomo/event_methods.rb +6 -2
  10. data/lib/apotomo/invoke_event_handler.rb +5 -3
  11. data/lib/apotomo/javascript_generator.rb +19 -16
  12. data/lib/apotomo/rails/controller_methods.rb +84 -131
  13. data/lib/apotomo/rails/view_helper.rb +15 -31
  14. data/lib/apotomo/railtie.rb +24 -0
  15. data/lib/apotomo/request_processor.rb +17 -48
  16. data/lib/apotomo/test_case.rb +5 -5
  17. data/lib/apotomo/tree_node.rb +52 -61
  18. data/lib/apotomo/version.rb +1 -1
  19. data/lib/apotomo/widget.rb +70 -146
  20. data/lib/apotomo/widget/javascript_methods.rb +39 -0
  21. data/lib/apotomo/widget_shortcuts.rb +14 -40
  22. data/lib/generators/apotomo/widget_generator.rb +8 -9
  23. data/lib/generators/erb/widget_generator.rb +17 -0
  24. data/lib/generators/haml/widget_generator.rb +20 -0
  25. data/lib/generators/{apotomo/templates → templates}/view.erb +1 -1
  26. data/lib/generators/templates/view.haml +4 -0
  27. data/lib/generators/{apotomo/templates → templates}/widget.rb +1 -1
  28. data/lib/generators/{apotomo/templates → templates}/widget_test.rb +1 -1
  29. data/lib/generators/test_unit/widget_generator.rb +14 -0
  30. data/test/rails/caching_test.rb +10 -17
  31. data/test/rails/controller_methods_test.rb +9 -81
  32. data/test/rails/rails_integration_test.rb +76 -60
  33. data/test/rails/view_helper_test.rb +17 -28
  34. data/test/rails/widget_generator_test.rb +19 -31
  35. data/test/support/test_case_methods.rb +6 -20
  36. data/test/test_helper.rb +15 -25
  37. data/test/unit/event_handler_test.rb +1 -0
  38. data/test/unit/event_methods_test.rb +20 -8
  39. data/test/unit/event_test.rb +5 -0
  40. data/test/unit/javascript_generator_test.rb +19 -19
  41. data/test/unit/render_test.rb +17 -112
  42. data/test/unit/request_processor_test.rb +73 -111
  43. data/test/unit/test_case_test.rb +13 -7
  44. data/test/unit/widget_shortcuts_test.rb +24 -53
  45. data/test/unit/widget_test.rb +76 -36
  46. data/test/widgets/mouse/eat.erb +1 -0
  47. data/test/{fixtures → widgets}/mouse/eating.html.erb +0 -0
  48. data/test/{fixtures → widgets}/mouse/educate.html.erb +0 -0
  49. data/test/{fixtures → widgets}/mouse/feed.html.erb +0 -0
  50. data/test/{fixtures → widgets}/mouse/make_me_squeak.html.erb +0 -0
  51. data/test/{fixtures → widgets}/mouse/posing.html.erb +0 -0
  52. data/test/widgets/mouse/snuggle.html.erb +1 -0
  53. metadata +32 -50
  54. data/lib/apotomo/container_widget.rb +0 -10
  55. data/lib/apotomo/persistence.rb +0 -112
  56. data/lib/apotomo/rails/view_methods.rb +0 -7
  57. data/lib/apotomo/stateful_widget.rb +0 -29
  58. data/lib/apotomo/transition.rb +0 -46
  59. data/lib/generators/apotomo/templates/view.haml +0 -4
  60. data/test/dummy/log/production.log +0 -0
  61. data/test/dummy/log/server.log +0 -0
  62. data/test/dummy/public/javascripts/application.js +0 -2
  63. data/test/dummy/public/javascripts/controls.js +0 -965
  64. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  65. data/test/dummy/public/javascripts/effects.js +0 -1123
  66. data/test/dummy/public/javascripts/prototype.js +0 -6001
  67. data/test/dummy/public/javascripts/rails.js +0 -175
  68. data/test/dummy/script/rails +0 -6
  69. data/test/dummy/tmp/app/cells/mouse_widget.rb +0 -11
  70. data/test/dummy/tmp/app/cells/mouse_widget/snuggle.html.erb +0 -7
  71. data/test/dummy/tmp/app/cells/mouse_widget/squeak.html.erb +0 -7
  72. data/test/dummy/tmp/test/widgets/mouse_widget_test.rb +0 -12
  73. data/test/fixtures/application_widget_tree.rb +0 -2
  74. data/test/fixtures/mouse/snuggle.html.erb +0 -1
  75. data/test/rails/view_methods_test.rb +0 -38
  76. data/test/unit/container_test.rb +0 -21
  77. data/test/unit/invoke_test.rb +0 -126
  78. data/test/unit/persistence_test.rb +0 -201
  79. data/test/unit/stateful_widget_test.rb +0 -58
  80. data/test/unit/test_addressing.rb +0 -110
  81. data/test/unit/test_jump_to_state.rb +0 -89
  82. data/test/unit/test_tab_panel.rb +0 -71
  83. data/test/unit/transition_test.rb +0 -34
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ test/dummy/log/*
5
+ test/dummy/tmp/*
data/CHANGES.textile CHANGED
@@ -1,17 +1,45 @@
1
- h2. 1.0.5
1
+ h2. 1.1
2
2
 
3
+ h3. Changes
4
+ * Widgets now reside in @app/widgets/@ and have the @Widget@ appendix per convention, identical to cells and controllers. This introduces the following changes, illustrated with an imaginary @CommentsWidget@:
5
+ ** @widget(:comments, ...)@ will search and instantiate @CommentsWidget@ (note the missing "Widget").
6
+ ** The @CommentsWidget@ views are searched in @app/widgets/comments/@ (note the missing "_widget").
7
+ * Including Apotomo::Rails::ControllerMethods by hand is optional. The first call to Controller.has_widgets will include the real module.
8
+ * You can now @#render_widget@ in your widget views to render children.
9
+ * @#widget@ now accepts one arg only (the widget prefix). @widget(:comments)@ sets id to @:comments@. We also removed the start state argument.
10
+ * Start states are no longer accepted, you have to explicitely pass the state to #render_widget. That's why #invoke now requires an explicit state as well.
11
+ * The event is no longer added to #options at triggering time.
12
+ * Options passed in #render_widget are no longer merged with #options. They are passed as state-args to reduce complexity.
13
+ * We no longer have @opts and @params but #options and #params from Cell::Base.
14
+ * The params hash is appended to the event in RequestProcessor#process_for. You can now live completely without accessing the global #params.
15
+ * #respond/#update with :selector does not longer prefix the selector with #. It's up to you.
16
+ * Event delegates #[] to #data.
17
+
18
+ h3. Removals
19
+ * Removed #param, it is simply too complex.
20
+ * Removed render :render_children and :invoke options. Use #render_widget in your state/view.
21
+ * Removed render :suppress_js as it was ugly and kills children.
22
+ * Removed #jump_to_state and #last_state.
23
+ * Removed `@cell`, now longer available in state views.
24
+ * Removed #cell, #container and #section widget shortcuts.
25
+ * Removed @rendered_children@ local in views. Use #render_widget.
26
+ * Removed ContainerWidget, nobody needs it.
27
+
3
28
  h3. Bugfixes
4
- * Fixed a bug in Widget.responds_to_event. Thanks to Scott Rainey for urging.
29
+ * Widget.responds_to_event no longer shares its options with multiple widget instances of the same class.
30
+
5
31
 
6
32
  h2. 1.0.4
7
33
 
8
34
  h3. Bugfixes
9
- * Caching states works, again. Thanks to Gudleik Rasch for spotting.
10
- * We cleanly require cells-3.4.x now. Thanks to Ryan Bates who remarked that Apotomo 1.0.x tries to require cells-3.5, which was wrong.
11
-
35
+ * Caching states works, again. Thanks to Gudleik Rasch for spotting.
36
+ * We cleanly require cells-3.4.x now. Thanks to Ryan Bates who remarked that Apotomo 1.0.x tries to require cells-3.5, which was wrong.
37
+
12
38
  h3. Notes
13
- * Removed the usage of state-args. If you want the event instance in your triggered state, use @opts[:event] or upgrade to apotomo-1.1.
14
-
39
+
40
+ * Removed the usage of state-args. If you want the event instance in your triggered state, use @opts[:event] or upgrade to apotomo-1.1.
41
+
42
+
15
43
  h2. 1.0.3
16
44
 
17
45
  h3. Bugfixes
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
-
5
- #gem "rails", :path => "/home/nick/projects/rayls"
data/README.rdoc CHANGED
@@ -42,7 +42,7 @@ Let's wrap that comments block in a widget.
42
42
 
43
43
  Go and generate a widget stub.
44
44
 
45
- $ rails generate apotomo:widget CommentsWidget display write --haml
45
+ $ rails generate apotomo:widget CommentsWidget display write -e haml
46
46
  create app/cells/
47
47
  create app/cells/comments_widget
48
48
  create app/cells/comments_widget.rb
@@ -84,8 +84,8 @@ A widget is like a cell which is like a mini-controller.
84
84
  class CommentsWidget < Apotomo::Widget
85
85
  responds_to_event :submit, :with => :write
86
86
 
87
- def display
88
- @comments = param(:post).comments # the parameter from outside.
87
+ def display(args)
88
+ @comments = args[:post].comments # the parameter from outside.
89
89
  render
90
90
  end
91
91
 
@@ -93,9 +93,9 @@ Having +display+ as the default state when rendering, this method collects comme
93
93
 
94
94
  And look at line 2 - if encountering a <tt>:submit</tt> event we invoke +write+, which is simply another state. How cool is that?
95
95
 
96
- def write
97
- @comment = Comment.new(:post => param(:post))
98
- @comment.update_attributes param(:comment) # like params[].
96
+ def write(evt)
97
+ @comment = Comment.new(:post_id => evt[:post_id])
98
+ @comment.update_attributes evt[:comment] # a bit like params[].
99
99
 
100
100
  update :state => :display
101
101
  end
@@ -160,8 +160,8 @@ Look, +replace+ basically generates
160
160
 
161
161
  If that's not what you want, do
162
162
 
163
- def write
164
- if param(:comment)[:text].explicit?
163
+ def write(evt)
164
+ if evt[:comment][:text].explicit?
165
165
  render :text => 'alert("Hey, you wanted to submit a pervert comment!");'
166
166
  end
167
167
  end
@@ -210,4 +210,4 @@ If you wanna be cool, subscribe to our feed[http://feeds.feedburner.com/Apotomo]
210
210
 
211
211
 
212
212
  == License
213
- Copyright (c) 2007-2010 Nick Sutterer <apotonick@gmail.com> under the MIT License
213
+ Copyright (c) 2007-2011 Nick Sutterer <apotonick@gmail.com> under the MIT License
data/apotomo.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.email = ["apotonick@gmail.com"]
13
13
  s.homepage = "http://github.com/apotonick/apotomo"
14
14
  s.summary = %q{Web components for Rails.}
15
- s.description = %q{Web component framework for Rails providing page widgets that trigger events and know when and how to update themselves with AJAX.}
15
+ s.description = %q{Web component framework for Rails providing widgets that trigger events and know when and how to update themselves with AJAX.}
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -20,8 +20,8 @@ Gem::Specification.new do |s|
20
20
  s.require_paths = ["lib"]
21
21
 
22
22
  s.add_dependency "rails", "~> 3.0"
23
- s.add_dependency "cells", "~> 3.4.0"
24
- s.add_dependency "onfire", "~> 0.1.1"
23
+ s.add_dependency "cells", "~> 3.5.4"
24
+ s.add_dependency "onfire", "~> 0.1.2"
25
25
  s.add_dependency "hooks", "~> 0.1.3"
26
26
 
27
27
  s.add_development_dependency "shoulda"
data/lib/apotomo.rb CHANGED
@@ -1,33 +1,8 @@
1
- # Copyright (c) 2007-2010 Nick Sutterer <apotonick@gmail.com>
2
- #
3
- # The MIT License
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the "Software"), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in
13
- # all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- # THE SOFTWARE.
22
-
23
- require "rails/railtie"
24
- require 'rails/engine'
25
-
26
1
  module Apotomo
27
2
  class << self
28
3
  def js_framework=(js_framework)
29
4
  @js_framework = js_framework
30
- @js_generator = ::Apotomo::JavascriptGenerator.new(js_framework)
5
+ @js_generator = JavascriptGenerator.new(js_framework)
31
6
  end
32
7
 
33
8
  attr_reader :js_generator, :js_framework
@@ -43,31 +18,13 @@ module Apotomo
43
18
  yield self
44
19
  end
45
20
  end
46
-
47
- # Piotr Sarnacki: Railtie :P
48
- class Railtie < Rails::Railtie
49
- rake_tasks do
50
- load "apotomo/apotomo.rake"
51
- end
52
-
53
- # As we are a Railtie only, the routes won't be loaded automatically. Beside that, we want our
54
- # route to be the very first (otherwise #resources might supersede it).
55
- initializer :prepend_apotomo_routes, :after => :add_routing_paths do |app|
56
- app.routes_reloader.paths.unshift(File.dirname(__FILE__) + "/../config/routes.rb")
57
- end
58
- end
59
21
  end
60
22
 
61
-
62
23
  require 'apotomo/widget'
63
- require 'apotomo/stateful_widget'
64
- require 'apotomo/container_widget'
24
+ require 'apotomo/railtie'
65
25
  require 'apotomo/widget_shortcuts'
66
26
  require 'apotomo/rails/controller_methods'
67
-
68
-
69
27
  require 'apotomo/javascript_generator'
70
- Apotomo.js_framework = :jquery ### DISCUSS: move to rails.rb
28
+ require 'apotomo/test_case' if Rails.env == "test"
71
29
 
72
- ### FIXME: only load in test env.
73
- require 'apotomo/test_case' #if defined?("Rails") and Rails.env == "test"
30
+ Apotomo.js_framework = :jquery ### DISCUSS: move to rails.rb
data/lib/apotomo/event.rb CHANGED
@@ -5,5 +5,7 @@ module Apotomo
5
5
  def _dump(depth)
6
6
  raise "You're trying to serialize an instance of Apotomo::Event. Don't do that."
7
7
  end
8
+
9
+ delegate :[], :to => :data
8
10
  end
9
11
  end
@@ -18,6 +18,3 @@ module Apotomo
18
18
 
19
19
  end
20
20
  end
21
-
22
- require 'apotomo/invoke_event_handler'
23
- require 'apotomo/proc_event_handler'
@@ -1,4 +1,4 @@
1
- require 'apotomo/event_handler'
1
+ require 'apotomo/invoke_event_handler'
2
2
 
3
3
  module Apotomo
4
4
  # Introduces event-processing functions into the StatefulWidget.
@@ -77,7 +77,7 @@ module Apotomo
77
77
  # which can be queried in a triggered state.
78
78
  #
79
79
  # def on_drop(event)
80
- # if event.data[:area] == 59
80
+ # if event[:area] == 59
81
81
  def trigger(*args)
82
82
  fire(*args)
83
83
  end
@@ -87,5 +87,9 @@ module Apotomo
87
87
  def local_event_handlers(event)
88
88
  event_table.all_handlers_for(event.type, event.source.name) # we key with widget_id.
89
89
  end
90
+
91
+ def event_for(*args) # defined in Onfire: we want Apotomo::Event.
92
+ Event.new(*args)
93
+ end
90
94
  end
91
95
  end
@@ -1,10 +1,12 @@
1
+ require 'apotomo/event_handler'
2
+
1
3
  module Apotomo
2
4
  class InvokeEventHandler < EventHandler
3
5
  attr_accessor :widget_id, :state
4
6
 
5
- def initialize(opts={})
6
- @widget_id = opts.delete(:widget_id)
7
- @state = opts.delete(:state)
7
+ def initialize(options={})
8
+ @widget_id = options.delete(:widget_id)
9
+ @state = options.delete(:state)
8
10
  end
9
11
 
10
12
  def process_event(event)
@@ -31,27 +31,30 @@ module Apotomo
31
31
  end
32
32
 
33
33
  module Prototype
34
- def prototype; end
35
- def element(id); "$(\"#{id}\")"; end
36
- def xhr(url); "new Ajax.Request(\"#{url}\")"; end
37
- def update(id, markup); element(id) + '.update("'+escape(markup)+'")'; end
38
- def replace(id, markup); element(id) + '.replace("'+escape(markup)+'")'; end
34
+ def prototype; end
35
+ def element(id); "$(\"#{id}\")"; end
36
+ def update(id, markup); element(id) + '.update("'+escape(markup)+'")'; end
37
+ def replace(id, markup); element(id) + '.replace("'+escape(markup)+'")'; end
38
+ def update_id(id, markup); update(id, markup); end
39
+ def replace_id(id, markup); replace(id, markup); end
39
40
  end
40
41
 
41
42
  module Right
42
- def right; end
43
- def element(id); "$(\"#{id}\")"; end
44
- def xhr(url); "new Xhr(\"#{url}\", {evalScripts:true}).send()"; end
45
- def update(id, markup); element(id) + '.update("'+escape(markup)+'")'; end
46
- def replace(id, markup); element(id) + '.replace("'+escape(markup)+'")'; end
43
+ def right; end
44
+ def element(id); "$(\"#{id}\")"; end
45
+ def update(id, markup); element(id) + '.update("'+escape(markup)+'")'; end
46
+ def replace(id, markup); element(id) + '.replace("'+escape(markup)+'")'; end
47
+ def update_id(id, markup); update(id, markup); end
48
+ def replace_id(id, markup); replace(id, markup); end
47
49
  end
48
50
 
49
51
  module Jquery
50
- def jquery; end
51
- def element(id); "$(\"##{id}\")"; end
52
- def xhr(url); "$.ajax({url: \"#{url}\"})"; end
53
- def update(id, markup); element(id) + '.html("'+escape(markup)+'")'; end
54
- def replace(id, markup); element(id) + '.replaceWith("'+escape(markup)+'")'; end
52
+ def jquery; end
53
+ def element(id); "$(\"#{id}\")"; end
54
+ def update(id, markup); element(id) + '.html("'+escape(markup)+'")'; end
55
+ def replace(id, markup); element(id) + '.replaceWith("'+escape(markup)+'")'; end
56
+ def update_id(id, markup); update("##{id}", markup); end
57
+ def replace_id(id, markup); replace("##{id}", markup); end
55
58
  end
56
59
  end
57
- end
60
+ end
@@ -1,151 +1,104 @@
1
1
  require 'apotomo/request_processor'
2
- require 'apotomo/rails/view_methods'
3
2
 
4
- module Apotomo
5
- module Rails
6
- module ControllerMethods
7
- include WidgetShortcuts
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- extend WidgetShortcuts
12
-
13
- class_inheritable_array :has_widgets_blocks
14
- self.has_widgets_blocks = []
15
-
16
- helper ::Apotomo::Rails::ViewMethods
17
-
18
- after_filter :apotomo_freeze
19
- end
20
-
21
- module ClassMethods
22
- # Yields the root widget to setup your widgets for a controller. The block is executed in
23
- # controller _instance_ context, so you may use instance methods and variables of the
24
- # controller.
25
- #
26
- # Example:
27
- # class PostsController < ApplicationController
28
- # has_widgets do |root|
29
- # root << widget(:comments_widget, 'post-comments', :user => @current_user)
30
- # end
31
- def has_widgets(&block)
32
- has_widgets_blocks << block
33
- end
34
- end
35
-
36
- def bound_use_widgets_blocks
37
- session[:bound_use_widgets_blocks] ||= ProcHash.new
38
- end
39
-
40
- def flush_bound_use_widgets_blocks
41
- session[:bound_use_widgets_blocks] = nil
42
- end
43
-
44
- def apotomo_request_processor
45
- return @apotomo_request_processor if @apotomo_request_processor
46
-
47
- # happens once per request:
48
- ### DISCUSS: policy in production?
49
- options = { :flush_widgets => params[:flush_widgets],
50
- :js_framework => Apotomo.js_framework || :prototype,
51
- } ### TODO: process rails options (flush_tree, version)
52
-
53
- @apotomo_request_processor = Apotomo::RequestProcessor.new(self, session, options, self.class.has_widgets_blocks)
54
-
55
- flush_bound_use_widgets_blocks if @apotomo_request_processor.widgets_flushed?
56
-
57
-
58
- @apotomo_request_processor
59
- end
3
+ module Apotomo
4
+ module Rails
5
+ # Lazy-loads Apotomo support into controllers when needed.
6
+ module ControllerMethodsLoader
7
+ def has_widgets(*args, &block)
8
+ include ControllerMethods
9
+ has_widgets(*args, &block)
10
+ end
11
+ end
12
+
13
+
14
+ module ActionViewMethods
15
+ delegate :render_widget, :url_for_event, :to => :controller
16
+ end
17
+
18
+ module ControllerMethods
19
+ include WidgetShortcuts
20
+ extend ActiveSupport::Concern
21
+
22
+ included do
23
+ extend WidgetShortcuts
60
24
 
61
- def apotomo_root
62
- apotomo_request_processor.root
63
- end
25
+ class_inheritable_array :has_widgets_blocks
26
+ self.has_widgets_blocks = []
64
27
 
65
- # Yields the root widget for manipulating the widget tree in a controller action.
66
- # Note that the passed block is executed once per session and not in every request.
28
+ helper ActionViewMethods
29
+ end
30
+
31
+ module ClassMethods
32
+ # Yields the root widget to setup your widgets for a controller. The block is executed in
33
+ # controller _instance_ context, so you may use instance methods and variables of the
34
+ # controller.
67
35
  #
68
36
  # Example:
69
- # def login
70
- # use_widgets do |root|
71
- # root << widget(:login_widget, 'login_box')
37
+ # class PostsController < ApplicationController
38
+ # has_widgets do |root|
39
+ # root << widget(:comments_widget, 'post-comments', :user => @current_user)
72
40
  # end
73
- #
74
- # @box = render_widget 'login_box'
75
- # end
76
- def use_widgets(&block)
77
- root = apotomo_root ### DISCUSS: let RequestProcessor initialize so we get flushed, eventually. maybe add a :before filter for that? or move #use_widgets to RequestProcessor?
78
-
79
- return if bound_use_widgets_blocks.include?(block)
80
-
81
- yield root
82
-
83
- bound_use_widgets_blocks << block # remember the proc.
84
- end
85
-
86
-
87
- def render_widget(widget, options={}, &block)
88
- apotomo_request_processor.render_widget_for(widget, options, &block)
89
- end
90
-
91
- def apotomo_freeze
92
- apotomo_request_processor.freeze!
41
+ def has_widgets(&block)
42
+ has_widgets_blocks << block
93
43
  end
44
+ end
94
45
 
95
- def render_event_response
96
- page_updates = apotomo_request_processor.process_for({:type => params[:type], :source => params[:source]})
97
-
98
- return render_iframe_updates(page_updates) if params[:apotomo_iframe]
99
-
100
- render :text => apotomo_request_processor.render_page_updates(page_updates), :content_type => Mime::JS
101
- end
102
-
103
- # Returns the url to trigger a +type+ event from +:source+, which is a non-optional parameter.
104
- # Additional +options+ will be appended to the query string.
105
- #
106
- # Note that this method will use the framework's internal routing if available (e.g. #url_for in Rails).
107
- #
108
- # Example:
109
- # url_for_event(:paginate, :source => 'mouse', :page => 2)
110
- # #=> http://apotomo.de/mouse/process_event_request?type=paginate&source=mouse&page=2
111
- def url_for_event(type, options)
112
- options.reverse_merge!(:type => type)
113
-
114
- apotomo_event_path(apotomo_request_processor.address_for(options))
115
- end
46
+ def apotomo_request_processor
47
+ return @apotomo_request_processor if @apotomo_request_processor
116
48
 
117
- protected
49
+ # happens once per request:
50
+ options = { :js_framework => Apotomo.js_framework || :prototype } # FIXME: remove :prototype
118
51
 
119
- def parent_controller
120
- self
121
- end
52
+ @apotomo_request_processor = Apotomo::RequestProcessor.new(self, options, self.class.has_widgets_blocks)
53
+ end
54
+
55
+ def apotomo_root
56
+ apotomo_request_processor.root
57
+ end
58
+
59
+ def render_widget(*args, &block)
60
+ apotomo_request_processor.render_widget_for(*args, &block)
61
+ end
62
+
63
+ def render_event_response
64
+ page_updates = apotomo_request_processor.process_for(params)
122
65
 
66
+ return render_iframe_updates(page_updates) if params[:apotomo_iframe]
123
67
 
68
+ render :text => page_updates.join("\n"), :content_type => Mime::JS
69
+ end
70
+
71
+ # Returns the url to trigger a +type+ event from +:source+, which is a non-optional parameter.
72
+ # Additional +options+ will be appended to the query string.
73
+ #
74
+ # Note that this method will use the framework's internal routing if available (e.g. #url_for in Rails).
75
+ #
76
+ # Example:
77
+ # url_for_event(:paginate, :source => 'mouse', :page => 2)
78
+ # #=> http://apotomo.de/mouse/process_event_request?type=paginate&source=mouse&page=2
79
+ def url_for_event(type, options)
80
+ options.reverse_merge!(:type => type)
81
+
82
+ apotomo_event_path(apotomo_request_processor.address_for(options))
83
+ end
84
+
85
+ protected
86
+
87
+ # TODO: remove me! only needed in widget_shortcuts.
88
+ def parent_controller
89
+ self
90
+ end
91
+
92
+
93
+ # Renders the page updates through an iframe. Copied from responds_to_parent,
94
+ # see http://github.com/markcatley/responds_to_parent .
95
+ def render_iframe_updates(page_updates)
96
+ escaped_script = Apotomo::JavascriptGenerator.escape(page_updates.join("\n"))
124
97
 
125
- # Renders the page updates through an iframe. Copied from responds_to_parent,
126
- # see http://github.com/markcatley/responds_to_parent .
127
- def render_iframe_updates(page_updates)
128
- script = apotomo_request_processor.render_page_updates(page_updates)
129
- escaped_script = Apotomo::JavascriptGenerator.escape(script)
130
-
131
- render :text => "<html><body><script type='text/javascript' charset='utf-8'>
98
+ render :text => "<html><body><script type='text/javascript' charset='utf-8'>
132
99
  var loc = document.location;
133
100
  with(window.parent) { setTimeout(function() { window.eval('#{escaped_script}'); window.loc && loc.replace('about:blank'); }, 1) }
134
101
  </script></body></html>", :content_type => 'text/html'
135
- end
136
-
137
- class ProcHash < Array
138
- def id_for_proc(proc)
139
- proc.to_s.split('@').last
140
- end
141
-
142
- def <<(proc)
143
- super(id_for_proc(proc))
144
- end
145
-
146
- def include?(proc)
147
- super(id_for_proc(proc))
148
- end
149
102
  end
150
103
  end
151
104
  end