apotomo 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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