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 +13 -0
- data/apotomo.gemspec +3 -2
- data/lib/apotomo/debugging.rb +9 -0
- data/lib/apotomo/event.rb +2 -2
- data/lib/apotomo/rails/controller_methods.rb +1 -1
- data/lib/apotomo/version.rb +1 -1
- data/lib/apotomo/widget/event_methods.rb +122 -0
- data/lib/apotomo/widget/javascript_methods.rb +15 -11
- data/lib/apotomo/{tree_node.rb → widget/tree_node.rb} +0 -0
- data/lib/apotomo/widget.rb +11 -11
- data/lib/generators/apotomo/widget_generator.rb +16 -6
- data/lib/generators/erb/widget_generator.rb +4 -10
- data/lib/generators/haml/widget_generator.rb +4 -13
- data/lib/generators/slim/widget_generator.rb +11 -0
- data/lib/generators/templates/view.slim +4 -0
- data/test/rails/widget_generator_test.rb +12 -0
- data/test/unit/event_methods_test.rb +39 -6
- data/test/unit/event_test.rb +6 -13
- data/test/unit/widget_test.rb +21 -5
- metadata +25 -9
- data/lib/apotomo/event_methods.rb +0 -95
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.
|
24
|
-
s.add_dependency "onfire", "~> 0.
|
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
|
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
|
6
|
-
|
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(:
|
39
|
+
# root << widget(:comments, :user => current_user)
|
40
40
|
# end
|
41
41
|
def has_widgets(&block)
|
42
42
|
has_widgets_blocks << block
|
data/lib/apotomo/version.rb
CHANGED
@@ -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
|
9
|
-
#
|
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
|
-
#
|
14
|
-
#
|
13
|
+
# def hungry
|
14
|
+
# replace
|
15
15
|
#
|
16
|
-
#
|
16
|
+
# will render the current state's view and wrap it like
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
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 => :
|
29
|
-
# #=> "$(\"
|
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
|
data/lib/apotomo/widget.rb
CHANGED
@@ -2,13 +2,14 @@ require 'cells'
|
|
2
2
|
require 'onfire'
|
3
3
|
require 'hooks'
|
4
4
|
|
5
|
-
|
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
|
-
#
|
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> -
|
115
|
-
# * <tt>:
|
116
|
-
# *
|
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::
|
121
|
+
# class MouseWidget < Apotomo::Widget
|
121
122
|
# def eat
|
122
|
-
# # ... do something
|
123
123
|
# render
|
124
124
|
# end
|
125
125
|
#
|
126
|
-
#
|
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
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
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/
|
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 <
|
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/
|
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 <
|
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
|
@@ -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 [
|
116
|
+
assert_equal [handler('mum', :answer_squeak)], @mum.event_table.all_handlers_for(:peep, 'mum')
|
85
117
|
end
|
86
118
|
|
87
|
-
should "
|
88
|
-
|
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
|
92
|
-
assert_equal [
|
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 [
|
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
|
|
data/test/unit/event_test.rb
CHANGED
@@ -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 "
|
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 "
|
26
|
-
|
27
|
-
|
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
|
data/test/unit/widget_test.rb
CHANGED
@@ -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
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
-
|
9
|
-
version: 1.1.
|
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-
|
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
|
-
-
|
46
|
-
version: 3.5.
|
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
|
-
|
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
|