client_side_validations 3.2.0.beta.1 → 3.2.0.beta.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.
@@ -24,4 +24,5 @@ Gem::Specification.new do |s|
24
24
  s.add_development_dependency 'shotgun'
25
25
  s.add_development_dependency 'thin'
26
26
  s.add_development_dependency 'json'
27
+ s.add_development_dependency 'coffee-script'
27
28
  end
@@ -11,6 +11,7 @@ require 'client_side_validations/active_model' if defined?(::ActiveModel)
11
11
  require 'client_side_validations/active_record' if defined?(::ActiveRecord)
12
12
  require 'client_side_validations/action_view' if defined?(::ActionView)
13
13
  if defined?(::Rails)
14
+ require 'client_side_validations/generators'
14
15
  require 'client_side_validations/middleware'
15
16
  require 'client_side_validations/engine'
16
17
  end
@@ -0,0 +1,12 @@
1
+ module ClientSideValidations
2
+ module Generators
3
+ Assets = []
4
+
5
+ def self.register_assets(klass)
6
+ Assets.push(*klass.assets)
7
+ end
8
+ end
9
+ end
10
+
11
+ require 'client_side_validations/generators/rails_validations'
12
+
@@ -0,0 +1,15 @@
1
+ module ClientSideValidations
2
+ module Generators
3
+ class RailsValidations
4
+ def self.assets
5
+ [{
6
+ :path => File.expand_path('../../../../vendor/assets/javascripts', __FILE__),
7
+ :file => 'rails.validations.js'
8
+ }]
9
+ end
10
+
11
+ Generators.register_assets(self)
12
+ end
13
+ end
14
+ end
15
+
@@ -1,3 +1,3 @@
1
1
  module ClientSideValidations
2
- VERSION = '3.2.0.beta.1'
2
+ VERSION = '3.2.0.beta.2'
3
3
  end
