client_side_validations 3.2.0.rc.1 → 3.2.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,4 +26,5 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency 'thin'
27
27
  s.add_development_dependency 'json'
28
28
  s.add_development_dependency 'coffee-script'
29
+ s.add_development_dependency 'jquery-rails'
29
30
  end
@@ -1,12 +1,7 @@
1
1
  module ClientSideValidations
2
- module Config
3
- class << self
4
- attr_accessor :uniqueness_validator_disabled
5
- @uniqueness_validator_disabled = false
6
- end
7
- end
8
2
  end
9
3
 
4
+ require 'client_side_validations/config'
10
5
  require 'client_side_validations/active_model' if defined?(::ActiveModel)
11
6
  require 'client_side_validations/active_record' if defined?(::ActiveRecord)
12
7
  require 'client_side_validations/action_view' if defined?(::ActionView)
@@ -34,6 +34,13 @@ module ClientSideValidations::ActionView::Helpers
34
34
  end
35
35
  end
36
36
 
37
+ def validate(*attrs)
38
+ attrs.each do |attr|
39
+ build_validation_options(attr)
40
+ end
41
+ nil
42
+ end
43
+
37
44
  def initialize_with_client_side_validations(object_name, object, template, options, proc)
38
45
  initialize_without_client_side_validations(object_name, object, template, options, proc)
39
46
  @options[:validators] = { object => {} }
@@ -58,22 +65,26 @@ module ClientSideValidations::ActionView::Helpers
58
65
  end
59
66
 
60
67
  def select_with_client_side_validations(method, choices, options = {}, html_options = {})
61
- build_validation_options(method, html_options.merge(:validate => options[:validate]))
68
+ build_validation_options(method, html_options.merge(:name => options[:name]))
69
+ html_options.delete(:validate)
62
70
  select_without_client_side_validations(method, choices, options, html_options)
63
71
  end
64
72
 
65
73
  def collection_select_with_client_side_validations(method, collection, value_method, text_method, options = {}, html_options = {})
66
- build_validation_options(method, html_options.merge(:validate => options[:validate]))
74
+ build_validation_options(method, html_options.merge(:name => options[:name]))
75
+ html_options.delete(:validate)
67
76
  collection_select_without_client_side_validations(method, collection, value_method, text_method, options, html_options)
68
77
  end
69
78
 
70
79
  def grouped_collection_select_with_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
71
- build_validation_options(method, html_options.merge(:validate => options[:validate]))
80
+ build_validation_options(method, html_options.merge(:name => options[:name]))
81
+ html_options.delete(:validate)
72
82
  grouped_collection_select_without_client_side_validations(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
73
83
  end
74
84
 
75
85
  def time_zone_select_with_client_side_validations(method, priority_zones = nil, options = {}, html_options = {})
76
- build_validation_options(method, html_options.merge(:validate => options[:validate]))
86
+ build_validation_options(method, html_options.merge(:name => options[:name]))
87
+ html_options.delete(:validate)
77
88
  time_zone_select_without_client_side_validations(method, priority_zones = nil, options, html_options)
78
89
  end
79
90
 
@@ -6,6 +6,7 @@ module ClientSideValidations::ActiveRecord
6
6
  end
7
7
 
8
8
  def self.is_unique?(klass, attribute, value, params)
9
+ klass = find_topmost_superclass(klass)
9
10
  value = type_cast_value(klass, attribute, value)
10
11
  column = klass.columns_hash[attribute.to_s]
11
12
  value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s if column.text?
@@ -46,5 +47,13 @@ module ClientSideValidations::ActiveRecord
46
47
  klass.columns_hash[attribute].type_cast(value)
47
48
  end
48
49
 
50
+ def self.find_topmost_superclass(klass)
51
+ if is_class?(klass.superclass)
52
+ find_topmost_superclass(klass.superclass)
53
+ else
54
+ klass
55
+ end
56
+ end
57
+
49
58
  end
50
59
  end
@@ -0,0 +1,8 @@
1
+ module ClientSideValidations
2
+ module Config
3
+ class << self
4
+ attr_accessor :uniqueness_validator_disabled
5
+ @uniqueness_validator_disabled = false
6
+ end
7
+ end
8
+ end
@@ -43,14 +43,20 @@ module ClientSideValidations
43
43
  class Uniqueness < Base
44
44
  IGNORE_PARAMS = %w{case_sensitive id scope}
45
45
  REGISTERED_ORMS = []
46
+ class NotValidatable < StandardError; end
46
47
 
47
48
  def response
48
- if is_unique?
49
- self.status = 404
50
- self.body = 'true'
51
- else
52
- self.status = 200
53
- self.body = 'false'
49
+ begin
50
+ if is_unique?
51
+ self.status = 404
52
+ self.body = 'true'
53
+ else
54
+ self.status = 200
55
+ self.body = 'false'
56
+ end
57
+ rescue NotValidatable
58
+ self.status = 500
59
+ self.body = ''
54
60
  end
55
61
  super
56
62
  end
@@ -77,6 +83,10 @@ module ClientSideValidations
77
83
  value = request.params[resource][attribute]
78
84
  middleware_class = nil
79
85
 
86
+ unless Array.wrap(klass._validators[attribute.to_sym]).find { |v| v.kind == :uniqueness }
87
+ raise NotValidatable
88
+ end
89
+
80
90
  registered_orms.each do |orm|
81
91
  if orm.is_class?(klass)
82
92
  middleware_class = orm
@@ -1,3 +1,3 @@
1
1
  module ClientSideValidations
2
- VERSION = '3.2.0.rc.1'
2
+ VERSION = '3.2.0.rc.2'
3
3
  end
@@ -1,5 +1,8 @@
1
1
  # ClientSideValidations Initializer
2
2
 
3
+ # Uncomment to disable uniqueness validator, possible security issue
4
+ # ClientSideValidations::Config.uniqueness_validator_disabled = true
5
+
3
6
  # Uncomment the following block if you want each input field to have the validation messages attached.
4
7
  # ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
5
8
  # unless html_tag =~ /^<label/
@@ -4,102 +4,28 @@
4
4
 
5
5
  $ = jQuery;
6
6
 
7
+ $.fn.disableClientSideValidations = function() {
8
+ return ClientSideValidations.disable(this);
9
+ };
10
+
11
+ $.fn.enableClientSideValidations = function() {
12
+ this.filter('form[data-validate]').each(function() {
13
+ return ClientSideValidations.enablers.form(this);
14
+ });
15
+ return this.filter(':input').each(function() {
16
+ return ClientSideValidations.enablers.input(this);
17
+ });
18
+ };
19
+
20
+ $.fn.resetClientSideValidations = function() {
21
+ return this.filter('form[data-validate]').each(function() {
22
+ return ClientSideValidations.reset(this);
23
+ });
24
+ };
25
+
7
26
  $.fn.validate = function() {
8
27
  return this.filter('form[data-validate]').each(function() {
9
- var addError, binding, event, form, removeError, settings, _ref, _ref1;
10
- form = $(this);
11
- settings = window.ClientSideValidations.forms[form.attr('id')];
12
- addError = function(element, message) {
13
- return ClientSideValidations.formBuilders[settings.type].add(element, settings, message);
14
- };
15
- removeError = function(element) {
16
- return ClientSideValidations.formBuilders[settings.type].remove(element, settings);
17
- };
18
- form.submit(function(eventData) {
19
- if (!form.isValid(settings.validators)) {
20
- return eventData.preventDefault();
21
- }
22
- });
23
- _ref = {
24
- 'ajax:beforeSend': function(eventData) {
25
- if (eventData.target === this) {
26
- return form.isValid(settings.validators);
27
- }
28
- },
29
- 'form:validate:after': function(eventData) {
30
- return ClientSideValidations.callbacks.form.after(form, eventData);
31
- },
32
- 'form:validate:before': function(eventData) {
33
- return ClientSideValidations.callbacks.form.before(form, eventData);
34
- },
35
- 'form:validate:fail': function(eventData) {
36
- return ClientSideValidations.callbacks.form.fail(form, eventData);
37
- },
38
- 'form:validate:pass': function(eventData) {
39
- return ClientSideValidations.callbacks.form.pass(form, eventData);
40
- }
41
- };
42
- for (event in _ref) {
43
- binding = _ref[event];
44
- form.bind(event, binding);
45
- }
46
- _ref1 = {
47
- 'focusout': function() {
48
- return $(this).isValid(settings.validators);
49
- },
50
- 'change': function() {
51
- return $(this).data('changed', true);
52
- },
53
- 'element:validate:after': function(eventData) {
54
- return ClientSideValidations.callbacks.element.after($(this), eventData);
55
- },
56
- 'element:validate:before': function(eventData) {
57
- return ClientSideValidations.callbacks.element.before($(this), eventData);
58
- },
59
- 'element:validate:fail': function(eventData, message) {
60
- var element;
61
- element = $(this);
62
- return ClientSideValidations.callbacks.element.fail(element, message, function() {
63
- return addError(element, message);
64
- }, eventData);
65
- },
66
- 'element:validate:pass': function(eventData) {
67
- var element;
68
- element = $(this);
69
- return ClientSideValidations.callbacks.element.pass(element, function() {
70
- return removeError(element);
71
- }, eventData);
72
- }
73
- };
74
- for (event in _ref1) {
75
- binding = _ref1[event];
76
- form.find(':input:enabled:not(:radio):not([id$=_confirmation])').live(event, binding);
77
- }
78
- form.find(':checkbox').live('click', function() {
79
- $(this).isValid(settings.validators);
80
- return true;
81
- });
82
- return form.find('[id$=_confirmation]').each(function() {
83
- var confirmationElement, element, _ref2, _results;
84
- confirmationElement = $(this);
85
- element = form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + ":input");
86
- if (element[0]) {
87
- _ref2 = {
88
- 'focusout': function() {
89
- return element.data('changed', true).isValid(settings.validators);
90
- },
91
- 'keyup': function() {
92
- return element.data('changed', true).isValid(settings.validators);
93
- }
94
- };
95
- _results = [];
96
- for (event in _ref2) {
97
- binding = _ref2[event];
98
- _results.push($("#" + (confirmationElement.attr('id'))).live(event, binding));
99
- }
100
- return _results;
101
- }
102
- });
28
+ return $(this).enableClientSideValidations();
103
29
  });
104
30
  };
