apotomo 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.textile CHANGED
@@ -1,3 +1,16 @@
1
+ h2. 1.1.1
2
+
3
+ h3. Additions
4
+ * You can now attach event handlers to other widgets simply by using the @:passing@ option: @responds_to_event :click, :passing => :root@.
5
+ * If you want to debug events, just include the (WIP) @apotomo/debugging@ file and watch your server output on the console.
6
+
7
+ h3. Changes
8
+ * @Widget.responds_to_event@ is inheritable now.
9
+ * The generator now places namespaced widgets into the correct sub-directories.
10
+
11
+ h3. Removals
12
+ * Removed the alias @Widget.respond_to_event@, please use @Widget.responds_to_event@.
13
+
1
14
  h2. 1.1
2
15
 
3
16
  h3. Changes
data/apotomo.gemspec CHANGED
@@ -20,9 +20,10 @@ 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.5.4"
24
- s.add_dependency "onfire", "~> 0.1.2"
23
+ s.add_dependency "cells", "~> 3.5.6"
24
+ s.add_dependency "onfire", "~> 0.2.0"
25
25
  s.add_dependency "hooks", "~> 0.1.3"
26
26
 
27
27
  s.add_development_dependency "shoulda"
28
+ s.add_development_dependency "slim"
28
29
  end
@@ -0,0 +1,9 @@
1
+ require "onfire/debugging"
2
+
3
+ Apotomo::Event.class_eval do
4
+ include Onfire::Event::Debugging
5
+
6
+ debug do |widget, event|
7
+ puts "#{widget.name}: #{event}"
8
+ end
9
+ end
data/lib/apotomo/event.rb CHANGED
@@ -2,8 +2,8 @@ module Apotomo
2
2
  # Events are created by Apotomo in #fire. They bubble up from their source to root and trigger
3
3
  # event handlers.
4
4
  class Event < Onfire::Event
5
- def _dump(depth)
6
- raise "You're trying to serialize an instance of Apotomo::Event. Don't do that."
5
+ def to_s
6
+ "<Event :#{type} source=#{source.widget_id}>"
7
7
  end
8
8
 
9
9
  delegate :[], :to => :data
@@ -36,7 +36,7 @@ module Apotomo
36
36
  # Example:
37
37
  # class PostsController < ApplicationController
38
38
  # has_widgets do |root|
39
- # root << widget(:comments_widget, 'post-comments', :user => @current_user)
39
+ # root << widget(:comments, :user => current_user)
40
40
  # end
41
41
  def has_widgets(&block)
42
42
  has_widgets_blocks << block
@@ -1,3 +1,3 @@
1
1
  module Apotomo
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.1'
3
3
  end
