formotion 1.1.5 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +18 -0
- data/README.md +1 -1
- data/app/app_delegate.rb +2 -1
- data/examples/Persistence/app/app_delegate.rb +4 -179
- data/examples/Persistence/app/controller.rb +53 -0
- data/lib/formotion/form/form.rb +24 -21
- data/lib/formotion/patch/ui_text_view.rb +1 -1
- data/lib/formotion/row/row.rb +43 -3
- data/lib/formotion/row_type/base.rb +7 -1
- data/lib/formotion/row_type/button.rb +2 -2
- data/lib/formotion/row_type/check_row.rb +3 -0
- data/lib/formotion/row_type/date_row.rb +62 -8
- data/lib/formotion/row_type/image_row.rb +6 -3
- data/lib/formotion/row_type/options_row.rb +1 -0
- data/lib/formotion/row_type/picker_row.rb +14 -9
- data/lib/formotion/row_type/slider_row.rb +4 -3
- data/lib/formotion/row_type/string_row.rb +7 -3
- data/lib/formotion/row_type/switch_row.rb +1 -0
- data/lib/formotion/row_type/text_row.rb +7 -3
- data/lib/formotion/version.rb +1 -1
- data/spec/form/persist_spec.rb +12 -4
- data/spec/functional/slider_row_spec.rb +1 -1
- data/spec/row_type/date_spec.rb +21 -1
- data/spec/support/ui_control_wrap_extension.rb +0 -1
- metadata +5 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 1.2 - January 3, 2013
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
- Added `:picker_mode` row property which lets you choose what type of date picker you're using (i.e. `:date`, `:time`, `:date_time`, or `:countdown`)
|
6
|
+
|
7
|
+
- Added `:text_alignment` row property which controls how a row's input field's text is aligned (i.e. `:right` (default), `:left`, or `:center`).
|
8
|
+
|
9
|
+
- Added `:editable` row property which controls if a user can interact with the row's control (a text input, slider, etc)
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
- Fixed size issue with iPhone apps running @2x on an iPad (see `row_type/base.rb#field_buffer`)
|
14
|
+
|
15
|
+
- Fixed bug in `PickerRow` where KVOing `:value` changes woulnd't reflect in the picker UI.
|
16
|
+
|
17
|
+
- Fixed bug in a `UITextView` patch that removed copy and paste by default for all `UITextView`s.
|
18
|
+
|
1
19
|
## 1.1.5 - November 9, 2012
|
2
20
|
|
3
21
|
### Features
|
data/README.md
CHANGED
@@ -116,7 +116,7 @@ To add your own, check [the guide to adding new row types](https://github.com/cl
|
|
116
116
|
|
117
117
|
`Formotion::Form`, `Formotion::Section`, and `Formotion::Row` all respond to a `::PROPERTIES` attribute. These are settable as an attribute (ie `section.title = 'title'`) or in the initialization hash (ie `{sections: [{title: 'title', ...}]}`). Check the comments in the 3 main files (`form.rb`, `section.rb`, and `row.rb` for details on what these do).
|
118
118
|
|
119
|
-
###
|
119
|
+
### Retrieve
|
120
120
|
|
121
121
|
You have `form#submit`, `form#on_submit`, and `form#render` at your disposal. Here's an example:
|
122
122
|
|
data/app/app_delegate.rb
CHANGED
@@ -2,184 +2,9 @@ class AppDelegate
|
|
2
2
|
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
3
3
|
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
4
4
|
|
5
|
-
@
|
6
|
-
title: "Persist Example",
|
7
|
-
persist_as: "example",
|
8
|
-
sections: [{
|
9
|
-
title: "Section Title",
|
10
|
-
footer: "This is the footer for the section. It's good for displaying detailed data about the section.",
|
11
|
-
rows: [{
|
12
|
-
title: "Static",
|
13
|
-
type: :static,
|
14
|
-
}, {
|
15
|
-
title: "Email",
|
16
|
-
key: :email,
|
17
|
-
placeholder: "me@mail.com",
|
18
|
-
type: :email,
|
19
|
-
auto_correction: :no,
|
20
|
-
auto_capitalization: :none
|
21
|
-
}, {
|
22
|
-
title: "Gender",
|
23
|
-
key: :gender,
|
24
|
-
type: :options,
|
25
|
-
items: ['Female', 'Male']
|
26
|
-
}, {
|
27
|
-
title: "Password",
|
28
|
-
key: :password,
|
29
|
-
placeholder: "required",
|
30
|
-
type: :string,
|
31
|
-
secure: true
|
32
|
-
}, {
|
33
|
-
title: "Phone",
|
34
|
-
key: :phone,
|
35
|
-
placeholder: "555-555-5555",
|
36
|
-
type: :phone,
|
37
|
-
auto_correction: :no,
|
38
|
-
auto_capitalization: :none
|
39
|
-
}, {
|
40
|
-
title: "Number",
|
41
|
-
key: :number,
|
42
|
-
placeholder: "12345",
|
43
|
-
type: :number,
|
44
|
-
auto_correction: :no,
|
45
|
-
auto_capitalization: :none
|
46
|
-
}, {
|
47
|
-
title: "Subtitle",
|
48
|
-
subtitle: "Confirmation",
|
49
|
-
key: :confirm,
|
50
|
-
placeholder: "required",
|
51
|
-
type: :string,
|
52
|
-
secure: true
|
53
|
-
}, {
|
54
|
-
title: "Row Height",
|
55
|
-
key: :row_height,
|
56
|
-
placeholder: "60px",
|
57
|
-
type: :string,
|
58
|
-
row_height: 60
|
59
|
-
}, {
|
60
|
-
title: "Text",
|
61
|
-
key: :text,
|
62
|
-
type: :text,
|
63
|
-
placeholder: "Enter your text here",
|
64
|
-
row_height: 100
|
65
|
-
}, {
|
66
|
-
title: "Check",
|
67
|
-
key: :check,
|
68
|
-
type: :check,
|
69
|
-
value: true
|
70
|
-
}, {
|
71
|
-
title: "Remember?",
|
72
|
-
key: :remember,
|
73
|
-
type: :switch,
|
74
|
-
}, {
|
75
|
-
title: "Date Full",
|
76
|
-
subtitle: "w/ :value",
|
77
|
-
value: 326937600,
|
78
|
-
key: :date_long,
|
79
|
-
type: :date,
|
80
|
-
format: :full
|
81
|
-
}, {
|
82
|
-
title: "Date Medium",
|
83
|
-
subtitle: "w/ :value",
|
84
|
-
value: 1341273600,
|
85
|
-
key: :date_medium,
|
86
|
-
type: :date,
|
87
|
-
format: :medium
|
88
|
-
}, {
|
89
|
-
title: "Date Short",
|
90
|
-
subtitle: "w/ :placeholder",
|
91
|
-
placeholder: "DOB",
|
92
|
-
key: :date_short,
|
93
|
-
type: :date,
|
94
|
-
format: :short
|
95
|
-
}, {
|
96
|
-
title: "Slider",
|
97
|
-
key: :slider,
|
98
|
-
type: :slider,
|
99
|
-
range: (1..100),
|
100
|
-
value: 25
|
101
|
-
}]
|
102
|
-
}, {
|
103
|
-
title: "Subforms",
|
104
|
-
rows: [{
|
105
|
-
title: "Subform",
|
106
|
-
subtitle: "With display_key",
|
107
|
-
type: :subform,
|
108
|
-
key: :subform,
|
109
|
-
display_key: :type,
|
110
|
-
subform: {
|
111
|
-
title: "Account Type",
|
112
|
-
sections: [{
|
113
|
-
key: :type,
|
114
|
-
select_one: true,
|
115
|
-
rows: [{
|
116
|
-
title: "Free",
|
117
|
-
key: :Free,
|
118
|
-
type: :check,
|
119
|
-
}, {
|
120
|
-
title: "Basic",
|
121
|
-
value: true,
|
122
|
-
key: :Basic,
|
123
|
-
type: :check,
|
124
|
-
}, {
|
125
|
-
title: "Pro",
|
126
|
-
key: :Pro,
|
127
|
-
type: :check,
|
128
|
-
}]
|
129
|
-
}, {
|
130
|
-
rows: [{
|
131
|
-
title: "Advanced",
|
132
|
-
type: :subform,
|
133
|
-
key: :advanced,
|
134
|
-
subform: {
|
135
|
-
title: "Advanced",
|
136
|
-
sections: [{
|
137
|
-
key: :currency,
|
138
|
-
select_one: true,
|
139
|
-
rows: [{
|
140
|
-
title: "USD",
|
141
|
-
value: true,
|
142
|
-
key: :usd,
|
143
|
-
type: :check,
|
144
|
-
}, {
|
145
|
-
title: "EUR",
|
146
|
-
key: :eur,
|
147
|
-
type: :check,
|
148
|
-
}, {
|
149
|
-
title: "CHF",
|
150
|
-
key: :chf,
|
151
|
-
type: :check,
|
152
|
-
}]
|
153
|
-
}, {
|
154
|
-
rows: [{
|
155
|
-
title: 'Back',
|
156
|
-
type: :back
|
157
|
-
}]
|
158
|
-
}]
|
159
|
-
}
|
160
|
-
}]
|
161
|
-
}, {
|
162
|
-
rows: [{
|
163
|
-
title: 'Back',
|
164
|
-
type: :back
|
165
|
-
}]
|
166
|
-
}]
|
167
|
-
}
|
168
|
-
}]
|
169
|
-
}]
|
170
|
-
})
|
5
|
+
@view_controller =AccountSettingsController.alloc.initController
|
171
6
|
|
172
|
-
@view_controller =
|
173
|
-
@view_controller.form.on_submit do |form|
|
174
|
-
form.active_row && form.active_row.text_field.resignFirstResponder
|
175
|
-
alert = UIAlertView.alloc.init
|
176
|
-
alert.title = "@form.render"
|
177
|
-
alert.message = @form.render.to_s
|
178
|
-
alert.addButtonWithTitle("OK")
|
179
|
-
alert.show
|
180
|
-
end
|
181
|
-
|
182
|
-
@view_controller.navigationItem.leftBarButtonItem = UIBarButtonItem.alloc.initWithTitle("Reset", style: UIBarButtonItemStyleBordered, target:self, action:'reset_form')
|
7
|
+
@view_controller.navigationItem.leftBarButtonItem = UIBarButtonItem.alloc.initWithTitle("Render", style: UIBarButtonItemStyleBordered, target:self, action:'reset_form')
|
183
8
|
|
184
9
|
@navigation_controller = UINavigationController.alloc.initWithRootViewController(@view_controller)
|
185
10
|
|
@@ -190,10 +15,10 @@ class AppDelegate
|
|
190
15
|
end
|
191
16
|
|
192
17
|
def submit
|
193
|
-
@form.submit
|
18
|
+
@view_controller.form.submit
|
194
19
|
end
|
195
20
|
|
196
21
|
def reset_form
|
197
|
-
|
22
|
+
AccountSettingsController.set_api_url_and_key_from_saved_settings
|
198
23
|
end
|
199
24
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class AccountSettingsController < Formotion::FormController
|
2
|
+
PERSIST_AS = :account_settings
|
3
|
+
|
4
|
+
API_SERVER = "hello_world"
|
5
|
+
API_KEY = "123123secret"
|
6
|
+
|
7
|
+
SETTINGS_HASH = {
|
8
|
+
title: "Application",
|
9
|
+
persist_as: PERSIST_AS,
|
10
|
+
sections: [{
|
11
|
+
rows: [{
|
12
|
+
title: "Server",
|
13
|
+
type: :string,
|
14
|
+
key: :server,
|
15
|
+
value: API_SERVER,
|
16
|
+
auto_correction: :no,
|
17
|
+
auto_capitalization: :none
|
18
|
+
}, {
|
19
|
+
title: "API Key",
|
20
|
+
value: API_KEY,
|
21
|
+
type: :string,
|
22
|
+
key: :api_key,
|
23
|
+
secure: false,
|
24
|
+
auto_correction: :no,
|
25
|
+
auto_capitalization: :none
|
26
|
+
}]
|
27
|
+
}]
|
28
|
+
}
|
29
|
+
|
30
|
+
def self.set_api_url_and_key_from_saved_settings
|
31
|
+
form = Formotion::Form.new(SETTINGS_HASH)
|
32
|
+
form.open
|
33
|
+
server_url_str = form.render[:server]
|
34
|
+
server_api_key = form.render[:api_key]
|
35
|
+
p "server_url_str #{server_url_str}"
|
36
|
+
p "server_api_key #{server_api_key}"
|
37
|
+
if server_url_str && server_api_key
|
38
|
+
if NSURLConnection.canHandleRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(server_url_str)))
|
39
|
+
#Tillless::ApiHelper.set_api_url(server_url_str)
|
40
|
+
#Tillless::ApiHelper.set_api_key(server_api_key)
|
41
|
+
else
|
42
|
+
NSLog "Unable to set url from saved config in app_delegate: #{server_url_str}"
|
43
|
+
end
|
44
|
+
else
|
45
|
+
NSLog "No configuration found"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def initController
|
50
|
+
f = Formotion::Form.persist(SETTINGS_HASH)
|
51
|
+
initWithForm(f)
|
52
|
+
end
|
53
|
+
end
|
data/lib/formotion/form/form.rb
CHANGED
@@ -229,18 +229,20 @@ module Formotion
|
|
229
229
|
# places observers to save on changes
|
230
230
|
def open
|
231
231
|
@form_observer ||= lambda { |form, saved_form|
|
232
|
-
form.
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
232
|
+
form.sections.each_with_index do |section, s_index|
|
233
|
+
section.rows.each_with_index do |row, index|
|
234
|
+
temp_row = saved_form.sections[s_index].rows[index]
|
235
|
+
|
236
|
+
if row.subform?
|
237
|
+
@saved_subform = temp_row.subform.to_form
|
238
|
+
@form_observer.call(row.subform.to_form, @saved_subform)
|
239
|
+
@saved_subform = nil
|
240
|
+
else
|
241
|
+
row.value = temp_row.value
|
242
|
+
|
243
|
+
observe(row, "value") do |old_value, new_value|
|
244
|
+
self.save
|
245
|
+
end
|
244
246
|
end
|
245
247
|
end
|
246
248
|
end
|
@@ -260,15 +262,16 @@ module Formotion
|
|
260
262
|
App::Persistence[persist_key] = nil
|
261
263
|
|
262
264
|
@form_resetter ||= lambda { |form, original_form|
|
263
|
-
form.
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
265
|
+
form.sections.each_with_index do |section, s_index|
|
266
|
+
section.rows.each_with_index do |row, index|
|
267
|
+
temp_row = original_form.sections[s_index].rows[index]
|
268
|
+
|
269
|
+
if row.subform?
|
270
|
+
original_subform = temp_row.subform.to_form
|
271
|
+
@form_resetter.call(row.subform.to_form, original_subform)
|
272
|
+
else
|
273
|
+
row.value = temp_row.value
|
274
|
+
end
|
272
275
|
end
|
273
276
|
end
|
274
277
|
}
|
@@ -18,7 +18,7 @@ class UITextView
|
|
18
18
|
attr_accessor :menu_options_enabled
|
19
19
|
|
20
20
|
def canPerformAction(action, withSender:sender)
|
21
|
-
self.menu_options_enabled
|
21
|
+
self.menu_options_enabled.nil? ? true : self.menu_options_enabled
|
22
22
|
end
|
23
23
|
|
24
24
|
# block takes argument textView; should return true/false
|
data/lib/formotion/row/row.rb
CHANGED
@@ -13,14 +13,26 @@ module Formotion
|
|
13
13
|
# either Formotion::RowType or a string/symbol representation of one
|
14
14
|
# see row_type.rb
|
15
15
|
:type,
|
16
|
+
# Stores possible date pickers mode; corresponds to UIDatePickerMode______
|
17
|
+
# OPTIONS: :time, :date, :date_time, :countdown
|
18
|
+
# DEFAULT is :date
|
19
|
+
:picker_mode,
|
16
20
|
# Stores possible formatting information (used by date pickers, etc)
|
17
21
|
# if :type == :date, accepts values in [:short, :medium, :long, :full]
|
18
22
|
:format,
|
19
23
|
# alternative title for row (only used in EditRow for now)
|
20
24
|
:alt_title,
|
25
|
+
# determines if the user can edit the row
|
26
|
+
# OPTIONS: true, false
|
27
|
+
# DEFAULT: true
|
28
|
+
:editable,
|
21
29
|
|
22
30
|
# The following apply only to text-input fields
|
23
31
|
|
32
|
+
# text alignment of the input field
|
33
|
+
# OPTIONS: :left, :right, :center
|
34
|
+
# DEFAULT is :right
|
35
|
+
:text_alignment,
|
24
36
|
# placeholder text
|
25
37
|
:placeholder,
|
26
38
|
# whether or not the entry field is secure (like a password)
|
@@ -169,7 +181,7 @@ module Formotion
|
|
169
181
|
end
|
170
182
|
|
171
183
|
def subform?
|
172
|
-
self.type ==
|
184
|
+
self.type.to_s == "subform"
|
173
185
|
end
|
174
186
|
|
175
187
|
#########################
|
@@ -218,6 +230,33 @@ module Formotion
|
|
218
230
|
@clear_button = const_int_get("UITextFieldViewMode", value)
|
219
231
|
end
|
220
232
|
|
233
|
+
def text_alignment=(alignment)
|
234
|
+
@text_alignment = const_int_get("UITextAlignment", alignment)
|
235
|
+
end
|
236
|
+
|
237
|
+
def editable=(editable)
|
238
|
+
case editable
|
239
|
+
when TrueClass
|
240
|
+
when FalseClass
|
241
|
+
when NSNull
|
242
|
+
editable = false
|
243
|
+
when NilClass
|
244
|
+
editable = false
|
245
|
+
when NSString
|
246
|
+
editable = (editable == "true")
|
247
|
+
else
|
248
|
+
raise Formotion::InvalidClassError, "Invalid class for `Row#editable`: #{editable.inspect}; should be TrueClass, FalseCLass, or NSString"
|
249
|
+
end
|
250
|
+
@editable = editable
|
251
|
+
end
|
252
|
+
|
253
|
+
def editable?
|
254
|
+
if !self.editable.nil?
|
255
|
+
return self.editable
|
256
|
+
end
|
257
|
+
true
|
258
|
+
end
|
259
|
+
|
221
260
|
#########################
|
222
261
|
# setters for callbacks
|
223
262
|
|
@@ -305,8 +344,9 @@ module Formotion
|
|
305
344
|
UIReturnKeyYahoo, UIReturnKeyDone, UIReturnKeyEmergencyCall,
|
306
345
|
UITextFieldViewModeNever, UITextFieldViewModeAlways, UITextFieldViewModeWhileEditing,
|
307
346
|
UITextFieldViewModeUnlessEditing, NSDateFormatterShortStyle, NSDateFormatterMediumStyle,
|
308
|
-
NSDateFormatterLongStyle, NSDateFormatterFullStyle
|
347
|
+
NSDateFormatterLongStyle, NSDateFormatterFullStyle,
|
348
|
+
UITextAlignmentRight, UITextAlignmentCenter, UITextAlignmentLeft
|
309
349
|
]
|
310
350
|
end
|
311
351
|
end
|
312
|
-
end
|
352
|
+
end
|
@@ -3,7 +3,13 @@ module Formotion
|
|
3
3
|
class Base
|
4
4
|
attr_accessor :row, :tableView
|
5
5
|
|
6
|
-
|
6
|
+
def self.field_buffer
|
7
|
+
if Device.iphone? or App.window.size.width <= 320
|
8
|
+
20
|
9
|
+
else
|
10
|
+
64
|
11
|
+
end
|
12
|
+
end
|
7
13
|
|
8
14
|
def tableView
|
9
15
|
@tableView ||= self.row.form.table
|
@@ -17,8 +17,8 @@ module Formotion
|
|
17
17
|
((self.frame.size.send(dimen) - frame.size.send(dimen)) / 2.0)
|
18
18
|
}
|
19
19
|
|
20
|
-
self.textLabel.center = CGPointMake(self.frame.size.width / 2 - (
|
21
|
-
self.detailTextLabel.center = CGPointMake(self.frame.size.width / 2 - (
|
20
|
+
self.textLabel.center = CGPointMake(self.frame.size.width / 2 - (Formotion::RowType::Base.field_buffer / 2), self.textLabel.center.y)
|
21
|
+
self.detailTextLabel.center = CGPointMake(self.frame.size.width / 2 - (Formotion::RowType::Base.field_buffer / 2), self.detailTextLabel.center.y)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
nil
|
@@ -26,16 +26,13 @@ module Formotion
|
|
26
26
|
if date_style && date_style.to_s[-5..-1] != "style"
|
27
27
|
date_style = (date_style.to_s + "_style").to_sym
|
28
28
|
end
|
29
|
+
|
29
30
|
formatter.dateStyle = self.row.send(:const_int_get, "NSDateFormatter", date_style || NSDateFormatterShortStyle)
|
31
|
+
formatter.timeStyle = NSDateFormatterNoStyle
|
30
32
|
formatter
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
def formatted_value
|
35
|
-
return formatter.stringFromDate(self.date_value) if self.date_value
|
36
|
-
self.row.value
|
37
|
-
end
|
38
|
-
|
39
36
|
def after_build(cell)
|
40
37
|
self.row.text_field.inputView = self.picker
|
41
38
|
update
|
@@ -44,12 +41,16 @@ module Formotion
|
|
44
41
|
def picker
|
45
42
|
@picker ||= begin
|
46
43
|
picker = UIDatePicker.alloc.initWithFrame(CGRectZero)
|
47
|
-
picker.datePickerMode =
|
44
|
+
picker.datePickerMode = self.picker_mode
|
48
45
|
picker.hidden = false
|
49
46
|
picker.date = self.date_value || NSDate.date
|
50
47
|
|
51
48
|
picker.when(UIControlEventValueChanged) do
|
52
|
-
self.row.
|
49
|
+
if self.row.picker_mode == :countdown
|
50
|
+
self.row.value = @picker.countDownDuration
|
51
|
+
else
|
52
|
+
self.row.value = @picker.date.timeIntervalSince1970.to_i
|
53
|
+
end
|
53
54
|
update
|
54
55
|
end
|
55
56
|
|
@@ -57,10 +58,63 @@ module Formotion
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
61
|
+
def picker_mode
|
62
|
+
case self.row.picker_mode
|
63
|
+
when :time
|
64
|
+
UIDatePickerModeTime
|
65
|
+
when :date_time
|
66
|
+
UIDatePickerModeDateAndTime
|
67
|
+
when :countdown
|
68
|
+
UIDatePickerModeCountDownTimer
|
69
|
+
else
|
70
|
+
UIDatePickerModeDate
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def formatted_value
|
75
|
+
if self.date_value
|
76
|
+
return case self.row.picker_mode
|
77
|
+
when :time
|
78
|
+
old_date_style = formatter.dateStyle
|
79
|
+
formatter.dateStyle = NSDateFormatterNoStyle
|
80
|
+
formatter.timeStyle = NSDateFormatterShortStyle
|
81
|
+
formatted = formatter.stringFromDate(self.date_value)
|
82
|
+
formatter.dateStyle = old_date_style
|
83
|
+
formatter.timeStyle = NSDateFormatterNoStyle
|
84
|
+
formatted
|
85
|
+
when :date_time
|
86
|
+
old_date_style = formatter.dateStyle
|
87
|
+
formatter.dateStyle = NSDateFormatterShortStyle
|
88
|
+
formatter.timeStyle = NSDateFormatterShortStyle
|
89
|
+
formatted = formatter.stringFromDate(self.date_value)
|
90
|
+
formatter.dateStyle = old_date_style
|
91
|
+
formatter.timeStyle = NSDateFormatterNoStyle
|
92
|
+
formatted
|
93
|
+
when :countdown
|
94
|
+
time = self.row.value
|
95
|
+
date = NSDate.dateWithTimeIntervalSinceReferenceDate(time)
|
96
|
+
old_date_style = formatter.dateStyle
|
97
|
+
old_time_zone = formatter.timeZone
|
98
|
+
|
99
|
+
formatter.dateFormat = "HH:mm"
|
100
|
+
formatter.timeZone = NSTimeZone.timeZoneForSecondsFromGMT(0)
|
101
|
+
formatted = formatter.stringFromDate(date)
|
102
|
+
|
103
|
+
formatter.dateStyle = old_date_style
|
104
|
+
formatter.timeZone = old_time_zone
|
105
|
+
formatter.dateFormat = nil
|
106
|
+
formatted
|
107
|
+
else
|
108
|
+
formatter.stringFromDate(self.date_value)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
self.row.value
|
112
|
+
end
|
113
|
+
|
60
114
|
# Used when row.value changes
|
61
115
|
def update_text_field(new_value)
|
62
116
|
self.row.text_field.text = self.formatted_value
|
63
117
|
end
|
64
118
|
end
|
65
119
|
end
|
66
|
-
end
|
120
|
+
end
|
@@ -36,15 +36,18 @@ module Formotion
|
|
36
36
|
|
37
37
|
field_frame = formotion_field.frame
|
38
38
|
field_frame.origin.y = 10
|
39
|
-
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width +
|
40
|
-
field_frame.size.width = self.frame.size.width - field_frame.origin.x -
|
41
|
-
field_frame.size.height = self.frame.size.height -
|
39
|
+
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width + Formotion::RowType::Base.field_buffer
|
40
|
+
field_frame.size.width = self.frame.size.width - field_frame.origin.x - Formotion::RowType::Base.field_buffer
|
41
|
+
field_frame.size.height = self.frame.size.height - Formotion::RowType::Base.field_buffer
|
42
42
|
formotion_field.frame = field_frame
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
def on_select(tableView, tableViewDelegate)
|
48
|
+
if !row.editable?
|
49
|
+
return
|
50
|
+
end
|
48
51
|
@action_sheet = UIActionSheet.alloc.init
|
49
52
|
@action_sheet.delegate = self
|
50
53
|
|
@@ -10,6 +10,7 @@ module Formotion
|
|
10
10
|
segmentedControl = UISegmentedControl.alloc.initWithItems(item_names || [])
|
11
11
|
segmentedControl.selectedSegmentIndex = name_index_of_value(row.value) if row.value
|
12
12
|
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar
|
13
|
+
segmentedControl.userInteractionEnabled = row.editable?
|
13
14
|
cell.accessoryView = cell.editingAccessoryView = segmentedControl
|
14
15
|
|
15
16
|
segmentedControl.when(UIControlEventValueChanged) do
|
@@ -18,17 +18,12 @@ module Formotion
|
|
18
18
|
picker.dataSource = self
|
19
19
|
picker.delegate = self
|
20
20
|
|
21
|
-
if self.row.value
|
22
|
-
picker_row = name_index_of_value(row.value)
|
23
|
-
if picker_row != nil
|
24
|
-
picker.selectRow(picker_row, inComponent:0, animated:false)
|
25
|
-
else
|
26
|
-
warn "Picker item '#{row.value}' not found in #{row.items.inspect} for '#{row.key}'"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
21
|
picker
|
31
22
|
end
|
23
|
+
|
24
|
+
select_picker_value(row.value) if self.row.value
|
25
|
+
|
26
|
+
@picker
|
32
27
|
end
|
33
28
|
|
34
29
|
def numberOfComponentsInPickerView(pickerView)
|
@@ -55,6 +50,16 @@ module Formotion
|
|
55
50
|
|
56
51
|
def update_text_field(new_value)
|
57
52
|
self.row.text_field.text = name_for_value(new_value)
|
53
|
+
select_picker_value(new_value)
|
54
|
+
end
|
55
|
+
|
56
|
+
def select_picker_value(new_value)
|
57
|
+
picker_row = name_index_of_value(new_value)
|
58
|
+
if picker_row != nil
|
59
|
+
@picker.selectRow(picker_row, inComponent:0, animated:false)
|
60
|
+
else
|
61
|
+
warn "Picker item '#{row.value}' not found in #{row.items.inspect} for '#{row.key}'"
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
60
65
|
def row_value
|
@@ -15,6 +15,7 @@ module Formotion
|
|
15
15
|
slideView.tag = SLIDER_VIEW_TAG
|
16
16
|
slideView.setValue(row.value, animated:true) if row.value
|
17
17
|
slideView.accessibilityLabel = (row.title || "") + " Slider"
|
18
|
+
slideView.userInteractionEnabled = row.editable?
|
18
19
|
|
19
20
|
slideView.when(UIControlEventValueChanged) do
|
20
21
|
break_with_semaphore do
|
@@ -38,9 +39,9 @@ module Formotion
|
|
38
39
|
|
39
40
|
field_frame = formotion_field.frame
|
40
41
|
field_frame.origin.y = 10
|
41
|
-
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width +
|
42
|
-
field_frame.size.width = self.frame.size.width - field_frame.origin.x -
|
43
|
-
field_frame.size.height = self.frame.size.height -
|
42
|
+
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width + Formotion::RowType::Base.field_buffer
|
43
|
+
field_frame.size.width = self.frame.size.width - field_frame.origin.x - Formotion::RowType::Base.field_buffer
|
44
|
+
field_frame.size.height = self.frame.size.height - Formotion::RowType::Base.field_buffer
|
44
45
|
formotion_field.frame = field_frame
|
45
46
|
end
|
46
47
|
end
|
@@ -30,7 +30,7 @@ module Formotion
|
|
30
30
|
|
31
31
|
field.clearButtonMode = UITextFieldViewModeWhileEditing
|
32
32
|
field.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter
|
33
|
-
field.textAlignment = UITextAlignmentRight
|
33
|
+
field.textAlignment = row.text_alignment || UITextAlignmentRight
|
34
34
|
|
35
35
|
field.keyboardType = keyboardType
|
36
36
|
|
@@ -39,6 +39,7 @@ module Formotion
|
|
39
39
|
field.autocapitalizationType = row.auto_capitalization if row.auto_capitalization
|
40
40
|
field.autocorrectionType = row.auto_correction if row.auto_correction
|
41
41
|
field.clearButtonMode = row.clear_button || UITextFieldViewModeWhileEditing
|
42
|
+
field.enabled = row.editable?
|
42
43
|
|
43
44
|
add_callbacks(field)
|
44
45
|
|
@@ -51,9 +52,9 @@ module Formotion
|
|
51
52
|
formotion_field.sizeToFit
|
52
53
|
|
53
54
|
field_frame = formotion_field.frame
|
54
|
-
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width +
|
55
|
+
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width + Formotion::RowType::Base.field_buffer
|
55
56
|
field_frame.origin.y = ((self.frame.size.height - field_frame.size.height) / 2.0).round
|
56
|
-
field_frame.size.width = self.frame.size.width - field_frame.origin.x -
|
57
|
+
field_frame.size.width = self.frame.size.width - field_frame.origin.x - Formotion::RowType::Base.field_buffer
|
57
58
|
formotion_field.frame = field_frame
|
58
59
|
end
|
59
60
|
end
|
@@ -127,6 +128,9 @@ module Formotion
|
|
127
128
|
end
|
128
129
|
|
129
130
|
def on_select(tableView, tableViewDelegate)
|
131
|
+
if !row.editable?
|
132
|
+
return
|
133
|
+
end
|
130
134
|
row.text_field.becomeFirstResponder
|
131
135
|
end
|
132
136
|
|
@@ -20,6 +20,7 @@ module Formotion
|
|
20
20
|
field.autocapitalizationType = row.auto_capitalization if row.auto_capitalization
|
21
21
|
field.autocorrectionType = row.auto_correction if row.auto_correction
|
22
22
|
field.placeholder = row.placeholder
|
23
|
+
field.enabled = row.editable?
|
23
24
|
|
24
25
|
field.on_begin do |text_field|
|
25
26
|
row.on_begin_callback && row.on_begin_callback.call
|
@@ -60,9 +61,9 @@ module Formotion
|
|
60
61
|
|
61
62
|
field_frame = formotion_field.frame
|
62
63
|
field_frame.origin.y = 10
|
63
|
-
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width +
|
64
|
-
field_frame.size.width = self.frame.size.width - field_frame.origin.x -
|
65
|
-
field_frame.size.height = self.frame.size.height -
|
64
|
+
field_frame.origin.x = self.textLabel.frame.origin.x + self.textLabel.frame.size.width + Formotion::RowType::Base.field_buffer
|
65
|
+
field_frame.size.width = self.frame.size.width - field_frame.origin.x - Formotion::RowType::Base.field_buffer
|
66
|
+
field_frame.size.height = self.frame.size.height - Formotion::RowType::Base.field_buffer
|
66
67
|
formotion_field.frame = field_frame
|
67
68
|
end
|
68
69
|
end
|
@@ -72,6 +73,9 @@ module Formotion
|
|
72
73
|
end
|
73
74
|
|
74
75
|
def on_select(tableView, tableViewDelegate)
|
76
|
+
if !row.editable?
|
77
|
+
return
|
78
|
+
end
|
75
79
|
field.becomeFirstResponder
|
76
80
|
end
|
77
81
|
|
data/lib/formotion/version.rb
CHANGED
data/spec/form/persist_spec.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
describe "Form Persisting" do
|
2
2
|
|
3
3
|
it "works" do
|
4
|
+
key = "test_#{rand(255)}"
|
5
|
+
App::Persistence["FORMOTION_#{key}"] = nil
|
6
|
+
App::Persistence["FORMOTION_#{key}_ORIGINAL"] = nil
|
4
7
|
f = Formotion::Form.persist({
|
5
|
-
persist_as:
|
8
|
+
persist_as: key,
|
6
9
|
sections: [
|
7
10
|
rows: [ {
|
8
11
|
key: "first",
|
@@ -24,8 +27,11 @@ describe "Form Persisting" do
|
|
24
27
|
end
|
25
28
|
|
26
29
|
it "works with subforms" do
|
27
|
-
|
28
|
-
|
30
|
+
key = "test_#{rand(255)}"
|
31
|
+
App::Persistence["FORMOTION_#{key}"] = nil
|
32
|
+
App::Persistence["FORMOTION_#{key}_ORIGINAL"] = nil
|
33
|
+
hash = {
|
34
|
+
persist_as: key,
|
29
35
|
sections: [
|
30
36
|
rows: [ {
|
31
37
|
key: :subform,
|
@@ -44,7 +50,9 @@ describe "Form Persisting" do
|
|
44
50
|
}
|
45
51
|
]
|
46
52
|
]
|
47
|
-
}
|
53
|
+
}
|
54
|
+
f = Formotion::Form.persist(hash)
|
55
|
+
f.to_hash.should == hash
|
48
56
|
|
49
57
|
r = f.sections[0].rows[0].subform.to_form.sections[0].rows[0]
|
50
58
|
r.value = "new value"
|
data/spec/row_type/date_spec.rb
CHANGED
@@ -59,4 +59,24 @@ describe "Date Row" do
|
|
59
59
|
@row.text_field.text.should == expected_output
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
|
+
# Modes
|
64
|
+
{
|
65
|
+
:date => '1/1/00',
|
66
|
+
:time => '12:57 AM',
|
67
|
+
:date_time => '1/1/00, 12:57 AM',
|
68
|
+
:countdown => '00:57'
|
69
|
+
}.each do |mode, expected_output|
|
70
|
+
|
71
|
+
it "should display chosen mode #{mode} date/time format #{expected_output}" do
|
72
|
+
@row.format = :short
|
73
|
+
@row.picker_mode = mode
|
74
|
+
cell = @row.make_cell
|
75
|
+
@row.object.picker.date = NSDate.dateWithTimeIntervalSince1970(MILLENIUM)
|
76
|
+
@row.object.picker.trigger UIControlEventValueChanged
|
77
|
+
|
78
|
+
@row.text_field.text.should == expected_output
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formotion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bubble-wrap
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- examples/Persistence/README.md
|
82
82
|
- examples/Persistence/Rakefile
|
83
83
|
- examples/Persistence/app/app_delegate.rb
|
84
|
+
- examples/Persistence/app/controller.rb
|
84
85
|
- examples/Persistence/spec/main_spec.rb
|
85
86
|
- gh-pages/assets/css/bootstrap-responsive.css
|
86
87
|
- gh-pages/assets/css/bootstrap-responsive.min.css
|
@@ -197,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
197
198
|
version: '0'
|
198
199
|
segments:
|
199
200
|
- 0
|
200
|
-
hash:
|
201
|
+
hash: 3006402350062917066
|
201
202
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
202
203
|
none: false
|
203
204
|
requirements:
|
@@ -206,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
207
|
version: '0'
|
207
208
|
segments:
|
208
209
|
- 0
|
209
|
-
hash:
|
210
|
+
hash: 3006402350062917066
|
210
211
|
requirements: []
|
211
212
|
rubyforge_project:
|
212
213
|
rubygems_version: 1.8.23
|