105
31
 
@@ -120,35 +46,35 @@
120
46
 
121
47
  validateForm = function(form, validators) {
122
48
  var valid;
123
- form.trigger('form:validate:before');
49
+ form.trigger('form:validate:before.ClientSideValidations');
124
50
  valid = true;
125
- form.find(':input:enabled').each(function() {
51
+ form.find(':input:enabled:visible[data-validate]').each(function() {
126
52
  if (!$(this).isValid(validators)) {
127
53
  valid = false;
128
54
  }
129
55
  return true;
130
56
  });
131
57
  if (valid) {
132
- form.trigger('form:validate:pass');
58
+ form.trigger('form:validate:pass.ClientSideValidations');
133
59
  } else {
134
- form.trigger('form:validate:fail');
60
+ form.trigger('form:validate:fail.ClientSideValidations');
135
61
  }
136
- form.trigger('form:validate:after');
62
+ form.trigger('form:validate:after.ClientSideValidations');
137
63
  return valid;
138
64
  };
139
65
 
140
66
  validateElement = function(element, validators) {
141
67
  var afterValidate, destroyInputName, executeValidators, failElement, local, passElement, remote;
142
- element.trigger('element:validate:before');
68
+ element.trigger('element:validate:before.ClientSideValidations');
143
69
  passElement = function() {
144
- return element.trigger('element:validate:pass').data('valid', null);
70
+ return element.trigger('element:validate:pass.ClientSideValidations').data('valid', null);
145
71
  };
146
72
  failElement = function(message) {
147
- element.trigger('element:validate:fail', message).data('valid', false);
73
+ element.trigger('element:validate:fail.ClientSideValidations', message).data('valid', false);
148
74
  return false;
149
75
  };
150
76
  afterValidate = function() {
151
- return element.trigger('element:validate:after').data('valid') !== false;
77
+ return element.trigger('element:validate:after.ClientSideValidations').data('valid') !== false;
152
78
  };
153
79
  executeValidators = function(context) {
154
80
  var fn, kind, message, valid, validator, _i, _len, _ref;
@@ -200,6 +126,141 @@
200
126
  window.ClientSideValidations.forms = {};
201
127
  }
202
128
 
129
+ window.ClientSideValidations.reset = function(form) {
130
+ var $form, key;
131
+ $form = $(form);
132
+ ClientSideValidations.disable(form);
133
+ ClientSideValidations.disable($form.find(':input'));
134
+ for (key in form.ClientSideValidations.settings.validators) {
135
+ form.ClientSideValidations.removeError($form.find("[name='" + key + "']"));
136
+ }
137
+ return ClientSideValidations.enablers.form(form);
138
+ };
139
+
140
+ window.ClientSideValidations.disable = function(target) {
141
+ var $target;
142
+ $target = $(target);
143
+ $target.off('.ClientSideValidations');
144
+ $target.removeData('valid');
145
+ $target.removeData('changed');
146
+ return $target.filter(':input').each(function() {
147
+ return $(this).removeAttr('data-validate');
148
+ });
149
+ };
150
+
151
+ window.ClientSideValidations.enablers = {
152
+ form: function(form) {
153
+ var $form, binding, event, _ref;
154
+ $form = $(form);
155
+ form.ClientSideValidations = {
156
+ settings: window.ClientSideValidations.forms[$form.attr('id')],
157
+ addError: function(element, message) {
158
+ return ClientSideValidations.formBuilders[form.ClientSideValidations.settings.type].add(element, form.ClientSideValidations.settings, message);
159
+ },
160
+ removeError: function(element) {
161
+ return ClientSideValidations.formBuilders[form.ClientSideValidations.settings.type].remove(element, form.ClientSideValidations.settings);
162
+ }
163
+ };
164
+ _ref = {
165
+ 'submit.ClientSideValidations': function(eventData) {
166
+ if (!$form.isValid(form.ClientSideValidations.settings.validators)) {
167
+ eventData.preventDefault();
168
+ return eventData.stopImmediatePropagation();
169
+ }
170
+ },
171
+ 'ajax:beforeSend.ClientSideValidations': function(eventData) {
172
+ if (eventData.target === this) {
173
+ return $form.isValid(form.ClientSideValidations.settings.validators);
174
+ }
175
+ },
176
+ 'form:validate:after.ClientSideValidations': function(eventData) {
177
+ return ClientSideValidations.callbacks.form.after($form, eventData);
178
+ },
179
+ 'form:validate:before.ClientSideValidations': function(eventData) {
180
+ return ClientSideValidations.callbacks.form.before($form, eventData);
181
+ },
182
+ 'form:validate:fail.ClientSideValidations': function(eventData) {
183
+ return ClientSideValidations.callbacks.form.fail($form, eventData);
184
+ },
185
+ 'form:validate:pass.ClientSideValidations': function(eventData) {
186
+ return ClientSideValidations.callbacks.form.pass($form, eventData);
187
+ }
188
+ };
189
+ for (event in _ref) {
190
+ binding = _ref[event];
191
+ $form.on(event, binding);
192
+ }
193
+ return $form.find(':input').each(function() {
194
+ return ClientSideValidations.enablers.input(this);
195
+ });
196
+ },
197
+ input: function(input) {
198
+ var $form, $input, binding, event, form, _ref;
199
+ $input = $(input);
200
+ form = input.form;
201
+ $form = $(form);
202
+ _ref = {
203
+ 'focusout.ClientSideValidations': function() {
204
+ return $(this).isValid(form.ClientSideValidations.settings.validators);
205
+ },
206
+ 'change.ClientSideValidations': function() {
207
+ return $(this).data('changed', true);
208
+ },
209
+ 'element:validate:after.ClientSideValidations': function(eventData) {
210
+ return ClientSideValidations.callbacks.element.after($(this), eventData);
211
+ },
212
+ 'element:validate:before.ClientSideValidations': function(eventData) {
213
+ return ClientSideValidations.callbacks.element.before($(this), eventData);
214
+ },
215
+ 'element:validate:fail.ClientSideValidations': function(eventData, message) {
216
+ var element;
217
+ element = $(this);
218
+ return ClientSideValidations.callbacks.element.fail(element, message, function() {
219
+ return form.ClientSideValidations.addError(element, message);
220
+ }, eventData);
221
+ },
222
+ 'element:validate:pass.ClientSideValidations': function(eventData) {
223
+ var element;
224
+ element = $(this);
225
+ return ClientSideValidations.callbacks.element.pass(element, function() {
226
+ return form.ClientSideValidations.removeError(element);
227
+ }, eventData);
228
+ }
229
+ };
230
+ for (event in _ref) {
231
+ binding = _ref[event];
232
+ $input.filter(':enabled:not(:radio):not([id$=_confirmation]):visible').each(function() {
233
+ return $(this).attr('data-validate', true);
234
+ }).on(event, binding);
235
+ }
236
+ $input.filter(':checkbox:visible').on('click.ClientSideValidations', function() {
237
+ $(this).isValid(form.ClientSideValidations.settings.validators);
238
+ return true;
239
+ });
240
+ return $input.filter('[id$=_confirmation]:visible').each(function() {
241
+ var confirmationElement, element, _ref1, _results;
242
+ confirmationElement = $(this);
243
+ element = $form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + ":input");
244
+ if (element[0]) {
245
+ _ref1 = {
246
+ 'focusout.ClientSideValidations': function() {
247
+ return element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
248
+ },
249
+ 'keyup.ClientSideValidations': function() {
250
+ return element.data('changed', true).isValid(form.ClientSideValidations.settings.validators);
251
+ }
252
+ };
253
+ _results = [];
254
+ for (event in _ref1) {
255
+ binding = _ref1[event];
256
+ _results.push($("#" + (confirmationElement.attr('id'))).on(event, binding));
257
+ }
258
+ return _results;
259
+ }
260
+ });
261
+ }
262
+ };
263
+
203
264
  window.ClientSideValidations.validators = {
204
265
  all: function() {
205
266
  return jQuery.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote);
@@ -314,7 +375,7 @@
314
375
  }
315
376
  },
316
377
  exclusion: function(element, options) {
317
- var lower, message, o, upper, _ref;
378
+ var lower, message, option, upper, _ref;
318
379
  message = this.presence(element, options);
319
380
  if (message) {
320
381
  if (options.allow_blank === true) {
@@ -328,8 +389,8 @@
328
389
  _ref1 = options["in"];
329
390
  _results = [];
330
391
  for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
331
- o = _ref1[_i];
332
- _results.push(o.toString());
392
+ option = _ref1[_i];
393
+ _results.push(option.toString());
333
394
  }
334
395
  return _results;
335
396
  })(), _ref) >= 0) {
@@ -345,7 +406,7 @@
345
406
  }
346
407
  },
347
408
  inclusion: function(element, options) {
348
- var lower, message, o, upper, _ref;
409
+ var lower, message, option, upper, _ref;
349
410
  message = this.presence(element, options);
350
411
  if (message) {
351
412
  if (options.allow_blank === true) {
@@ -359,8 +420,8 @@
359
420
  _ref1 = options["in"];
360
421
  _results = [];
361
422
  for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
362
- o = _ref1[_i];
363
- _results.push(o.toString());
423
+ option = _ref1[_i];
424
+ _results.push(option.toString());
364
425
  }
365
426
  return _results;
366
427
  })(), _ref) >= 0) {
@@ -442,8 +503,8 @@
442
503
  if (scoped_element[0] && scoped_element.val() !== scope_value) {
443
504
  data.scope[key] = scoped_element.val();
444
505
  scoped_element.unbind("change." + element.id).bind("change." + element.id, function() {
445
- element.trigger('change');
446
- return element.trigger('focusout');
506
+ element.trigger('change.ClientSideValidations');
507
+ return element.trigger('focusout.ClientSideValidations');
447
508
  });
448
509
  } else {
449
510
  data.scope[key] = scope_value;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: client_side_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0.rc.1
4
+ version: 3.2.0.rc.2
5
5
  prerelease: 6
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-04 00:00:00.000000000 Z
12
+ date: 2012-10-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -155,6 +155,22 @@ dependencies:
155
155
  - - ! '>='
156
156
  - !ruby/object:Gem::Version
157
157
  version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: jquery-rails
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
158
174
  description: Client Side Validations
159
175
  email:
160
176
  - bcardarella@gmail.com
@@ -179,6 +195,7 @@ files:
179
195
  - lib/client_side_validations/active_record.rb
180
196
  - lib/client_side_validations/active_record/middleware.rb
181
197
  - lib/client_side_validations/active_record/uniqueness.rb
198
+ - lib/client_side_validations/config.rb
182
199
  - lib/client_side_validations/core_ext.rb
183
200
  - lib/client_side_validations/core_ext/range.rb
184
201
  - lib/client_side_validations/core_ext/regexp.rb
@@ -206,7 +223,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
223
  version: '0'
207
224
  segments:
208
225
  - 0
209
- hash: 4549078949979817551
226
+ hash: -4404664315488432309
210
227
  required_rubygems_version: !ruby/object:Gem::Requirement
211
228
  none: false
212
229
  requirements: