client_side_validations 2.6.2 → 2.6.3
Sign up to get free protection for your applications and to get access to all the features.
- data/javascript/lib/client_side_validations.js +46 -173
- data/lib/client_side_validations/adapters/action_view.rb +72 -39
- data/lib/client_side_validations/adapters/active_model.rb +4 -2
- data/lib/client_side_validations/adapters/orm_base.rb +1 -1
- data/lib/client_side_validations/orm.rb +129 -6
- metadata +4 -4
@@ -1,182 +1,55 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
}, jQuery.validator.format("Invalid format."));
|
1
|
+
jQuery.validator.addMethod("format", function(value, element, params) {
|
2
|
+
var pattern = new RegExp(params, "i");
|
3
|
+
return this.optional(element) || pattern.test(value);
|
4
|
+
}, jQuery.validator.format("Invalid format."));
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
jQuery.validator.addMethod("acceptance", function(value, element, params) {
|
7
|
+
return element.checked;
|
8
|
+
}, jQuery.validator.format("Was not accepted."));
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
10
|
+
jQuery.validator.addMethod("inclusion", function(value, element, params) {
|
11
|
+
if (this.optional(element)) {
|
12
|
+
return true;
|
13
|
+
} else {
|
14
|
+
|
15
|
+
for (var i=0, len=params.length; i<len; ++i ) {
|
16
|
+
if (value == String(params[i])) {
|
17
|
+
return true;
|
20
18
|
}
|
21
19
|
}
|
22
|
-
|
23
|
-
|
20
|
+
}
|
21
|
+
return false;
|
22
|
+
}, jQuery.validator.format("Not included in list."));
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
return true;
|
28
|
-
} else {
|
29
|
-
for (var i=0, len=params.length; i<len; ++i ) {
|
30
|
-
if (value == String(params[i])) {
|
31
|
-
return false;
|
32
|
-
}
|
33
|
-
}
|
34
|
-
}
|
24
|
+
jQuery.validator.addMethod("exclusion", function(value, element, params) {
|
25
|
+
if (this.optional(element)) {
|
35
26
|
return true;
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
for (var i in this) {
|
41
|
-
var form = $(this[i]);
|
42
|
-
var object = form.attr('object-csv');
|
43
|
-
var form_id = form.attr('id');
|
44
|
-
var object_id = null;
|
45
|
-
var adapter = 'jquery.validate';
|
46
|
-
|
47
|
-
if (/edit/.test(form_id)) {
|
48
|
-
object_id = /edit_\w+_(\d+)/.exec(form_id)[1];
|
49
|
-
}
|
50
|
-
|
51
|
-
if (eval("typeof(" + object + "_validation_options)") != "undefined") {
|
52
|
-
var options = eval(object + '_validation_options');
|
53
|
-
} else {
|
54
|
-
var options = { }
|
55
|
-
}
|
56
|
-
var client = new ClientSideValidations(object, adapter, object_id)
|
57
|
-
var rules = eval(object + '_validation_rules');
|
58
|
-
var validations = client.adaptValidations(rules);
|
59
|
-
options.rules = validations.rules;
|
60
|
-
options.messages = validations.messages;
|
61
|
-
options.ignore = ':hidden';
|
62
|
-
form.validate(options);
|
27
|
+
} else {
|
28
|
+
for (var i=0, len=params.length; i<len; ++i ) {
|
29
|
+
if (value == String(params[i])) {
|
30
|
+
return false;
|
63
31
|
}
|
64
32
|
}
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
name = this.id + '[' + attr + ']';
|
82
|
-
rules[name] = {};
|
83
|
-
messages[name] = {};
|
84
|
-
for(var validation in this.validations[attr]) {
|
85
|
-
rule = null;
|
86
|
-
required = false;
|
87
|
-
switch(validation) {
|
88
|
-
case 'presence':
|
89
|
-
rule = 'required';
|
90
|
-
value = true;
|
91
|
-
break;
|
92
|
-
case 'format':
|
93
|
-
value = this.validations[attr][validation]['with'];
|
94
|
-
required = !this.validations[attr][validation]['allow_blank'];
|
95
|
-
break;
|
96
|
-
case 'numericality':
|
97
|
-
rule = 'digits';
|
98
|
-
value = true;
|
99
|
-
required = !this.validations[attr][validation]['allow_blank'];
|
100
|
-
break;
|
101
|
-
case 'length':
|
102
|
-
if ('minimum' in this.validations[attr][validation] && 'maximum' in this.validations[attr][validation]) {
|
103
|
-
maxrule = 'maxlength';
|
104
|
-
rules[name][maxrule] = this.validations[attr][validation]['maximum'];
|
105
|
-
messages[name][maxrule] = this.validations[attr][validation]['message_max'];
|
106
|
-
|
107
|
-
rule = 'minlength';
|
108
|
-
value = this.validations[attr][validation]['minimum'];
|
109
|
-
this.validations[attr][validation]['message'] = this.validations[attr][validation]['message_min']
|
110
|
-
} else if('minimum' in this.validations[attr][validation]) {
|
111
|
-
rule = 'minlength';
|
112
|
-
value = this.validations[attr][validation]['minimum'];
|
113
|
-
} else if('maximum' in this.validations[attr][validation]) {
|
114
|
-
rule = 'maxlength';
|
115
|
-
value = this.validations[attr][validation]['maximum'];
|
116
|
-
}
|
117
|
-
break;
|
118
|
-
case 'uniqueness':
|
119
|
-
rule = 'remote';
|
120
|
-
value = {
|
121
|
-
url: '/validations/uniqueness.json',
|
122
|
-
data: {}
|
123
|
-
}
|
124
|
-
if(object_id) {
|
125
|
-
value['data'][this.id + '[id]'] = function() {
|
126
|
-
return String(object_id);
|
127
|
-
}
|
128
|
-
}
|
129
|
-
required = !this.validations[attr][validation]['allow_blank'];
|
130
|
-
break;
|
131
|
-
case 'confirmation':
|
132
|
-
rule = 'equalTo';
|
133
|
-
value = "[name='" + this.id + "[" + attr + "_confirmation]" + "']";
|
134
|
-
break;
|
135
|
-
case 'acceptance':
|
136
|
-
rule = 'acceptance';
|
137
|
-
value = true;
|
138
|
-
break;
|
139
|
-
case 'inclusion':
|
140
|
-
rule = 'inclusion';
|
141
|
-
value = this.validations[attr][validation]['in']
|
142
|
-
required = !this.validations[attr][validation]['allow_blank'];
|
143
|
-
break;
|
144
|
-
case 'exclusion':
|
145
|
-
rule = 'exclusion';
|
146
|
-
value = this.validations[attr][validation]['in']
|
147
|
-
required = !this.validations[attr][validation]['allow_blank'];
|
148
|
-
break;
|
149
|
-
|
150
|
-
default:
|
151
|
-
}
|
152
|
-
if(rule == null) {
|
153
|
-
rule = validation;
|
154
|
-
}
|
155
|
-
|
156
|
-
if (typeof(value) != 'undefined') {
|
157
|
-
rules[name][rule] = value;
|
158
|
-
messages[name][rule] = this.validations[attr][validation]['message'];
|
159
|
-
}
|
160
|
-
if (required && rules[name]['required'] == null) {
|
161
|
-
rules[name].required = true;
|
162
|
-
messages[name].required = this.validations[attr][validation]['message'];
|
163
|
-
}
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
|
-
result = {
|
168
|
-
rules : rules,
|
169
|
-
messages : messages
|
170
|
-
};
|
171
|
-
|
172
|
-
return result;
|
173
|
-
};
|
174
|
-
|
175
|
-
switch(this.adapter) {
|
176
|
-
case 'jquery.validate':
|
177
|
-
return this.jQueryValidateAdapter();
|
178
|
-
break;
|
179
|
-
default:
|
33
|
+
}
|
34
|
+
return true;
|
35
|
+
}, jQuery.validator.format("Is reserved."));
|
36
|
+
|
37
|
+
jQuery.validator.addMethod("islength", function(value, element, length) {
|
38
|
+
return this.optional(element) || value.length == length;
|
39
|
+
}, jQuery.validator.format("Is the wrong length."));
|
40
|
+
|
41
|
+
$.extend($.fn, {
|
42
|
+
clientSideValidations: function() {
|
43
|
+
for (var i = 0; i < this.size(); i++) {
|
44
|
+
var form = $(this[i]);
|
45
|
+
var object = form.attr('data-csv');
|
46
|
+
var validate_options = eval(object + "_validate_options");
|
47
|
+
validate_options.options.ignore = ':hidden';
|
48
|
+
form.validate(validate_options);
|
180
49
|
}
|
181
|
-
}
|
182
|
-
}
|
50
|
+
}
|
51
|
+
});
|
52
|
+
|
53
|
+
$(function() {
|
54
|
+
$('form[data-csv]').clientSideValidations();
|
55
|
+
});
|
@@ -7,20 +7,18 @@ module DNCLabs
|
|
7
7
|
def self.included(base)
|
8
8
|
form_method = base.instance_method(:form_for)
|
9
9
|
base.class_eval do
|
10
|
+
attr_accessor :validate_options
|
11
|
+
|
10
12
|
define_method(:form_for) do |record_or_name_or_array, *args, &proc|
|
11
|
-
options =
|
12
|
-
options.symbolize_keys!
|
13
|
+
options = Hash.new { |h, k| h[k] = {}}
|
14
|
+
options.merge!(args.extract_options!.symbolize_keys!)
|
13
15
|
script = ""
|
14
16
|
if validations = options.delete(:validations)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
object, rules, csv_options = csv_get_variables(validations, record_or_name_or_array)
|
19
|
-
options[:html]['object-csv'] = object
|
20
|
-
csv_rules = %{var #{object}_validation_rules=#{rules};}
|
21
|
-
script = %{<script type='text/javascript'>#{csv_rules}#{csv_options}</script>}
|
17
|
+
set_validate_options(validations, record_or_name_or_array)
|
18
|
+
options[:html]['data-csv'] = validate_options.delete('data-csv')
|
19
|
+
script = %{<script type='text/javascript'>var #{options[:html]['data-csv']}_validate_options=#{validate_options.to_json};</script>}
|
22
20
|
end
|
23
|
-
args << options
|
21
|
+
args << {}.merge(options)
|
24
22
|
result = form_method.bind(self).call(record_or_name_or_array, *args, &proc)
|
25
23
|
|
26
24
|
if rails3?
|
@@ -36,67 +34,102 @@ module DNCLabs
|
|
36
34
|
private
|
37
35
|
|
38
36
|
def rails3?
|
39
|
-
version=
|
37
|
+
version =
|
40
38
|
if defined?(ActionPack::VERSION::MAJOR)
|
41
39
|
ActionPack::VERSION::MAJOR
|
42
40
|
end
|
43
41
|
!version.blank? && version >= 3
|
44
42
|
end
|
45
43
|
|
46
|
-
def
|
47
|
-
|
44
|
+
def set_validate_options(validations, record_or_name_or_array)
|
45
|
+
options = ::ClientSideValidations.default_options || { }
|
46
|
+
|
48
47
|
case validations
|
49
48
|
when true
|
50
|
-
|
49
|
+
object_name = get_object_name(record_or_name_or_array)
|
50
|
+
data_csv = get_data_csv(record_or_name_or_array)
|
51
|
+
validate_options = rules_and_messages(record_or_name_or_array)
|
51
52
|
when Hash
|
52
53
|
validations.symbolize_keys!
|
53
54
|
if validations.has_key?(:instance)
|
54
|
-
|
55
|
-
|
55
|
+
object_name = get_object_name(validations[:instance])
|
56
|
+
data_csv = get_data_csv(validations[:instance])
|
57
|
+
validate_options = validations[:instance].validate_options
|
56
58
|
elsif validations.has_key?(:class)
|
57
|
-
|
58
|
-
|
59
|
+
object_name = get_object_name(validations[:class].new)
|
60
|
+
data_csv = get_data_csv(validations[:instance].new)
|
61
|
+
validate_options = validations[:class].new.validate_options
|
59
62
|
else
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
csv_options.merge!(validations[:options])
|
63
|
+
object_name = get_object_name(record_or_name_or_array)
|
64
|
+
data_csv = get_data_csv(record_or_name_or_array)
|
65
|
+
validate_options = rules_and_messages(record_or_name_or_array)
|
64
66
|
end
|
67
|
+
|
68
|
+
options.merge!(validations[:options] || {})
|
65
69
|
else
|
66
|
-
|
67
|
-
|
70
|
+
object_name = get_object_name(validations)
|
71
|
+
data_csv = get_data_csv(validations)
|
72
|
+
validate_options = validations.new.validate_options
|
68
73
|
end
|
69
74
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
75
|
+
self.validate_options = build_validate_options(object_name, validate_options, options, data_csv)
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_validate_options(object_name, validate_options, options, data_csv)
|
79
|
+
%w{rules messages}.each do |option|
|
80
|
+
validate_options[option].keys.each do |key|
|
81
|
+
validate_options[option]["#{object_name}[#{key}]"] = validate_options[option].delete(key)
|
82
|
+
end
|
74
83
|
end
|
75
84
|
|
76
|
-
[
|
85
|
+
validate_options['options'] = options unless options.empty?
|
86
|
+
validate_options['data-csv'] = data_csv
|
87
|
+
validate_options
|
77
88
|
end
|
78
89
|
|
79
|
-
def
|
90
|
+
def convert_options_to_json(options)
|
80
91
|
json = []
|
81
|
-
|
92
|
+
options.each do |k, v|
|
82
93
|
json << %{#{k}:#{v}}
|
83
94
|
end
|
84
95
|
%{{#{json.join(',')}}}
|
85
96
|
end
|
86
97
|
|
87
|
-
def
|
98
|
+
def rules_and_messages(record_or_name_or_array)
|
88
99
|
case record_or_name_or_array
|
89
100
|
when String, Symbol
|
90
|
-
|
91
|
-
rules = object.camelize.constantize.new.validations_to_json
|
101
|
+
record_or_name_or_array.to_s.camelize.constantize.new.validate_options
|
92
102
|
when Array
|
93
|
-
|
103
|
+
rules_and_messages(record_or_name_or_array.last)
|
94
104
|
else
|
95
|
-
|
96
|
-
|
105
|
+
record_or_name_or_array.validate_options
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_data_csv(object)
|
110
|
+
case object
|
111
|
+
when String, Symbol
|
112
|
+
object.to_s
|
113
|
+
when Array
|
114
|
+
get_data_csv(object.last)
|
115
|
+
when Class
|
116
|
+
object.to_s.underscore
|
117
|
+
else
|
118
|
+
dom_id(object)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_object_name(object)
|
123
|
+
case object
|
124
|
+
when String, Symbol
|
125
|
+
object.to_s
|
126
|
+
when Array
|
127
|
+
get_object_name(object.last)
|
128
|
+
when Class
|
129
|
+
get_object_name(object.new)
|
130
|
+
else
|
131
|
+
ActionController::RecordIdentifier.singular_class_name(object)
|
97
132
|
end
|
98
|
-
|
99
|
-
[object, rules]
|
100
133
|
end
|
101
134
|
end # BaseMethods
|
102
135
|
|
@@ -5,7 +5,7 @@ module DNCLabs
|
|
5
5
|
module Adapters
|
6
6
|
class ActiveModel < ORMBase
|
7
7
|
|
8
|
-
def
|
8
|
+
def validations_to_hash(attr)
|
9
9
|
base._validators[attr.to_sym].inject({}) do |hash, validation|
|
10
10
|
hash.merge!(build_validation_hash(validation.clone))
|
11
11
|
end
|
@@ -48,7 +48,9 @@ module DNCLabs
|
|
48
48
|
when :format
|
49
49
|
I18n.translate(i18n_prefix + 'errors.messages.invalid')
|
50
50
|
when :length
|
51
|
-
if count = validation.options[:
|
51
|
+
if count = validation.options[:is]
|
52
|
+
I18n.translate(i18n_prefix + 'errors.messages.wrong_length').sub(orm_error_interpolation(:count), count.to_s)
|
53
|
+
elsif count = validation.options[:minimum]
|
52
54
|
I18n.translate(i18n_prefix + 'errors.messages.too_short').sub(orm_error_interpolation(:count), count.to_s)
|
53
55
|
elsif count = validation.options[:maximum]
|
54
56
|
I18n.translate(i18n_prefix + 'errors.messages.too_long').sub(orm_error_interpolation(:count), count.to_s)
|
@@ -1,15 +1,138 @@
|
|
1
1
|
module DNCLabs
|
2
2
|
module ClientSideValidations
|
3
|
-
def
|
4
|
-
|
3
|
+
def validate_options
|
4
|
+
rules = Hash.new { |h, field| h[field] = {} }
|
5
|
+
messages = Hash.new { |h, field| h[field] = {} }
|
5
6
|
validation_fields.each do |field|
|
6
|
-
|
7
|
+
validations = validations_to_hash(field)
|
8
|
+
rules[field.to_s].merge!(extract_rules(validations, field))
|
9
|
+
messages[field.to_s].merge!(extract_messages(validations))
|
7
10
|
end
|
8
|
-
|
11
|
+
{"rules" => rules, "messages" => messages}
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
12
|
-
dnc_csv_adapter.
|
14
|
+
def validations_to_hash(field)
|
15
|
+
dnc_csv_adapter.validations_to_hash(field)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def convert_kind(kind, options = nil)
|
21
|
+
case kind
|
22
|
+
when 'acceptance', 'exclusion', 'inclusion'
|
23
|
+
kind
|
24
|
+
when 'confirmation'
|
25
|
+
'equalTo'
|
26
|
+
when 'presence'
|
27
|
+
'required'
|
28
|
+
when 'numericality'
|
29
|
+
'digits'
|
30
|
+
when 'length'
|
31
|
+
if options['is']
|
32
|
+
'islength'
|
33
|
+
elsif options['minimum'] && options['maximum']
|
34
|
+
['minlength', 'maxlength']
|
35
|
+
elsif options['minimum']
|
36
|
+
'minlength'
|
37
|
+
elsif options['maximum']
|
38
|
+
'maxlength'
|
39
|
+
end
|
40
|
+
when 'uniqueness'
|
41
|
+
'remote'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_rules(validations, field = nil)
|
46
|
+
rules = {}
|
47
|
+
validations.each do |kind, options|
|
48
|
+
kind = convert_kind(kind, options)
|
49
|
+
value = case kind
|
50
|
+
when 'acceptance'
|
51
|
+
true
|
52
|
+
when 'equalTo'
|
53
|
+
%{[name="#{field}_confirmation"]}
|
54
|
+
when 'required'
|
55
|
+
true
|
56
|
+
when 'digits'
|
57
|
+
true
|
58
|
+
when 'exclusion', 'inclusion'
|
59
|
+
options['in']
|
60
|
+
when 'islength'
|
61
|
+
options['is']
|
62
|
+
when 'minlength'
|
63
|
+
options['minimum']
|
64
|
+
when 'maxlength'
|
65
|
+
options['maximum']
|
66
|
+
when 'remote'
|
67
|
+
if self.new_record?
|
68
|
+
data = {}
|
69
|
+
else
|
70
|
+
data = { "#{self.class.to_s.underscore}[id]" => self.id}
|
71
|
+
end
|
72
|
+
{'url' => '/validations/uniqueness.json', 'data' => data}
|
73
|
+
end
|
74
|
+
|
75
|
+
unless Array === kind
|
76
|
+
rules[kind] = value
|
77
|
+
else
|
78
|
+
kind.each do |k|
|
79
|
+
special_rule = case k
|
80
|
+
when 'minlength'
|
81
|
+
options['minimum']
|
82
|
+
when 'maxlength'
|
83
|
+
options['maximum']
|
84
|
+
end
|
85
|
+
|
86
|
+
rules[k] = special_rule
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
if required?(kind, options)
|
91
|
+
unless rules['required']
|
92
|
+
rules['required'] = true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
rules
|
98
|
+
end
|
99
|
+
|
100
|
+
def extract_messages(validations)
|
101
|
+
messages = {}
|
102
|
+
validations.each do |kind, options|
|
103
|
+
kind = convert_kind(kind, options)
|
104
|
+
unless Array === kind
|
105
|
+
messages[kind] = options['message']
|
106
|
+
else
|
107
|
+
kind.each do |k|
|
108
|
+
special_message = case k
|
109
|
+
when 'minlength'
|
110
|
+
options['message'] = options['message_min']
|
111
|
+
'message_min'
|
112
|
+
when 'maxlength'
|
113
|
+
'message_max'
|
114
|
+
end
|
115
|
+
|
116
|
+
messages[k] = options[special_message]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
if required?(kind, options)
|
121
|
+
unless messages['required']
|
122
|
+
messages['required'] = options['message']
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
messages
|
127
|
+
end
|
128
|
+
|
129
|
+
def required?(kind, options)
|
130
|
+
case kind
|
131
|
+
when 'digits', 'exclusion', 'inclusion', 'islength', 'minlength', 'remote'
|
132
|
+
!options['allow_blank']
|
133
|
+
when Array
|
134
|
+
required?('minlength', options) if kind.include?('minlength')
|
135
|
+
end
|
13
136
|
end
|
14
137
|
|
15
138
|
def validation_fields
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: client_side_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 2.6.
|
9
|
+
- 3
|
10
|
+
version: 2.6.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Cardarella
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-25 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|