formtastic_validation 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -2,7 +2,14 @@ h1. formtastic_validation
2
2
 
3
3
  h2. Introduction
4
4
 
5
- Formtastic validation adds client side validation to your forms.
5
+ Formtastic validation adds client side validation to your forms. Visit the "demo app":http://formtastic-validation-app.heroku.com/ and its "repo":http://github.com/liangzan/formtastic_validation_app to see it in action.
6
+
7
+ h2. Features
8
+
9
+ * works with existing formtastic code. no need to modify anything
10
+ * javascript lib agnostic.
11
+ * no AJAX that pounds your servers. its completely client side javascript
12
+ * unobtrusive and very light weight
6
13
 
7
14
  h2. Dependencies
8
15
 
@@ -15,6 +22,8 @@ h2. Installation
15
22
  <pre>
16
23
  $ gem install formtastic_validation
17
24
  </pre>
25
+
26
+ Remember to add the gem into your config
18
27
 
19
28
  Then run the generators to add the files on
20
29
 
@@ -29,13 +38,9 @@ This adds a configuration file to config/initializers and a couple of javascript
29
38
  After that you need to add this to your application layout
30
39
 
31
40
  <pre>
32
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
33
- <html lang='en-US' xml:lang='en-US' xmlns='http://www.w3.org/1999/xhtml'>
34
41
  <head>
35
- <meta content='text/html; charset=utf-8' http-equiv='Content-type'/>
36
- <title>Formtastic Validation</title>
37
42
  <%= javascript_include_tag 'livevalidation-1.3.min' %>
38
- <%= javascript_include_tag 'formtastic_validation-0.1.0.min' %>
43
+ <%= javascript_include_tag 'formtastic_validation-0.1.2.min' %>
39
44
  <script type="text/javascript">
40
45
  function initialize() {
41
46
  var formtasticValidation = new FormtasticValidation;
@@ -45,19 +50,23 @@ After that you need to add this to your application layout
45
50
  </head>
46
51
  <body onload="initialize()">
47
52
  </body>
48
- </html>
49
53
  </pre>
50
54
 
51
- Two things to add:
55
+ What the above does:
56
+
57
+ * it included the livevalidation and formtastic_validation javascript files
58
+ * it ran a function that instantiates a FormatasticValidation object and let it call initialize()
52
59
 
53
- * include the livevalidation and formtastic_validation javascript files
54
- * run a function that instantiates a FormatasticValidation object and let it call initialize()
55
60
  h2. Usage
56
61
 
57
62
  There is nothing to change in your existing code. You should see "Thankyou!" appearing next to fields which passed the validations. Forms which do not fufil the validations will fail to submit.
58
63
 
59
64
  Validation options work.
60
65
 
66
+ h2. Configuration
67
+
68
+ The valid message can be changed in the formtastic_validation configuration file under config/initializers
69
+
61
70
  h2. CSS Styling
62
71
 
63
72
  You can style the validation messages with the css selectors
@@ -70,6 +79,8 @@ You can style the validation messages with the css selectors
70
79
 
71
80
  h2. Caveats
72
81
 
82
+ This gem is Rails 2 compatible. Rails 3 update is coming....
83
+
73
84
  Only the following validations work:
74
85
 
75
86
  # validates_presence_of
@@ -85,6 +96,11 @@ validates_size_of does not work. Do use my "fork":http://rubygems.org/gems/liang
85
96
 
86
97
  The rest do not work as they depend on server queries.
87
98
 
99
+ h2. Alternative implementations
100
+
101
+ http://github.com/dnclabs/client_side_validations
102
+ http://github.com/grimen/validatious-on-rails
103
+
88
104
  h2. Note on Patches/Pull Requests
89
105
 
90
106
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{formtastic_validation}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wong Liang Zan"]
12
- s.date = %q{2010-08-31}
12
+ s.date = %q{2010-09-08}
13
13
  s.description = %q{A formtastic extension that does client side validation}
14
14
  s.email = %q{zan@liangzan.net}
15
15
  s.extra_rdoc_files = [
@@ -26,12 +26,14 @@ Gem::Specification.new do |s|
26
26
  "formtastic_validation.gemspec",
27
27
  "javascripts/README.textile",
28
28
  "javascripts/build/formtastic_validation-0.1.0.min.js",
29
+ "javascripts/build/formtastic_validation-0.1.1.min.js",
30
+ "javascripts/build/formtastic_validation-0.1.2.min.js",
29
31
  "javascripts/lib/livevalidation-1.3.min.js",
30
32
  "javascripts/src/formtastic_validation.js",
31
33
  "lib/formtastic_validation.rb",
32
34
  "rails_generators/formtastic_validation/formtastic_validation_generator.rb",
33
35
  "rails_generators/formtastic_validation/templates/config/initializers/formtastic_validation.rb",
34
- "rails_generators/formtastic_validation/templates/public/javascripts/formtastic_validation-0.1.0.min.js",
36
+ "rails_generators/formtastic_validation/templates/public/javascripts/formtastic_validation-0.1.2.min.js",
35
37
  "rails_generators/formtastic_validation/templates/public/javascripts/livevalidation-1.3.min.js",
36
38
  "spec/formtastic_validation_spec.rb",
37
39
  "spec/spec.opts",
@@ -8,7 +8,7 @@ Do install yui-compressor before attempting to build the files.
8
8
 
9
9
  h2. Testing
10
10
 
11
- Testing is done using cuucmber on the formtastic validation app
11
+ Testing is done using cucmber on the formtastic validation "demo app":http://github.com/liangzan/formtastic_validation_app
12
12
 
13
13
  h2. Building
14
14
 
@@ -0,0 +1 @@
1
+ var FormtasticValidation=function(){this.VERSION="0.1.0";this.selectInputElements=function(){var d=document.getElementsByTagName("input");var e=new Array;for(var b=0;b<d.length;b++){var a=d[b];var c=a.getAttribute("type");if(this.isValidInputType(c)){e.push(d[b])}}return e};this.isValidInputType=function(a){switch(a){case"text":case"password":case"radio":case"checkbox":return true;default:return false}};this.getValidationAttributes=function(e){var b={};var f=e.attributes;var d,a;for(var c=0;c<f.length;c++){d=this.extractValidationKey(f[c].name);a=f[c].value;if(d!=null){b[d]=a}}return b};this.extractValidationKey=function(b){var c=/validation_(\w+)/;var a=b.match(c);return a!=null?a[1]:null};this.extractFormatRegex=function(b){var c=/^\/(.*)\/$/;var a=b.match(c);return a!=null?a[1]:null};this.confirmationID=function(b){var a=b.getAttribute("id");return a+"_confirmation"};this.bindInputElements=function(c,a,b){var e=new LiveValidation(c,{validMessage:b.valid_message});var f,d;switch(a){case"validates_acceptance_of":e.add(Validate.Acceptance,{failureMessage:b.message});break;case"validates_confirmation_of":d=new LiveValidation(this.confirmationID(c));d.add(Validate.Confirmation,{match:c,failureMessage:b.message});break;case"validates_exclusion_of":e.add(Validate.Exclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_format_of":f=this.extractFormatRegex(b["with"]);e.add(Validate.Format,{pattern:new RegExp(f),failureMessage:b.message});break;case"validates_inclusion_of":e.add(Validate.Inclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_size_of":case"validates_length_of":e.add(Validate.Length,{is:b.is,minimum:b.minimum,maximum:b.maximum,wrongLengthMessage:b.wrong_length,tooShortMessage:b.too_short,tooLongMessage:b.too_long});break;case"validates_numericality_of":e.add(Validate.Numericality,{is:b.equal_to,minimum:b.greater_than_or_equal_to,maximum:b.less_than_or_equal_to,onlyinteger:b.only_integer,failureMessage:b.message});break;case"validates_presence_of":e.add(Validate.Presence,{failureMessage:b.message});break}}};FormtasticValidation.prototype.initialize=function(){var f=this.selectInputElements();var d,e,a;for(var c=0;c<f.length;c++){d=f[c].getAttribute("validation");if(d!=null){e=d.split(" ");for(var b=0;b<e.length;b++){a=this.getValidationAttributes(f[c]);this.bindInputElements(f[c],e[b],a)}}}};
@@ -0,0 +1 @@
1
+ var FormtasticValidation=function(){this.VERSION="0.1.0";this.selectInputElements=function(){var d=document.getElementsByTagName("input");var e=new Array;for(var b=0;b<d.length;b++){var a=d[b];var c=a.getAttribute("type");if(this.isValidInputType(c)){e.push(d[b])}}return e};this.isValidInputType=function(a){switch(a){case"text":case"password":case"radio":case"checkbox":return true;default:return false}};this.getValidationAttributes=function(e){var b={};var f=e.attributes;var d,a;for(var c=0;c<f.length;c++){d=this.extractValidationKey(f[c].name);a=f[c].value;if(d!=null){b[d]=a}}return b};this.extractValidationKey=function(b){var c=/validation_(\w+)/;var a=b.match(c);return a!=null?a[1]:null};this.extractFormatRegex=function(b){var c=/^\/(.*)\/$/;var a=b.match(c);return a!=null?a[1]:null};this.confirmationID=function(b){var a=b.getAttribute("id");return a+"_confirmation"};this.bindInputElements=function(c,a,b){var e=new LiveValidation(c,{validMessage:b.valid_message});var f,d;switch(a){case"validates_acceptance_of":e.add(Validate.Acceptance,{failureMessage:b.message});break;case"validates_confirmation_of":d=new LiveValidation(this.confirmationID(c),{validMessage:b.valid_message});d.add(Validate.Confirmation,{match:c,failureMessage:b.message});break;case"validates_exclusion_of":e.add(Validate.Exclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_format_of":f=this.extractFormatRegex(b["with"]);e.add(Validate.Format,{pattern:new RegExp(f),failureMessage:b.message});break;case"validates_inclusion_of":e.add(Validate.Inclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_size_of":case"validates_length_of":e.add(Validate.Length,{is:b.is,minimum:b.minimum,maximum:b.maximum,wrongLengthMessage:b.wrong_length,tooShortMessage:b.too_short,tooLongMessage:b.too_long});break;case"validates_numericality_of":e.add(Validate.Numericality,{is:b.equal_to,minimum:b.greater_than_or_equal_to,maximum:b.less_than_or_equal_to,onlyinteger:b.only_integer,failureMessage:b.message});break;case"validates_presence_of":e.add(Validate.Presence,{failureMessage:b.message});break}}};FormtasticValidation.prototype.initialize=function(){var f=this.selectInputElements();var d,e,a;for(var c=0;c<f.length;c++){d=f[c].getAttribute("validation");if(d!=null){e=d.split(" ");for(var b=0;b<e.length;b++){a=this.getValidationAttributes(f[c]);this.bindInputElements(f[c],e[b],a)}}}};
@@ -63,7 +63,7 @@ var FormtasticValidation = function() {
63
63
  };
64
64
 
65
65
  this.bindInputElements = function(element, validation, options) {
66
- var elementValidation = new LiveValidation(element);
66
+ var elementValidation = new LiveValidation(element, {validMessage: options["valid_message"]});
67
67
  var formatRegex, confirmationElement;
68
68
 
69
69
  switch(validation) {
@@ -71,7 +71,7 @@ var FormtasticValidation = function() {
71
71
  elementValidation.add(Validate.Acceptance, {failureMessage: options["message"]});
72
72
  break;
73
73
  case "validates_confirmation_of":
74
- confirmationElement = new LiveValidation(this.confirmationID(element));
74
+ confirmationElement = new LiveValidation(this.confirmationID(element), {validMessage: options["valid_message"]});
75
75
  confirmationElement.add(Validate.Confirmation, {match: element, failureMessage: options["message"]});
76
76
  break;
77
77
  case "validates_exclusion_of":
@@ -111,4 +111,4 @@ FormtasticValidation.prototype.initialize = function() {
111
111
  }
112
112
  }
113
113
  }
114
- };
114
+ };
@@ -1,6 +1,11 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+
1
4
  module FormtasticValidation
2
5
 
3
6
  NAMESPACE = 'validation'
7
+ @@valid_message = "Thank you!"
8
+ mattr_accessor :valid_message
4
9
 
5
10
  def self.included(base)
6
11
  base.class_eval {
@@ -30,11 +35,15 @@ module FormtasticValidation
30
35
  def validation_tags(attribute, input_html)
31
36
  tags = []
32
37
  @object.class.reflect_on_validations_for(attribute).each do |validation|
33
- tags << { :validation => validation.macro }.merge(validation.options)
38
+ tags << { :validation => validation.macro }.merge(validation.options.merge(validation_valid_message_tag))
34
39
  end
35
40
  stack_tags(tags, input_html)
36
41
  end
37
42
 
43
+ def validation_valid_message_tag
44
+ { :valid_message => @@valid_message }
45
+ end
46
+
38
47
  def stack_tags(tags, input_html)
39
48
  vtags = validates_tags(tags.dup)
40
49
  otags = options_tags(tags.dup)
@@ -2,7 +2,7 @@ class FormtasticValidationGenerator < Rails::Generator::Base
2
2
 
3
3
  def manifest
4
4
  record do |m|
5
- m.file 'public/javascripts/formtastic_validation-0.1.0.min.js', 'public/javascripts/formtastic_validation-0.1.0.min.js'
5
+ m.file 'public/javascripts/formtastic_validation-0.1.2.min.js', 'public/javascripts/formtastic_validation-0.1.2.min.js'
6
6
  m.file 'public/javascripts/livevalidation-1.3.min.js', 'public/javascripts/livevalidation-1.3.min.js'
7
7
  m.file 'config/initializers/formtastic_validation.rb', 'config/initializers/formtastic_validation.rb'
8
8
  end
@@ -1,3 +1,6 @@
1
1
  if Object.const_defined? "Formtastic"
2
2
  Formtastic::SemanticFormBuilder.send(:include, FormtasticValidation)
3
+
4
+ # Set the default valid message. Default is Thank you!.
5
+ # FormtasticValidation.valid_message = "its correct!"
3
6
  end
@@ -0,0 +1 @@
1
+ var FormtasticValidation=function(){this.VERSION="0.1.0";this.selectInputElements=function(){var d=document.getElementsByTagName("input");var e=new Array;for(var b=0;b<d.length;b++){var a=d[b];var c=a.getAttribute("type");if(this.isValidInputType(c)){e.push(d[b])}}return e};this.isValidInputType=function(a){switch(a){case"text":case"password":case"radio":case"checkbox":return true;default:return false}};this.getValidationAttributes=function(e){var b={};var f=e.attributes;var d,a;for(var c=0;c<f.length;c++){d=this.extractValidationKey(f[c].name);a=f[c].value;if(d!=null){b[d]=a}}return b};this.extractValidationKey=function(b){var c=/validation_(\w+)/;var a=b.match(c);return a!=null?a[1]:null};this.extractFormatRegex=function(b){var c=/^\/(.*)\/$/;var a=b.match(c);return a!=null?a[1]:null};this.confirmationID=function(b){var a=b.getAttribute("id");return a+"_confirmation"};this.bindInputElements=function(c,a,b){var e=new LiveValidation(c,{validMessage:b.valid_message});var f,d;switch(a){case"validates_acceptance_of":e.add(Validate.Acceptance,{failureMessage:b.message});break;case"validates_confirmation_of":d=new LiveValidation(this.confirmationID(c),{validMessage:b.valid_message});d.add(Validate.Confirmation,{match:c,failureMessage:b.message});break;case"validates_exclusion_of":e.add(Validate.Exclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_format_of":f=this.extractFormatRegex(b["with"]);e.add(Validate.Format,{pattern:new RegExp(f),failureMessage:b.message});break;case"validates_inclusion_of":e.add(Validate.Inclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_size_of":case"validates_length_of":e.add(Validate.Length,{is:b.is,minimum:b.minimum,maximum:b.maximum,wrongLengthMessage:b.wrong_length,tooShortMessage:b.too_short,tooLongMessage:b.too_long});break;case"validates_numericality_of":e.add(Validate.Numericality,{is:b.equal_to,minimum:b.greater_than_or_equal_to,maximum:b.less_than_or_equal_to,onlyinteger:b.only_integer,failureMessage:b.message});break;case"validates_presence_of":e.add(Validate.Presence,{failureMessage:b.message});break}}};FormtasticValidation.prototype.initialize=function(){var f=this.selectInputElements();var d,e,a;for(var c=0;c<f.length;c++){d=f[c].getAttribute("validation");if(d!=null){e=d.split(" ");for(var b=0;b<e.length;b++){a=this.getValidationAttributes(f[c]);this.bindInputElements(f[c],e[b],a)}}}};
@@ -21,6 +21,23 @@ describe "FormtasticValidation#input" do
21
21
  output_buffer.should have_tag('input[@validation="validates_whatever"]')
22
22
  end
23
23
 
24
+ it 'should add a valid message tag' do
25
+ @bob.class.should_receive(:reflect_on_validations_for).with(:name).any_number_of_times.and_return([mock('MacroReflection', :macro => :validates_whatever, :name => :name, :options => {})])
26
+ semantic_form_for(@bob) do |builder|
27
+ concat(builder.input(:name))
28
+ end
29
+ output_buffer.should have_tag('input[@validation_valid_message="valid!"]')
30
+ end
31
+
32
+ it 'should allow changes to the valid message tag' do
33
+ @bob.class.should_receive(:reflect_on_validations_for).with(:name).any_number_of_times.and_return([mock('MacroReflection', :macro => :validates_whatever, :name => :name, :options => {})])
34
+ FormtasticValidation.valid_message = "Its correct!"
35
+ semantic_form_for(@bob) do |builder|
36
+ concat(builder.input(:name))
37
+ end
38
+ output_buffer.should have_tag('input[@validation_valid_message="Its correct!"]')
39
+ end
40
+
24
41
  it "should add multiple validation tags separated by space" do
25
42
  @bob.class.should_receive(:reflect_on_validations_for).with(:name).any_number_of_times.and_return([mock('MacroReflection', :macro => :validates_whatever, :name => :name, :options => {}), mock('MacroReflection', :macro => :validates_anything, :name => :name, :options => {})])
26
43
  semantic_form_for(@bob) do |builder|
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formtastic_validation
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Wong Liang Zan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-31 00:00:00 +08:00
18
+ date: 2010-09-08 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -165,12 +165,14 @@ files:
165
165
  - formtastic_validation.gemspec
166
166
  - javascripts/README.textile
167
167
  - javascripts/build/formtastic_validation-0.1.0.min.js
168
+ - javascripts/build/formtastic_validation-0.1.1.min.js
169
+ - javascripts/build/formtastic_validation-0.1.2.min.js
168
170
  - javascripts/lib/livevalidation-1.3.min.js
169
171
  - javascripts/src/formtastic_validation.js
170
172
  - lib/formtastic_validation.rb
171
173
  - rails_generators/formtastic_validation/formtastic_validation_generator.rb
172
174
  - rails_generators/formtastic_validation/templates/config/initializers/formtastic_validation.rb
173
- - rails_generators/formtastic_validation/templates/public/javascripts/formtastic_validation-0.1.0.min.js
175
+ - rails_generators/formtastic_validation/templates/public/javascripts/formtastic_validation-0.1.2.min.js
174
176
  - rails_generators/formtastic_validation/templates/public/javascripts/livevalidation-1.3.min.js
175
177
  - spec/formtastic_validation_spec.rb
176
178
  - spec/spec.opts
@@ -1 +0,0 @@
1
- var FormtasticValidation=function(){this.VERSION="0.1.0";this.selectInputElements=function(){var d=document.getElementsByTagName("input");var e=new Array;for(var b=0;b<d.length;b++){var a=d[b];var c=a.getAttribute("type");if(this.isValidInputType(c)){e.push(d[b])}}return e};this.isValidInputType=function(a){switch(a){case"text":case"password":case"radio":case"checkbox":return true;default:return false}};this.getValidationAttributes=function(e){var b={};var f=e.attributes;var d,a;for(var c=0;c<f.length;c++){d=this.extractValidationKey(f[c].name);a=f[c].value;if(d!=null){b[d]=a}}return b};this.extractValidationKey=function(b){var c=/validation_(\w+)/;var a=b.match(c);return a!=null?a[1]:null};this.extractFormatRegex=function(b){var c=/^\/(.*)\/$/;var a=b.match(c);return a!=null?a[1]:null};this.confirmationID=function(b){var a=b.getAttribute("id");return a+"_confirmation"};this.bindInputElements=function(c,a,b){var e=new LiveValidation(c);var f,d;switch(a){case"validates_acceptance_of":e.add(Validate.Acceptance,{failureMessage:b.message});break;case"validates_confirmation_of":d=new LiveValidation(this.confirmationID(c));d.add(Validate.Confirmation,{match:c,failureMessage:b.message});break;case"validates_exclusion_of":e.add(Validate.Exclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_format_of":f=this.extractFormatRegex(b["with"]);e.add(Validate.Format,{pattern:new RegExp(f),failureMessage:b.message});break;case"validates_inclusion_of":e.add(Validate.Inclusion,{within:JSON.parse(b["in"]),allowNull:b.allow_nil,failureMessage:b.message});break;case"validates_size_of":case"validates_length_of":e.add(Validate.Length,{is:b.is,minimum:b.minimum,maximum:b.maximum,wrongLengthMessage:b.wrong_length,tooShortMessage:b.too_short,tooLongMessage:b.too_long});break;case"validates_numericality_of":e.add(Validate.Numericality,{is:b.equal_to,minimum:b.greater_than_or_equal_to,maximum:b.less_than_or_equal_to,onlyinteger:b.only_integer,failureMessage:b.message});break;case"validates_presence_of":e.add(Validate.Presence,{failureMessage:b.message});break}}};FormtasticValidation.prototype.initialize=function(){var f=this.selectInputElements();var d,e,a;for(var c=0;c<f.length;c++){d=f[c].getAttribute("validation");if(d!=null){e=d.split(" ");for(var b=0;b<e.length;b++){a=this.getValidationAttributes(f[c]);this.bindInputElements(f[c],e[b],a)}}}};