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

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.
@@ -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: