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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71061dad41a80a78a4e7b26faa6fb78d284beaee
|
4
|
+
data.tar.gz: 4d6462cfe38e455077bf4736376beb84ef1ba46a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0217c216bf843420d86d38f2ef6120af5f4057d68328cae4bb28aa65d0628aeb78a8c5af21eeef22fa90a944713fae98f2827b21dc1750dc11400947b83ea4e9
|
7
|
+
data.tar.gz: 116b36b2b66855546e79d7033fcf1473926c8d3085e049c14ff8b803a8e7e737768decb49b29ffff9ebc6144e4ed5510da27afc542f309524deec2e9a185600c
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LIST_OF_ROW_TYPES.md
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
[Subform](#subform)<br/>
|
20
20
|
[Template](#template)<br/>
|
21
21
|
[MapView](#mapview)<br/>
|
22
|
+
[WebLink](#weblink)<br/>
|
22
23
|
[WebView](#webview)<br/>
|
23
24
|
[PagedImage](#pagedimage)<br/>
|
24
25
|
[Tags](#tags)<br/>
|
@@ -38,6 +39,8 @@ All row types accept following properties:
|
|
38
39
|
value: 'Some Value', # The initial value passed to the row
|
39
40
|
title: 'Title', # Title of the row
|
40
41
|
subtitle: 'Subtitle', # Subtitle of the row
|
42
|
+
image: nil, # Image for the cell's imageView. Accepts a string, UIImage, URL string, or NSURL
|
43
|
+
image_placeholder: nil # Used only when you are loading remote images. Accpets a string or UIImage
|
41
44
|
type: :string, # The type of row (string, phone, switch, etc)
|
42
45
|
row_height: 100 # Height of the row
|
43
46
|
}
|
@@ -70,11 +73,12 @@ All character based row types accept following properties:
|
|
70
73
|
type: :string,
|
71
74
|
placeholder: 'James Bond',
|
72
75
|
auto_correction: :no,
|
73
|
-
auto_capitalization: :none
|
76
|
+
auto_capitalization: :none,
|
77
|
+
input_accessory: :done
|
74
78
|
}
|
75
79
|
```
|
76
80
|
|
77
|
-
The `StringRow` is a simple text input row and opens a `UIKeyboardTypeDefault` keyboard when editing.
|
81
|
+
The `StringRow` is a simple text input row and opens a `UIKeyboardTypeDefault` keyboard when editing. `input_accessory` can be nil or `:done`, and shows a toolbar with a done button above the keyboard.
|
78
82
|
|
79
83
|
|
80
84
|
### <a name="text"></a> Text row
|
@@ -355,7 +359,8 @@ The `SliderRow` takes a ruby range as `range` property that defines the min and
|
|
355
359
|
key: :pick,
|
356
360
|
type: :picker,
|
357
361
|
items: ["Ruby", "Motion", "Rocks"],
|
358
|
-
value: "Motion"
|
362
|
+
value: "Motion",
|
363
|
+
input_accessory: :done
|
359
364
|
}
|
360
365
|
```
|
361
366
|
|
@@ -432,13 +437,60 @@ Use a `:display_key` to show the value of the subform in the row:
|
|
432
437
|
```ruby
|
433
438
|
{
|
434
439
|
title: "Map",
|
435
|
-
type: :
|
436
|
-
value: coordinates, # of type CLLocationCoordinate2D
|
440
|
+
type: :map,
|
441
|
+
value: coordinates, # of type CLLocationCoordinate2D, CLCircularRegion, or a Hash of options
|
437
442
|
row_height: 200 # for better viewing
|
438
443
|
}
|
439
444
|
```
|
440
445
|
|
441
|
-
Shows a map with a pin at the coordinates from value.
|
446
|
+
Shows a map with a pin at the coordinates from value. If you pass a `CLLocationCoordinate2D` or `CLCircularRegion`, a pin will be placed at the coordinates. You can pass a hash of options like this:
|
447
|
+
|
448
|
+
```ruby
|
449
|
+
{
|
450
|
+
title: "Map",
|
451
|
+
type: :map,
|
452
|
+
value: {
|
453
|
+
coord: coordinates,
|
454
|
+
enabled: true, # Whether the user can interact with the map.
|
455
|
+
type: MKMapTypeStandard, # The type of map to show. See MKMapType documentation.
|
456
|
+
animated: true, # Whether setting the region should animate. This property also applies to annotation titles.
|
457
|
+
pin: {
|
458
|
+
coord: coordinates, # Must be a CLLocationCoordinate2D
|
459
|
+
title: nil, # Title of the annotation
|
460
|
+
subtitle: nil # Subtitle of the annotation
|
461
|
+
}
|
462
|
+
}
|
463
|
+
row_height: 200 # for better viewing
|
464
|
+
}
|
465
|
+
```
|
466
|
+
|
467
|
+
If you pass `pin: nil` the map will not display an annotation. Annotations with titles will automatically pop open the annotation. _Note: If you set a title on an annotation it will automatically invalidate `enabled:false` and the map will be interactable._
|
468
|
+
|
469
|
+
### <a name="weblink"></a> WebLink row
|
470
|
+
```ruby
|
471
|
+
{
|
472
|
+
title: "My Awesome Site",
|
473
|
+
type: :web_link,
|
474
|
+
value: "http://www.myawesomesite.com" # URL to be opened. Can also be an NSURL
|
475
|
+
}
|
476
|
+
```
|
477
|
+
|
478
|
+
You can also allow the user to confirm leaving your app:
|
479
|
+
```ruby
|
480
|
+
{
|
481
|
+
title: "My Awesome Site",
|
482
|
+
type: :web_link,
|
483
|
+
warn: true,
|
484
|
+
# or pass a hash to :warn.
|
485
|
+
# Here are the default values (Bubblewrap alert options):
|
486
|
+
# warn: {
|
487
|
+
# title: "Leaving #{App.name}",
|
488
|
+
# message: "This action will leave #{App.name} and open Safari.",
|
489
|
+
# buttons: ["Cancel", "OK"]
|
490
|
+
# }
|
491
|
+
value: "http://www.myawesomesite.com", # URL to be opened
|
492
|
+
}
|
493
|
+
```
|
442
494
|
|
443
495
|
|
444
496
|
### <a name="webview"></a> WebView row
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
$:.unshift("/Library/RubyMotion/lib")
|
2
|
-
require 'motion/project'
|
2
|
+
require 'motion/project/template/ios'
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "bundler/setup"
|
5
|
-
|
5
|
+
Bundler.require
|
6
6
|
$:.unshift("./lib/")
|
7
7
|
require './lib/formotion'
|
8
8
|
require 'guard/motion'
|
@@ -10,6 +10,10 @@ require 'guard/motion'
|
|
10
10
|
Motion::Project::App.setup do |app|
|
11
11
|
# Use `rake config' to see complete project settings.
|
12
12
|
app.name = 'Formotion'
|
13
|
+
|
14
|
+
app.pods do
|
15
|
+
pod 'JMImageCache'
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
19
|
namespace :spec do
|
data/app/app_delegate.rb
CHANGED
@@ -11,6 +11,7 @@ class AppDelegate
|
|
11
11
|
title: "Photo",
|
12
12
|
key: :photo,
|
13
13
|
type: :image,
|
14
|
+
image: "camera",
|
14
15
|
deletable: true
|
15
16
|
},{
|
16
17
|
title: "Picker",
|
@@ -31,6 +32,11 @@ class AppDelegate
|
|
31
32
|
placeholder: "required",
|
32
33
|
type: :string,
|
33
34
|
secure: true
|
35
|
+
}, {
|
36
|
+
title: "Remote Loaded Image",
|
37
|
+
type: :static,
|
38
|
+
image: "http://placekitten.com/80/80?t=#{Time.now.to_i}",
|
39
|
+
image_placeholder: "camera"
|
34
40
|
}, {
|
35
41
|
title: "Password",
|
36
42
|
subtitle: "Confirmation",
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
$:.unshift("/Library/RubyMotion/lib")
|
3
|
-
require 'motion/project'
|
3
|
+
require 'motion/project/template/ios'
|
4
4
|
|
5
|
-
|
6
|
-
require 'bundler'
|
7
|
-
Bundler.require
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
Bundler.require
|
8
|
+
rescue LoadError
|
9
|
+
end
|
8
10
|
|
9
11
|
Motion::Project::App.setup do |app|
|
10
12
|
# Use `rake config' to see complete project settings.
|
11
13
|
app.name = 'KitchenSink'
|
14
|
+
app.pods do
|
15
|
+
pod 'SDWebImage'
|
16
|
+
end
|
12
17
|
end
|
@@ -14,15 +14,28 @@ class AppDelegate
|
|
14
14
|
title: "Email",
|
15
15
|
key: :email,
|
16
16
|
placeholder: "me@mail.com",
|
17
|
+
image: "email",
|
17
18
|
type: :email,
|
18
19
|
auto_correction: :no,
|
19
|
-
auto_capitalization: :none
|
20
|
+
auto_capitalization: :none,
|
21
|
+
input_accessory: :done
|
22
|
+
}, {
|
23
|
+
title: "Image Accessory",
|
24
|
+
subtitle: "You can add an image to any row type",
|
25
|
+
image: "arrow-up",
|
26
|
+
type: :static
|
27
|
+
}, {
|
28
|
+
title: "Image from URL",
|
29
|
+
subtitle: "Or from a URL!",
|
30
|
+
image: "http://placekitten.com/80/80?t=#{Time.now.to_i}",
|
31
|
+
type: :static
|
20
32
|
}, {
|
21
33
|
title: "Gender",
|
22
34
|
key: :gender,
|
23
35
|
type: :picker,
|
24
|
-
items: [['Female', 'f'], ['Male', 'm']],
|
25
|
-
value: 'm'
|
36
|
+
items: [['Female', 'f'],['fds', 'df'],['fddfsfds', 'f3'],['fdfafds', 'f33'], ['Male', 'm']],
|
37
|
+
value: 'm',
|
38
|
+
input_accessory: :done
|
26
39
|
}, {
|
27
40
|
title: "Password",
|
28
41
|
key: :password,
|
@@ -35,14 +48,16 @@ class AppDelegate
|
|
35
48
|
placeholder: "555-555-5555",
|
36
49
|
type: :phone,
|
37
50
|
auto_correction: :no,
|
38
|
-
auto_capitalization: :none
|
51
|
+
auto_capitalization: :none,
|
52
|
+
input_accessory: :done
|
39
53
|
}, {
|
40
54
|
title: "Number",
|
41
55
|
key: :number,
|
42
56
|
placeholder: "12345",
|
43
57
|
type: :number,
|
44
58
|
auto_correction: :no,
|
45
|
-
auto_capitalization: :none
|
59
|
+
auto_capitalization: :none,
|
60
|
+
input_accessory: :done
|
46
61
|
}, {
|
47
62
|
title: "Subtitle",
|
48
63
|
subtitle: "Confirmation",
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -6,6 +6,8 @@ class AppDelegate
|
|
6
6
|
|
7
7
|
@view_controller.navigationItem.leftBarButtonItem = UIBarButtonItem.alloc.initWithTitle("Render", style: UIBarButtonItemStyleBordered, target:self, action:'reset_form')
|
8
8
|
|
9
|
+
@view_controller.navigationItem.rightBarButtonItem = UIBarButtonItem.alloc.initWithTitle("Save", style: UIBarButtonItemStyleBordered, target:self, action:'submit')
|
10
|
+
|
9
11
|
@navigation_controller = UINavigationController.alloc.initWithRootViewController(@view_controller)
|
10
12
|
|
11
13
|
@window.rootViewController = @navigation_controller
|
@@ -4,6 +4,41 @@ class AccountSettingsController < Formotion::FormController
|
|
4
4
|
API_SERVER = "hello_world"
|
5
5
|
API_KEY = "123123secret"
|
6
6
|
|
7
|
+
SPECIAL_OPTIONS_HASH = {
|
8
|
+
title: "Special options",
|
9
|
+
sections: [{
|
10
|
+
rows: [{
|
11
|
+
title: "Phone Number",
|
12
|
+
value: "555-555-5555",
|
13
|
+
type: "phone",
|
14
|
+
key: "phone"
|
15
|
+
}, {
|
16
|
+
title: "Address",
|
17
|
+
value: "90210",
|
18
|
+
type: "string",
|
19
|
+
key: "address"
|
20
|
+
}]
|
21
|
+
}]
|
22
|
+
}
|
23
|
+
|
24
|
+
DISPLAY_KEY_HASH = {
|
25
|
+
title: "Alert Sounds",
|
26
|
+
sections: [{
|
27
|
+
key: :sound,
|
28
|
+
select_one: true,
|
29
|
+
rows: [{
|
30
|
+
title: "Beeps",
|
31
|
+
key: :Beeps,
|
32
|
+
value: true,
|
33
|
+
type: :check
|
34
|
+
},{
|
35
|
+
title: "Boops",
|
36
|
+
key: :Boops,
|
37
|
+
type: :check
|
38
|
+
}]
|
39
|
+
}]
|
40
|
+
}
|
41
|
+
|
7
42
|
SETTINGS_HASH = {
|
8
43
|
title: "Application",
|
9
44
|
persist_as: PERSIST_AS,
|
@@ -24,6 +59,37 @@ class AccountSettingsController < Formotion::FormController
|
|
24
59
|
auto_correction: :no,
|
25
60
|
auto_capitalization: :none
|
26
61
|
}]
|
62
|
+
}, {
|
63
|
+
rows: [{
|
64
|
+
title: "Name",
|
65
|
+
type: :string,
|
66
|
+
key: :name,
|
67
|
+
value: "Clay",
|
68
|
+
auto_correction: :no,
|
69
|
+
auto_capitalization: :none
|
70
|
+
}, {
|
71
|
+
title: "Password",
|
72
|
+
value: "Secret",
|
73
|
+
type: :string,
|
74
|
+
key: :password,
|
75
|
+
secure: false,
|
76
|
+
auto_correction: :no,
|
77
|
+
auto_capitalization: :none
|
78
|
+
}]
|
79
|
+
}, {
|
80
|
+
title: "w/ Subforms",
|
81
|
+
rows: [{
|
82
|
+
title: "Special Options",
|
83
|
+
type: :subform,
|
84
|
+
key: :special_options,
|
85
|
+
subform: SPECIAL_OPTIONS_HASH
|
86
|
+
}, {
|
87
|
+
title: "w/ Display Key",
|
88
|
+
type: :subform,
|
89
|
+
key: :alert_sound,
|
90
|
+
display_key: :sound,
|
91
|
+
subform: DISPLAY_KEY_HASH
|
92
|
+
}]
|
27
93
|
}]
|
28
94
|
}
|
29
95
|
|
data/lib/formotion/form/form.rb
CHANGED
@@ -267,19 +267,26 @@ module Formotion
|
|
267
267
|
end
|
268
268
|
|
269
269
|
def open
|
270
|
-
@form_observer ||=
|
270
|
+
@form_observer ||= ->(form, saved_render, uses_display_key = false) {
|
271
|
+
no_saved_render = saved_render.nil?
|
272
|
+
saved_render ||= {}
|
273
|
+
|
271
274
|
form.sections.each_with_index do |section, s_index|
|
272
275
|
section.rows.each_with_index do |row, index|
|
273
276
|
next if row.templated?
|
274
277
|
saved_row_value = saved_render[row.key]
|
275
278
|
|
279
|
+
if uses_display_key && section.select_one && saved_render.include?(section.key.to_s)
|
280
|
+
saved_row_value = row.key.to_s == saved_render[section.key.to_s].to_s
|
281
|
+
end
|
282
|
+
|
276
283
|
if row.subform?
|
277
|
-
@form_observer.call(row.subform.to_form, saved_row_value)
|
284
|
+
@form_observer.call(row.subform.to_form, saved_row_value, !!row.display_key)
|
278
285
|
elsif row.type == :template
|
279
286
|
row.value = saved_row_value
|
280
287
|
row.object.update_template_rows
|
281
288
|
else
|
282
|
-
row.value = saved_row_value
|
289
|
+
row.value = saved_row_value if !no_saved_render
|
283
290
|
end
|
284
291
|
end
|
285
292
|
end
|
@@ -294,8 +301,10 @@ module Formotion
|
|
294
301
|
|
295
302
|
# places hash of values into application persistance
|
296
303
|
def save
|
297
|
-
|
298
|
-
|
304
|
+
rendered = render
|
305
|
+
recursive_delete_nil(rendered)
|
306
|
+
App::Persistence[persist_key] = rendered
|
307
|
+
App::Persistence[original_persist_key] ||= rendered
|
299
308
|
end
|
300
309
|
|
301
310
|
def reset
|
@@ -54,7 +54,7 @@ module Formotion
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# Creates a Formotion::Form out of the model
|
57
|
-
def
|
57
|
+
def to_form_hash
|
58
58
|
rows = self.class.form_properties.collect { |options|
|
59
59
|
{
|
60
60
|
title: options[:property].capitalize,
|
@@ -63,14 +63,16 @@ module Formotion
|
|
63
63
|
value: self.send(options[:property])
|
64
64
|
}.merge(options)
|
65
65
|
}
|
66
|
-
|
66
|
+
return {
|
67
67
|
title: self.class.form_title || self.class.to_s.capitalize,
|
68
68
|
sections: [{
|
69
|
-
|
70
|
-
|
69
|
+
rows: rows
|
70
|
+
}]
|
71
71
|
}
|
72
|
+
end
|
72
73
|
|
73
|
-
|
74
|
+
def to_form
|
75
|
+
form = Formotion::Form.new(to_form_hash)
|
74
76
|
form.on_submit do
|
75
77
|
self.on_submit
|
76
78
|
end
|
@@ -96,4 +98,4 @@ module Formotion
|
|
96
98
|
p "need to implement on_submit in your Formable model #{self.class.to_s}"
|
97
99
|
end
|
98
100
|
end
|
99
|
-
end
|
101
|
+
end
|