@@ -0,0 +1,122 @@
1
+ require 'apotomo/invoke_event_handler'
2
+
3
+ module Apotomo
4
+ # Event-related methods and onfire bridge for Widget.
5
+ module EventMethods
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ after_initialize :add_class_event_handlers
10
+
11
+ inheritable_attr :responds_to_event_options
12
+ self.responds_to_event_options = []
13
+ end
14
+
15
+
16
+ attr_writer :page_updates
17
+
18
+ def page_updates
19
+ @page_updates ||= []
20
+ end
21
+
22
+
23
+ module ClassMethods
24
+ # Instructs the widget to look out for +type+ events. If an appropriate event starts from or passes the widget,
25
+ # the defined trigger state is executed.
26
+ #
27
+ # class MouseWidget < Apotomo::Widget
28
+ # responds_to_event :squeak
29
+ #
30
+ # def squeak(evt)
31
+ # update
32
+ # end
33
+ #
34
+ # Calls #squeak when a <tt>:squeak</tt> event is encountered.
35
+ #
36
+ # == Options
37
+ # Any option except the event +type+ is optional.
38
+ #
39
+ # [<tt>:with => state</tt>]
40
+ # executes +state+, defaults to +type+.
41
+ # responds_to_event :squeak, :with => :chirp
42
+ # will invoke the +#chirp+ state method.
43
+ # [<tt>:on => id</tt>]
44
+ # execute the trigger state on another widget.
45
+ # responds_to_event :squeak, :on => :cat
46
+ # will invoke the +#squeak+ state on the +:cat+ widget.
47
+ # [<tt>:from => id</tt>]
48
+ # executes the state <em>only</em> if the event origins from +id+.
49
+ # responds_to_event :squeak, :from => :kid
50
+ # will invoke the +#squeak+ state if +:kid+ triggered <em>and</em> if +:kid+ is a decendent of the current widget.
51
+ # [<tt>:passing => id</tt>]
52
+ # attaches the observer to another widget. Useful if you want to catch bubbling events in +root+.
53
+ # responds_to_event :squeak, :passing => :root
54
+ # will invoke the state on the current widget if the event passes +:root+ (which is highly probable).
55
+ #
56
+ # == Inheritance
57
+ # Note that the observers are inherited. This allows deriving a widget class without having to redefine the
58
+ # responds_to_event blocks.
59
+ def responds_to_event(*options)
60
+ # DISCUSS: this is a Hooks.declarative_attr candidate, too.
61
+ return set_global_event_handler(*options) if options.dup.extract_options![:passing]
62
+
63
+ responds_to_event_options << options
64
+ end
65
+
66
+ private
67
+ # Adds an event handler to a non-local widget. Called in #responds_to_event when the
68
+ # :passing option is set.
69
+ #
70
+ # This usually leads to something like
71
+ # root.respond_to_event :click, :on => 'jerry'
72
+ def set_global_event_handler(type, options)
73
+ after_add do
74
+ opts = options.reverse_merge(:on => widget_id)
75
+ root.find_widget(opts.delete(:passing)).respond_to_event(type, opts)
76
+ end
77
+ end
78
+ end
79
+
80
+ # Same as #responds_to_event but executed on the widget instance, only.
81
+ def respond_to_event(type, options={})
82
+ options = options.reverse_merge(:once => true,
83
+ :with => type,
84
+ :on => self.name)
85
+
86
+ handler = InvokeEventHandler.new(:widget_id => options[:on], :state => options[:with])
87
+
88
+ return if options[:once] and event_table.all_handlers_for(type, options[:from]).include?(handler)
89
+
90
+ on(type, :call => handler, :from => options[:from])
91
+ end
92
+
93
+ # Fire an event of +type+ and let it bubble up. You may add arbitrary payload data to the event.
94
+ #
95
+ # Example:
96
+ #
97
+ # trigger(:dropped, :area => 59)
98
+ #
99
+ # which can be queried in a triggered state.
100
+ #
101
+ # def on_drop(event)
102
+ # if event[:area] == 59
103
+ def trigger(*args)
104
+ fire(*args)
105
+ end
106
+
107
+ # Get all handlers from self for the passed event (overriding Onfire#local_event_handlers).
108
+ def handlers_for_event(event)
109
+ event_table.all_handlers_for(event.type, event.source.name) # we key with widget_id.
110
+ end
111
+
112
+ protected
113
+ def event_for(*args) # defined in Onfire: we want Apotomo::Event.
114
+ Event.new(*args)
115
+ end
116
+
117
+ # Actually executes the #responds_to_event calls from the class on the instance.
118
+ def add_class_event_handlers(*)
119
+ self.class.responds_to_event_options.each { |options| respond_to_event(*options) }
120
+ end
121
+ end
122
+ end
@@ -5,28 +5,32 @@ module Apotomo
5
5
  Apotomo.js_generator.escape(script)
6
6
  end
7
7
 
8
- # Wraps the rendered content in a replace statement targeted at your +Apotomo.js_framework+ setting.
9
- # Use +:selector+ to change the selector.
8
+ # Wraps the rendered content in a replace statement according to your +Apotomo.js_framework+ setting.
9
+ # Received the same options as #render plus an optional +selector+ to change the selector.
10
10
  #
11
- # Example:
11
+ # Example (with <tt>Apotomo.js_framework = :jquery</tt>):
12
12
  #
13
- # Assuming you set
14
- # Apotomo.js_framework = :jquery
13
+ # def hungry
14
+ # replace
15
15
  #
16
- # and call replace in a state
16
+ # will render the current state's view and wrap it like
17
17
  #
18
- # replace :view => :squeak, :selector => "div#mouse"
19
- # #=> "$(\"div#mouse\").replaceWith(\"<div id=\\\"mum\\\">squeak!<\\/div>\")"
18
+ # "$(\"#mouse\").replaceWith(\"<div id=\\\"mouse\\\">hungry!<\\/div>\")"
19
+ #
20
+ # You may pass a selector and pass options to render here, as well.
21
+ #
22
+ # replace "#jerry h1", :view => :squeak
23
+ # #=> "$(\"#jerry h1\").replaceWith(\"<div id=\\\"mouse\\\">squeak!<\\/div>\")"
20
24
  def replace(*args)
