ruby_motion_query 0.6.1 → 0.7.0
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/motion/ruby_motion_query/actions.rb +10 -0
- data/motion/ruby_motion_query/animations.rb +89 -9
- data/motion/ruby_motion_query/data.rb +7 -2
- data/motion/ruby_motion_query/debug.rb +3 -3
- data/motion/ruby_motion_query/event.rb +6 -2
- data/motion/ruby_motion_query/events.rb +28 -16
- data/motion/ruby_motion_query/grid.rb +3 -3
- data/motion/ruby_motion_query/stylers/ui_view_styler.rb +6 -0
- data/motion/ruby_motion_query/subviews.rb +20 -11
- data/motion/ruby_motion_query/validation.rb +151 -22
- data/motion/ruby_motion_query/validation_event.rb +24 -0
- data/motion/ruby_motion_query/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f9a3624a7543f1c6a828948bb3d2da590c8ad78
|
4
|
+
data.tar.gz: f377f2d6321fbe5a18b2e1fa4a8fedfff7023f63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25be56991e401ba84649de80eccf69a45f7df4691507a7c1c5e8f1d2bb783bac5a8625608c0d757282bd8fe27bde29fe3afcf1d5b22eedba7b037f684c69a4a2
|
7
|
+
data.tar.gz: 9ccb416fa1ea67824729649c1b2e884682ec8b04feece7aec42f3dc2b705de0f2d3880a25d3a301ebc9dfd47fa6d86b20bc64df11c426ca975d6b5b313661fc7
|
@@ -73,6 +73,16 @@ module RubyMotionQuery
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
# Allow users to set data with equals
|
77
|
+
#
|
78
|
+
# @return [RMQ]
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# rmq(my_view).data = 'some data'
|
82
|
+
def data=(new_data)
|
83
|
+
data(new_data)
|
84
|
+
end
|
85
|
+
|
76
86
|
# @return [RMQ]
|
77
87
|
def send(method, args = nil)
|
78
88
|
selected.each do |view|
|
@@ -5,21 +5,33 @@ module RubyMotionQuery
|
|
5
5
|
#
|
6
6
|
# @return [RMQ]
|
7
7
|
def animate(opts = {}, &block)
|
8
|
-
|
8
|
+
|
9
9
|
animations_callback = (block || opts[:animations] || opts[:changes])
|
10
|
+
before_callback = opts[:before]
|
10
11
|
after_callback = (opts[:completion] || opts[:after])
|
11
12
|
return self unless animations_callback
|
12
13
|
|
13
|
-
|
14
14
|
working_selected = self.selected
|
15
15
|
self_rmq = self
|
16
16
|
|
17
17
|
working_selected.each do |view|
|
18
18
|
view_rmq = self_rmq.wrap(view)
|
19
19
|
|
20
|
+
return_var = nil
|
21
|
+
|
22
|
+
if before_callback
|
23
|
+
return_var = before_callback.call(view_rmq)
|
24
|
+
end
|
25
|
+
|
20
26
|
animations_lambda = -> do
|
21
|
-
|
22
|
-
|
27
|
+
case animations_callback.arity
|
28
|
+
when 0
|
29
|
+
animations_callback.call
|
30
|
+
when 1
|
31
|
+
animations_callback.call(view_rmq)
|
32
|
+
when 2
|
33
|
+
animations_callback.call(view_rmq, return_var)
|
34
|
+
end
|
23
35
|
end
|
24
36
|
|
25
37
|
after_lambda = if after_callback
|
@@ -146,7 +158,7 @@ module RubyMotionQuery
|
|
146
158
|
opts = {
|
147
159
|
duration: 0.5,
|
148
160
|
animations: ->(cq) {
|
149
|
-
cq.style do |st|
|
161
|
+
cq.style do |st|
|
150
162
|
st.opacity = 1.0
|
151
163
|
st.scale = 0.8
|
152
164
|
end
|
@@ -168,14 +180,14 @@ module RubyMotionQuery
|
|
168
180
|
duration: 0.4 + (rand(8) / 10),
|
169
181
|
options: UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionBeginFromCurrentState,
|
170
182
|
animations: ->(cq) {
|
171
|
-
cq.style do |st|
|
183
|
+
cq.style do |st|
|
172
184
|
st.top = @rmq.device.height + st.height
|
173
|
-
st.rotation = 180 + rand(50)
|
185
|
+
st.rotation = 180 + rand(50)
|
174
186
|
end
|
175
187
|
},
|
176
188
|
completion: ->(did_finish, q) {
|
177
189
|
if did_finish
|
178
|
-
q.style do |st|
|
190
|
+
q.style do |st|
|
179
191
|
st.rotation = 0
|
180
192
|
end
|
181
193
|
|
@@ -196,6 +208,74 @@ module RubyMotionQuery
|
|
196
208
|
self.fade_out(duration: 0.2, after: lambda {|did_finish, rmq| rmq.animations.fade_in(duration: 0.2)})
|
197
209
|
end
|
198
210
|
|
211
|
+
# @return [RMQ]
|
212
|
+
def slide_in(opts = {})
|
213
|
+
from_direction = opts[:from_direction] || :right
|
214
|
+
|
215
|
+
opts = {
|
216
|
+
duration: 0.5,
|
217
|
+
options: UIViewAnimationOptionCurveEaseIn,
|
218
|
+
before: ->(bq) {
|
219
|
+
start_frame = bq.get.frame
|
220
|
+
|
221
|
+
case from_direction
|
222
|
+
when :right
|
223
|
+
bq.move(l: rmq.device.width)
|
224
|
+
when :left
|
225
|
+
bq.move(l: -rmq.device.width)
|
226
|
+
when :top
|
227
|
+
bq.move(t: -rmq.device.height)
|
228
|
+
else :bottom
|
229
|
+
bq.move(t: rmq.device.height)
|
230
|
+
end
|
231
|
+
start_frame
|
232
|
+
},
|
233
|
+
animations: ->(aq, return_var) {
|
234
|
+
aq.frame = return_var
|
235
|
+
}
|
236
|
+
}.merge(opts)
|
237
|
+
|
238
|
+
@rmq.animate(opts)
|
239
|
+
end
|
240
|
+
|
241
|
+
# @return [RMQ]
|
242
|
+
def slide_out(opts = {})
|
243
|
+
remove_view = opts[:remove_view]
|
244
|
+
to_direction = opts[:to_direction] || :left
|
245
|
+
|
246
|
+
opts = {
|
247
|
+
duration: 0.5,
|
248
|
+
options: UIViewAnimationOptionCurveEaseIn,
|
249
|
+
before: ->(bq) {
|
250
|
+
start_frame = bq.get.frame
|
251
|
+
start_frame
|
252
|
+
},
|
253
|
+
animations: ->(aq, return_var) {
|
254
|
+
case to_direction
|
255
|
+
when :right
|
256
|
+
aq.move(l: rmq.device.screen_width)
|
257
|
+
when :left
|
258
|
+
aq.move(l: -rmq.device.screen_width)
|
259
|
+
when :top
|
260
|
+
aq.move(t: -rmq.device.screen_height)
|
261
|
+
else :bottom
|
262
|
+
aq.move(t: rmq.device.screen_height)
|
263
|
+
end
|
264
|
+
},
|
265
|
+
completion: ->(did_finish, q) {
|
266
|
+
if did_finish
|
267
|
+
if remove_view
|
268
|
+
q.remove
|
269
|
+
else
|
270
|
+
q.hide
|
271
|
+
end
|
272
|
+
end
|
273
|
+
}
|
274
|
+
}.merge(opts)
|
275
|
+
|
276
|
+
@rmq.animate(opts)
|
277
|
+
end
|
278
|
+
|
199
279
|
# @return [RMQ]
|
200
280
|
def start_spinner(style = UIActivityIndicatorViewStyleGray)
|
201
281
|
spinner = Animations.window_spinner(style)
|
@@ -210,7 +290,7 @@ module RubyMotionQuery
|
|
210
290
|
@rmq.create_rmq_in_context(spinner)
|
211
291
|
end
|
212
292
|
|
213
|
-
protected
|
293
|
+
protected
|
214
294
|
|
215
295
|
def self.window_spinner(style = UIActivityIndicatorViewStyleGray)
|
216
296
|
@_window_spinner ||= begin
|
@@ -12,7 +12,12 @@ module RubyMotionQuery
|
|
12
12
|
tags.keys
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
def validation_errors; @_validation_errors ||= {}; end
|
16
|
+
def validation_errors=(value); @_validation_errors = value; end
|
17
|
+
def validations; @_validations ||= []; end
|
18
|
+
def validations=(value); @_validations = value; end
|
19
|
+
|
20
|
+
# *Do not* use this, use {RMQ#tag} instead:
|
16
21
|
# @example
|
17
22
|
# rmq(my_view).tag(:foo)
|
18
23
|
def tag(*tag_or_tags)
|
@@ -25,7 +30,7 @@ module RubyMotionQuery
|
|
25
30
|
end
|
26
31
|
elsif tag_or_tags.is_a?(Hash)
|
27
32
|
tag_or_tags.each do |tag_name, tag_value|
|
28
|
-
tags[tag_name] = tag_value
|
33
|
+
tags[tag_name] = tag_value
|
29
34
|
end
|
30
35
|
elsif tag_or_tags.is_a?(Symbol)
|
31
36
|
tags[tag_or_tags] = 1
|
@@ -13,7 +13,7 @@ module RubyMotionQuery
|
|
13
13
|
end
|
14
14
|
|
15
15
|
# @return [Debug]
|
16
|
-
def debug
|
16
|
+
def debug
|
17
17
|
Debug
|
18
18
|
end
|
19
19
|
end
|
@@ -48,7 +48,7 @@ module RubyMotionQuery
|
|
48
48
|
Deep log - #{label}
|
49
49
|
At: #{Time.now.to_s}
|
50
50
|
|
51
|
-
Callers:
|
51
|
+
Callers:
|
52
52
|
#{callers.join("\n - ")}
|
53
53
|
|
54
54
|
Objects:
|
@@ -61,7 +61,7 @@ module RubyMotionQuery
|
|
61
61
|
label
|
62
62
|
end
|
63
63
|
|
64
|
-
# Warning, this is very slow to output log, checking truthy however is
|
64
|
+
# Warning, this is very slow to output log, checking truthy however is
|
65
65
|
# basically as performant as an if statement
|
66
66
|
#
|
67
67
|
# @example
|
@@ -3,7 +3,9 @@ module RubyMotionQuery
|
|
3
3
|
attr_accessor :block, :recognizer, :event, :sdk_event_or_recognizer, :gesture, :sender
|
4
4
|
|
5
5
|
def initialize(sender, event, block)
|
6
|
-
if
|
6
|
+
if CONTROL_EVENTS[event] == ValidationEvent
|
7
|
+
return ValidationEvent.new(block)
|
8
|
+
elsif @sdk_event_or_recognizer = VIEW_GESTURES[event]
|
7
9
|
@gesture = true
|
8
10
|
elsif sender.is_a?(UIControl)
|
9
11
|
@gesture = false
|
@@ -127,7 +129,9 @@ module RubyMotionQuery
|
|
127
129
|
|
128
130
|
application: UIControlEventApplicationReserved,
|
129
131
|
system: UIControlEventSystemReserved,
|
130
|
-
all: UIControlEventAllEvents
|
132
|
+
all: UIControlEventAllEvents,
|
133
|
+
valid: ValidationEvent,
|
134
|
+
invalid: ValidationEvent
|
131
135
|
}
|
132
136
|
|
133
137
|
VIEW_GESTURES = {
|
@@ -39,6 +39,9 @@ module RubyMotionQuery
|
|
39
39
|
# :application
|
40
40
|
# :system
|
41
41
|
# :all
|
42
|
+
#
|
43
|
+
# :valid
|
44
|
+
# :invalid
|
42
45
|
|
43
46
|
# Gestures for UIView
|
44
47
|
# :tap
|
@@ -53,17 +56,17 @@ module RubyMotionQuery
|
|
53
56
|
# :long_press
|
54
57
|
|
55
58
|
# Options for gestures
|
56
|
-
# :cancels_touches_in_view
|
57
|
-
# :delegate
|
58
|
-
# :taps_required
|
59
|
-
# :fingers_required
|
60
|
-
# :maximum_number_of_touches
|
61
|
-
# :minimum_number_of_touches
|
62
|
-
# :allowable_movement
|
63
|
-
# :minimum_press_duration
|
64
|
-
# :direction
|
65
|
-
# :rotation
|
66
|
-
# :scale
|
59
|
+
# :cancels_touches_in_view
|
60
|
+
# :delegate
|
61
|
+
# :taps_required
|
62
|
+
# :fingers_required
|
63
|
+
# :maximum_number_of_touches
|
64
|
+
# :minimum_number_of_touches
|
65
|
+
# :allowable_movement
|
66
|
+
# :minimum_press_duration
|
67
|
+
# :direction
|
68
|
+
# :rotation
|
69
|
+
# :scale
|
67
70
|
#
|
68
71
|
# @example
|
69
72
|
# rmq.append(UIButton).on(:touch) do |sender|
|
@@ -86,7 +89,7 @@ module RubyMotionQuery
|
|
86
89
|
# end
|
87
90
|
def on(event, args = {}, &block)
|
88
91
|
selected.each do |view|
|
89
|
-
events(view).on(view, event, args, &block)
|
92
|
+
events(view).on(view, event, args, &block)
|
90
93
|
end
|
91
94
|
|
92
95
|
self
|
@@ -130,8 +133,8 @@ module RubyMotionQuery
|
|
130
133
|
def on(view, event, args = {}, &block)
|
131
134
|
raise "[RMQ Error] Event already exists on this object: #{event}. Remove first, using .off" if @event_set[event]
|
132
135
|
|
133
|
-
if rmqe =
|
134
|
-
rmqe.set_options(args)
|
136
|
+
if rmqe = event_instance(view, event, block)
|
137
|
+
rmqe.set_options(args) if rmqe.respond_to? :set_options
|
135
138
|
|
136
139
|
@event_set[event] = rmqe
|
137
140
|
end
|
@@ -143,14 +146,23 @@ module RubyMotionQuery
|
|
143
146
|
events.flatten!
|
144
147
|
events = @event_set.keys if events.length == 0
|
145
148
|
|
146
|
-
events.each do |event|
|
149
|
+
events.each do |event|
|
147
150
|
if rm_event = @event_set.delete(event)
|
148
|
-
rm_event.remove
|
151
|
+
rm_event.remove
|
149
152
|
end
|
150
153
|
end
|
151
154
|
|
152
155
|
self
|
153
156
|
end
|
154
157
|
|
158
|
+
private
|
159
|
+
|
160
|
+
def event_instance(view, event, block)
|
161
|
+
if [:valid, :invalid].include? event
|
162
|
+
RubyMotionQuery::ValidationEvent.new(view, event, block)
|
163
|
+
else
|
164
|
+
RubyMotionQuery::Event.new(view, event, block)
|
165
|
+
end
|
166
|
+
end
|
155
167
|
end
|
156
168
|
end
|
@@ -104,13 +104,13 @@ module RubyMotionQuery
|
|
104
104
|
NAV_BAR_BOTTOM = 64
|
105
105
|
|
106
106
|
DEFAULT = {
|
107
|
-
num_columns:
|
107
|
+
num_columns: 12,
|
108
108
|
column_gutter: 10,
|
109
|
-
num_rows:
|
109
|
+
num_rows: 18,
|
110
110
|
row_gutter: 10,
|
111
111
|
content_left_margin: 10,
|
112
112
|
content_right_margin: 10,
|
113
|
-
content_top_margin:
|
113
|
+
content_top_margin: 74,
|
114
114
|
content_bottom_margin: 10
|
115
115
|
}
|
116
116
|
|
@@ -381,6 +381,12 @@ module RubyMotionQuery
|
|
381
381
|
def accessibility_label=(value)
|
382
382
|
@view.accessibilityLabel = value
|
383
383
|
end
|
384
|
+
|
385
|
+
def validation_errors=(values)
|
386
|
+
# set custom validation messages on rules
|
387
|
+
@view.rmq_data.validation_errors = values
|
388
|
+
end
|
389
|
+
|
384
390
|
end
|
385
391
|
end
|
386
392
|
end
|
@@ -50,7 +50,7 @@ module RubyMotionQuery
|
|
50
50
|
end
|
51
51
|
|
52
52
|
if created
|
53
|
-
new_view.rmq_did_create(self.wrap(new_view))
|
53
|
+
new_view.rmq_did_create(self.wrap(new_view))
|
54
54
|
new_view.rmq_created
|
55
55
|
end
|
56
56
|
new_view.rmq_build
|
@@ -65,16 +65,16 @@ module RubyMotionQuery
|
|
65
65
|
end
|
66
66
|
alias :insert :add_subview
|
67
67
|
|
68
|
-
# Performs a create, then appends view to the end of the subview array of the
|
68
|
+
# Performs a create, then appends view to the end of the subview array of the
|
69
69
|
# views you have selected (or the rootview if you have nothing selected).
|
70
70
|
#
|
71
71
|
# When you build, create, or append a view, the method rmq_build is called
|
72
72
|
# inside the view. If you are creating a your own subclass of a UIView, then
|
73
|
-
# that is a good place to do your initialization. Your view is created, then
|
73
|
+
# that is a good place to do your initialization. Your view is created, then
|
74
74
|
# appended, then rmq_build is called, then the style is applied (if it exists)
|
75
75
|
#
|
76
|
-
# @example
|
77
|
-
# # Creating a new view instance then append it. Passing in the class
|
76
|
+
# @example
|
77
|
+
# # Creating a new view instance then append it. Passing in the class
|
78
78
|
# # to create
|
79
79
|
# rmq.append(UIButton, :my_button_style)
|
80
80
|
# @title = rmq.append(ULabel, :title).get
|
@@ -82,7 +82,7 @@ module RubyMotionQuery
|
|
82
82
|
# # You can also pass in an existing view
|
83
83
|
# my_view = UIView.alloc.initWithFrame([[0,0],[10,10]])
|
84
84
|
# rmq.append(my_view, :my_style)
|
85
|
-
#
|
85
|
+
#
|
86
86
|
# # Stylename is optional
|
87
87
|
# rmq.append(UIImageView)
|
88
88
|
#
|
@@ -121,21 +121,21 @@ module RubyMotionQuery
|
|
121
121
|
end
|
122
122
|
alias :prepend! :unshift!
|
123
123
|
|
124
|
-
# Creates a view then returns an rmq with that view in it. It does not add that
|
124
|
+
# Creates a view then returns an rmq with that view in it. It does not add that
|
125
125
|
# view to the view tree (append does this). This is useful for stuff like creating
|
126
|
-
# table cells. You can use the rmq_did_create method, just like you do when you
|
126
|
+
# table cells. You can use the rmq_did_create method, just like you do when you
|
127
127
|
# append a subview
|
128
128
|
#
|
129
129
|
# @return [RMQ] wrapping the view that was just create
|
130
130
|
#
|
131
131
|
# @example
|
132
132
|
# def tableView(table_view, cellForRowAtIndexPath: index_path)
|
133
|
-
# cell = tableView.dequeueReusableCellWithIdentifier(CELL_IDENTIFIER) || begin
|
133
|
+
# cell = tableView.dequeueReusableCellWithIdentifier(CELL_IDENTIFIER) || begin
|
134
134
|
# rmq.create(StoreCell, :store_cell, reuse_identifier: CELL_IDENTIFIER)
|
135
135
|
# end
|
136
136
|
# end
|
137
137
|
#
|
138
|
-
# class StoreCell < UITableViewCell
|
138
|
+
# class StoreCell < UITableViewCell
|
139
139
|
# def rmq_did_create(self_in_rmq)
|
140
140
|
# self_in_rmq.append(UILabel, :title_label)
|
141
141
|
# end
|
@@ -160,7 +160,7 @@ module RubyMotionQuery
|
|
160
160
|
# in collectionview cells for example
|
161
161
|
#
|
162
162
|
# @example
|
163
|
-
# # In your collectionview
|
163
|
+
# # In your collectionview
|
164
164
|
# rmq.build(cell) unless cell.reused
|
165
165
|
#
|
166
166
|
# # Then in your cell
|
@@ -174,6 +174,15 @@ module RubyMotionQuery
|
|
174
174
|
add_subview view, opts
|
175
175
|
end
|
176
176
|
|
177
|
+
# Same as build, but instantly returns the view, without having to use .get
|
178
|
+
#
|
179
|
+
# @example
|
180
|
+
# @my_cell = rmq.build! cell
|
181
|
+
def build!(view, style = nil, opts = {})
|
182
|
+
build(view, style, opts).get
|
183
|
+
end
|
184
|
+
|
185
|
+
|
177
186
|
protected
|
178
187
|
|
179
188
|
def create_view(klass, opts)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module RubyMotionQuery
|
2
2
|
class RMQ
|
3
|
+
|
3
4
|
# @return [Validation]
|
4
5
|
def self.validation
|
5
6
|
Validation
|
@@ -9,9 +10,105 @@ module RubyMotionQuery
|
|
9
10
|
def validation
|
10
11
|
Validation
|
11
12
|
end
|
12
|
-
|
13
|
+
|
14
|
+
# @return [RMQ]
|
15
|
+
def validates(rule, options={})
|
16
|
+
selected.each do |view|
|
17
|
+
view.rmq_data.validations << Validation.new(rule, options)
|
18
|
+
end
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [RMQ]
|
23
|
+
def clear_validations!
|
24
|
+
selected.each do |view|
|
25
|
+
view.rmq_data.validations = []
|
26
|
+
end
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# This method validates all the selected and is responsible
|
31
|
+
# for calling invalid/valid events
|
32
|
+
#
|
33
|
+
# @return [Boolean] false if any validations fail
|
34
|
+
def valid?
|
35
|
+
result = true
|
36
|
+
|
37
|
+
selected.each do |view|
|
38
|
+
view.rmq_data.validations.each do |validation|
|
39
|
+
|
40
|
+
has_events = view.rmq_data.events
|
41
|
+
|
42
|
+
if validation.valid?(rmq(view).data)
|
43
|
+
if has_events && view.rmq_data.events.has_event?(:valid)
|
44
|
+
view.rmq_data.events[:valid].fire!
|
45
|
+
end
|
46
|
+
else
|
47
|
+
if has_events && view.rmq_data.events.has_event?(:invalid)
|
48
|
+
view.rmq_data.events[:invalid].fire!
|
49
|
+
end
|
50
|
+
result = false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
return result
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Array] of error messages for failed validations
|
58
|
+
def validation_errors
|
59
|
+
errors = []
|
60
|
+
selected.each do |view|
|
61
|
+
view.rmq_data.validations.each do |validation|
|
62
|
+
unless validation.valid_status
|
63
|
+
default_error = "Validation Error - input requires valid #{validation.rule_name.to_s}."
|
64
|
+
rule_message = view.rmq_data.validation_errors[validation.rule_name] || default_error
|
65
|
+
errors.push(rule_message)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return errors
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [Array] of views where validations have failed
|
73
|
+
def invalid
|
74
|
+
invalid = []
|
75
|
+
selected.each do |view|
|
76
|
+
view.rmq_data.validations.each do |validation|
|
77
|
+
invalid.push(view) unless validation.valid_status
|
78
|
+
end
|
79
|
+
end
|
80
|
+
return invalid
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [Array] of views where validations have failed
|
84
|
+
def valid
|
85
|
+
invalid = []
|
86
|
+
selected.each do |view|
|
87
|
+
view.rmq_data.validations.each do |validation|
|
88
|
+
invalid.push(view) if validation.valid_status
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return invalid
|
92
|
+
end
|
93
|
+
|
94
|
+
end # End RMQ
|
13
95
|
|
14
96
|
class Validation
|
97
|
+
attr_reader :valid_status, :rule_name
|
98
|
+
|
99
|
+
def initialize(rule, options={})
|
100
|
+
@rule = @@validation_methods[rule]
|
101
|
+
raise "RMQ validation error: :#{rule} is not one of the supported validation methods." unless @rule
|
102
|
+
@rule_name = rule
|
103
|
+
@options = options
|
104
|
+
@valid_status = true
|
105
|
+
end
|
106
|
+
|
107
|
+
def valid?(data, options={})
|
108
|
+
@options = options.merge(@options)
|
109
|
+
@valid_status = @rule.call(data, @options)
|
110
|
+
end
|
111
|
+
|
15
112
|
class << self
|
16
113
|
# Validation Regex from jQuery validation -> https://github.com/jzaefferer/jquery-validation/blob/master/src/core.js#L1094-L1200
|
17
114
|
EMAIL = Regexp.new('^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$')
|
@@ -26,18 +123,52 @@ module RubyMotionQuery
|
|
26
123
|
USZIP = Regexp.new('^\d{5}(-\d{4})?$')
|
27
124
|
# 7 or 10 digit number, delimiters are spaces, dashes, or periods
|
28
125
|
USPHONE = Regexp.new('^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})$')
|
29
|
-
|
126
|
+
# Strong password (at least [8 chars, 1 upper, 1 lower, 1 number])
|
127
|
+
STRONGPW = Regexp.new('^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{8,}$')
|
128
|
+
# Has at least 1 uppercase letter
|
129
|
+
HASUPPER = Regexp.new('^(?=.*[A-Z]).+$')
|
130
|
+
# Has at least 1 lowercase letter
|
131
|
+
HASLOWER = Regexp.new('^(?=.*[a-z]).+$')
|
132
|
+
# Has some kind of value not just whitespace (doesn't require data to be stripped)
|
133
|
+
PRESENCE = Regexp.new('\S+')
|
30
134
|
|
31
135
|
@@validation_methods = {
|
32
|
-
:email => lambda { |value| Validation.regex_match?(value, EMAIL)},
|
33
|
-
:url => lambda { |value| Validation.regex_match?(value, URL)},
|
34
|
-
:dateiso => lambda { |value| Validation.regex_match?(value, DATEISO)},
|
35
|
-
:number => lambda { |value| Validation.regex_match?(value, NUMBER)},
|
36
|
-
:digits => lambda { |value| Validation.regex_match?(value, DIGITS)},
|
37
|
-
:ipv4 => lambda { |value| Validation.regex_match?(value, IPV4)},
|
38
|
-
:time => lambda { |value| Validation.regex_match?(value, TIME)},
|
39
|
-
:uszip => lambda { |value| Validation.regex_match?(value, USZIP)},
|
40
|
-
:usphone => lambda { |value| Validation.regex_match?(value, USPHONE)}
|
136
|
+
:email => lambda { |value, opts| Validation.regex_match?(value, EMAIL)},
|
137
|
+
:url => lambda { |value, opts| Validation.regex_match?(value, URL)},
|
138
|
+
:dateiso => lambda { |value, opts| Validation.regex_match?(value, DATEISO)},
|
139
|
+
:number => lambda { |value, opts| Validation.regex_match?(value, NUMBER)},
|
140
|
+
:digits => lambda { |value, opts| Validation.regex_match?(value, DIGITS)},
|
141
|
+
:ipv4 => lambda { |value, opts| Validation.regex_match?(value, IPV4)},
|
142
|
+
:time => lambda { |value, opts| Validation.regex_match?(value, TIME)},
|
143
|
+
:uszip => lambda { |value, opts| Validation.regex_match?(value, USZIP)},
|
144
|
+
:usphone => lambda { |value, opts| Validation.regex_match?(value, USPHONE)},
|
145
|
+
:strong_password => lambda { |value, opts| Validation.regex_match?(value, STRONGPW)},
|
146
|
+
:has_upper => lambda { |value, opts| Validation.regex_match?(value, HASUPPER)},
|
147
|
+
:has_lower => lambda { |value, opts| Validation.regex_match?(value, HASLOWER)},
|
148
|
+
:presence => lambda { |value, opts| Validation.regex_match?(value, PRESENCE)},
|
149
|
+
:length => lambda { |value, opts|
|
150
|
+
opts = {
|
151
|
+
exact_length: nil,
|
152
|
+
max_length: Float::INFINITY,
|
153
|
+
min_length: 0,
|
154
|
+
strip: false
|
155
|
+
}.merge(opts)
|
156
|
+
|
157
|
+
# Range magic 8..16
|
158
|
+
if opts[:exact_length].is_a? Range
|
159
|
+
opts[:min_length] = opts[:exact_length].begin
|
160
|
+
opts[:max_length] = opts[:exact_length].end
|
161
|
+
opts[:exact_length] = nil
|
162
|
+
end
|
163
|
+
|
164
|
+
# allowing option to strip input before assessing length
|
165
|
+
value.strip! if opts[:strip]
|
166
|
+
|
167
|
+
# check length validation
|
168
|
+
v = if opts[:exact_length] then (value.length == opts[:exact_length]) else true end
|
169
|
+
v = v && value.length <= opts[:max_length]
|
170
|
+
v = v && value.length >= opts[:min_length]
|
171
|
+
}
|
41
172
|
}
|
42
173
|
|
43
174
|
# Add tags
|
@@ -46,23 +177,21 @@ module RubyMotionQuery
|
|
46
177
|
# rmq.validation.valid?(53.8, :number)
|
47
178
|
# rmq.validation.valid?(54, :digits)
|
48
179
|
# rmq.validation.valid?('https://www.tacoland.com', :url)
|
49
|
-
# rmq.validation.valid?('2014-03-02'
|
180
|
+
# rmq.validation.valid?('2014-03-02', :dateiso)
|
181
|
+
# rmq.validation.valid?('', :email, allow_blank: true)
|
50
182
|
#
|
51
183
|
# @return [Boolean]
|
52
|
-
def valid?(value,
|
53
|
-
#shortcircuit if debugging
|
184
|
+
def valid?(value, rule, options={})
|
185
|
+
# shortcircuit if debugging
|
54
186
|
return true if RubyMotionQuery::RMQ.debugging?
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
return false unless @@validation_methods[rule].call(value)
|
60
|
-
end
|
61
|
-
true
|
187
|
+
# shortcircuit for optionals
|
188
|
+
return true if (options[:allow_blank] && (value.nil? || value.empty?))
|
189
|
+
|
190
|
+
Validation.new(rule).valid?(value, options)
|
62
191
|
end
|
63
192
|
|
64
193
|
def regex_match?(value, regex)
|
65
|
-
(value.to_s =~ regex)
|
194
|
+
(value.to_s =~ regex) != nil
|
66
195
|
end
|
67
196
|
|
68
197
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RubyMotionQuery
|
2
|
+
class ValidationEvent
|
3
|
+
def initialize(sender, event, block)
|
4
|
+
@sender = sender
|
5
|
+
@event = event
|
6
|
+
@block = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def fire!
|
10
|
+
|
11
|
+
if @block
|
12
|
+
case @block.arity
|
13
|
+
when 2
|
14
|
+
@block.call(@sender, self)
|
15
|
+
when 1
|
16
|
+
@block.call(@sender)
|
17
|
+
else
|
18
|
+
@block.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_motion_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Werth
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-08-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bacon
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- motion/ruby_motion_query/traverse.rb
|
101
101
|
- motion/ruby_motion_query/utils.rb
|
102
102
|
- motion/ruby_motion_query/validation.rb
|
103
|
+
- motion/ruby_motion_query/validation_event.rb
|
103
104
|
- motion/ruby_motion_query/version.rb
|
104
105
|
- templates/collection_view_controller/app/controllers/name_controller.rb
|
105
106
|
- templates/collection_view_controller/app/stylesheets/name_cell_stylesheet.rb
|