client_side_validations 3.2.0.beta.1 → 3.2.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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