21
25
  wrap_in_javascript_for(:replace, *args)
22
26
  end
23
27
 
24
- # Same as replace except that the content is wrapped in an update statement.
28
+ # Same as #replace except that the content is wrapped in an update statement.
25
29
  #
26
30
  # Example for +:jquery+:
27
31
  #
28
- # update :view => :squeak
29
- # #=> "$(\"mum\").html(\"<div id=\\\"mum\\\">squeak!<\\/div>\")"
32
+ # update :view => :peek
33
+ # #=> "$(\"#mouse\").html(\"looking...")"
30
34
  def update(*args)
31
35
  wrap_in_javascript_for(:update, *args)
32
36
  end
File without changes
@@ -2,13 +2,14 @@ require 'cells'
2
2
  require 'onfire'
3
3
  require 'hooks'
4
4
 
5
- require 'apotomo/tree_node'
5
+
6
6
  require 'apotomo/event'
7
- require 'apotomo/event_methods'
8
7
  require 'apotomo/widget_shortcuts'
9
8
  require 'apotomo/rails/view_helper'
10
9
  require 'apotomo/rails/controller_methods' # FIXME.
11
10
 
11
+ require 'apotomo/widget/tree_node'
12
+ require 'apotomo/widget/event_methods'
12
13
  require 'apotomo/widget/javascript_methods'
13
14
 
14
15
 
@@ -108,22 +109,21 @@ module Apotomo
108
109
  render_state(state)
109
110
  end
110
111
 
111
- # Render the view for the current state. Usually called at the end of a state method.
112
+ # Renders and returns a view for the current state. That's why it is usually called at the end of
113
+ # a state method.
112
114
  #
113
115
  # ==== Options
114
- # * <tt>:view</tt> - Specifies the name of the view file to render. Defaults to the current state name.
115
- # * <tt>:template_format</tt> - Allows using a format different to <tt>:html</tt>.
116
- # * <tt>:layout</tt> - If set to a valid filename inside your cell's view_paths, the current state view will be rendered inside the layout (as known from controller actions). Layouts should reside in <tt>app/cells/layouts</tt>.
117
- # * see Cell::Base#render for additional options
116
+ # * <tt>:view</tt> - Renders +view+. Defaults to the current state name.
117
+ # * <tt>:state</tt> - Invokes the +state+ method and returns whatever the state returns.
118
+ # * See http://rdoc.info/gems/cells/3.5.4/Cell/Rails#render-instance_method
118
119
  #
119
120
  # Example:
120
- # class MouseWidget < Apotomo::StatefulWidget
121
+ # class MouseWidget < Apotomo::Widget
121
122
  # def eat
122
- # # ... do something
123
123
  # render
124
124
  # end
125
125
  #
126
- # will just render the view <tt>eat.haml</tt>.
126
+ # render the view <tt>eat.haml</tt>.
127
127
  #
128
128
  # render :js => "alert('SQUEAK!');"
129
129
  #
@@ -141,7 +141,7 @@ module Apotomo
141
141
  end
142
142
 
143
143
 
144
- # Returns the widget named <tt>widget_id</tt> as long as it is below self or self itself.
144
+ # Returns the widget named +widget_id+ if it's a descendent or self.
145
145
  def find_widget(widget_id)
146
146
  find {|node| node.name.to_s == widget_id.to_s}
147
147
  end
@@ -2,17 +2,27 @@ require 'generators/cells/base'
2
2
 
3
3
  module Apotomo
4
4
  module Generators
5
- class WidgetGenerator < ::Cells::Generators::Base
6
- source_root File.expand_path(File.join(File.dirname(__FILE__), '../templates'))
7
-
8
- def create_cell_file
9
- template 'widget.rb', File.join('app/widgets', class_path, "#{file_name}_widget.rb")
5
+ module BasePathMethods
6
+ private
7
+ def base_path
8
+ File.join('app/widgets', class_path, file_name)
10
9
  end
10
+ end
11
+
12
+ class WidgetGenerator < ::Cells::Generators::Base
13
+ include BasePathMethods
11
14
 
12
- check_class_collision :suffix => "Widget"
15
+ source_root File.expand_path('../../templates', __FILE__)
13
16
 
14
17
  hook_for(:template_engine)
15
18
  hook_for(:test_framework) # TODO: implement rspec-apotomo.
19
+
20
+ check_class_collision :suffix => "Widget"
21
+
22
+
23
+ def create_cell_file
24
+ template 'widget.rb', "#{base_path}_widget.rb"
25
+ end
16
26
  end
17
27
  end
18
28
  end
@@ -1,17 +1,11 @@
1
- require 'generators/cells/base'
1
+ require 'generators/erb/cell_generator'
2
+ require 'generators/apotomo/widget_generator'
2
3
 
3
4
  module Erb
4
5
  module Generators
5
- class WidgetGenerator < ::Cells::Generators::Base
6
+ class WidgetGenerator < CellGenerator
7
+ include ::Apotomo::Generators::BasePathMethods
6
8
  source_root File.expand_path('../../templates', __FILE__)
7
-
8
- def create_views
9
- for state in actions do
10
- @state = state
11
- @path = File.join('app/widgets', file_name, "#{state}.html.erb")
12
- template "view.erb", @path
13
- end
14
- end
15
9
  end
16
10
  end
17
11
  end
@@ -1,20 +1,11 @@
1
- require 'generators/cells/base'
1
+ require 'generators/haml/cell_generator'
2
+ require 'generators/apotomo/widget_generator'
2
3
 
3
4
  module Haml
4
5
  module Generators
5
- class WidgetGenerator < ::Cells::Generators::Base
6
+ class WidgetGenerator < CellGenerator
7
+ include ::Apotomo::Generators::BasePathMethods
6
8
  source_root File.expand_path('../../templates', __FILE__)
7
-
8
- def create_views
9
- for state in actions do
10
- @state = state
11
- @path = File.join('app/widgets', file_name, "#{state}.html.haml")
12
-
13
- template "view.haml", @path
14
- end
15
- end
16
9
  end
17
10
  end
18
11
  end
19
-
20
-
@@ -0,0 +1,11 @@
1
+ require 'generators/slim/cell_generator'
2
+ require 'generators/apotomo/widget_generator'
3
+
4
+ module Slim
5
+ module Generators
6
+ class WidgetGenerator < CellGenerator
7
+ include ::Apotomo::Generators::BasePathMethods
8
+ source_root File.expand_path('../../templates', __FILE__)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ h1
2
+ <%= class_name %>Widget#<%= @state %>
3
+ p
4
+ Find me in <%= @path %>
@@ -34,6 +34,18 @@ class WidgetGeneratorTest < Rails::Generators::TestCase
34
34
  assert_file "app/widgets/gerbil/squeak.html.haml", %r(app/widgets/gerbil/squeak\.html\.haml)
35
35
  assert_file "test/widgets/gerbil_widget_test.rb"
36
36
  end
37
+
38
+ should "create slim assets with -e slim" do
39
+ run_generator %w(Gerbil squeak snuggle -e slim -t test_unit)
40
+
41
+ assert_file "app/widgets/gerbil_widget.rb", /class GerbilWidget < Apotomo::Widget/
42
+ assert_file "app/widgets/gerbil_widget.rb", /def snuggle/
43
+ assert_file "app/widgets/gerbil_widget.rb", /def squeak/
44
+ assert_file "app/widgets/gerbil/snuggle.html.slim", %r(app/widgets/gerbil/snuggle\.html\.slim)
45
+ assert_file "app/widgets/gerbil/snuggle.html.slim", %r(p)
46
+ assert_file "app/widgets/gerbil/squeak.html.slim", %r(app/widgets/gerbil/squeak\.html\.slim)
47
+ assert_file "test/widgets/gerbil_widget_test.rb"
48
+ end
37
49
  end
38
50
  end
39
51
  end
@@ -3,6 +3,11 @@ require 'test_helper'
3
3
  class EventMethodsTest < Test::Unit::TestCase
4
4
  include Apotomo::TestCaseMethods::TestController
5
5
 
6
+ def handler(id, state)
7
+ Apotomo::InvokeEventHandler.new(:widget_id => id, :state => state)
8
+ end
9
+
10
+
6
11
  context "#respond_to_event and #fire" do
7
12
  setup do
8
13
  mum_and_kid!
@@ -70,28 +75,56 @@ class EventMethodsTest < Test::Unit::TestCase
70
75
  assert_equal [{:volume => 9}], @mum.list
71
76
  end
72
77
 
