formotion 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.1.5 - November 9, 2012
2
+
3
+ ### Features
4
+
5
+ - Added `form.values = { key: "value" }`, which will set all of the form's `value`s for each specified `key` en-masse.
6
+
7
+ - `:options` and `:picker` rows support a mapping between the displayed value and the row's value. Ex: `row.items = [["User 1", user1_id], ["User 2", user2_id]]
8
+
9
+ - `:static` rows are now able to use `:placeholder` and `:value` attributes to display text along the right-hand side.
10
+
1
11
  ## 1.1.4 - October 27, 2012
2
12
 
3
13
  ### Features
@@ -20,8 +20,9 @@ class AppDelegate
20
20
  }, {
21
21
  title: "Gender",
22
22
  key: :gender,
23
- type: :options,
24
- items: ['Female', 'Male']
23
+ type: :picker,
24
+ items: [['Female', 'f'], ['Male', 'm']],
25
+ value: 'm'
25
26
  }, {
26
27
  title: "Password",
27
28
  key: :password,
@@ -194,6 +194,34 @@ module Formotion
194
194
  kv
195
195
  end
196
196
 
197
+ def values=(data)
198
+ self.sections.each {|section|
199
+ if section.select_one?
200
+ # see if one of the select one value is used
201
+ unless (section.rows.map{ |r| r.key } & data.keys).empty?
202
+ section.rows.each { |row|
203
+ row.value = data.has_key?(row.key) ? true : nil
204
+ }
205
+ end
206
+ else
207
+ section.rows.each {|row|
208
+ next if row.button?
209
+ if row.template_parent
210
+ # If this row is part of a template
211
+ # use the parent's key
212
+ row.value = data[row.template_parent_key] if data.has_key?(row.template_parent_key)
213
+ elsif row.subform
214
+ row.subform.to_form.values = data
215
+ else
216
+ row.value = data[row.key] if data.has_key?(row.key)
217
+ end
218
+ }
219
+ end
220
+ }
221
+ end
222
+
223
+ alias_method :fill_out, :values=
224
+
197
225
  #########################
198
226
  # Persisting Forms
199
227
 
@@ -0,0 +1,43 @@
1
+ module Formotion
2
+ module RowType
3
+ module ItemsMapper
4
+ def items
5
+ if !row.items
6
+ []
7
+ elsif row.items[0].is_a?(Enumerable)
8
+ row.items
9
+ else
10
+ row.items.map {|i| [i, i]}
11
+ end
12
+ end
13
+
14
+ def item_names
15
+ self.items.map { |name, value| name }
16
+ end
17
+
18
+ def item_names_hash
19
+ hash = {}
20
+ self.items.each do |name, value|
21
+ hash[name] = value
22
+ end
23
+ hash
24
+ end
25
+
26
+ def name_index_of_value(value)
27
+ item_names.index(item_names_hash.invert[value])
28
+ end
29
+
30
+ def value_for_name_index(index)
31
+ item_names_hash[item_names[index]]
32
+ end
33
+
34
+ def value_for_name(name)
35
+ item_names_hash[name]
36
+ end
37
+
38
+ def name_for_value(value)
39
+ item_names_hash.invert[value].to_s
40
+ end
41
+ end
42
+ end
43
+ end
@@ -2,23 +2,25 @@ module Formotion
2
2
  module RowType
3
3
  class OptionsRow < Base
4
4
  include BW::KVO
5
+ include RowType::ItemsMapper
5
6
 
6
7
  def build_cell(cell)
7
8
  cell.selectionStyle = UITableViewCellSelectionStyleNone
8
- segmentedControl = UISegmentedControl.alloc.initWithItems(row.items || [])
9
- segmentedControl.selectedSegmentIndex = row.items.index(row.value) if row.value
9
+
10
+ segmentedControl = UISegmentedControl.alloc.initWithItems(item_names || [])
11
+ segmentedControl.selectedSegmentIndex = name_index_of_value(row.value) if row.value
10
12
  segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar
11
13
  cell.accessoryView = cell.editingAccessoryView = segmentedControl
12
14
 
13
15
  segmentedControl.when(UIControlEventValueChanged) do
14
16
  break_with_semaphore do
15
- row.value = row.items[segmentedControl.selectedSegmentIndex]
17
+ row.value = value_for_name_index(segmentedControl.selectedSegmentIndex)
16
18
  end
17
19
  end
18
20
  observe(self.row, "value") do |old_value, new_value|
19
21
  break_with_semaphore do
20
22
  if row.value
21
- segmentedControl.selectedSegmentIndex = row.items.index(row.value)
23
+ segmentedControl.selectedSegmentIndex = name_index_of_value(row.value)
22
24
  else
23
25
  segmentedControl.selectedSegmentIndex = UISegmentedControlNoSegment
24
26
  end
@@ -27,8 +29,6 @@ module Formotion
27
29
 
28
30
  nil
29
31
  end
30
-
31
-
32
32
  end
33
33
  end
34
34
  end
@@ -3,9 +3,11 @@
3
3
  module Formotion
4
4
  module RowType
5
5
  class PickerRow < StringRow
6
+ include RowType::ItemsMapper
6
7
 
7
8
  def after_build(cell)
8
9
  self.row.text_field.inputView = self.picker
10
+ self.row.text_field.text = name_for_value(row.value).to_s
9
11
  end
10
12
 
11
13
  def picker
@@ -17,8 +19,8 @@ module Formotion
17
19
  picker.delegate = self
18
20
 
19
21
  if self.row.value
20
- picker_row = self.row.items.index(row.value)
21
- if picker_row
22
+ picker_row = name_index_of_value(row.value)
23
+ if picker_row != nil
22
24
  picker.selectRow(picker_row, inComponent:0, animated:false)
23
25
  else
24
26
  warn "Picker item '#{row.value}' not found in #{row.items.inspect} for '#{row.key}'"
@@ -34,21 +36,30 @@ module Formotion
34
36
  end
35
37
 
36
38
  def pickerView(pickerView, numberOfRowsInComponent:component)
37
- self.row.items.size
39
+ self.items.size
38
40
  end
39
41
 
40
42
  def pickerView(pickerView, titleForRow:index, forComponent:component)
41
- self.row.items[index]
43
+ self.item_names[index]
42
44
  end
43
45
 
44
46
  def pickerView(pickerView, didSelectRow:index, inComponent:component)
45
- update_row(self.row.items[index])
47
+ update_text_field(value_for_name_index(index))
46
48
  end
47
49
 
48
- def update_row(value)
49
- self.row.text_field && self.row.text_field.text = value
50
+ def on_change(text_field)
51
+ break_with_semaphore do
52
+ row.value = value_for_name(text_field.text)
53
+ end
54
+ end
55
+
56
+ def update_text_field(new_value)
57
+ self.row.text_field.text = name_for_value(new_value)
50
58
  end
51
59
 
60
+ def row_value
61
+ name_for_value(row.value)
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -1,6 +1,9 @@
1
1
  module Formotion
2
2
  module RowType
3
- class StaticRow < Base
3
+ class StaticRow < StringRow
4
+ def after_build(cell)
5
+ self.row.text_field.enabled = false
6
+ end
4
7
  end
5
8
  end
6
9
  end
@@ -69,12 +69,17 @@ module Formotion
69
69
  end
70
70
 
71
71
  field.placeholder = row.placeholder
72
- field.text = row.value.to_s
72
+ field.text = row_value
73
73
  cell.addSubview(field)
74
74
  field
75
75
 
76
76
  end
77
77
 
78
+ # overriden in subclasses
79
+ def row_value
80
+ row.value.to_s
81
+ end
82
+
78
83
  def add_callbacks(field)
79
84
  if row.on_enter_callback
80
85
  field.should_return? do |text_field|
@@ -1,3 +1,3 @@
1
1
  module Formotion
2
- VERSION = "1.1.4"
2
+ VERSION = "1.1.5"
3
3
  end
data/spec/form_spec.rb CHANGED
@@ -68,6 +68,75 @@ describe "Forms" do
68
68
  @form.render[:email].should == 'something@email.com'
69
69
  end
70
70
 
71
+ it "fills out form values correctly" do
72
+ @form = Formotion::Form.new(sections: [{
73
+ rows: [{
74
+ key: :email,
75
+ type: :email,
76
+ editable: true,
77
+ title: 'Email'
78
+ }]}])
79
+
80
+ @form.values = { :email => 'something@email.com' }
81
+
82
+ row = @form.sections[0].rows[0]
83
+ row.value.should == 'something@email.com'
84
+ end
85
+
86
+ it "fills out form values correctly with a select one" do
87
+ @form = Formotion::Form.new(sections: [{
88
+ select_one: true,
89
+ rows: [{
90
+ title: "A",
91
+ key: :a,
92
+ type: :check,
93
+ value: true
94
+ }, {
95
+ title: "B",
96
+ key: :b,
97
+ type: :check,
98
+ }, {
99
+ title: "C",
100
+ key: :c,
101
+ type: :check,
102
+ }]
103
+ }])
104
+
105
+ @form.values = { :b => true }
106
+
107
+ row = @form.sections[0].rows[0]
108
+ row.value.should == nil
109
+ row = @form.sections[0].rows[1]
110
+ row.value.should == true
111
+ row = @form.sections[0].rows[2]
112
+ row.value.should == nil
113
+ end
114
+
115
+ it "fills out form values correctly with a template" do
116
+ @form = Formotion::Form.new(sections: [
117
+ {
118
+ title: 'Your nicknames',
119
+ rows: [{
120
+ title: "Add nickname",
121
+ key: :nicknames,
122
+ type: :template,
123
+ template: {
124
+ title: 'Nickname',
125
+ type: :string,
126
+ placeholder: 'Enter here',
127
+ indented: true,
128
+ deletable: true
129
+ }
130
+ }]
131
+ }])
132
+
133
+
134
+ @form.values = { :nicknames => ["Nici", "Sam"] }
135
+
136
+ row = @form.sections[0].rows[0]
137
+ row.value.should == ["Nici", "Sam"]
138
+ end
139
+
71
140
  it "render with subforms works correctly" do
72
141
  @form = Formotion::Form.new(sections: [{
73
142
  rows: [{
@@ -92,6 +161,30 @@ describe "Forms" do
92
161
  @form.render[:subform][:email].should == 'something@email.com'
93
162
  end
94
163
 
164
+ it "fills out subform values correctly" do
165
+ @form = Formotion::Form.new(sections: [{
166
+ rows: [{
167
+ type: :subform,
168
+ key: :subform,
169
+ subform: {
170
+ sections: [{
171
+ rows: [{
172
+ key: :email,
173
+ type: :email,
174
+ editable: true,
175
+ title: 'Email'
176
+ }]
177
+ }]
178
+ }
179
+ }]}])
180
+
181
+ @form.values = { :email => 'something@email.com' }
182
+
183
+ subform = @form.sections[0].rows[0].subform.to_form
184
+ row = subform.sections[0].rows[0]
185
+ row.value.should == 'something@email.com'
186
+ end
187
+
95
188
  it "hashifying should be same as input" do
96
189
  h = {
97
190
  sections: [{
@@ -42,4 +42,16 @@ describe "Options Row" do
42
42
  @row.value = nil
43
43
  cell.accessoryView.selectedSegmentIndex.should == UISegmentedControlNoSegment
44
44
  end
45
+
46
+ it "should work with name-value items" do
47
+ @row = Formotion::Row.new(title: "Options", key: :options, type: :options,
48
+ items: [["First", 1], ["Second", 2]], value: 1)
49
+ @row.reuse_identifier = 'test'
50
+ cell = @row.make_cell
51
+
52
+ cell.accessoryView.selectedSegmentIndex.should == 0
53
+
54
+ @row.value = 2
55
+ cell.accessoryView.selectedSegmentIndex.should == 1
56
+ end
45
57
  end
@@ -23,4 +23,16 @@ describe "Picker Row" do
23
23
 
24
24
  @row.text_field.text.should == "Motion"
25
25
  end
26
+
27
+ it "should work with name-value items" do
28
+ @row = Formotion::Row.new(title: "Picker", key: :picker, type: :picker,
29
+ items: [["Ruby", 1], ["Motion", 2]], value: 1)
30
+ @row.reuse_identifier = 'test'
31
+ cell = @row.make_cell
32
+
33
+ @row.text_field.text.should == "Ruby"
34
+
35
+ @row.value = 2
36
+ @row.text_field.text.should == "Motion"
37
+ end
26
38
  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.1.4
4
+ version: 1.1.5
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: 2012-10-27 00:00:00.000000000 Z
12
+ date: 2012-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bubble-wrap
@@ -128,6 +128,7 @@ files:
128
128
  - lib/formotion/row_type/edit_row.rb
129
129
  - lib/formotion/row_type/email_row.rb
130
130
  - lib/formotion/row_type/image_row.rb
131
+ - lib/formotion/row_type/items_mapper.rb
131
132
  - lib/formotion/row_type/number_row.rb
132
133
  - lib/formotion/row_type/options_row.rb
133
134
  - lib/formotion/row_type/phone_row.rb
@@ -196,7 +197,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
197
  version: '0'
197
198
  segments:
198
199
  - 0
199
- hash: 4124450526448919813
200
+ hash: 1737578013626732185
200
201
  required_rubygems_version: !ruby/object:Gem::Requirement
201
202
  none: false
202
203
  requirements:
@@ -205,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
206
  version: '0'
206
207
  segments:
207
208
  - 0
208
- hash: 4124450526448919813
209
+ hash: 1737578013626732185
209
210
  requirements: []
210
211
  rubyforge_project:
211
212
  rubygems_version: 1.8.23