@@ -0,0 +1,56 @@
1
+ module ClientSideValidations
2
+ module Generators
3
+ class CopyAssetsGenerator < Rails::Generators::Base
4
+
5
+ def copy_javascript_asset
6
+ if self.class == CopyAssetsGenerator || !asset_pipeline_enabled?
7
+ assets.each do |asset|
8
+ source_paths << asset[:path]
9
+ copy_file asset[:file], "#{asset_directory}/#{asset[:file]}"
10
+ end
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def self.asset_directory
17
+ if asset_pipeline_enabled?
18
+ "app#{Rails.configuration.assets.prefix}/javascripts"
19
+ else
20
+ 'public/javascripts'
21
+ end
22
+ end
23
+
24
+ def asset_directory
25
+ CopyAssetsGenerator.asset_directory
26
+ end
27
+
28
+ def self.assets
29
+ Assets
30
+ end
31
+
32
+ def assets
33
+ CopyAssetsGenerator.assets
34
+ end
35
+
36
+ def self.asset_file_names
37
+ assets.map { |asset| asset[:file] }.join(', ')
38
+ end
39
+
40
+ def self.asset_pipeline_enabled?
41
+ (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
42
+ end
43
+
44
+ def asset_pipeline_enabled?
45
+ self.class.asset_pipeline_enabled?
46
+ end
47
+
48
+ def self.installation_message
49
+ "Copies #{asset_file_names} to #{asset_directory}"
50
+ end
51
+
52
+ desc installation_message
53
+ end
54
+ end
55
+ end
56
+
@@ -1,44 +1,21 @@
1
+ require 'generators/client_side_validations/copy_assets_generator'
2
+
1
3
  module ClientSideValidations
2
4
  module Generators
3
- class InstallGenerator < Rails::Generators::Base
4
- source_root File.expand_path('../../templates/client_side_validations', __FILE__)
5
-
6
- private
7
-
8
- def self.asset_pipeline_enabled?
9
- (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
10
- end
11
-
12
- def asset_pipeline_enabled?
13
- self.class.asset_pipeline_enabled?
14
- end
15
-
16
- public
17
-
18
- if asset_pipeline_enabled?
19
- desc 'Creates a ClientSideValidations initializer.'
20
- else
21
- desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
22
- end
5
+ class InstallGenerator < CopyAssetsGenerator
23
6
 
24
7
  def copy_initializer
8
+ source_paths << File.expand_path('../../templates/client_side_validations', __FILE__)
25
9
  copy_file 'initializer.rb', 'config/initializers/client_side_validations.rb'
26
10
  end
27
11
 
28
- def copy_javascript_asset
29
- unless asset_pipeline_enabled?
30
- copy_file '../../../../vendor/assets/javascripts/rails.validations.js', 'public/javascripts/rails.validations.js'
31
- end
32
- end
12
+ private
33
13
 
34
- def show_readme
35
- if Rails.version >= '3.1'
36
- readme 'README.rails.3.1' if behavior == :invoke
37
- else
38
- readme 'README.rails.3.0' if behavior == :invoke
39
- end
14
+ def self.installation_message
15
+ "Copies initializer into config/initializers and #{super.downcase}"
40
16
  end
41
17
 
18
+ desc installation_message
42
19
  end
43
20
  end
44
21
  end
@@ -1,74 +1,79 @@
1
- /*!
2
- * Rails 3 Client Side Validations - v3.2.0.beta.1
3
- * https://github.com/bcardarella/client_side_validations
4
- *
5
- * Copyright (c) 2011 Brian Cardarella
6
- * Licensed under the MIT license
7
- * http://www.opensource.org/licenses/mit-license.php
8
- */
9
1
 
10
- (function ($) {
11
- $.fn.validate = function () {
12
- return this.filter('form[data-validate]').each(function () {
13
- var form = $(this),
14
- settings = window['ClientSideValidations']['forms'][form.attr('id')],
15
- addError = function (element, message) {
16
- ClientSideValidations.formBuilders[settings.type].add(element, settings, message);
17
- },
18
- removeError = function (element) {
19
- ClientSideValidations.formBuilders[settings.type].remove(element, settings);
20
- };
2
+ /*
3
+ Rails 3 Client Side Validations - v3.2.0.beta.2
4
+ https://github.com/bcardarella/client_side_validations
21
5
 
22
- // Set up the events for the form
23
- form
24
- .submit( function () { return form.isValid(settings.validators); })
25
- .bind('ajax:beforeSend', function (eventData) { if(eventData.target == this) return form.isValid(settings.validators); })
26
- // Callbacks
27
- .bind('form:validate:after', function (eventData) { ClientSideValidations.callbacks.form.after( form, eventData); } )
28
- .bind('form:validate:before', function (eventData) { ClientSideValidations.callbacks.form.before(form, eventData); } )
29
- .bind('form:validate:fail', function (eventData) { ClientSideValidations.callbacks.form.fail( form, eventData); } )
30
- .bind('form:validate:pass', function (eventData) { ClientSideValidations.callbacks.form.pass( form, eventData); } )
6
+ Copyright (c) 2012 Brian Cardarella
7
+ Licensed under the MIT license
8
+ http://www.opensource.org/licenses/mit-license.php
9
+ */
31
10
 
32
- // Set up the events for each validatable form element
33
- .find('[data-validate="true"]:input:enabled:not(:radio)')
34
- .live('focusout', function () { $(this).isValid(settings.validators); })
35
- .live('change', function () { $(this).data('changed', true); })
36
- // Callbacks
37
- .live('element:validate:after', function (eventData) { ClientSideValidations.callbacks.element.after( $(this), eventData); })
38
- .live('element:validate:before', function (eventData) { ClientSideValidations.callbacks.element.before($(this), eventData); })
39
- .live('element:validate:fail', function (eventData, message) {
40
- var element = $(this);
41
- ClientSideValidations.callbacks.element.fail(element, message, function () {
42
- addError(element, message);
43
- }, eventData); })
44
- .live('element:validate:pass', function (eventData) {
45
- var element = $(this);
46
- ClientSideValidations.callbacks.element.pass(element, function () {
47
- removeError(element);
48
- }, eventData); })
49
- // Checkboxes - Live events don't support filter
50
- .end().find('[data-validate="true"]:checkbox')
51
- .live('click', function () { $(this).isValid(settings.validators); })
52
- // Inputs for confirmations
53
- .end().find('[id*=_confirmation]').each(function () {
54
- var confirmationElement = $(this),
55
- element = form.find('#' + this.id.match(/(.+)_confirmation/)[1] + '[data-validate="true"]:input');
11
+ (function() {
12
+ var $, validateElement, validateForm;
56
13
 
57
- if (element[0]) {
58
- $('#' + confirmationElement.attr('id'))
59
- .live('focusout', function () {
60
- element.data('changed', true).isValid(settings.validators);
61
- })
62
- .live('keyup', function () {
63
- element.data('changed', true).isValid(settings.validators);
64
- });
65
- }
66
- });
14
+ $ = jQuery;
67
15
 
16
+ $.fn.validate = function() {
17
+ return this.filter('form[data-validate]').each(function() {
18
+ var addError, form, removeError, settings;
19
+ form = $(this);
20
+ settings = window['ClientSideValidations']['forms'][form.attr('id')];
21
+ addError = function(element, message) {
22
+ return ClientSideValidations.formBuilders[settings.type].add(element, settings, message);
23
+ };
24
+ removeError = function(element) {
25
+ return ClientSideValidations.formBuilders[settings.type].remove(element, settings);
26
+ };
27
+ return form.submit(function() {
28
+ return form.isValid(settings.validators);
29
+ }).bind('ajax:beforeSend', function(eventData) {
30
+ if (eventData.target === this) return form.isValid(settings.validators);
31
+ }).bind('form:validate:after', function(eventData) {
32
+ return ClientSideValidations.callbacks.form.after(form, eventData);
33
+ }).bind('form:validate:before', function(eventData) {
34
+ return ClientSideValidations.callbacks.form.before(form, eventData);
35
+ }).bind('form:validate:fail', function(eventData) {
36
+ return ClientSideValidations.callbacks.form.fail(form, eventData);
37
+ }).bind('form:validate:pass', function(eventData) {
38
+ return ClientSideValidations.callbacks.form.pass(form, eventData);
39
+ }).find('[data-validate="true"]:input:enabled:not(:radio)').live('focusout', function() {
40
+ return $(this).isValid(settings.validators);
41
+ }).live('change', function() {
42
+ return $(this).data('changed', true);
43
+ }).live('element:validate:after', function(eventData) {
44
+ return ClientSideValidations.callbacks.element.after($(this), eventData);
45
+ }).live('element:validate:before', function(eventData) {
46
+ return ClientSideValidations.callbacks.element.before($(this), eventData);
47
+ }).live('element:validate:fail', function(eventData, message) {
48
+ var element;
49
+ element = $(this);
50
+ return ClientSideValidations.callbacks.element.fail(element, message, function() {
51
+ return addError(element, message);
52
+ }, eventData);
53
+ }).live('element:validate:pass', function(eventData, message) {
54
+ var element;
55
+ element = $(this);
56
+ return ClientSideValidations.callbacks.element.pass(element, function() {
57
+ return removeError(element);
58
+ }, eventData);
59
+ }).end().find('[data-validate="true"]:checkbox').live('click', function() {
60
+ return $(this).isValid(settings.validators);
61
+ }).end().find('[id*=_confirmation]').each(function() {
62
+ var confirmationElement, element;
63
+ confirmationElement = $(this);
64
+ element = form.find("#" + (this.id.match(/(.+)_confirmation/)[1]) + "[data-validate='true']:input");
65
+ if (element[0]) {
66
+ return $("#" + (confirmationElement.attr('id'))).live('focusout', function() {
67
+ return element.data('changed', true).isValid(settings.validators);
68
+ }).live('keyup', function() {
69
+ return element.data('changed', true).isValid(settings.validators);
70
+ });
71
+ }
72
+ });
68
73
  });
69
74
  };
70
75
 
71
- $.fn.isValid = function (validators) {
76
+ $.fn.isValid = function(validators) {
72
77
  if ($(this[0]).is('form')) {
73
78
  return validateForm($(this[0]), validators);
74
79
  } else {
@@ -76,300 +81,287 @@
76
81
  }
77
82
  };
78
83
 
79
- var validateForm = function (form, validators) {
80
- var valid = true;
81
-
84
+ validateForm = function(form, validators) {
85
+ var valid;
86
+ valid = true;
82
87
  form.trigger('form:validate:before').find('[data-validate="true"]:input:enabled').each(function() {
83
- if (!$(this).isValid(validators)) { valid = false; }
88
+ if (!$(this).isValid(validators)) valid = false;
89
+ if (valid) {
90
+ form.trigger('form:validate:pass');
91
+ } else {
92
+ form.trigger('form:validate:fail');
93
+ }
94
+ return form.trigger('form:validate:after');
84
95
  });
85
-
86
- if (valid) {
87
- form.trigger('form:validate:pass');
88
- } else {
89
- form.trigger('form:validate:fail');
90
- }
91
-
92
- form.trigger('form:validate:after');
93
96
  return valid;
94
- },
95
- validateElement = function (element, validators) {
96
- element.trigger('element:validate:before');
97
-
98
- if (element.data('changed') !== false) {
99
- var valid = true;
100
- element.data('changed', false);
97
+ };
101
98
 
102
- // Because 'length' is defined on the list of validators we cannot call jQuery.each on
103
- for (kind in ClientSideValidations.validators.local) {
99
+ validateElement = function(element, validators) {
100
+ var kind, message, valid;
101
+ element.trigger('element:validate:before');
102
+ if (element.data('changed') !== false) {
103
+ valid = true;
104
+ element.data('changed', false);
105
+ for (kind in ClientSideValidations.validators.local) {
106
+ if (validators[kind] && (message = ClientSideValidations.validators.all()[kind](element, validators[kind]))) {
107
+ element.trigger('element:validate:fail', message).data('valid', false);
108
+ valid = false;
109
+ break;
110
+ }
111
+ }
112
+ if (valid) {
113
+ for (kind in ClientSideValidations.validators.remote) {
104
114
  if (validators[kind] && (message = ClientSideValidations.validators.all()[kind](element, validators[kind]))) {
105
115
  element.trigger('element:validate:fail', message).data('valid', false);
106
116
  valid = false;
107
117
  break;
108
118
  }
109
119
  }
110
-
111
- if (valid) {
112
- for (kind in ClientSideValidations.validators.remote) {
113
- if (validators[kind] && (message = ClientSideValidations.validators.all()[kind](element, validators[kind]))) {
114
- element.trigger('element:validate:fail', message).data('valid', false);
115
- valid = false;
116
- break;
117
- }
118
- }
119
- }
120
-
121
- if (valid) { element.data('valid', null); element.trigger('element:validate:pass'); }
122
120
  }
123
-
121
+ if (valid) {
122
+ element.data('valid', null);
123
+ element.trigger('element:validate:pass');
124
+ }
124
125
  element.trigger('element:validate:after');
125
- return element.data('valid') === false ? false : true;
126
- };
126
+ if (element.data('valid') === false) {
127
+ return false;
128
+ } else {
129
+ return true;
130
+ }
131
+ }
132
+ };
127
133
 
128
- // Main hook
129
- // If new forms are dynamically introduced into the DOM the .validate() method
130
- // must be invoked on that form
131
- $(function () { $('form[data-validate]').validate(); });
132
- })(jQuery);
134
+ $(function() {
135
+ return $('form[data-validate]').validate();
136
+ });
133
137
 
134
- var ClientSideValidations = {
135
- forms: {},
136
- validators: {
137
- all: function() { return jQuery.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote); },
138
- local: {
139
- presence: function (element, options) {
140
- if (/^\s*$/.test(element.val() || "")) {
141
- return options.message;
142
- }
138
+ window.ClientSideValidations = {
139
+ forms: {},
140
+ validators: {
141
+ all: function() {
142
+ return $.extend({}, ClientSideValidations.validators.local, ClientSideValidations.validators.remote);
143
143
  },
144
- acceptance: function (element, options) {
145
- switch (element.attr('type')) {
146
- case 'checkbox':
147
- if (!element.attr('checked')) {
148
- return options.message;
149
- }
150
- break;
151
- case 'text':
152
- if (element.val() != (options.accept || '1')) {
144
+ local: {
145
+ presence: function(element, options) {
146
+ if (/^\s*$/.test(element.val() || "")) return options.message;
147
+ },
148
+ acceptance: function(element, options) {
149
+ switch (element.attr('type')) {
150
+ case 'checkbox':
151
+ if (!element.attr('checked')) return options.message;
152
+ break;
153
+ case 'text':
154
+ if (element.val() !== (options.accept || '1').toString()) {
155
+ return options.message;
156
+ }
157
+ }
158
+ },
159
+ format: function(element, options) {
160
+ var message;
161
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {} else if (message) {
162
+ return message;
163
+ } else {
164
+ if (options['with'] && !options['with'].test(element.val())) {
153
165
  return options.message;
154
166
  }
155
- break;
156
- }
157
- },
158
- format: function (element, options) {
159
- if ((message = this.presence(element, options)) && options.allow_blank === true) {
160
- return;
161
- } else if (message) {
162
- return message;
163
- } else {
164
- if (options['with'] && !options['with'].test(element.val())) {
165
- return options.message;
166
- } else if (options['without'] && options['without'].test(element.val())) {
167
- return options.message;
168
167
  }
169
- }
170
- },
171
- numericality: function (element, options) {
172
- if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val())) {
173
- return options.messages.numericality;
174
- }
175
-
176
- if (options.only_integer && !/^[+-]?\d+$/.test(element.val())) {
177
- return options.messages.only_integer;
178
- }
179
-
180
- var CHECKS = { greater_than: '>', greater_than_or_equal_to: '>=',
181
- equal_to: '==', less_than: '<', less_than_or_equal_to: '<=' };
182
-
183
- for (check in CHECKS) {
184
- if (options[check] !== undefined && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
185
- return options.messages[check];
168
+ },
169
+ numericality: function(element, options) {
170
+ var CHECKS, check;
171
+ if (!/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d*)?$/.test(element.val())) {
172
+ return options.messages.numericality;
186
173
  }
187
- }
188
-
189
- if (options.odd && !(parseInt(element.val(), 10) % 2)) {
190
- return options.messages.odd;
191
- }
192
-
193
- if (options.even && (parseInt(element.val(), 10) % 2)) {
194
- return options.messages.even;
195
- }
196
- },
197
- length: function (element, options) {
198
- var blankOptions = {},
199
- CHECKS = { is: '==', minimum: '>=', maximum: '<=' },
200
- tokenizer = options.js_tokenizer || "split('')",
201
- tokenized_length = new Function("element", "return (element.val()." + tokenizer + " || '').length;")(element);
202
- if (options.is) {
203
- blankOptions.message = options.messages.is;
204
- } else if (options.minimum) {
205
- blankOptions.message = options.messages.minimum;
206
- }
207
- if ((message = this.presence(element, blankOptions)) && options.allow_blank === true) {
208
- return;
209
- } else if (message) {
210
- return message;
211
- } else {
174
+ if (options.only_integer && !/^[+-]?\d+$/.test(element.val())) {
175
+ return options.messages.only_integer;
176
+ }
177
+ CHECKS = {
178
+ greater_than: '>',
179
+ greater_than_or_equal_to: '>=',
180
+ equal_to: '==',
181
+ less_than: '<',
182
+ less_than_or_equal_to: '<='
183
+ };
212
184
  for (check in CHECKS) {
213
- if (options[check] && !(new Function("return " + tokenized_length + CHECKS[check] + options[check])())) {
185
+ if (options[check] !== void 0 && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
214
186
  return options.messages[check];
215
187
  }
216
188
  }
217
- }
218
- },
219
- exclusion: function (element, options) {
220
- var lower = null, upper = null;
221
- if ((message = this.presence(element, options)) && options.allow_blank === true) {
222
- return;
223
- } else if (message) {
224
- return message;
225
- } else {
226
- if (options['in']) {
227
- for (i = 0; i < options['in'].length; i = i + 1) {
228
- if (options['in'][i] == element.val()) {
189
+ if (options.odd && !(parseInt(element.val(), 10) % 2)) {
190
+ return options.messages.odd;
191
+ }
192
+ if (options.even && (parseInt(element.val(), 10) % 2)) {
193
+ return options.messages.even;
194
+ }
195
+ },
196
+ length: function(element, options) {
197
+ var CHECKS, blankOptions, check, message, tokenized_length, tokenizer;
198
+ blankOptions = {};
199
+ CHECKS = {
200
+ is: '==',
201
+ minimum: '>=',
202
+ maximum: '<='
203
+ };
204
+ tokenizer = options.js_tokenizer || "split('')";
205
+ tokenized_length = new Function("element", "return (element.val()." + tokenizer + " || '').length;")(element);
206
+ if (options.is) {
207
+ blankOptions.message = options.messages.is;
208
+ } else if (options.minimum) {
209
+ blankOptions.message = options.messages.minimum;
210
+ }
211
+ if ((message = this.presence(element, blankOptions)) && options.allow_blank === true) {} else if (message) {
212
+ return message;
213
+ } else {
214
+ for (check in CHECKS) {
215
+ if (options[check] && !(new Function("return " + tokenized_length + CHECKS[check] + options[check])())) {
216
+ return options.messages[check];
217
+ }
218
+ }
219
+ }
220
+ },
221
+ exclusion: function(element, options) {
222
+ var lower, message, upper, value;
223
+ lower = null;
224
+ upper = null;
225
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {} else if (message) {
226
+ return message;
227
+ } else {
228
+ if (options['in']) {
229
+ for (value in options['in']) {
230
+ if (value.toString() === element.val()) return options.message;
231
+ }
232
+ } else if (options.range) {
233
+ lower = options.range[0];
234
+ upper = options.range[1];
235
+ if (element.val() >= lower && element.val() <= upper) {
229
236
  return options.message;
230
237
  }
231
238
  }
232
- } else if (options.range) {
233
- lower = options.range[0];
234
- upper = options.range[1];
235
- if (element.val() >= lower && element.val() <= upper) {
239
+ }
240
+ },
241
+ inclusion: function(element, options) {
242
+ var lower, message, upper, value;
243
+ lower = null;
244
+ upper = null;
245
+ if ((message = this.presence(element, options)) && options.allow_blank === true) {} else if (message) {
246
+ return message;
247
+ } else {
248
+ if (options['in']) {
249
+ for (value in options['in']) {
250
+ if (value.toString() === element.val()) return;
251
+ }
236
252
  return options.message;
253
+ } else if (options.range) {
254
+ lower = options.range[0];
255
+ upper = options.range[1];
256
+ if (element.val() >= lower && element.val() <= upper) {} else {
257
+ return options.message;
258
+ }
237
259
  }
238
260
  }
261
+ },
262
+ confirmation: function(element, options) {
263
+ if (element.val() !== $("#" + (element.attr('id')) + "_confirmation").val()) {
264
+ return options.message;
265
+ }
239
266
  }
240
267
  },
241
- inclusion: function (element, options) {
242
- var lower = null, upper = null;
243
- if ((message = this.presence(element, options)) && options.allow_blank === true) {
244
- return;
245
- } else if (message) {
246
- return message;
247
- } else {
248
- if (options['in']) {
249
- for (i = 0; i < options['in'].length; i = i + 1) {
250
- if (options['in'][i] == element.val()) {
251
- return;
268
+ remote: {
269
+ uniqueness: function(element, options) {
270
+ var data, key, message, name, scoped_element;
271
+ if ((message = ClientSideValidations.validators.local.presence(element, options)) && options.allow_blank === true) {} else if (message) {
272
+ return message;
273
+ } else {
274
+ data = {};
275
+ name = null;
276
+ data.case_sensitive = !!options.case_sensitive;
277
+ if (options.id) data.id = options.id;
278
+ if (options.scope) {
279
+ data.scope = {};
280
+ for (key in options.scope) {
281
+ scoped_element = $('[name="' + element.attr('name').replace(/\[\w+\]$/, '[' + key + ']' + '"]'));
282
+ if (scoped_element[0] && scoped_element.val() !== options.scope[key]) {
283
+ data.scope[key] = scoped_element.val();
284
+ scoped_element.unbind("change." + element.id).bind("change." + element.id, function() {
285
+ element.trigger('change');
286
+ return element.trigger('focusout');
287
+ });
288
+ } else {
289
+ data.scope[key] = options.scope[key];
290
+ }
252
291
  }
253
292
  }
254
- return options.message;
255
- } else if (options.range) {
256
- lower = options.range[0];
257
- upper = options.range[1];
258
-
259
- if (element.val() >= lower && element.val() <= upper) {
260
- return;
293
+ if (/_attributes\]/.test(element.attr('name'))) {
294
+ name = element.attr('name').match(/\[\w+_attributes\]/g).pop().match(/\[(\w+)_attributes\]/).pop();
295
+ name += /(\[\w+\])$/.exec(element.attr('name'))[1];
261
296
  } else {
297
+ name = element.attr('name');
298
+ }
299
+ if (options['class']) {
300
+ name = "" + options['class'] + "[" + (name.split('[')[1]);
301
+ }
302
+ data[name] = element.val();
303
+ if ($.ajax({
304
+ url: '/validators/uniqueness',
305
+ data: data,
306
+ async: false
307
+ }).status === 200) {
262
308
  return options.message;
263
309
  }
264
310
  }
265
311
  }
266
- },
267
- confirmation: function (element, options) {
268
- if (element.val() !== jQuery('#' + element.attr('id') + '_confirmation').val()) {
269
- return options.message;
270
- }
271
312
  }
272
313
  },
273
- remote: {
274
- uniqueness: function (element, options) {
275
- if ((message = ClientSideValidations.validators.local.presence(element, options)) && options.allow_blank === true) {
276
- return;
277
- } else if (message) {
278
- return message;
279
- } else {
280
- var data = {},
281
- name = null;
282
- data.case_sensitive = !!options.case_sensitive;
283
- if (options.id) {
284
- data.id = options.id;
314
+ formBuilders: {
315
+ 'ActionView::Helpers::FormBuilder': {
316
+ add: function(element, settings, message) {
317
+ var inputErrorField, label, labelErrorField;
318
+ if (element.data('valid') !== false && $("label.message[for='" + (element.attr('id')) + "']")[0] === void 0) {
319
+ inputErrorField = $(settings.input_tag);
320
+ labelErrorField = $(settings.label_tag);
321
+ label = $("label[for='" + (element.attr('id')) + "']:not(.message)");
322
+ if (element.attr('autofocus')) element.attr('autofocus', false);
323
+ element.before(inputErrorField);
324
+ inputErrorField.find('span#input_tag').replaceWith(element);
325
+ inputErrorField.find('label.message').attr('for', element.attr('id'));
326
+ labelErrorField.find('label.message').attr('for', element.attr('id'));
327
+ label.replaceWith(labelErrorField);
328
+ labelErrorField.find('label#label_tag').replaceWith(label);
285
329
  }
286
-
287
- if (options.scope) {
288
- data.scope = {};
289
- for (key in options.scope) {
290
- var scoped_element = jQuery('[name="' + element.attr('name').replace(/\[\w+\]$/, '[' + key + ']' + '"]'));
291
- if (scoped_element[0] && scoped_element.val() !== options.scope[key]) {
292
- data.scope[key] = scoped_element.val();
293
- scoped_element.unbind('change.' + element.id).bind('change.' + element.id, function() { element.trigger('change'); element.trigger('focusout'); });
294
- } else {
295
- data.scope[key] = options.scope[key];
296
- }
297
- }
298
- }
299
-
300
- // Kind of a hack but this will isolate the resource name and attribute.
301
- // e.g. user[records_attributes][0][title] => records[title]
302
- // e.g. user[record_attributes][title] => record[title]
303
- // Server side handles classifying the resource properly
304
- if (/_attributes\]/.test(element.attr('name'))) {
305
- name = element.attr('name').match(/\[\w+_attributes\]/g).pop().match(/\[(\w+)_attributes\]/).pop();
306
- name += /(\[\w+\])$/.exec(element.attr('name'))[1];
307
- } else {
308
- name = element.attr('name');
309
- }
310
-
311
- // Override the name if a nested module class is passed
312
- if (options['class']) {
313
- name = options['class'] + '[' + name.split('[')[1];
314
- }
315
- data[name] = element.val();
316
-
317
- if (jQuery.ajax({
318
- url: '/validators/uniqueness',
319
- data: data,
320
- async: false
321
- }).status === 200) {
322
- return options.message;
330
+ return $("label.message[for='" + (element.attr('id')) + "']").text(message);
331
+ },
332
+ remove: function(element, settings) {
333
+ var errorFieldClass, inputErrorField, label, labelErrorField;
334
+ errorFieldClass = $(settings.input_tag).attr('class');
335
+ inputErrorField = element.closest("." + errorFieldClass);
336
+ label = $("label[for='" + (element.attr('id')) + "']:not(.message)");
337
+ labelErrorField = label.closest("." + errorFieldClass);
338
+ if (inputErrorField[0]) {
339
+ inputErrorField.find("#" + (element.attr('id'))).detach();
340
+ inputErrorField.replaceWith(element);
341
+ label.detach();
342
+ return labelErrorField.replaceWith(label);
323
343
  }
324
344
  }
325
345
  }
326
- }
327
- },
328
- formBuilders: {
329
- 'ActionView::Helpers::FormBuilder': {
330
- add: function (element, settings, message) {
331
- if (element.data('valid') !== false && jQuery('label.message[for="' + element.attr('id') + '"]')[0] === undefined) {
332
- var inputErrorField = jQuery(settings.input_tag),
333
- labelErrorField = jQuery(settings.label_tag),
334
- label = jQuery('label[for="' + element.attr('id') + '"]:not(.message)');
335
-
336
- if (element.attr('autofocus')) { element.attr('autofocus', false); }
337
- element.before(inputErrorField);
338
- inputErrorField.find('span#input_tag').replaceWith(element);
339
- inputErrorField.find('label.message').attr('for', element.attr('id'));
340
- labelErrorField.find('label.message').attr('for', element.attr('id'));
341
- label.replaceWith(labelErrorField);
342
- labelErrorField.find('label#label_tag').replaceWith(label);
346
+ },
347
+ callbacks: {
348
+ element: {
349
+ after: function(element, eventData) {},
350
+ before: function(element, eventData) {},
351
+ fail: function(element, message, addError, eventData) {
352
+ return addError();
353
+ },
354
+ pass: function(element, removeError, eventData) {
355
+ return removeError();
343
356
  }
344
- jQuery('label.message[for="' + element.attr('id') + '"]').text(message);
345
357
  },
346
- remove: function (element, settings) {
347
- var errorFieldClass = jQuery(settings.input_tag).attr('class'),
348
- inputErrorField = element.closest('.' + errorFieldClass),
349
- label = jQuery('label[for="' + element.attr('id') + '"]:not(.message)'),
350
- labelErrorField = label.closest('.' + errorFieldClass);
351
-
352
- if (inputErrorField[0]) {
353
- inputErrorField.find('#' + element.attr('id')).detach();
354
- inputErrorField.replaceWith(element);
355
- label.detach();
356
- labelErrorField.replaceWith(label);
357
- }
358
+ form: {
359
+ after: function(form, eventData) {},
360
+ before: function(form, eventData) {},
361
+ fail: function(form, eventData) {},
362
+ pass: function(form, eventData) {}
358
363
  }
359
- },
360
- },
361
- callbacks: {
362
- element: {
363
- after: function (element, eventData) { },
364
- before: function (element, eventData) { },
365
- fail: function (element, message, addError, eventData) { addError(); },
366
- pass: function (element, removeError, eventData) { removeError(); }
367
- },
368
- form: {
369
- after: function (form, eventData) { },
370
- before: function (form, eventData) { },
371
- fail: function (form, eventData) { },
372
- pass: function (form, eventData) { }
373
364
  }
374
- }
375
- };
365
+ };
366
+
367
+ }).call(this);
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.beta.1
4
+ version: 3.2.0.beta.2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-22 00:00:00.000000000Z
12
+ date: 2012-01-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70255205329720 !ruby/object:Gem::Requirement
16
+ requirement: &70281071642860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70255205329720
24
+ version_requirements: *70281071642860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sqlite3
27
- requirement: &70255205329100 !ruby/object:Gem::Requirement
27
+ requirement: &70281071642120 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70255205329100
35
+ version_requirements: *70281071642120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: mocha
38
- requirement: &70255205328360 !ruby/object:Gem::Requirement
38
+ requirement: &70281071641060 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70255205328360
46
+ version_requirements: *70281071641060
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sinatra
49
- requirement: &70255205327620 !ruby/object:Gem::Requirement
49
+ requirement: &70281071640160 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70255205327620
57
+ version_requirements: *70281071640160
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: shotgun
60
- requirement: &70255205326900 !ruby/object:Gem::Requirement
60
+ requirement: &70281071639680 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70255205326900
68
+ version_requirements: *70281071639680
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thin
71
- requirement: &70255205326360 !ruby/object:Gem::Requirement
71
+ requirement: &70281071639200 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70255205326360
79
+ version_requirements: *70281071639200
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: json
82
- requirement: &70255205325800 !ruby/object:Gem::Requirement
82
+ requirement: &70281071638700 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,18 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70255205325800
90
+ version_requirements: *70281071638700
91
+ - !ruby/object:Gem::Dependency
92
+ name: coffee-script
93
+ requirement: &70281071638160 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70281071638160
91
102
  description: Client Side Validations
92
103
  email:
93
104
  - bcardarella@gmail.com
@@ -117,11 +128,12 @@ files:
117
128
  - lib/client_side_validations/core_ext/regexp.rb
118
129
  - lib/client_side_validations/engine.rb
119
130
  - lib/client_side_validations/files.rb
131
+ - lib/client_side_validations/generators.rb
132
+ - lib/client_side_validations/generators/rails_validations.rb
120
133
  - lib/client_side_validations/middleware.rb
121
134
  - lib/client_side_validations/version.rb
122
- - lib/generators/client_side_validations/copy_asset_generator.rb
135
+ - lib/generators/client_side_validations/copy_assets_generator.rb
123
136
  - lib/generators/client_side_validations/install_generator.rb
124
- - lib/generators/templates/client_side_validations/README.rails.3.1
125
137
  - lib/generators/templates/client_side_validations/initializer.rb
126
138
  - vendor/assets/javascripts/rails.validations.js
127
139
  homepage: https://github.com/bcardarella/client_side_validations
@@ -1,36 +0,0 @@
1
- module ClientSideValidations
2
- module Generators
3
- class CopyAssetGenerator < Rails::Generators::Base
4
- source_root File.expand_path('../../../../vendor/assets/javascripts', __FILE__)
5
-
6
- private
7
-
8
- def self.asset_pipeline_enabled?
9
- (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
10
- end
11
-
12
- def asset_pipeline_enabled?
13
- self.class.asset_pipeline_enabled?
14
- end
15
-
16
- public
17
-
18
- if asset_pipeline_enabled?
19
- desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to app/assets/javascripts.'
20
- else
21
- desc 'Creates a ClientSideValidations initializer and copies rails.validations.js to public/javascripts.'
22
- end
23
-
24
- def copy_javascript_asset
25
- if asset_pipeline_enabled?
26
- destination = 'app/assets/javascripts'
27
- else
28
- destination = 'public/javascripts'
29
- end
30
-
31
- copy_file 'rails.validations.js', "#{destination}/rails.validations.js"
32
- end
33
- end
34
- end
35
- end
36
-
@@ -1,7 +0,0 @@
1
- *********************
2
- ClientSideValidations
3
- *********************
4
-
5
- In your app/assets/javascripts/application.js file add the following:
6
-
7
- //= require rails.validations