diff --git a/Gruntfile.js b/Gruntfile.js
index 01475ae..48b12ba 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -44,12 +44,10 @@ module.exports = function (grunt) {
livereload: {
files: [
'dev/*.html',
+ 'dev/*.css',
'.tmp/*.html',
'.tmp/*.js',
- 'nod.js',
- '{.tmp,<%= nod.app %>/lib/{,*/}*.css',
- '{.tmp,<%= nod.app %>/lib/{,*/}*.js',
- '<%= nod.app %>/lib/{,*/}*.{png,jpg,jpeg,webp}'
+ 'nod*.js'
],
tasks: ['livereload']
}
@@ -122,7 +120,11 @@ module.exports = function (grunt) {
jade: {
compile: {
options: {
- pretty: true
+ pretty: true,
+ client: false,
+ data: function(dest, src) {
+ return {nodVersion: nodConfig.version, compiledAt: new Date()};
+ }
},
files: {
"./index.html": ["dev/index.jade"],
@@ -178,7 +180,7 @@ module.exports = function (grunt) {
'.tmp/init.js',
'dev/tail.js'
],
- dest: 'nod.js'
+ dest: 'nod-<%=nod.version%>.js'
}
},
uglify: {
@@ -186,8 +188,8 @@ module.exports = function (grunt) {
banner: '<%= nod.banner %>'
},
dist: {
- src: ['nod.js'],
- dest: 'nod.min.js'
+ src: ['nod-<%=nod.version%>.js'],
+ dest: 'nod-<%=nod.version%>.min.js'
}
},
useminPrepare: {
diff --git a/bower.json b/bower.json
index 8ab0406..6b7f4bc 100644
--- a/bower.json
+++ b/bower.json
@@ -1,11 +1,16 @@
{
- "name": "jquery-nod",
- "version": "1.0.5",
- "main": "./nod.js",
- "dependencies": {
- "jquery": ">=1.8"
- },
- "devDependencies": {
- "bootstrap": "~2.3.1"
- }
+ "name": "jquery-nod",
+ "version": "1.0.5",
+ "main": "./nod.js",
+ "ignore": [
+ "lib",
+ "index.html"
+ ],
+ "dependencies": {
+ "jquery": ">=1.9.0"
+ },
+ "devDependencies": {
+ "bootstrap": "~3.1.1",
+ "google-code-prettify": "~1.0.1"
+ }
}
diff --git a/dev/examples/ex1.jade b/dev/examples/ex1.jade
index ee06562..8bee33a 100644
--- a/dev/examples/ex1.jade
+++ b/dev/examples/ex1.jade
@@ -1,19 +1,21 @@
hr#example1
form#ex1.form-horizontal
- .control-group
- label.control-label Mandatory field
- .controls
- input(type='text')
- .controls
- button(type='submit').btn Submit
- script
+ .form-group
+ label.control-label.col-sm-2 Mandatory field
+ .col-sm-10
+ input.form-control(type='text')
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ button(type='submit').btn.btn-default Submit
+
+ script(type='text/javascript').
var metrics = [
[ 'input', 'presence', 'Cannot be empty' ]
];
$("#ex1").nod( metrics );
.code
- pre.prettyprint.lang-html <form id="ex1" class="form-horizontal">
- | <div class="control-group">
+ pre.prettyprint.lang-html <form id="ex1" class="form-inline">
+ | <div class="form-group">
| <label class="control-label">Mandatory field</label>
| <div class="controls">
| <input type="text">
diff --git a/dev/examples/ex2.jade b/dev/examples/ex2.jade
index 8ef6172..97548e6 100644
--- a/dev/examples/ex2.jade
+++ b/dev/examples/ex2.jade
@@ -1,10 +1,11 @@
hr#example2
form#ex2.form-horizontal
- .control-group
- label.control-label Search for number
- .controls
- input(type='text',placeholder="type a number and hit enter").search_field
- script
+ .form-group
+ label.control-label.col-sm-2 Search for number
+ .col-sm-10
+ input.form-control(type='text',placeholder="type a number and hit enter").search_field
+
+ script(type='text/javascript').
var metrics = [
[ '.search_field', 'integer', 'Must be a number' ]
];
@@ -12,11 +13,13 @@ form#ex2.form-horizontal
disableSubmitBtn : false
}
$("#ex2").nod( metrics, options );
+
.code
- pre.prettyprint.lang-html <form id="ex2" class="form-horizontal">
- | <div class="control-group">
+ pre.prettyprint.lang-html
+ | <form id="ex2" class="form-inline">
+ | <div class="form-group">
| <label class="control-label">Search for number</label>
- | <div class="controls">
+ | <div class="controls">
| <input type="text" class="search_field" placeholder="type a number and hit enter">
| </div>
| </div>
diff --git a/dev/examples/ex3.jade b/dev/examples/ex3.jade
index b321178..2a9b010 100644
--- a/dev/examples/ex3.jade
+++ b/dev/examples/ex3.jade
@@ -1,40 +1,42 @@
hr#example3
form#ex3.form-horizontal
- .control-group
- label.control-label Type "foo"
- .controls
- input(type='text').ex3a
- .control-group
- .control-label
- label Select something
- .controls
- select#ex3select
- option(value="") Select something please
- option(value="1") Pick this
- option(value="2") Or this
- option(value="3") But not this
- option(value="4") This is fine though
- .controls
- button(type='submit').btn Submit
- script
+ .form-group
+ label.control-label.col-sm-2 Type "foo"
+ .col-sm-10
+ input.form-control(type='text').ex3a
+
+ .form-group
+ label.control-label.col-sm-2 Select something
+ .col-sm-10
+ select#ex3select.form-control
+ option(value="") Select something please
+ option(value="1") Pick this
+ option(value="2") Or this
+ option(value="3") But not this
+ option(value="4") This is fine though
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ button(type='submit').btn.btn-default Submit
+
+ script(type='text/javascript').
var metrics = [
[ '.ex3a', 'exact:foo', 'I told you to type "foo"!' ],
[ '#ex3select', 'presence', 'Pick something' ],
[ '#ex3select', 'not:3', 'I told you not to pick this one!' ],
];
var options = {
- 'groupClass' : 'warning',
+ 'groupClass' : 'has-error',
};
$("#ex3").nod( metrics, options );
.code
- pre.prettyprint.lang-html <form id="ex3" class="form-horizontal">
- | <div class="control-group">
+ pre.prettyprint.lang-html <form id="ex3" class="form-inline">
+ | <div class="form-group">
| <label class="control-label">Type "foo"</label>
| <div class="controls">
| <input type="text" class="ex3a">
| </div>
| </div>
- | <div class="control-group">
+ | <div class="form-group">
| <div class="control-label">
| <label>Select something</label>
| </div>
@@ -58,6 +60,6 @@ form#ex3.form-horizontal
| [ '#ex3select', 'not:3', 'I told you not to pick this one!' ],
| ];
| var options = {
- | 'groupClass' : 'warning',
+ | 'groupClass' : 'has-error',
| };
| $("#ex3").nod( metrics, options );
diff --git a/dev/examples/ex4.jade b/dev/examples/ex4.jade
index 05d3a90..7c65e0a 100644
--- a/dev/examples/ex4.jade
+++ b/dev/examples/ex4.jade
@@ -2,21 +2,23 @@
hr#example4
form#ex4.form-horizontal
p Leave at least one number
- .control-group
- label.control-label Home
- .controls
- input(type='text')#ex4a_home
- .control-group
- label.control-label Work
- .controls
- input(type='text')#ex4a_work
- .control-group
- label.control-label Mobile
- .controls
- input(type='text')#ex4a_mobile
- .controls
- button(type='submit').btn Call me
- script
+ .form-group
+ label.control-label.col-sm-2 Home
+ .col-sm-10
+ input.form-control(type='text')#ex4a_home
+ .form-group
+ label.control-label.col-sm-2 Work
+ .col-sm-10
+ input.form-control(type='text')#ex4a_work
+ .form-group
+ label.control-label.col-sm-2 Mobile
+ .col-sm-10
+ input.form-control(type='text')#ex4a_mobile
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ button(type='submit').btn.btn-default Call me
+
+ script(type='text/javascript').
var metrics = [
[ '#ex4a_home, #ex4a_work, #ex4a_mobile', 'one-of', 'Add at least one number' ]
];
@@ -24,21 +26,21 @@ form#ex4.form-horizontal
// use http://www.opinionatedgeek.com/DotNet/Tools/HTMLEncode/Encode.aspx
.code
- pre.prettyprint.lang-html <form id="ex4" class="form-horizontal">
+ pre.prettyprint.lang-html <form id="ex4" class="form-inline">
| <p>Leave at least one number</p>
- | <div class="control-group">
+ | <div class="form-group">
| <label class="control-label">Home</label>
| <div class="controls">
| <input type="text" id="ex4a_home">
| </div>
| </div>
- | <div class="control-group">
+ | <div class="form-group">
| <label class="control-label">Work</label>
| <div class="controls">
| <input type="text" id="ex4a_work">
| </div>
| </div>
- | <div class="control-group">
+ | <div class="form-group">
| <label class="control-label">Mobile</label>
| <div class="controls">
| <input type="text" id="ex4a_mobile">
diff --git a/dev/index.jade b/dev/index.jade
index a396f96..87b0265 100644
--- a/dev/index.jade
+++ b/dev/index.jade
@@ -1,24 +1,27 @@
-!!! 5
+doctype html
html
head
title Nod!
meta(charset="utf-8")
- link(href="lib/bootstrap-combined.min.css",rel="stylesheet")
- link(href="lib/prettify.css")
- script(src="lib/jquery.min.js")
- script(src="lib/bootstrap.min.js")
- script(src="lib/prettify.js")
- script(src="nod.min.js")
- style
- body {margin-bottom:100px}
- .code { display: none }
- .nod_msg { background: #fcc; display: inline-block; padding: 2px 5px; margin-left: 5px; border-radius: 5px; }
- .container {margin-top:20px}
- h2 {margin-top:1.4em}
- .nod_msg {
- font-weight: bold;
+ link(href="test/components/bootstrap/dist/css/bootstrap.min.css",rel="stylesheet")
+ link(href="test/components/google-code-prettify/src/prettify.css")
+ script(src="test/components/jquery/dist/jquery.min.js")
+ script(src="test/components/bootstrap/dist/js/bootstrap.min.js")
+ script(src="test/components/google-code-prettify/src/prettify.js")
+
+ script(src="nod-#{nodVersion}.min.js")
+
+ style(type='text/css').
+ .code {
+ display: none;
+ margin-top: .8em;
+ }
+ footer {
+ height: 80px;
+ padding: 2em;
+ font-size: larger;
+ color: black;
}
- .input-append, .input-prepend { font-size: 14px; } /* bug in bootstrap? */
/* prettify */
.com { color: #93a1a1; }
@@ -31,7 +34,7 @@ html
.pln { color: #48484c; }
.prettyprint {
- padding: 8px;
+ padding: 8px 0;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
}
@@ -41,41 +44,22 @@ html
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
}
/* Specify class=linenums on a pre to get line numbering */
- ol.linenums {
- margin: 0 0 0 33px; /* IE indents via margin-left */
- }
ol.linenums li {
padding-left: 12px;
color: #bebec5;
- line-height: 20px;
- text-shadow: 0 1px 0 #fff;
+ line-height: 1.6em;
}
- script
- $(document).ready(function(){
- var see_code = $('',
- {html:"See code", class:"btn btn-mini see-code" }
- ).on( 'click', function() {
- $(this).next('.code').trigger('tgl');
- });
- $( 'form' ).on( 'submit', submitForm = function( e ) { e.preventDefault(); } ).after( see_code );
- $( '.code' ).on( 'tgl', function() {
- el = $(this);
- el.is(':visible') ? el.slideUp() : el.slideDown();
- });
- });
-
-
body
-
.container
- a(href="//github.com/casperin/nod",style="margin-top:10px;").btn.btn-success.pull-right
- i.icon-heart.icon-white
+ a(href="//github.com/casperin/nod",style="margin-top:10px;").btn.btn-lg.btn-success.pull-right
+ i.glyphicon.glyphicon-heart
| Fork me
- h1 Nod v.1.0.4
+ h1 Nod v#{nodVersion}
small A frontend validation jQuery plugin
+ span.pull-right Compiled at #{compiledAt}
hr
p Writing frontend validation for forms is painfully boring. So I made this in the hopes that it will help make it a little less agonizing for you.
p It's designed to
@@ -262,7 +246,7 @@ html
td groupClass
td String
td 'error'
- td The .control-group
will get this class if an error is found. Can be set to anything you like, but error
, info
, warning
, or success
makes the most sense with bootstrap.
+ td The .form-group
will get this class if an error is found. Can be set to anything you like, but error
, info
, warning
, or success
makes the most sense with bootstrap.
tr
td submitBtnSelector
td String
@@ -291,8 +275,8 @@ html
tr
td groupSelector
td String
- td '.control-group'
- td The selector for something surrounding your input elements. Like .control-group
in bootstrap forms.
+ td '.form-group'
+ td The selector for something surrounding your input elements. Like .form-group
in bootstrap forms.
h2#notes Notes
@@ -300,21 +284,21 @@ html
h3#radio Radio buttons
p These can be a bit tricky to validate, so here's an example.
pre.prettyprint.lang-html.linenums
- |
#bar
on line 4 though. To validate for presence on these fields, we don't need the #bar
, we just do
pre.prettyprint.lang-js.linenums
| var metrics = [
@@ -412,4 +396,21 @@ html
include examples/ex3
include examples/ex4
+ .container
+ footer.text-center Nod
+
+ script(type='text/javascript').
+ $(function() {
+ var see_code = $('',
+ {html:"See code", class:"btn btn-sm btn-warning see-code" }
+ ).on( 'click', function() {
+ $(this).next('.code').trigger('tgl');
+ });
+ $( 'form' ).on( 'submit', submitForm = function( e ) { e.preventDefault(); } ).after( see_code );
+ $( '.code' ).on( 'tgl', function() {
+ el = $(this);
+ el.is(':visible') ? el.slideUp() : el.slideDown();
+ });
+ });
+
script !function($) { $(function(){ window.prettyPrint && prettyPrint() }) }(window.jQuery);
diff --git a/dev/test.jade b/dev/test.jade
index d424c48..5a1158c 100644
--- a/dev/test.jade
+++ b/dev/test.jade
@@ -1,13 +1,13 @@
-!!! 5
+doctype html
html
head
meta(charset="utf-8")
title Testing Nod
- link(href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css",rel="stylesheet")
- script(src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js")
- script(src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/js/bootstrap.min.js")
- style
- body {margin-bottom:100px}
+ link(href="test/components/bootstrap/dist/css/bootstrap.min.css",rel="stylesheet")
+ script(src="test/components/jquery/dist/jquery.min.js")
+ script(src="test/components/bootstrap/dist/js/bootstrap.min.js")
+
+ style(type='text/css').
.nod_msg {
font-weight: bold;
margin-left: 5px;
@@ -15,61 +15,50 @@ html
body
-
-
-
.container
-
-
+ h4 Compiled at #{compiledAt}
fieldset
legend The testing facility
- form(action="foo.html")#form.form.form-horizontal
+ form(action="foo.html")#form.form-horizontal
//
- .control-group
- .controls
+ .form-group
label.radio
- input(type='radio',name='a',value='a1')#bar
+ input.form-control(type='radio',name='a',value='a1')#bar
| First
label.radio
- input(type='radio',name='a',value='a2')
+ input.form-control(type='radio',name='a',value='a2')
| Second
label.radio
- input(type='radio',name='a',value='a3')
+ input.form-control(type='radio',name='a',value='a3')
| Third
+ .form-group
+ label.control-label.col-sm-2 One
+ .col-sm-10
+ input.form-control(type="text",autofocus)#one
- .control-group
- .control-label
- label One
- .controls
- input(type="text",autofocus)#one
-
-
- .control-group
- .control-label
- label Label two
- .controls
- input(type="text")#two
-
-
- .control-group
- .control-label
- label Label three
- .controls
- input(type="text")#three
+ .form-group
+ label.control-label.col-sm-2 Label two
+ .col-sm-10
+ input.form-control(type="text")#two
- .controls
- button(data-loading-text="loading...",type="submit")#submit_btn.btn.btn-success Go go!
+ .form-group
+ label.control-label.col-sm-2 Label three
+ .col-sm-10
+ input.form-control(type="text")#three
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ button(data-loading-text="loading...",type="submit")#submit_btn.btn.btn-success Go go!
//
script(src='nod.min.js')
script(src="checker.js")
script(src="listener.js")
script(src="msg.js")
- script(src="nod.js")
+ script(src="nod-#{nodVersion}.min.js")
script(src="init.js")
script(src="dev/test_nod.js")
diff --git a/index.html b/index.html
index 0636287..336512b 100644
--- a/index.html
+++ b/index.html
@@ -3,23 +3,24 @@
Writing frontend validation for forms is painfully boring. So I made this in the hopes that it will help make it a little less agonizing for you.
It's designed to
@@ -84,17 +65,14 @@While it isn't strictly Bootstrap dependent, it defaults to the structure that bootstrap uses for its forms. However it should be flexible enough to accomodate most any structure.
Comments, bugs, suggestions and ideas are all very much appreciated.
-
- The plugin is made as a jQuery plugin and is activated like this: $("#form").nod( metrics );
The metrics
is a list that you build beforehand. It is basically a list of each selector and how you want it validated.
-
The plugin is made as a jQuery plugin and is activated like this: $("#form").nod( metrics );
The metrics
is a list that you build beforehand. It is basically a list of each selector and how you want it validated.
Example:
var metrics = [ [ '#foo', 'presence', 'Cannot be empty' ], [ '#bar', 'min-length:4', 'Must be at least 4 characters long' ] ]; - -$( "#form" ).nod( metrics );+ +$( "#form" ).nod( metrics );
Each "sublist" consists of three parts:
.control-group
will get this class if an error is found. Can be set to anything you like, but error
, info
, warning
, or success
makes the most sense with bootstrap..form-group
will get this class if an error is found. Can be set to anything you like, but error
, info
, warning
, or success
makes the most sense with bootstrap..control-group
in bootstrap forms..form-group
in bootstrap forms.These can be a bit tricky to validate, so here's an example.
-<div class="control-group"> - <div class="controls"> - <label class="radio"> - <input type="radio" name="a" value="a1" id="bar"> First +<div class="form-group"> + <div class="controls"> + <label class="radio"> + <input type="radio" name="a" value="a1" id="bar"> First </label> - <label class="radio"> - <input type="radio" name="a" value="a2"> Second + <label class="radio"> + <input type="radio" name="a" value="a2"> Second </label> - <label class="radio"> - <input type="radio" name="a" value="a3"> Third + <label class="radio"> + <input type="radio" name="a" value="a3"> Third </label> </div> </div> <!-- ... --> -<button data-loading-text="loading..." type="submit" class="btn btn-success">Submit form</button>+<button data-loading-text="loading..." type="submit" class="btn btn-success">Submit form</button>
Pretty standard html. Notice the #bar
on line 4 though. To validate for presence on these fields, we don't need the #bar
, we just do
var metrics = [ ['[name=a]', 'presence', 'You must click on at least one radio button'] ]; - -$( "#form" ).nod( metrics );+ +$( "#form" ).nod( metrics );
However if we want people to specifically click on a particular radio button, we do (line 2 is still important)
var metrics = [ ['[name=a]', 'presence', 'You must click on at least one radio button'], ['#bar', 'exact:a1', 'You must click on *this* radio button'] ]; - -$( "#form" ).nod( metrics );+ +$( "#form" ).nod( metrics );
Conversely we can use the keyword not
instead of exact
.
Notice name
attribute is mandatory on the input fields for all of these.
Yes, it works. Here's some code:
var getFn = function( value ) { - return $.get('check_email.php', value); + $.get('check_email.php', value); }; - + var metrics = [ ['#email', getFn, 'This email is already in use'] ]; - -$( "#form" ).nod( metrics );+ +$( "#form" ).nod( metrics );
Nod.js will take whatever response it gets from the server and eval it (if possible) to a boolean and use that as an indicator for whether the input is valid. This means that a "truthy" responses like "true"
, 1
, true
, "foo"
will all return true (the field is valid) and conversely "false"
, 0
, false
will return false and be interpreted as if the field is not valid.
Also, if your submit button has data-loading-text
, this will be swapped while the check is going on if it was initiated by a click of that button (and swapped back when done, regardless of errors).
Notice This feature is all very beta'ish and kind of hard to test fully. So if you find any errors or things that could be handled more gracefully, then I'd appreciate the feedback.
+Notice This feature is all very beta'ish and kind of hard to test fully. So if you find any errors or things that could be handled more gracefully, then I'd appreciate the feedback.
Don't use this. Validating emails should be done backend (by sending an email) and not frontend. I've used the most lax regex for checking emails that I could find (RFC822) so as to err on the side of letting too many emails through rather than rejecting valid emails; but really, you ought not to use frontend email validation at all.
That said, the ones who write the code are not always the ones who get to decide which features to implement, so I've included the feature regardless of what I think about its use. Hope it makes your life a little better.
@@ -317,7 +295,7 @@var submitFn = function( event, data ) { console.log( data ); } - + $( '#form' ).on( 'silentSubmit', submitFn );
This is used mainly (only?) if you want to submit your form by ajax.
As you can see, you'll get an object with the element (actually the $(el)
) and one with the error message.