78
+
79
+ context "#responds_to_event with :passing" do
80
+ setup do
81
+ class AdolescentMouse < MouseWidget
82
+ responds_to_event :squeak, :passing => :root
83
+ end
84
+
85
+ @root = mouse_mock(:root)
86
+ end
87
+
88
+ should "add handlers to root when called with :passing" do
89
+ @root << AdolescentMouse.new(parent_controller, 'jerry')
90
+
91
+ assert_equal [handler('jerry', :squeak)], @root.event_table.all_handlers_for(:squeak, 'jerry')
92
+ end
93
+
94
+ should "inherit :passing handlers" do
95
+ @root << Class.new(AdolescentMouse).new(parent_controller, 'jerry')
96
+
97
+ assert_equal [handler('jerry', :squeak)], @root.event_table.all_handlers_for(:squeak, 'jerry')
98
+ end
99
+
100
+ end
101
+
73
102
  context "#responds_to_event in class context" do
74
103
  setup do
75
104
  class AdultMouse < MouseWidget
76
105
  responds_to_event :peep, :with => :answer_squeak
77
106
  end
78
107
  class BabyMouse < AdultMouse
108
+ responds_to_event :peep
79
109
  responds_to_event :footsteps, :with => :squeak
80
110
  end
111
+
112
+ @mum = AdultMouse.new(parent_controller, 'mum')
81
113
  end
82
114
 
83
115
  should "add the handlers at creation time" do
84
- assert_equal [Apotomo::InvokeEventHandler.new(:widget_id => 'mum', :state => :answer_squeak)], AdultMouse.new(parent_controller, 'mum', :show).event_table.all_handlers_for(:peep, 'mum')
116
+ assert_equal [handler('mum', :answer_squeak)], @mum.event_table.all_handlers_for(:peep, 'mum')
85
117
  end
86
118
 
87
- should "not inherit handlers for now" do
88
- assert_equal [], BabyMouse.new(parent_controller, 'kid', :show).event_table.all_handlers_for(:peep, 'kid')
119
+ should "inherit handlers" do
120
+ @peep_handlers = BabyMouse.new(parent_controller, 'kid', :show).event_table.all_handlers_for(:peep, 'kid')
121
+ assert_equal [handler('kid', :answer_squeak), handler('kid', :peep)], @peep_handlers
89
122
  end
90
123
 
91
- should "not add the same handler to each instance" do
92
- assert_equal [Apotomo::InvokeEventHandler.new(:widget_id => 'mum', :state => :answer_squeak)], AdultMouse.new(parent_controller, 'mum', :show).event_table.all_handlers_for(:peep, 'mum')
124
+ should "not share responds_to_event options between different instances" do
125
+ assert_equal [handler('mum', :answer_squeak)], @mum.event_table.all_handlers_for(:peep, 'mum')
93
126
 
94
- assert_equal [Apotomo::InvokeEventHandler.new(:widget_id => 'dad', :state => :answer_squeak)], AdultMouse.new(parent_controller, 'dad', :show).event_table.all_handlers_for(:peep, 'dad')
127
+ assert_equal [handler('dad', :answer_squeak)], AdultMouse.new(parent_controller, 'dad', :show).event_table.all_handlers_for(:peep, 'dad')
95
128
  end
96
129
  end
97
130
 
@@ -1,12 +1,10 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class EventTest < Test::Unit::TestCase
4
+ include Apotomo::TestCaseMethods::TestController
5
+
4
6
  context "An Event" do
5
- should "require type and respond to #type" do
6
- assert_equal :footsteps, Apotomo::Event.new(:footsteps).type
7
- end
8
-
9
- should "require source and respond to #source" do
7
+ should "respond to #type and #source" do
10
8
  @event = Apotomo::Event.new(:footsteps, 'mum')
11
9
  assert_equal :footsteps, @event.type
12
10
  assert_equal 'mum', @event.source
@@ -22,14 +20,9 @@ class EventTest < Test::Unit::TestCase
22
20
  assert_equal :loud, @event[:volume]
23
21
  end
24
22
 
25
- should "complain when serialized" do
26
- assert_raises RuntimeError do
27
- Marshal.dump(Apotomo::Event.new(:footsteps, 'mum'))
28
- end
29
- end
30
-
31
- should "respond to #stopped?" do
32
- assert_not Apotomo::Event.new(:footsteps, 'mum').stopped?
23
+ should "respond to #to_s" do
24
+ @event = Apotomo::Event.new(:footsteps, mouse_mock('mum'))
25
+ assert_equal "<Event :footsteps source=mum>", @event.to_s
33
26
  end
