formotion 1.6 → 1.7
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +0 -3
- data/Gemfile +4 -1
- data/LIST_OF_ROW_TYPES.md +58 -6
- data/Rakefile +6 -2
- data/app/app_delegate.rb +6 -0
- data/examples/KitchenSink/Gemfile +2 -1
- data/examples/KitchenSink/Rakefile +9 -4
- data/examples/KitchenSink/app/app_delegate.rb +20 -5
- data/examples/KitchenSink/resources/arrow-up.png +0 -0
- data/examples/KitchenSink/resources/arrow-up@2x.png +0 -0
- data/examples/KitchenSink/resources/email.png +0 -0
- data/examples/KitchenSink/resources/email@2x.png +0 -0
- data/examples/Persistence/app/app_delegate.rb +2 -0
- data/examples/Persistence/app/controller.rb +66 -0
- data/lib/formotion/controller/form_controller.rb +1 -1
- data/lib/formotion/form/form.rb +14 -5
- data/lib/formotion/model/formable.rb +8 -6
- data/lib/formotion/patch/ui_text_field.rb +15 -1
- data/lib/formotion/row/row.rb +19 -3
- data/lib/formotion/row/row_cell_builder.rb +48 -2
- data/lib/formotion/row_type/button.rb +2 -2
- data/lib/formotion/row_type/date_row.rb +8 -1
- data/lib/formotion/row_type/image_row.rb +2 -2
- data/lib/formotion/row_type/map_row.rb +60 -23
- data/lib/formotion/row_type/object_row.rb +2 -2
- data/lib/formotion/row_type/picker_row.rb +32 -0
- data/lib/formotion/row_type/string_row.rb +5 -2
- data/lib/formotion/row_type/web_link_row.rb +48 -0
- data/lib/formotion/version.rb +1 -1
- data/resources/camera.png +0 -0
- data/resources/camera@2x.png +0 -0
- data/spec/functional/map_row_spec.rb +151 -4
- data/spec/functional/web_link_row_spec.rb +35 -0
- data/spec/row_spec.rb +109 -1
- data/spec/row_type/web_link_spec.rb +23 -0
- metadata +13 -2
@@ -39,7 +39,7 @@ class UITextField
|
|
39
39
|
# block takes argument textField
|
40
40
|
def on_end(&block)
|
41
41
|
add_delegate_method do
|
42
|
-
@delegate.
|
42
|
+
@delegate.textFieldDidEndEditing_callback = block
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -114,6 +114,11 @@ class UITextField_Delegate
|
|
114
114
|
if self.textFieldShouldEndEditing_callback
|
115
115
|
return self.textFieldShouldEndEditing_callback.call(theTextField)
|
116
116
|
end
|
117
|
+
|
118
|
+
if Device.ios_version >= "7.0"
|
119
|
+
theTextField.text = theTextField.text.gsub("\u00a0", " ").strip
|
120
|
+
end
|
121
|
+
|
117
122
|
true
|
118
123
|
end
|
119
124
|
|
@@ -127,6 +132,15 @@ class UITextField_Delegate
|
|
127
132
|
if self.shouldChangeCharactersInRange_callback
|
128
133
|
return self.shouldChangeCharactersInRange_callback.call(theTextField, range, string)
|
129
134
|
end
|
135
|
+
|
136
|
+
# fix for UITextField in iOS7 http://stackoverflow.com/questions/19569688/uitextfield-spacebar-does-not-advance-cursor-in-ios-7/20129483#20129483
|
137
|
+
if Device.ios_version >= "7.0"
|
138
|
+
if range.location == theTextField.text.length && string == " "
|
139
|
+
theTextField.text = theTextField.text.stringByAppendingString("\u00a0")
|
140
|
+
return false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
130
144
|
true
|
131
145
|
end
|
132
146
|
|
data/lib/formotion/row/row.rb
CHANGED
@@ -9,6 +9,10 @@ module Formotion
|
|
9
9
|
:value,
|
10
10
|
# set as cell.titleLabel.text
|
11
11
|
:title,
|
12
|
+
# set as cell.imageView.image
|
13
|
+
:image,
|
14
|
+
# an image placeholder for cell.imageView.image when using remote images
|
15
|
+
:image_placeholder,
|
12
16
|
# set as cell.detailLabel.text
|
13
17
|
:subtitle,
|
14
18
|
# configures the type of input this is (string, phone, switch, etc)
|
@@ -101,7 +105,13 @@ module Formotion
|
|
101
105
|
# Cell selection style
|
102
106
|
# OPTIONS: :blue, :gray, :none
|
103
107
|
# DEFAULT is :blue
|
104
|
-
:selection_style
|
108
|
+
:selection_style,
|
109
|
+
|
110
|
+
# The following apply only to weblink rows
|
111
|
+
|
112
|
+
# Whether or not to display a warning to the user before leaving the app.
|
113
|
+
# DEFAULT is false
|
114
|
+
:warn
|
105
115
|
]
|
106
116
|
PROPERTIES.each {|prop|
|
107
117
|
attr_accessor prop
|
@@ -139,6 +149,8 @@ module Formotion
|
|
139
149
|
attr_accessor :on_tap_callback
|
140
150
|
# callback for when a row is tapped
|
141
151
|
attr_accessor :on_delete_callback
|
152
|
+
# callback for when a row is exited
|
153
|
+
attr_accessor :on_end_callback
|
142
154
|
|
143
155
|
# RowType object
|
144
156
|
attr_accessor :object
|
@@ -264,7 +276,7 @@ module Formotion
|
|
264
276
|
end
|
265
277
|
|
266
278
|
def text_alignment=(alignment)
|
267
|
-
@text_alignment = const_int_get("
|
279
|
+
@text_alignment = const_int_get("NSTextAlignment", alignment)
|
268
280
|
end
|
269
281
|
|
270
282
|
def selection_style=(style)
|
@@ -305,6 +317,10 @@ module Formotion
|
|
305
317
|
self.on_begin_callback = block
|
306
318
|
end
|
307
319
|
|
320
|
+
def on_end(&block)
|
321
|
+
self.on_end_callback = block
|
322
|
+
end
|
323
|
+
|
308
324
|
# Used in :button type rows
|
309
325
|
def on_tap(&block)
|
310
326
|
self.on_tap_callback = block
|
@@ -398,7 +414,7 @@ module Formotion
|
|
398
414
|
UITextFieldViewModeNever, UITextFieldViewModeAlways, UITextFieldViewModeWhileEditing,
|
399
415
|
UITextFieldViewModeUnlessEditing, NSDateFormatterShortStyle, NSDateFormatterMediumStyle,
|
400
416
|
NSDateFormatterLongStyle, NSDateFormatterFullStyle,
|
401
|
-
|
417
|
+
NSTextAlignmentRight, NSTextAlignmentCenter, NSTextAlignmentLeft
|
402
418
|
]
|
403
419
|
end
|
404
420
|
end
|
@@ -23,13 +23,20 @@ module Formotion
|
|
23
23
|
cell.textLabel.text = new_value
|
24
24
|
end
|
25
25
|
|
26
|
+
if row.image
|
27
|
+
Formotion::RowCellBuilder.set_image(cell, row)
|
28
|
+
observe(row, "image") do |old_value, new_value|
|
29
|
+
Formotion::RowCellBuilder.set_image(cell, row)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
26
33
|
cell.detailTextLabel.text = row.subtitle
|
27
34
|
observe(row, "subtitle") do |old_value, new_value|
|
28
35
|
cell.detailTextLabel.text = new_value
|
29
36
|
end
|
30
37
|
|
31
38
|
edit_field = row.object.build_cell(cell)
|
32
|
-
|
39
|
+
|
33
40
|
if edit_field and edit_field.respond_to?("accessibilityLabel=")
|
34
41
|
label = row.accessibility
|
35
42
|
label = row.title unless label
|
@@ -39,5 +46,44 @@ module Formotion
|
|
39
46
|
[cell, edit_field]
|
40
47
|
end
|
41
48
|
|
49
|
+
def self.set_image(cell, row)
|
50
|
+
if row.image.is_a?(NSURL) || (row.image.is_a?(String) && row.image.include?("http"))
|
51
|
+
# Use a remote image helper to set the image.
|
52
|
+
image_url = row.image
|
53
|
+
image_url = NSURL.URLWithString(image_url) unless image_url.is_a?(NSURL)
|
54
|
+
|
55
|
+
placeholder = row.image_placeholder
|
56
|
+
placeholder = UIImage.imageNamed(placeholder) if placeholder.is_a?(String)
|
57
|
+
|
58
|
+
if cell.imageView.respond_to?("setImageWithURLRequest:placeholderImage:success:failure:")
|
59
|
+
# Use AFNetworking
|
60
|
+
request = NSURLRequest.requestWithURL(image_url)
|
61
|
+
cell.imageView.setImageWithURLRequest(request, placeholderImage: placeholder, success: ->(request, response, image) {
|
62
|
+
cell.imageView.image = image
|
63
|
+
cell.setNeedsLayout
|
64
|
+
}, failure: ->(request, response, error) {
|
65
|
+
|
66
|
+
})
|
67
|
+
elsif cell.imageView.respond_to?("setImageWithURL:placeholderImage:completed:")
|
68
|
+
cell.imageView.setImageWithURL(image_url, placeholderImage: placeholder, completed: ->(image, error, cacheType) {
|
69
|
+
cell.imageView.image = image
|
70
|
+
cell.setNeedsLayout
|
71
|
+
})
|
72
|
+
elsif cell.imageView.respond_to?("setImageWithURL:placeholder:")
|
73
|
+
# Use JMImageCache
|
74
|
+
JMImageCache.sharedCache.imageForURL(image_url, completionBlock: ->(downloadedImage) {
|
75
|
+
cell.imageView.image = downloadedImage
|
76
|
+
cell.setNeedsLayout
|
77
|
+
})
|
78
|
+
else
|
79
|
+
raise "Please add the AFNetworking, SDWebImage, or JMImageCache pods to your project to use remote images in Formotion"
|
80
|
+
end
|
81
|
+
|
82
|
+
else
|
83
|
+
# Just set the image like normal
|
84
|
+
cell.imageView.image = (row.image.is_a? String) ? UIImage.imageNamed(row.image) : row.image
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
42
88
|
end
|
43
|
-
end
|
89
|
+
end
|
@@ -20,8 +20,8 @@ module Formotion
|
|
20
20
|
((self.frame.size.send(dimen) - frame.size.send(dimen)) / 2.0)
|
21
21
|
}
|
22
22
|
|
23
|
-
self.textLabel.center = CGPointMake(self.frame.size.width / 2
|
24
|
-
self.detailTextLabel.center = CGPointMake(self.frame.size.width / 2
|
23
|
+
self.textLabel.center = CGPointMake(self.frame.size.width / 2, self.textLabel.center.y)
|
24
|
+
self.detailTextLabel.center = CGPointMake(self.frame.size.width / 2, self.detailTextLabel.center.y)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
nil
|
@@ -40,6 +40,12 @@ module Formotion
|
|
40
40
|
|
41
41
|
def after_build(cell)
|
42
42
|
self.row.text_field.inputView = self.picker
|
43
|
+
# work around an iOS7 bug: http://bit.ly/KcwKSv
|
44
|
+
if row.picker_mode == :countdown
|
45
|
+
self.picker.setDate(self.picker.date, animated:true)
|
46
|
+
picker.countDownDuration = self.row.value
|
47
|
+
end
|
48
|
+
|
43
49
|
update
|
44
50
|
end
|
45
51
|
|
@@ -49,13 +55,14 @@ module Formotion
|
|
49
55
|
picker.datePickerMode = self.picker_mode
|
50
56
|
picker.hidden = false
|
51
57
|
picker.date = self.date_value || Time.now
|
58
|
+
picker.countDownDuration = self.row.value if row.picker_mode == :countdown
|
52
59
|
picker.minuteInterval = self.row.minute_interval if self.row.minute_interval
|
53
60
|
|
54
61
|
picker.when(UIControlEventValueChanged) do
|
55
62
|
if self.row.picker_mode == :countdown
|
56
63
|
self.row.value = @picker.countDownDuration
|
57
64
|
else
|
58
|
-
self.row.value = Time.at(@picker.date).to_i
|
65
|
+
self.row.value = Time.at(@picker.date).to_i
|
59
66
|
end
|
60
67
|
update
|
61
68
|
end
|
@@ -15,7 +15,7 @@ module Formotion
|
|
15
15
|
def build_cell(cell)
|
16
16
|
cell.selectionStyle = self.row.selection_style || UITableViewCellSelectionStyleBlue
|
17
17
|
# only show the "plus" when editable
|
18
|
-
add_plus_accessory(cell) if row.editable?
|
18
|
+
add_plus_accessory(cell) if row.editable? && (row.value == nil)
|
19
19
|
|
20
20
|
observe(self.row, "value") do |old_value, new_value|
|
21
21
|
@image_view.image = new_value
|
@@ -25,7 +25,7 @@ module Formotion
|
|
25
25
|
else
|
26
26
|
self.row.row_height = 44
|
27
27
|
# only show the "plus" when editable
|
28
|
-
add_plus_accessory(cell) if row.editable?
|
28
|
+
add_plus_accessory(cell) if row.editable? && (row.value == nil)
|
29
29
|
end
|
30
30
|
row.form.reload_data
|
31
31
|
end
|
@@ -3,31 +3,35 @@ motion_require 'base'
|
|
3
3
|
module Formotion
|
4
4
|
module RowType
|
5
5
|
class MapRowData
|
6
|
-
|
6
|
+
|
7
7
|
attr_accessor :pin, :options
|
8
8
|
#attr_accessor :title, :subtitle, :coordinate
|
9
|
-
|
10
|
-
def initialize(
|
11
|
-
@title=title
|
12
|
-
@subtitle=subtitle
|
13
|
-
@coordinate=
|
14
|
-
@options=options
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@title=options[:title]
|
12
|
+
@subtitle=options[:subtitle]
|
13
|
+
@coordinate=options[:coord]
|
14
|
+
@options=options[:options]
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def title
|
18
18
|
@title
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def subtitle
|
22
22
|
@subtitle
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def coordinate
|
26
|
-
@coordinate
|
26
|
+
if @coordinate.is_a? CLCircularRegion
|
27
|
+
@coordinate.center
|
28
|
+
else
|
29
|
+
@coordinate
|
30
|
+
end
|
27
31
|
end
|
28
|
-
|
32
|
+
|
29
33
|
end
|
30
|
-
|
34
|
+
|
31
35
|
class MapRow < Base
|
32
36
|
include BW::KVO
|
33
37
|
|
@@ -35,34 +39,67 @@ module Formotion
|
|
35
39
|
|
36
40
|
def set_pin
|
37
41
|
return unless row.value
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
|
43
|
+
unless row.value.is_a?(Hash)
|
44
|
+
coord = (row.value.is_a?(Array) and row.value.size==2) ? CLLocationCoordinate2D.new(row.value[0], row.value[1]) : row.value
|
45
|
+
row.value = {coord: coord, pin: {coord:coord}}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set Defaults
|
49
|
+
row.value = {
|
50
|
+
animated: true,
|
51
|
+
type: MKMapTypeStandard,
|
52
|
+
enabled: true
|
53
|
+
}.merge(row.value)
|
54
|
+
|
55
|
+
if row.value[:coord].is_a?(CLLocationCoordinate2D)
|
56
|
+
region = MKCoordinateRegionMakeWithDistance(row.value[:coord], 400.0, 480.0)
|
57
|
+
elsif row.value[:coord].is_a?(CLCircularRegion)
|
58
|
+
region = MKCoordinateRegionMakeWithDistance(
|
59
|
+
row.value[:coord].center,
|
60
|
+
row.value[:coord].radius * 2,
|
61
|
+
row.value[:coord].radius * 2
|
62
|
+
)
|
63
|
+
else
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
if row.value[:pin]
|
68
|
+
row.value[:pin] = {title: nil, subtitle:nil}.merge(row.value[:pin]) #Defaults
|
69
|
+
|
70
|
+
@map_row_data = MapRowData.new(row.value[:pin])
|
71
|
+
@map_view.removeAnnotations(@map_view.annotations)
|
44
72
|
@map_view.addAnnotation(@map_row_data)
|
73
|
+
@map_view.selectAnnotation(@map_row_data, animated:row.value[:animated]) if row.value[:pin][:title]
|
45
74
|
end
|
75
|
+
|
76
|
+
@map_view.setUserInteractionEnabled(row.value[:enabled])
|
77
|
+
@map_view.setMapType(row.value[:type])
|
78
|
+
@map_view.setRegion(region, animated:row.value[:animated])
|
46
79
|
end
|
47
|
-
|
80
|
+
|
48
81
|
def annotations
|
49
82
|
@map_view.annotations
|
50
83
|
end
|
51
84
|
|
85
|
+
def map
|
86
|
+
@map_view
|
87
|
+
end
|
88
|
+
|
52
89
|
def build_cell(cell)
|
53
90
|
cell.selectionStyle = self.row.selection_style || UITableViewCellSelectionStyleBlue
|
54
91
|
|
55
92
|
@map_view = MKMapView.alloc.init
|
56
93
|
@map_view.delegate = self
|
57
|
-
|
94
|
+
|
58
95
|
set_pin
|
59
|
-
|
96
|
+
|
60
97
|
observe(self.row, "value") do |old_value, new_value|
|
61
98
|
break_with_semaphore do
|
62
99
|
set_pin
|
63
100
|
end
|
64
101
|
end
|
65
|
-
|
102
|
+
|
66
103
|
@map_view.tag = MAP_VIEW_TAG
|
67
104
|
@map_view.contentMode = UIViewContentModeScaleAspectFit
|
68
105
|
@map_view.backgroundColor = UIColor.clearColor
|
@@ -17,7 +17,7 @@ module Formotion
|
|
17
17
|
|
18
18
|
field.clearButtonMode = UITextFieldViewModeWhileEditing
|
19
19
|
field.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter
|
20
|
-
field.textAlignment = row.text_alignment ||
|
20
|
+
field.textAlignment = row.text_alignment || NSTextAlignmentRight
|
21
21
|
|
22
22
|
field.keyboardType = keyboardType
|
23
23
|
|
@@ -54,7 +54,7 @@ module Formotion
|
|
54
54
|
field
|
55
55
|
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# Used when row.value changes
|
59
59
|
def update_text_field(new_value)
|
60
60
|
self.row.text_field.text = row_value.to_s
|
@@ -8,6 +8,38 @@ module Formotion
|
|
8
8
|
include RowType::ItemsMapper
|
9
9
|
include RowType::MultiChoiceRow
|
10
10
|
|
11
|
+
def input_accessory_view(input_accessory)
|
12
|
+
case input_accessory
|
13
|
+
when :done
|
14
|
+
@input_accessory ||= begin
|
15
|
+
tool_bar = UIToolbar.alloc.initWithFrame([[0, 0], [0, 44]])
|
16
|
+
tool_bar.autoresizingMask = UIViewAutoresizingFlexibleWidth
|
17
|
+
tool_bar.translucent = true
|
18
|
+
|
19
|
+
left_space = UIBarButtonItem.alloc.initWithBarButtonSystemItem(
|
20
|
+
UIBarButtonSystemItemFlexibleSpace,
|
21
|
+
target: nil,
|
22
|
+
action: nil)
|
23
|
+
|
24
|
+
done_button = UIBarButtonItem.alloc.initWithBarButtonSystemItem(
|
25
|
+
UIBarButtonSystemItemDone,
|
26
|
+
target: self,
|
27
|
+
action: :done_editing)
|
28
|
+
|
29
|
+
tool_bar.items = [left_space, done_button]
|
30
|
+
|
31
|
+
tool_bar
|
32
|
+
end
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Callback for "Done" button in input_accessory_view
|
39
|
+
def done_editing
|
40
|
+
self.row.text_field.endEditing(true)
|
41
|
+
end
|
42
|
+
|
11
43
|
def after_build(cell)
|
12
44
|
self.row.text_field.inputView = self.picker
|
13
45
|
self.row.text_field.text = name_for_value(row.value).to_s
|
@@ -33,7 +33,7 @@ module Formotion
|
|
33
33
|
|
34
34
|
field.clearButtonMode = UITextFieldViewModeWhileEditing
|
35
35
|
field.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter
|
36
|
-
field.textAlignment = row.text_alignment ||
|
36
|
+
field.textAlignment = row.text_alignment || NSTextAlignmentRight
|
37
37
|
|
38
38
|
field.keyboardType = keyboardType
|
39
39
|
|
@@ -112,6 +112,10 @@ module Formotion
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
|
+
field.on_end do |text_field|
|
116
|
+
row.on_end_callback && row.on_end_callback.call
|
117
|
+
end
|
118
|
+
|
115
119
|
field.on_begin do |text_field|
|
116
120
|
row.on_begin_callback && row.on_begin_callback.call
|
117
121
|
end
|
@@ -152,7 +156,6 @@ module Formotion
|
|
152
156
|
@input_accessory ||= begin
|
153
157
|
tool_bar = UIToolbar.alloc.initWithFrame([[0, 0], [0, 44]])
|
154
158
|
tool_bar.autoresizingMask = UIViewAutoresizingFlexibleWidth
|
155
|
-
tool_bar.barStyle = UIBarStyleBlack
|
156
159
|
tool_bar.translucent = true
|
157
160
|
|
158
161
|
left_space = UIBarButtonItem.alloc.initWithBarButtonSystemItem(
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Formotion
|
2
|
+
module RowType
|
3
|
+
class WebLinkRow < ObjectRow
|
4
|
+
|
5
|
+
def after_build(cell)
|
6
|
+
super
|
7
|
+
|
8
|
+
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator
|
9
|
+
self.row.text_field.hidden = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_select(tableView, tableViewDelegate)
|
13
|
+
if is_url?
|
14
|
+
if row.warn.nil? || row.warn == false
|
15
|
+
App.open_url row.value
|
16
|
+
else
|
17
|
+
warn
|
18
|
+
end
|
19
|
+
else
|
20
|
+
raise StandardError, "Row value for WebLinkRow should be a URL string or instance of NSURL."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_url?
|
25
|
+
(row.value.is_a?(String) && row.value[0..3] == "http") || row.value.is_a?(NSURL)
|
26
|
+
end
|
27
|
+
|
28
|
+
def warn
|
29
|
+
row.warn = {} unless row.warn.is_a? Hash #Convert value from true to a hash
|
30
|
+
row.warn = {
|
31
|
+
title: "Leaving #{App.name}",
|
32
|
+
message: "This action will leave #{App.name} and open Safari.",
|
33
|
+
buttons: ["Cancel", "OK"]
|
34
|
+
}.merge(row.warn)
|
35
|
+
|
36
|
+
BW::UIAlertView.new({
|
37
|
+
title: row.warn[:title],
|
38
|
+
message: row.warn[:message],
|
39
|
+
buttons: row.warn[:buttons],
|
40
|
+
cancel_button_index: 0
|
41
|
+
}) do |alert|
|
42
|
+
App.open_url(row.value) unless alert.clicked_button.cancel?
|
43
|
+
end.show
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|