diff --git a/lib/assets/javascripts/constants.js b/lib/assets/javascripts/constants.js
index e364441..6ce5d0c 100644
--- a/lib/assets/javascripts/constants.js
+++ b/lib/assets/javascripts/constants.js
@@ -1,7 +1,12 @@
(function(ctx){
var vals = {
PASSWORD_MIN_LENGTH: 8,
- PASSWORD_MAX_LENGTH: 128
+ PASSWORD_MAX_LENGTH: 128,
+
+ VALIDATION_MESSAGE_PASSWORD: "The password must be between 8 and 128 characters.",
+ VALIDATION_MESSAGE_EMAIL: "You must enter a valid email address.",
+ VALIDATION_MESSAGE_REQUIRED: "This field is required.",
+ VALIDATION_MESSAGE_PASSWORDS_MATCH: "The passwords must match."
};
for(var key in vals){
diff --git a/lib/assets/javascripts/utils/ariatiseForm.js b/lib/assets/javascripts/utils/ariatiseForm.js
index c787d77..69f571c 100644
--- a/lib/assets/javascripts/utils/ariatiseForm.js
+++ b/lib/assets/javascripts/utils/ariatiseForm.js
@@ -44,12 +44,12 @@
3. Prevent form to be submitted
*/
(function(ctx){
- var requiredFields=(function(selector){
- return $(selector).find('.form-control').filter('[aria-required="true"]');
+ // Collect all elements that are either required or have data-validation defined
+ var validatableFields=(function(selector){
+ return $(selector).find('.form-control').filter('[data-validation],[aria-required="true"]');
});
var blockHelp=(function (id,type){
- var msg='Please fill out this field with a valid '+type+'.'; //TODO internationalisation
- return ''+msg+'';
+ return ''+defaultValidationError(type)+'';
});
var ariaDescribedBy=(function(value){
return { 'aria-describedby': value };
@@ -57,33 +57,35 @@
var ariaInvalid=(function(value){
return { 'aria-invalid': value };
});
+ var defaultValidationError=(function(type){
+ if(dmproadmap.utils.validate[type] && dmproadmap.utils.validate[type].message){
+ return dmproadmap.utils.validate[type].message;
+ }
+ return '';
+ });
var validationStates={
hasWarning: 'has-warning',
hasError: 'has-error',
hasSuccess: 'has-success'
};
- var getTypeForSubmittableElement=(function(el){
- // Reference from https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Form-associated_content
- if($(el).is('input')){
- return $(el).attr('type'); // available types at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form__types
- }
- else if($(el).is('select')){
- return 'select';
- }
- else if($(el).is('textarea')){
- return 'textarea';
- }
- else
- return 'unknown';
+ var getValidationTypeForElement=(function(el){
+ var validation = $(el).attr('data-validation');
+ // if the specified validation type is defined
+ if(validation && dmproadmap.utils.validate[validation]){
+ return $(el).attr('data-validation');
+
+ }else if($(el).attr('aria-required') === 'true'){
+ return 'required';
+ }
+ return false;
});
var isValid=(function(type, value){
// TODO add more validation for each new type coming along by:
// 1. defining a function at dmproadmap.utils.validate
// 2. adding the case in the switch below
switch(type){
- case 'text':
- case 'textarea':
- return dmproadmap.utils.validate.text(value);
+ case 'required':
+ return dmproadmap.utils.validate.required(value);
case 'email':
return dmproadmap.utils.validate.email(value);
case 'password':
@@ -97,28 +99,49 @@
$(el).attr(ariaInvalid(false));
$(el).next().hide();
});
- var invalid=(function(el){
+ var invalid=(function(el,msg){
+ if(!msg){
+ msg = defaultValidationError(getValidationTypeForElement(el));
+ }
$(el).parent().addClass(validationStates.hasError);
$(el).attr(ariaInvalid(true));
- $(el).next().show();
+ $(el).next().text(msg).show();
+ });
+
+ ctx.displayValidationError=ctx.displayValidationError || (function(el,msg){
+ // Updates the validation error message for the element. If no msg is provided it will revert to the default message
+ if($(el)){
+ invalid(el,msg);
+ }
});
ctx.init=ctx.init || (function(options){
if($ && options && options.selector){
- requiredFields(options.selector).each(function(i,el){
+ validatableFields(options.selector).each(function(i,el){
$(el).attr(ariaDescribedBy('help'+i));
- $(el).after(blockHelp('help'+i, getTypeForSubmittableElement(el)));
+ $(el).after(blockHelp('help'+i, getValidationTypeForElement(el)));
});
+
$(options.selector+' [type="submit"]').click(function(e){
- requiredFields(options.selector).each(function(i,el){
- if(isValid(getTypeForSubmittableElement(el),$(el).val())){
- valid(el);
+ validatableFields(options.selector).each(function(i,el){
+ // If the element has a data-validation defined and the value is not blank
+ if($(el).attr('data-validation') && $(el).val().trim().length > 0){
+ if(isValid($(el).attr('data-validation'), $(el).val())){
+ valid(el);
+ }else{
+ e.preventDefault();
+ invalid(el);
}
- else{
- e.preventDefault();
- invalid(el);
+ // If the element is a required field make sure its not blank
+ }else if($(el).attr('aria-required') === "true"){
+ if(isValid('required', $(el).val())){
+ valid(el);
+ }else{
+ e.preventDefault();
+ invalid(el);
}
+ }
});
});
- }
+ }
});
})(define('dmproadmap.utils.ariatiseForm'));
\ No newline at end of file
diff --git a/lib/assets/javascripts/utils/validate.js b/lib/assets/javascripts/utils/validate.js
index 4d061c0..55af11c 100644
--- a/lib/assets/javascripts/utils/validate.js
+++ b/lib/assets/javascripts/utils/validate.js
@@ -5,7 +5,8 @@
@param value String to verify its length
@return true if it has a length greater than zero; otherwise, false.
*/
- ctx.text = ctx.text || (function(value){
+ ctx.required = ctx.required || (function(value){
+console.log("required: "+value);
if(Object.prototype.toString.call(value) === '[object String]')
return value.trim().length > 0;
return false;
@@ -31,10 +32,12 @@
value.trim().length <= dmproadmap.constants.PASSWORD_MAX_LENGTH);
return false;
});
+
/*
- validates whether the two values match (e.g. password and password_confirmation)
+ default error messages
*/
- ctx.matches = ctx.matches || (function(valueA, valueB){
- return valueA === valueB;
- });
+ ctx.required.message=ctx.required.message || dmproadmap.constants.VALIDATION_MESSAGE_REQUIRED;
+ ctx.email.message=ctx.email.message || dmproadmap.constants.VALIDATION_MESSAGE_EMAIL;
+ ctx.password.message=ctx.password.message || dmproadmap.constants.VALIDATION_MESSAGE_PASSWORD;;
+
})(define('dmproadmap.utils.validate'));
\ No newline at end of file
diff --git a/lib/assets/javascripts/views/devise/devise.js b/lib/assets/javascripts/views/devise/devise.js
index 3d8f845..2b5c775 100644
--- a/lib/assets/javascripts/views/devise/devise.js
+++ b/lib/assets/javascripts/views/devise/devise.js
@@ -2,6 +2,21 @@
// Password reset
dmproadmap.utils.ariatiseForm.init({ selector: '#user_request_reset_password' });
dmproadmap.utils.ariatiseForm.init({ selector: '#user_reset_password' });
+ dmproadmap.utils.ariatiseForm.init({ selector: '#invitation_create_account' });
-
+ $("[type='submit']").click(function(e){
+ // We have to specifically include the form name in the selectors here in case there are multiple
+ // devise forms (e.g. sign-in modal and the forgot password forms)
+ var frm = $(this).closest('form').attr('id'),
+ pwd = $("#"+frm+" #user_password"),
+ cnf = $("#"+frm+" #user_password_confirmation");
+
+ // If the password and password_confirmation are present and do not match display an error
+ if(pwd.val() && cnf.val()){
+ if(pwd.val() != cnf.val()){
+ e.preventDefault();
+ dmproadmap.utils.ariatiseForm.displayValidationError(cnf, dmproadmap.constants.VALIDATION_MESSAGE_PASSWORDS_MATCH);
+ }
+ }
+ });
});
\ No newline at end of file