34
27
  end
35
28
  end
@@ -50,7 +50,7 @@ class WidgetTest < ActiveSupport::TestCase
50
50
  assert_equal ['mum', 'kid'], @root.children.collect { |w| w.name }
51
51
  end
52
52
 
53
- should "inherit callbacks for now" do
53
+ should "inherit callbacks" do
54
54
  @berry = Class.new(@mum.class).new(@controller, 'berry', :squeak)
55
55
  @root << @berry
56
56
 
@@ -93,10 +93,26 @@ class WidgetTest < ActiveSupport::TestCase
93
93
  end
94
94
  end
95
95
 
96
- should "respond to #find_widget" do
97
- mum_and_kid!
98
- assert_not @mum.find_widget('pet')
99
- assert_equal @kid, @mum.find_widget('kid')
96
+ context "#find_widget" do
97
+ setup do
98
+ mum_and_kid!
99
+ end
100
+
101
+ should "find itself" do
102
+ assert_equal @mum, @mum.find_widget('mum')
103
+ end
104
+
105
+ should "return nil for not-existant widgets" do
106
+ assert_nil @mum.find_widget('pet')
107
+ end
108
+
109
+ should "find children" do
110
+ assert_equal @kid, @mum.find_widget('kid')
111
+ end
112
+
113
+ should "find treat 'id' and :id the same" do
114
+ assert_equal @mum.find_widget(:kid), @mum.find_widget('kid')
115
+ end
100
116
  end
101
117
 
102
118
  should "respond to the WidgetShortcuts methods, like #widget" do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 1
8
- - 0
9
- version: 1.1.0
8
+ - 1
9
+ version: 1.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nick Sutterer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-03-01 00:00:00 +01:00
17
+ date: 2011-03-25 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -42,8 +42,8 @@ dependencies:
42
42
  segments:
43
43
  - 3
44
44
  - 5
45
- - 4
46
- version: 3.5.4
45
+ - 6
46
+ version: 3.5.6
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
49
  - !ruby/object:Gem::Dependency
@@ -56,9 +56,9 @@ dependencies:
56
56
  - !ruby/object:Gem::Version
57
57
  segments:
58
58
  - 0
59
- - 1
60
59
  - 2
61
- version: 0.1.2
60
+ - 0
61
+ version: 0.2.0
62
62
  type: :runtime
63
63
  version_requirements: *id003
64
64
  - !ruby/object:Gem::Dependency
@@ -89,6 +89,19 @@ dependencies:
89
89
  version: "0"
90
90
  type: :development
91
91
  version_requirements: *id005
92
+ - !ruby/object:Gem::Dependency
93
+ name: slim
94
+ prerelease: false
95
+ requirement: &id006 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id006
92
105
  description: Web component framework for Rails providing widgets that trigger events and know when and how to update themselves with AJAX.
93
106
  email:
94
107
  - apotonick@gmail.com
@@ -109,9 +122,9 @@ files:
109
122
  - config/routes.rb
110
123
  - lib/apotomo.rb
111
124
  - lib/apotomo/apotomo.rake
125
+ - lib/apotomo/debugging.rb
112
126
  - lib/apotomo/event.rb
113
127
  - lib/apotomo/event_handler.rb
114
- - lib/apotomo/event_methods.rb
115
128
  - lib/apotomo/invoke_event_handler.rb
116
129
  - lib/apotomo/javascript_generator.rb
117
130
  - lib/apotomo/proc_event_handler.rb
@@ -120,17 +133,20 @@ files:
120
133
  - lib/apotomo/railtie.rb
121
134
  - lib/apotomo/request_processor.rb
122
135
  - lib/apotomo/test_case.rb
123
- - lib/apotomo/tree_node.rb
124
136
  - lib/apotomo/version.rb
125
137
  - lib/apotomo/widget.rb
138
+ - lib/apotomo/widget/event_methods.rb
126
139
  - lib/apotomo/widget/javascript_methods.rb
140
+ - lib/apotomo/widget/tree_node.rb
127
141
  - lib/apotomo/widget_shortcuts.rb
128
142
  - lib/generators/apotomo/USAGE
129
143
  - lib/generators/apotomo/widget_generator.rb
130
144
  - lib/generators/erb/widget_generator.rb
131
145
  - lib/generators/haml/widget_generator.rb
146
+ - lib/generators/slim/widget_generator.rb
132
147
  - lib/generators/templates/view.erb
133
148
  - lib/generators/templates/view.haml
149
+ - lib/generators/templates/view.slim
134
150
  - lib/generators/templates/widget.rb
135
151
  - lib/generators/templates/widget_test.rb
136
152
  - lib/generators/test_unit/widget_generator.rb
@@ -1,95 +0,0 @@
1
- require 'apotomo/invoke_event_handler'
2
-
3
- module Apotomo
4
- # Introduces event-processing functions into the StatefulWidget.
5
- module EventMethods
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- after_initialize :add_class_event_handlers
10
- end
11
-
12
- attr_writer :page_updates
13
-
14
- def page_updates
15
- @page_updates ||= []
16
- end
17
-
18
- def add_class_event_handlers(*)
19
- self.class.responds_to_event_options.each { |options| respond_to_event(*options) }
20
- end
21
-
22
- module ClassMethods
23
- def responds_to_event(*options)
24
- responds_to_event_options << options
25
- end
26
- alias_method :respond_to_event, :responds_to_event
27
-
28
- def responds_to_event_options
29
- @responds_to_event_options ||= []
30
- end
31
- end
32
- # Instructs the widget to look out for <tt>type</tt> Events that are passing by while bubbling.
33
- # If an appropriate event is encountered the widget will send the targeted widget (or itself) to another
34
- # state, which implies an update of the invoked widget.
35
- #
36
- # You may configure the event handler with the following <tt>options</tt>:
37
- # :with => (optional) the state to invoke on the target widget, defaults to +type+.
38
- # :on => (optional) the targeted widget's id, defaults to <tt>self.name</tt>
39
- # :from => (optional) the source id of the widget that triggered the event, defaults to any widget
40
- #
41
- # Example:
42
- #
43
- # trap = widget(:trap, :charged, 'mouse_trap')
44
- # trap.respond_to_event :mouseOver, :with => :catch_mouse
45
- #
46
- # This would instruct +trap+ to catch a <tt>:mouseOver</tt> event from any widget (including itself) and
47
- # to invoke the state <tt>:catch_mouse</tt> on itself as trigger.
48
- #
49
- #
50
- # hunter = widget(:form, :hunt_for_mice, 'my_form')
51
- # hunter << widget(:input_field, :smell_like_cheese, 'mouse_trap')
52
- # hunter << widget(:text_area, :stick_like_honey, 'bear_trap')
53
- # hunter.respond_to_event :captured, :from => 'mouse_trap', :with => :refill_cheese, :on => 'mouse_trap'
54
- #
55
- # As both the bear- and the mouse trap can trigger a <tt>:captured</tt> event the later <tt>respond_to_event</tt>
56
- # would invoke <tt>:refill_cheese</tt> on the <tt>mouse_trap</tt> widget as soon as this and only this widget fired.
57
- # It is important to understand the <tt>:from</tt> parameter as it filters the event source - it wouldn't make
58
- # sense to refill the mouse trap if the bear trap snapped, would it?
59
- def respond_to_event(type, options={})
60
- options = options.reverse_merge(:once => true,
61
- :with => type,
62
- :on => self.name)
63
-
64
- handler = InvokeEventHandler.new(:widget_id => options[:on], :state => options[:with])
65
-
66
- return if options[:once] and event_table.all_handlers_for(type, options[:from]).include?(handler)
67
-
68
- on(type, :do => handler, :from => options[:from])
69
- end
70
-
71
- # Fire an event of +type+ and let it bubble up. You may add arbitrary payload data to the event.
72
- #
73
- # Example:
74
- #
75
- # trigger(:dropped, :area => 59)
76
- #
77
- # which can be queried in a triggered state.
78
- #
79
- # def on_drop(event)
80
- # if event[:area] == 59
81
- def trigger(*args)
82
- fire(*args)
83
- end
84
-
85
- protected
86
- # Get all handlers from self for the passed event (overriding Onfire#local_event_handlers).
87
- def local_event_handlers(event)
88
- event_table.all_handlers_for(event.type, event.source.name) # we key with widget_id.
89
- end
90
-
91
- def event_for(*args) # defined in Onfire: we want Apotomo::Event.
92
- Event.new(*args)
93
- end
94
- end
95
- end