angular-auto-validate
Advanced tools
Comparing version
{ | ||
"name": "angular-auto-validate", | ||
"version": "1.18.6", | ||
"version": "1.18.14", | ||
"description": "An automatic validation module for AngularJS which gets rid of excess html in favour of dynamic element modification to notify the user of validation errors", | ||
@@ -5,0 +5,0 @@ "main": "dist/jcs-auto-validate.js", |
@@ -0,1 +1,32 @@ | ||
V1.18.14 23/08/2015 | ||
Fixed issue with globally changing default form validation options. | ||
V1.18.13 21/08/2015 | ||
Added a default value for the form option validateOnFormSubmit in the validator. | ||
V1.18.12 20/08/2015 | ||
Added the ability to defer validation until after a form submit by adding the attribute 'validate-on-form-submit="true"' | ||
to the form element. | ||
V1.18.11 20/08/2015 | ||
Fixed issue ngModelDecorator not working with angular-material due to incorrect pre and post function invocations | ||
V1.18.10 03/08/2015 | ||
Fixed issue #61 with globally disabling the library and enabling it for a particular form | ||
V1.18.9 03/08/2015 | ||
Fixed #68 | ||
Setting form to untouched and pristine when a form reset is requested | ||
V1.18.8 03/08/2015 | ||
Reset a form programatically is now possible via the resetForm method on the form controllers autoValidateFormOptions object | ||
or by raising the event 'form:{formName}:reset on the controllers scope. The formName is the value in the name attribute | ||
on the form tag which also corresponds to the formController.$name property. | ||
Fixes issue with removing external validation raised in https://github.com/jonsamwell/angular-auto-validate/issues/39 | ||
V1.18.7 01/08/2015 | ||
Added Spanish i18n file. | ||
Fixed issue https://github.com/jonsamwell/angular-auto-validate/issues/73 | ||
Added the ability to reset the form via the form controller (https://github.com/jonsamwell/angular-auto-validate/issues/82) | ||
V1.18.6 16/04/2015 | ||
@@ -2,0 +33,0 @@ Increased limit on findWithClassElementAsc in BS3Modifier to find an element. |
/* | ||
* angular-auto-validate - v1.18.6 - 2015-04-16 | ||
* angular-auto-validate - v1.18.14 - 2015-08-23 | ||
* https://github.com/jonsamwell/angular-auto-validate | ||
* Copyright (c) 2015 Jon Samwell (http://www.jonsamwell.com) | ||
*/ | ||
(function (angular) { | ||
(function (String, angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate', []); | ||
}(angular)); | ||
angular.module('jcs-autoValidate', []); | ||
(function (angular) { | ||
'use strict'; | ||
function ValidatorFn() { | ||
var elementStateModifiers = {}, | ||
enableValidElementStyling = true, | ||
enableInvalidElementStyling = true, | ||
validationEnabled = true, | ||
angular.module('jcs-autoValidate') | ||
.provider('validator', [ | ||
function () { | ||
var elementStateModifiers = {}, | ||
enableValidElementStyling = true, | ||
enableInvalidElementStyling = true, | ||
validationEnabled = true, | ||
toBoolean = function (value) { | ||
var v; | ||
if (value && value.length !== 0) { | ||
v = value.toLowerCase(); | ||
value = !(v === 'f' || v === '0' || v === 'false'); | ||
} else { | ||
value = false; | ||
} | ||
toBoolean = function (value) { | ||
var v; | ||
if (value && value.length !== 0) { | ||
v = value.toLowerCase(); | ||
value = !(v === 'f' || v === '0' || v === 'false'); | ||
} else { | ||
value = false; | ||
} | ||
return value; | ||
}, | ||
return value; | ||
}, | ||
getAttributeValue = function (el, attrName) { | ||
var val; | ||
getAttributeValue = function (el, attrName) { | ||
var val; | ||
if (el !== undefined) { | ||
val = el.attr(attrName) || el.attr('data-' + attrName); | ||
} | ||
if (el !== undefined) { | ||
val = el.attr(attrName) || el.attr('data-' + attrName); | ||
} | ||
return val; | ||
}, | ||
return val; | ||
}, | ||
attributeExists = function (el, attrName) { | ||
var exists; | ||
attributeExists = function (el, attrName) { | ||
var exists; | ||
if (el !== undefined) { | ||
exists = el.attr(attrName) !== undefined || el.attr('data-' + attrName) !== undefined; | ||
} | ||
if (el !== undefined) { | ||
exists = el.attr(attrName) !== undefined || el.attr('data-' + attrName) !== undefined; | ||
} | ||
return exists; | ||
}, | ||
return exists; | ||
}, | ||
getBooleanAttributeValue = function (el, attrName) { | ||
return toBoolean(getAttributeValue(el, attrName)); | ||
}, | ||
getBooleanAttributeValue = function (el, attrName) { | ||
return toBoolean(getAttributeValue(el, attrName)); | ||
}, | ||
validElementStylingEnabled = function (el) { | ||
return enableValidElementStyling && !getBooleanAttributeValue(el, 'disable-valid-styling'); | ||
}, | ||
validElementStylingEnabled = function (el) { | ||
return enableValidElementStyling && !getBooleanAttributeValue(el, 'disable-valid-styling'); | ||
}, | ||
invalidElementStylingEnabled = function (el) { | ||
return enableInvalidElementStyling && !getBooleanAttributeValue(el, 'disable-invalid-styling'); | ||
}; | ||
invalidElementStylingEnabled = function (el) { | ||
return enableInvalidElementStyling && !getBooleanAttributeValue(el, 'disable-invalid-styling'); | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#enable | ||
* @methodOf validator | ||
* | ||
* @description | ||
* By default auto validate will validate all forms and elements with an ngModel directive on. By | ||
* setting enabled to false you will explicitly have to opt in to enable validation on forms and child | ||
* elements. | ||
* | ||
* Note: this can be overridden by add the 'auto-validate-enabled="true/false' attribute to a form. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.enable(false); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {Boolean} isEnabled true to enable, false to disable. | ||
*/ | ||
this.enable = function (isEnabled) { | ||
validationEnabled = isEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#enable | ||
* @methodOf validator | ||
* | ||
* @description | ||
* By default auto validate will validate all forms and elements with an ngModel directive on. By | ||
* setting enabled to false you will explicitly have to opt in to enable validation on forms and child | ||
* elements. | ||
* | ||
* Note: this can be overridden by add the 'auto-validate-enabled="true/false' attribute to a form. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.enable(false); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {Boolean} isEnabled true to enable, false to disable. | ||
*/ | ||
this.enable = function (isEnabled) { | ||
validationEnabled = isEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#isEnabled | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Returns true if the library is enabeld. | ||
* | ||
* @return {Boolean} true if enabled, otherwise false. | ||
*/ | ||
this.isEnabled = function () { | ||
return validationEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#isEnabled | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Returns true if the library is enabeld. | ||
* | ||
* @return {Boolean} true if enabled, otherwise false. | ||
*/ | ||
this.isEnabled = function () { | ||
return validationEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setDefaultElementModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Sets the default element modifier that will be used by the validator | ||
* to change an elements UI state. Please ensure the modifier has been registered | ||
* before setting it as default. | ||
* | ||
* Note: this can be changed by setting the | ||
* element modifier attribute on the input element 'data-element-modifier="myCustomModifier"' | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setDefaultElementModifier('myCustomModifier'); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier. | ||
*/ | ||
this.setDefaultElementModifier = function (key) { | ||
if (elementStateModifiers[key] === undefined) { | ||
throw new Error('Element modifier not registered: ' + key); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name validator#setDefaultElementModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Sets the default element modifier that will be used by the validator | ||
* to change an elements UI state. Please ensure the modifier has been registered | ||
* before setting it as default. | ||
* | ||
* Note: this can be changed by setting the | ||
* element modifier attribute on the input element 'data-element-modifier="myCustomModifier"' | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setDefaultElementModifier('myCustomModifier'); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier. | ||
*/ | ||
this.setDefaultElementModifier = function (key) { | ||
if (elementStateModifiers[key] === undefined) { | ||
throw new Error('Element modifier not registered: ' + key); | ||
} | ||
this.defaultElementModifier = key; | ||
}; | ||
this.defaultElementModifier = key; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#registerDomModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.registerDomModifier('customDomModifier', { | ||
* makeValid: function (el) { | ||
* el.removeClass(el, 'invalid'); | ||
* el.addClass(el, 'valid'); | ||
* }, | ||
* makeInvalid: function (el, err, domManipulator) { | ||
* el.removeClass(el, 'valid'); | ||
* el.addClass(el, 'invalid'); | ||
* } | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier | ||
* @param {object} modifier An object which implements the elementModifier interface | ||
*/ | ||
this.registerDomModifier = function (key, modifier) { | ||
elementStateModifiers[key] = modifier; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#registerDomModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.registerDomModifier('customDomModifier', { | ||
* makeValid: function (el) { | ||
* el.removeClass(el, 'invalid'); | ||
* el.addClass(el, 'valid'); | ||
* }, | ||
* makeInvalid: function (el, err, domManipulator) { | ||
* el.removeClass(el, 'valid'); | ||
* el.addClass(el, 'invalid'); | ||
* } | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier | ||
* @param {object} modifier An object which implements the elementModifier interface | ||
*/ | ||
this.registerDomModifier = function (key, modifier) { | ||
elementStateModifiers[key] = modifier; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setErrorMessageResolver | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setErrorMessageResolver(function (errorKey, el) { | ||
* var defer = $q.defer(); | ||
* // resolve the correct error from the given key and resolve the returned promise. | ||
* return defer.promise(); | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {function} resolver A method that returns a promise with the resolved error message in. | ||
*/ | ||
this.setErrorMessageResolver = function (resolver) { | ||
this.errorMessageResolver = resolver; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setErrorMessageResolver | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setErrorMessageResolver(function (errorKey, el) { | ||
* var defer = $q.defer(); | ||
* // resolve the correct error from the given key and resolve the returned promise. | ||
* return defer.promise(); | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {function} resolver A method that returns a promise with the resolved error message in. | ||
*/ | ||
this.setErrorMessageResolver = function (resolver) { | ||
this.errorMessageResolver = resolver; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#getErrorMessage | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Resolves the error message for the given error type. | ||
* | ||
* @param {String} errorKey The error type. | ||
* @param {Element} el The UI element that is the focus of the error. | ||
* It is provided as the error message may need information from the element i.e. ng-min (the min allowed value). | ||
*/ | ||
this.getErrorMessage = function (errorKey, el) { | ||
var defer; | ||
if (this.errorMessageResolver === undefined) { | ||
throw new Error('Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name validator#getErrorMessage | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Resolves the error message for the given error type. | ||
* | ||
* @param {String} errorKey The error type. | ||
* @param {Element} el The UI element that is the focus of the error. | ||
* It is provided as the error message may need information from the element i.e. ng-min (the min allowed value). | ||
*/ | ||
this.getErrorMessage = function (errorKey, el) { | ||
var defer; | ||
if (this.errorMessageResolver === undefined) { | ||
throw new Error('Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
} | ||
if (attributeExists(el, 'disable-validation-message')) { | ||
defer = angular.injector(['ng']).get('$q').defer(); | ||
defer.resolve(''); | ||
return defer.promise; | ||
} else { | ||
return this.errorMessageResolver(errorKey, el); | ||
} | ||
}; | ||
if (attributeExists(el, 'disable-validation-message')) { | ||
defer = angular.injector(['ng']).get('$q').defer(); | ||
defer.resolve(''); | ||
return defer.promise; | ||
} else { | ||
return this.errorMessageResolver(errorKey, el); | ||
} | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setValidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables valid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setValidElementStyling = function (enabled) { | ||
enableValidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setValidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables valid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setValidElementStyling = function (enabled) { | ||
enableValidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setInvalidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables invalid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setInvalidElementStyling = function (enabled) { | ||
enableInvalidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setInvalidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables invalid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setInvalidElementStyling = function (enabled) { | ||
enableInvalidElementStyling = enabled; | ||
}; | ||
this.getDomModifier = function (el) { | ||
var modifierKey = (el !== undefined ? el.attr('element-modifier') : this.defaultElementModifier) || | ||
(el !== undefined ? el.attr('data-element-modifier') : this.defaultElementModifier) || | ||
this.defaultElementModifier; | ||
this.getDomModifier = function (el) { | ||
var modifierKey = (el !== undefined ? el.attr('element-modifier') : this.defaultElementModifier) || | ||
(el !== undefined ? el.attr('data-element-modifier') : this.defaultElementModifier) || | ||
this.defaultElementModifier; | ||
if (modifierKey === undefined) { | ||
throw new Error('Please set a default dom modifier via the setDefaultElementModifier method on the validator class.'); | ||
} | ||
if (modifierKey === undefined) { | ||
throw new Error('Please set a default dom modifier via the setDefaultElementModifier method on the validator class.'); | ||
} | ||
return elementStateModifiers[modifierKey]; | ||
}; | ||
return elementStateModifiers[modifierKey]; | ||
}; | ||
this.makeValid = function (el) { | ||
if (validElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeValid(el); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeValid = function (el) { | ||
if (validElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeValid(el); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeInvalid = function (el, errorMsg) { | ||
if (invalidElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeInvalid(el, errorMsg); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeInvalid = function (el, errorMsg) { | ||
if (invalidElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeInvalid(el, errorMsg); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeDefault = function (el) { | ||
var dm = this.getDomModifier(el); | ||
if (dm.makeDefault) { | ||
dm.makeDefault(el); | ||
} | ||
}; | ||
this.makeDefault = function (el) { | ||
var dm = this.getDomModifier(el); | ||
if (dm.makeDefault) { | ||
dm.makeDefault(el); | ||
} | ||
}; | ||
this.defaultFormValidationOptions = { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false, | ||
removeExternalValidationErrorsOnSubmit: true, | ||
validateOnFormSubmit: false | ||
}; | ||
this.defaultFormValidationOptions = { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false, | ||
removeExternalValidationErrorsOnSubmit: true | ||
}; | ||
this.$get = [ | ||
function () { | ||
return this; | ||
} | ||
]; | ||
} | ||
this.$get = [ | ||
function () { | ||
return this; | ||
} | ||
]; | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').provider('validator', ValidatorFn); | ||
(function (angular) { | ||
'use strict'; | ||
function Bootstrap3ElementModifierFn($log) { | ||
var reset = function (el) { | ||
angular.forEach(el.find('span'), function (spanEl) { | ||
spanEl = angular.element(spanEl); | ||
if (spanEl.hasClass('error-msg') || spanEl.hasClass('form-control-feedback') || spanEl.hasClass('control-feedback')) { | ||
spanEl.remove(); | ||
} | ||
}); | ||
angular.module('jcs-autoValidate') | ||
.factory('bootstrap3ElementModifier', [ | ||
'$log', | ||
function ($log) { | ||
var reset = function (el) { | ||
angular.forEach(el.find('span'), function (spanEl) { | ||
spanEl = angular.element(spanEl); | ||
if (spanEl.hasClass('error-msg') || spanEl.hasClass('form-control-feedback') || spanEl.hasClass('control-feedback')) { | ||
spanEl.remove(); | ||
} | ||
}); | ||
el.removeClass('has-success has-error has-feedback'); | ||
}, | ||
findWithClassElementAsc = function (el, klass) { | ||
var returnEl, | ||
parent = el; | ||
for (var i = 0; i <= 10; i += 1) { | ||
if (parent !== undefined && parent.hasClass(klass)) { | ||
returnEl = parent; | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
el.removeClass('has-success has-error has-feedback'); | ||
}, | ||
findWithClassElementAsc = function (el, klass) { | ||
var returnEl, | ||
parent = el; | ||
for (var i = 0; i <= 10; i += 1) { | ||
if (parent !== undefined && parent.hasClass(klass)) { | ||
returnEl = parent; | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
return returnEl; | ||
}, | ||
return returnEl; | ||
}, | ||
findWithClassElementDesc = function (el, klass) { | ||
var child; | ||
for (var i = 0; i < el.children.length; i += 1) { | ||
child = el.children[i]; | ||
if (child !== undefined && angular.element(child).hasClass(klass)) { | ||
break; | ||
} else if (child.children !== undefined) { | ||
child = findWithClassElementDesc(child, klass); | ||
if (child.length > 0) { | ||
break; | ||
} | ||
} | ||
} | ||
findWithClassElementDesc = function (el, klass) { | ||
var child; | ||
for (var i = 0; i < el.children.length; i += 1) { | ||
child = el.children[i]; | ||
if (child !== undefined && angular.element(child).hasClass(klass)) { | ||
break; | ||
} else if (child.children !== undefined) { | ||
child = findWithClassElementDesc(child, klass); | ||
if (child.length > 0) { | ||
break; | ||
} | ||
} | ||
} | ||
return angular.element(child); | ||
}, | ||
return angular.element(child); | ||
}, | ||
findFormGroupElement = function (el) { | ||
return findWithClassElementAsc(el, 'form-group'); | ||
}, | ||
findFormGroupElement = function (el) { | ||
return findWithClassElementAsc(el, 'form-group'); | ||
}, | ||
findInputGroupElement = function (el) { | ||
return findWithClassElementDesc(el, 'input-group'); | ||
}, | ||
findInputGroupElement = function (el) { | ||
return findWithClassElementDesc(el, 'input-group'); | ||
}, | ||
insertAfter = function (referenceNode, newNode) { | ||
referenceNode[0].parentNode.insertBefore(newNode[0], referenceNode[0].nextSibling); | ||
}, | ||
insertAfter = function (referenceNode, newNode) { | ||
referenceNode[0].parentNode.insertBefore(newNode[0], referenceNode[0].nextSibling); | ||
}, | ||
/** | ||
* @ngdoc property | ||
* @name bootstrap3ElementModifier#addValidationStateIcons | ||
* @propertyOf bootstrap3ElementModifier | ||
* @returns {bool} True if an state icon will be added to the element in the valid and invalid control | ||
* states. The default is false. | ||
*/ | ||
addValidationStateIcons = false, | ||
/** | ||
* @ngdoc property | ||
* @name bootstrap3ElementModifier#addValidationStateIcons | ||
* @propertyOf bootstrap3ElementModifier | ||
* @returns {bool} True if an state icon will be added to the element in the valid and invalid control | ||
* states. The default is false. | ||
*/ | ||
addValidationStateIcons = false, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#enableValidationStateIcons | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply an icon to the input element. | ||
* | ||
* @param {bool} enable - True to enable the icon otherwise false. | ||
*/ | ||
enableValidationStateIcons = function (enable) { | ||
addValidationStateIcons = enable; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#enableValidationStateIcons | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply an icon to the input element. | ||
* | ||
* @param {bool} enable - True to enable the icon otherwise false. | ||
*/ | ||
enableValidationStateIcons = function (enable) { | ||
addValidationStateIcons = enable; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeValid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
inputGroupEl; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeValid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
inputGroupEl; | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeInvalid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'), | ||
inputGroupEl; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeInvalid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'), | ||
inputGroupEl; | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeDefault | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply bootstrap 3 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
var frmGroupEl = findFormGroupElement(el); | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeDefault | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply bootstrap 3 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
var frmGroupEl = findFormGroupElement(el); | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}; | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
enableValidationStateIcons: enableValidationStateIcons, | ||
key: 'bs3' | ||
}; | ||
} | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
enableValidationStateIcons: enableValidationStateIcons, | ||
key: 'bs3' | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
Bootstrap3ElementModifierFn.$inject = [ | ||
'$log' | ||
]; | ||
(function (angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate').factory('bootstrap3ElementModifier', Bootstrap3ElementModifierFn); | ||
/* | ||
* Taken from https://github.com/angular/angular.js/issues/2690#issue-14462164 (with added tests of course!) | ||
/* | ||
* Taken from https://github.com/angular/angular.js/issues/2690#issue-14462164 (with added tests of course!) | ||
*/ | ||
function JCSDebounceFn($timeout) { | ||
var debounce = function (fn, timeout, apply) { | ||
timeout = angular.isUndefined(timeout) ? 0 : timeout; | ||
apply = angular.isUndefined(apply) ? true : apply; // !!default is true! most suitable to my experience | ||
var nthCall = 0; | ||
return function () { // intercepting fn | ||
var that = this; | ||
var argz = arguments; | ||
nthCall += 1; | ||
var later = (function (version) { | ||
return function () { | ||
if (version === nthCall) { | ||
return fn.apply(that, argz); | ||
} | ||
}; | ||
})(nthCall); | ||
return $timeout(later, timeout, apply); | ||
}; | ||
}; | ||
return { | ||
debounce: debounce | ||
}; | ||
} | ||
JCSDebounceFn.$inject = [ | ||
'$timeout' | ||
]; | ||
angular.module('jcs-autoValidate').factory('jcs-debounce', JCSDebounceFn); | ||
/** | ||
* Replaces string placeholders with corresponding template string | ||
*/ | ||
if (!('format' in String.prototype)) { | ||
String.prototype.format = function () { | ||
var args = arguments; | ||
return this.replace(/{(\d+)}/g, function (match, number) { | ||
return typeof args[number] !== undefined ? args[number] : match; | ||
}); | ||
}; | ||
} | ||
angular.autoValidate = angular.autoValidate || { | ||
errorMessages: {} | ||
}; | ||
angular.autoValidate.errorMessages['en-us'] = angular.autoValidate.errorMessages['en-gb'] = { | ||
defaultMsg: 'Please add error message for {0}', | ||
email: 'Please enter a valid email address', | ||
minlength: 'Please enter at least {0} characters', | ||
maxlength: 'You have entered more than the maximum {0} characters', | ||
min: 'Please enter the minimum number of {0}', | ||
max: 'Please enter the maximum number of {0}', | ||
required: 'This field is required', | ||
date: 'Please enter a valid date', | ||
pattern: 'Please ensure the entered information adheres to this pattern {0}', | ||
number: 'Please enter a valid number', | ||
url: 'Please enter a valid URL in the format of http(s)://www.google.com' | ||
}; | ||
function DefaultErrorMessageResolverFn($q, $http) { | ||
var currentCulture = 'en-gb', | ||
i18nFileRootPath = 'js/angular-auto-validate/dist/lang', | ||
cultureRetrievalPromise, | ||
loadRemoteCulture = function (culture) { | ||
cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase())); | ||
return cultureRetrievalPromise; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setI18nFileRootPath | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the root path to the il8n files on the server | ||
* | ||
* @param {String} rootPath - The root path on the server to the il8n file - this defaults | ||
* to 'js/angular-auto-validate/lang/' | ||
*/ | ||
angular.module('jcs-autoValidate').factory('jcs-debounce', [ | ||
'$timeout', | ||
function ($timeout) { | ||
var debounce = function (fn, timeout, apply) { | ||
timeout = angular.isUndefined(timeout) ? 0 : timeout; | ||
apply = angular.isUndefined(apply) ? true : apply; // !!default is true! most suitable to my experience | ||
var nthCall = 0; | ||
return function () { // intercepting fn | ||
var that = this; | ||
var argz = arguments; | ||
nthCall += 1; | ||
var later = (function (version) { | ||
return function () { | ||
if (version === nthCall) { | ||
return fn.apply(that, argz); | ||
} | ||
}; | ||
})(nthCall); | ||
setI18nFileRootPath = function (rootPath) { | ||
i18nFileRootPath = rootPath; | ||
}, | ||
return $timeout(later, timeout, apply); | ||
}; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setCulture | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the culture for the error messages by loading an the correct culture resource file. | ||
* | ||
* @param {String} culture - The new culture in the format of 'en-gb' etc. | ||
* @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should | ||
* return a promise which is resolved with the culture errorMessage object. If a function is not specified | ||
* the culture file is loaded from the **i18nFileRootPath**. | ||
* @returns {Promise} - A promise which is resolved with the loaded culture error messages object. | ||
*/ | ||
setCulture = function (culture, cultureLoadingFn) { | ||
var defer = $q.defer(); | ||
cultureLoadingFn = cultureLoadingFn || loadRemoteCulture; | ||
currentCulture = culture.toLowerCase(); | ||
if (angular.autoValidate.errorMessages[currentCulture] === undefined) { | ||
cultureRetrievalPromise = cultureLoadingFn(culture); | ||
cultureRetrievalPromise.then(function (response) { | ||
cultureRetrievalPromise = undefined; | ||
angular.autoValidate.errorMessages[currentCulture] = response.data; | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
}, function (err) { | ||
angular.autoValidate.errorMessages[currentCulture] = { | ||
defaultMsg: 'Loading culture failed!' | ||
}; | ||
cultureRetrievalPromise = null; | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
} | ||
return { | ||
debounce: debounce | ||
}; | ||
return defer.promise; | ||
}, | ||
getErrorMessages = function (culture) { | ||
var defer = $q.defer(); | ||
culture = culture === undefined ? currentCulture : culture.toLowerCase(); | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
}, function (err) { | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
} | ||
return defer.promise; | ||
}, | ||
getMessageTypeOverride = function (errorType, el) { | ||
var overrideKey; | ||
if (el) { | ||
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey" | ||
errorType += '-err-type'; | ||
overrideKey = el.attr('ng-' + errorType); | ||
if (overrideKey === undefined) { | ||
overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
]); | ||
}(angular)); | ||
(function (String, angular) { | ||
'use strict'; | ||
if (overrideKey) { | ||
overrideKey = overrideKey.replace(/[\W]/g, ''); | ||
} | ||
} | ||
return overrideKey; | ||
}, | ||
/** | ||
* Replaces string placeholders with corresponding template string | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#resolve | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Resolves a validate error type into a user validation error message | ||
* | ||
* @param {String} errorType - The type of validation error that has occurred. | ||
* @param {Element} el - The input element that is the source of the validation error. | ||
* @returns {Promise} A promise that is resolved when the validation message has been produced. | ||
*/ | ||
if (!('format' in String.prototype)) { | ||
String.prototype.format = function () { | ||
var args = arguments; | ||
return this.replace(/{(\d+)}/g, function (match, number) { | ||
return typeof args[number] !== undefined ? args[number] : match; | ||
}); | ||
}; | ||
} | ||
resolve = function (errorType, el) { | ||
var defer = $q.defer(), | ||
errMsg, | ||
parameters = [], | ||
parameter, | ||
messageTypeOverride; | ||
angular.autoValidate = angular.autoValidate || { | ||
errorMessages: {} | ||
}; | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
resolve(errorType, el).then(function (msg) { | ||
defer.resolve(msg); | ||
}); | ||
}); | ||
} else { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][errorType]; | ||
messageTypeOverride = getMessageTypeOverride(errorType, el); | ||
if (messageTypeOverride) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride]; | ||
} | ||
angular.autoValidate.errorMessages['en-us'] = angular.autoValidate.errorMessages['en-gb'] = { | ||
defaultMsg: 'Please add error message for {0}', | ||
email: 'Please enter a valid email address', | ||
minlength: 'Please enter at least {0} characters', | ||
maxlength: 'You have entered more than the maximum {0} characters', | ||
min: 'Please enter the minimum number of {0}', | ||
max: 'Please enter the maximum number of {0}', | ||
required: 'This field is required', | ||
date: 'Please enter a valid date', | ||
pattern: 'Please ensure the entered information adheres to this pattern {0}', | ||
number: 'Please enter a valid number', | ||
url: 'Please enter a valid URL in the format of http(s)://www.google.com' | ||
}; | ||
if (errMsg === undefined) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType); | ||
} | ||
angular.module('jcs-autoValidate') | ||
.factory('defaultErrorMessageResolver', [ | ||
'$q', | ||
'$http', | ||
function ($q, $http) { | ||
var currentCulture = 'en-gb', | ||
if (el && el.attr) { | ||
try { | ||
parameter = el.attr('ng-' + errorType); | ||
if (parameter === undefined) { | ||
parameter = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
i18nFileRootPath = 'js/angular-auto-validate/dist/lang', | ||
parameters.push(parameter || ''); | ||
cultureRetrievalPromise, | ||
errMsg = errMsg.format(parameters); | ||
} catch (e) {} | ||
} | ||
loadRemoteCulture = function (culture) { | ||
cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase())); | ||
return cultureRetrievalPromise; | ||
}, | ||
defer.resolve(errMsg); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setI18nFileRootPath | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the root path to the il8n files on the server | ||
* | ||
* @param {String} rootPath - The root path on the server to the il8n file - this defaults | ||
* to 'js/angular-auto-validate/lang/' | ||
*/ | ||
setI18nFileRootPath = function (rootPath) { | ||
i18nFileRootPath = rootPath; | ||
}, | ||
return defer.promise; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setCulture | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the culture for the error messages by loading an the correct culture resource file. | ||
* | ||
* @param {String} culture - The new culture in the format of 'en-gb' etc. | ||
* @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should | ||
* return a promise which is resolved with the culture errorMessage object. If a function is not specified | ||
* the culture file is loaded from the **i18nFileRootPath**. | ||
* @returns {Promise} - A promise which is resolved with the loaded culture error messages object. | ||
*/ | ||
setCulture = function (culture, cultureLoadingFn) { | ||
var defer = $q.defer(); | ||
cultureLoadingFn = cultureLoadingFn || loadRemoteCulture; | ||
currentCulture = culture.toLowerCase(); | ||
if (angular.autoValidate.errorMessages[currentCulture] === undefined) { | ||
cultureRetrievalPromise = cultureLoadingFn(culture); | ||
cultureRetrievalPromise.then(function (response) { | ||
cultureRetrievalPromise = undefined; | ||
angular.autoValidate.errorMessages[currentCulture] = response.data; | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
}, function (err) { | ||
angular.autoValidate.errorMessages[currentCulture] = { | ||
defaultMsg: 'Loading culture failed!' | ||
}; | ||
cultureRetrievalPromise = null; | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
} | ||
return { | ||
setI18nFileRootPath: setI18nFileRootPath, | ||
setCulture: setCulture, | ||
getErrorMessages: getErrorMessages, | ||
resolve: resolve | ||
}; | ||
} | ||
return defer.promise; | ||
}, | ||
DefaultErrorMessageResolverFn.$inject = [ | ||
'$q', | ||
'$http' | ||
]; | ||
getErrorMessages = function (culture) { | ||
var defer = $q.defer(); | ||
culture = culture === undefined ? currentCulture : culture.toLowerCase(); | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
}, function (err) { | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
} | ||
return defer.promise; | ||
}, | ||
angular.module('jcs-autoValidate').factory('defaultErrorMessageResolver', DefaultErrorMessageResolverFn); | ||
getMessageTypeOverride = function (errorType, el) { | ||
var overrideKey; | ||
function Foundation5ElementModifierFn() { | ||
var reset = function (el, inputEl) { | ||
angular.forEach(el.find('small'), function (smallEl) { | ||
if (angular.element(smallEl).hasClass('error')) { | ||
angular.element(smallEl).remove(); | ||
} | ||
}); | ||
if (el) { | ||
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey" | ||
errorType += '-err-type'; | ||
inputEl.removeClass('error'); | ||
}, | ||
findParentColumn = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 3; i += 1) { | ||
if (parent !== undefined && parent.hasClass('columns')) { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
return parent; | ||
}, | ||
overrideKey = el.attr('ng-' + errorType); | ||
if (overrideKey === undefined) { | ||
overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeValid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var parentColumn = findParentColumn(el); | ||
reset(parentColumn && parentColumn.length > 0 ? parentColumn : el, el); | ||
}, | ||
if (overrideKey) { | ||
overrideKey = overrideKey.replace(/[\W]/g, ''); | ||
} | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeInvalid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var parentColumn = findParentColumn(el), | ||
helpTextEl; | ||
reset(parentColumn || el, el); | ||
el.addClass('error'); | ||
if (parentColumn) { | ||
helpTextEl = angular.element('<small class="error">' + errorMsg + '</small>'); | ||
parentColumn.append(helpTextEl); | ||
} | ||
}, | ||
return overrideKey; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeDefault | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply foundation 5 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
makeValid(el); | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#resolve | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Resolves a validate error type into a user validation error message | ||
* | ||
* @param {String} errorType - The type of validation error that has occurred. | ||
* @param {Element} el - The input element that is the source of the validation error. | ||
* @returns {Promise} A promise that is resolved when the validation message has been produced. | ||
*/ | ||
resolve = function (errorType, el) { | ||
var defer = $q.defer(), | ||
errMsg, | ||
parameters = [], | ||
parameter, | ||
messageTypeOverride; | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
key: 'foundation5' | ||
}; | ||
} | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
resolve(errorType, el).then(function (msg) { | ||
defer.resolve(msg); | ||
}); | ||
}); | ||
} else { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][errorType]; | ||
messageTypeOverride = getMessageTypeOverride(errorType, el); | ||
if (messageTypeOverride) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride]; | ||
} | ||
angular.module('jcs-autoValidate').factory('foundation5ElementModifier', Foundation5ElementModifierFn); | ||
if (errMsg === undefined) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType); | ||
} | ||
function ElementUtilsFn() { | ||
var isElementVisible = function (el) { | ||
return el[0].offsetWidth > 0 && el[0].offsetHeight > 0; | ||
}; | ||
if (el && el.attr) { | ||
try { | ||
parameter = el.attr('ng-' + errorType); | ||
if (parameter === undefined) { | ||
parameter = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
return { | ||
isElementVisible: isElementVisible | ||
}; | ||
} | ||
parameters.push(parameter || ''); | ||
function ValidationManagerFn(validator, elementUtils) { | ||
var elementTypesToValidate = ['input', 'textarea', 'select', 'form'], | ||
errMsg = errMsg.format(parameters); | ||
} catch (e) {} | ||
} | ||
elementIsVisible = function (el) { | ||
return elementUtils.isElementVisible(el); | ||
}, | ||
defer.resolve(errMsg); | ||
} | ||
getFormOptions = function (el) { | ||
var frmCtrl = angular.element(el).controller('form'), | ||
options; | ||
return defer.promise; | ||
}; | ||
if (frmCtrl !== undefined && frmCtrl !== null) { | ||
options = frmCtrl.autoValidateFormOptions; | ||
} else { | ||
options = validator.defaultFormValidationOptions; | ||
} | ||
return { | ||
setI18nFileRootPath: setI18nFileRootPath, | ||
setCulture: setCulture, | ||
getErrorMessages: getErrorMessages, | ||
resolve: resolve | ||
}; | ||
} | ||
]); | ||
}(String, angular)); | ||
return options; | ||
}, | ||
(function (angular) { | ||
'use strict'; | ||
/** | ||
* Only validate if the element is present, it is visible | ||
* it is either a valid user input control (input, select, textare, form) or | ||
* it is a custom control register by the developer. | ||
* @param el | ||
* @param formOptions The validation options of the parent form | ||
* @returns {boolean} true to indicate it should be validated | ||
*/ | ||
shouldValidateElement = function (el, formOptions, formSubmitted) { | ||
var elementExists = el && el.length > 0, | ||
correctVisibilityToValidate, | ||
correctTypeToValidate, | ||
correctPhaseToValidate; | ||
angular.module('jcs-autoValidate') | ||
.factory('foundation5ElementModifier', [ | ||
if (elementExists) { | ||
correctVisibilityToValidate = elementIsVisible(el) || formOptions.validateNonVisibleControls; | ||
correctTypeToValidate = elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1 || | ||
el[0].hasAttribute('register-custom-form-control'); | ||
correctPhaseToValidate = formOptions.validateOnFormSubmit === false || | ||
(formOptions.validateOnFormSubmit === true && formSubmitted === true); | ||
} | ||
function () { | ||
var reset = function (el, inputEl) { | ||
angular.forEach(el.find('small'), function (smallEl) { | ||
if (angular.element(smallEl).hasClass('error')) { | ||
angular.element(smallEl).remove(); | ||
} | ||
}); | ||
return elementExists && correctVisibilityToValidate && correctTypeToValidate && correctPhaseToValidate; | ||
inputEl.removeClass('error'); | ||
}, | ||
findParentColumn = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 3; i += 1) { | ||
if (parent !== undefined && parent.hasClass('columns')) { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
}, | ||
return parent; | ||
}, | ||
/** | ||
* @ngdoc validateElement | ||
* @name validation#validateElement | ||
* @param {object} modelCtrl holds the information about the element e.g. $invalid, $valid | ||
* @param {options} | ||
* - forceValidation if set to true forces the validation even if the element is pristine | ||
* - disabled if set to true forces the validation is disabled and will return true | ||
* - validateNonVisibleControls if set to true forces the validation of non visible element i.e. display:block | ||
* @description | ||
* Validate the form element and make invalid/valid element model status. | ||
* | ||
* As of v1.17.22: | ||
* BREAKING CHANGE to validateElement on the validationManger. The third parameter is now the parent form's | ||
* autoValidateFormOptions object on the form controller. This can be left blank and will be found by the | ||
* validationManager. | ||
*/ | ||
validateElement = function (modelCtrl, el, options) { | ||
var isValid = true, | ||
frmOptions = options || getFormOptions(el), | ||
needsValidation = modelCtrl.$pristine === false || frmOptions.forceValidation, | ||
errorType, | ||
findErrorType = function ($errors) { | ||
var keepGoing = true, | ||
errorTypeToReturn; | ||
angular.forEach($errors, function (status, errortype) { | ||
if (keepGoing && status) { | ||
keepGoing = false; | ||
errorTypeToReturn = errortype; | ||
} | ||
}); | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeValid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var parentColumn = findParentColumn(el); | ||
reset(parentColumn && parentColumn.length > 0 ? parentColumn : el, el); | ||
}, | ||
return errorTypeToReturn; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeInvalid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var parentColumn = findParentColumn(el), | ||
helpTextEl; | ||
reset(parentColumn || el, el); | ||
el.addClass('error'); | ||
if (parentColumn) { | ||
helpTextEl = angular.element('<small class="error">' + errorMsg + '</small>'); | ||
parentColumn.append(helpTextEl); | ||
} | ||
}, | ||
if (frmOptions.disabled === false) { | ||
if ((frmOptions.forceValidation || | ||
(shouldValidateElement(el, frmOptions, frmOptions.formController.$submitted) && | ||
modelCtrl && | ||
needsValidation))) { | ||
isValid = !modelCtrl.$invalid; | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeDefault | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply foundation 5 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
makeValid(el); | ||
}; | ||
if (frmOptions.removeExternalValidationErrorsOnSubmit && modelCtrl.removeAllExternalValidation) { | ||
modelCtrl.removeAllExternalValidation(); | ||
} | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
key: 'foundation5' | ||
}; | ||
if (isValid) { | ||
validator.makeValid(el); | ||
} else { | ||
errorType = findErrorType(modelCtrl.$errors || modelCtrl.$error); | ||
if (errorType === undefined) { | ||
// we have a weird situation some users are encountering where a custom control | ||
// is valid but the ngModel is report it isn't and thus no valid error type can be found | ||
isValid = true; | ||
} else { | ||
validator.getErrorMessage(errorType, el).then(function (errorMsg) { | ||
validator.makeInvalid(el, errorMsg); | ||
}); | ||
} | ||
]); | ||
}(angular)); | ||
} | ||
} | ||
} | ||
(function (angular) { | ||
'use strict'; | ||
return isValid; | ||
}, | ||
angular.module('jcs-autoValidate') | ||
.factory('jcs-elementUtils', [ | ||
function () { | ||
var isElementVisible = function (el) { | ||
return el[0].offsetWidth > 0 && el[0].offsetHeight > 0; | ||
}; | ||
resetElement = function (element) { | ||
validator.makeDefault(element); | ||
}, | ||
return { | ||
isElementVisible: isElementVisible | ||
}; | ||
} | ||
]); | ||
resetForm = function (frmElement) { | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (element) { | ||
var controller, | ||
ctrlElement = angular.element(element); | ||
controller = ctrlElement.controller('ngModel'); | ||
angular.module('jcs-autoValidate') | ||
.factory('validationManager', [ | ||
'validator', | ||
'jcs-elementUtils', | ||
function (validator, elementUtils) { | ||
var elementTypesToValidate = ['input', 'textarea', 'select', 'form'], | ||
if (controller !== undefined) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
resetForm(ctrlElement); | ||
} else { | ||
controller.$setPristine(); | ||
} | ||
} | ||
}); | ||
}, | ||
elementIsVisible = function (el) { | ||
return elementUtils.isElementVisible(el); | ||
}, | ||
validateForm = function (frmElement) { | ||
var frmValid = true, | ||
frmCtrl = frmElement ? angular.element(frmElement).controller('form') : undefined, | ||
processElement = function (ctrlElement, force, formOptions) { | ||
var controller, isValid, ctrlFormOptions, originalForceValue; | ||
getFormOptions = function (el) { | ||
var frmCtrl = angular.element(el).controller('form'); | ||
return frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : validator.defaultFormValidationOptions; | ||
}, | ||
ctrlElement = angular.element(ctrlElement); | ||
controller = ctrlElement.controller('ngModel'); | ||
/** | ||
* Only validate if the element is present, it is visible | ||
* it is either a valid user input control (input, select, textare, form) or | ||
* it is a custom control register by the developer. | ||
* @param el | ||
* @param formOptions The validation options of the parent form | ||
* @returns {boolean} true to indicate it should be validated | ||
*/ | ||
shouldValidateElement = function (el, formOptions) { | ||
var result = el && | ||
el.length > 0 && | ||
(elementIsVisible(el) || formOptions.validateNonVisibleControls) && | ||
(elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1 || | ||
el[0].hasAttribute('register-custom-form-control')); | ||
return result; | ||
}, | ||
if (controller !== undefined && (force || shouldValidateElement(ctrlElement, formOptions, frmCtrl.$submitted))) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
validateForm(ctrlElement); | ||
} else { | ||
// we need to get the options for the element rather than use the passed in as the | ||
// element could be an ng-form and have different options to the parent form. | ||
ctrlFormOptions = getFormOptions(ctrlElement); | ||
originalForceValue = ctrlFormOptions.forceValidation; | ||
ctrlFormOptions.forceValidation = force; | ||
try { | ||
isValid = validateElement(controller, ctrlElement, ctrlFormOptions); | ||
frmValid = frmValid && isValid; | ||
} finally { | ||
ctrlFormOptions.forceValidation = originalForceValue; | ||
} | ||
} | ||
} | ||
}, | ||
clonedOptions; | ||
/** | ||
* @ngdoc validateElement | ||
* @name validation#validateElement | ||
* @param {object} modelCtrl holds the information about the element e.g. $invalid, $valid | ||
* @param {options} | ||
* - forceValidation if set to true forces the validation even if the element is pristine | ||
* - disabled if set to true forces the validation is disabled and will return true | ||
* - validateNonVisibleControls if set to true forces the validation of non visible element i.e. display:block | ||
* @description | ||
* Validate the form element and make invalid/valid element model status. | ||
* | ||
* As of v1.17.22: | ||
* BREAKING CHANGE to validateElement on the validationManger. The third parameter is now the parent form's | ||
* autoValidateFormOptions object on the form controller. This can be left blank and will be found by the | ||
* validationManager. | ||
*/ | ||
validateElement = function (modelCtrl, el, options) { | ||
var isValid = true, | ||
frmOptions = options || getFormOptions(el), | ||
needsValidation = modelCtrl.$pristine === false || frmOptions.forceValidation, | ||
errorType, | ||
findErrorType = function ($errors) { | ||
var keepGoing = true, | ||
errorTypeToReturn; | ||
angular.forEach($errors, function (status, errortype) { | ||
if (keepGoing && status) { | ||
keepGoing = false; | ||
errorTypeToReturn = errortype; | ||
} | ||
}); | ||
if (frmElement === undefined || (frmCtrl !== undefined && frmCtrl.autoValidateFormOptions.disabled)) { | ||
return frmElement !== undefined; | ||
} | ||
return errorTypeToReturn; | ||
}; | ||
//force the validation of controls | ||
clonedOptions = angular.copy(frmCtrl.autoValidateFormOptions); | ||
clonedOptions.forceValidation = true; | ||
if (frmOptions.disabled === false) { | ||
if ((frmOptions.forceValidation || (shouldValidateElement(el, frmOptions) && modelCtrl && needsValidation))) { | ||
isValid = !modelCtrl.$invalid; | ||
// IE8 holds the child controls collection in the all property | ||
// Firefox in the elements and chrome as a child iterator | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (ctrlElement) { | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
if (frmOptions.removeExternalValidationErrorsOnSubmit && modelCtrl.removeAllExternalValidation) { | ||
modelCtrl.removeAllExternalValidation(); | ||
} | ||
// If you have a custom form control that should be validated i.e. | ||
// <my-custom-element>...</my-custom-element> it will not be part of the forms | ||
// HTMLFormControlsCollection and thus won't be included in the above element iteration although | ||
// it will be on the Angular FormController (if it has a name attribute). So adding the directive | ||
// register-custom-form-control="" to the control root and autoValidate will include it in this | ||
// iteration. | ||
if (frmElement[0].customHTMLFormControlsCollection) { | ||
angular.forEach(frmElement[0].customHTMLFormControlsCollection, function (ctrlElement) { | ||
// need to force the validation as the element might not be a known form input type | ||
// so the normal validation process will ignore it. | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
} | ||
if (isValid) { | ||
validator.makeValid(el); | ||
} else { | ||
errorType = findErrorType(modelCtrl.$errors || modelCtrl.$error); | ||
if (errorType === undefined) { | ||
return frmValid; | ||
}, | ||
// we have a weird situation some users are encountering where a custom control | ||
// is valid but the ngModel is report it isn't and thus no valid error type can be found | ||
isValid = true; | ||
} else { | ||
validator.getErrorMessage(errorType, el).then(function (errorMsg) { | ||
validator.makeInvalid(el, errorMsg); | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
setElementValidationError = function (element, errorMsgKey, errorMsg) { | ||
if (errorMsgKey) { | ||
validator.getErrorMessage(errorMsgKey, element).then(function (msg) { | ||
validator.makeInvalid(element, msg); | ||
}); | ||
} else { | ||
validator.makeInvalid(element, errorMsg); | ||
} | ||
}; | ||
return isValid; | ||
}, | ||
return { | ||
setElementValidationError: setElementValidationError, | ||
validateElement: validateElement, | ||
validateForm: validateForm, | ||
resetElement: resetElement, | ||
resetForm: resetForm | ||
}; | ||
} | ||
resetElement = function (element) { | ||
validator.makeDefault(element); | ||
}, | ||
ValidationManagerFn.$inject = [ | ||
'validator', | ||
'jcs-elementUtils' | ||
]; | ||
resetForm = function (frmElement) { | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (element) { | ||
var controller, | ||
ctrlElement = angular.element(element); | ||
controller = ctrlElement.controller('ngModel'); | ||
angular.module('jcs-autoValidate').factory('jcs-elementUtils', ElementUtilsFn); | ||
angular.module('jcs-autoValidate').factory('validationManager', ValidationManagerFn); | ||
if (controller !== undefined) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
resetForm(ctrlElement); | ||
} else { | ||
controller.$setPristine(); | ||
} | ||
} | ||
}); | ||
}, | ||
function parseBooleanAttributeValue(val, defaultValue) { | ||
if ((val === undefined || val === null) && defaultValue !== undefined) { | ||
return defaultValue; | ||
} else { | ||
return val !== 'false'; | ||
} | ||
} | ||
validateForm = function (frmElement) { | ||
var frmValid = true, | ||
frmCtrl = frmElement ? angular.element(frmElement).controller('form') : undefined, | ||
processElement = function (ctrlElement, force, formOptions) { | ||
var controller, isValid, ctrlFormOptions; | ||
function parseOptions(ctrl, validator, attrs) { | ||
var opts = ctrl.autoValidateFormOptions = ctrl.autoValidateFormOptions || angular.copy(validator.defaultFormValidationOptions); | ||
opts.formController = ctrl; | ||
opts.forceValidation = false; | ||
opts.disabled = !validator.isEnabled() || parseBooleanAttributeValue(attrs.disableDynamicValidation, opts.disabled); | ||
opts.validateNonVisibleControls = parseBooleanAttributeValue(attrs.validateNonVisibleControls, opts.validateNonVisibleControls); | ||
opts.validateOnFormSubmit = parseBooleanAttributeValue(attrs.validateOnFormSubmit, opts.validateOnFormSubmit); | ||
opts.removeExternalValidationErrorsOnSubmit = attrs.removeExternalValidationErrorsOnSubmit === undefined ? | ||
opts.removeExternalValidationErrorsOnSubmit : | ||
parseBooleanAttributeValue(attrs.removeExternalValidationErrorsOnSubmit, opts.removeExternalValidationErrorsOnSubmit); | ||
ctrlElement = angular.element(ctrlElement); | ||
controller = ctrlElement.controller('ngModel'); | ||
// the library might be globally disabled but enabled on a particular form so check the | ||
// disableDynamicValidation attribute is on the form | ||
if (validator.isEnabled() === false && attrs.disableDynamicValidation === 'false') { | ||
opts.disabled = false; | ||
} | ||
} | ||
if (controller !== undefined && (force || shouldValidateElement(ctrlElement, formOptions))) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
validateForm(ctrlElement); | ||
} else { | ||
// we need to get the options for the element rather than use the passed in as the | ||
// element could be an ng-form and have different options to the parent form. | ||
ctrlFormOptions = getFormOptions(ctrlElement); | ||
ctrlFormOptions.forceValidation = force; | ||
isValid = validateElement(controller, ctrlElement, ctrlFormOptions); | ||
frmValid = frmValid && isValid; | ||
} | ||
} | ||
}, | ||
clonedOptions; | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'E', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
if (frmElement === undefined || (frmCtrl !== undefined && frmCtrl.autoValidateFormOptions.disabled)) { | ||
return frmElement !== undefined; | ||
} | ||
angular.module('jcs-autoValidate').directive('ngForm', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'EA', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
//force the validation of controls | ||
clonedOptions = angular.copy(frmCtrl.autoValidateFormOptions); | ||
clonedOptions.forceValidation = true; | ||
function FormResetDirectiveFn(validationManager) { | ||
return { | ||
restrict: 'E', | ||
link: function (scope, el) { | ||
var formController = el.controller('form'); | ||
// IE8 holds the child controls collection in the all property | ||
// Firefox in the elements and chrome as a child iterator | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (ctrlElement) { | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
function resetFn() { | ||
validationManager.resetForm(el); | ||
if (formController.$setPristine) { | ||
formController.$setPristine(); | ||
} | ||
// If you have a custom form control that should be validated i.e. | ||
// <my-custom-element>...</my-custom-element> it will not be part of the forms | ||
// HTMLFormControlsCollection and thus won't be included in the above element iteration although | ||
// it will be on the Angular FormController (if it has a name attribute). So adding the directive | ||
// register-custom-form-control="" to the control root and autoValidate will include it in this | ||
// iteration. | ||
if (frmElement[0].customHTMLFormControlsCollection) { | ||
angular.forEach(frmElement[0].customHTMLFormControlsCollection, function (ctrlElement) { | ||
// need to force the validation as the element might not be a known form input type | ||
// so the normal validation process will ignore it. | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
} | ||
if (formController.$setUntouched) { | ||
formController.$setUntouched(); | ||
} | ||
} | ||
return frmValid; | ||
}, | ||
if (formController !== undefined && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === false) { | ||
el.on('reset', resetFn); | ||
setElementValidationError = function (element, errorMsgKey, errorMsg) { | ||
if (errorMsgKey) { | ||
validator.getErrorMessage(errorMsgKey, element).then(function (msg) { | ||
validator.makeInvalid(element, msg); | ||
}); | ||
} else { | ||
validator.makeInvalid(element, errorMsg); | ||
} | ||
}; | ||
scope.$on('$destroy', function () { | ||
el.off('reset', resetFn); | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
return { | ||
setElementValidationError: setElementValidationError, | ||
validateElement: validateElement, | ||
validateForm: validateForm, | ||
resetElement: resetElement, | ||
resetForm: resetForm | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
FormResetDirectiveFn.$inject = [ | ||
'validationManager' | ||
]; | ||
(function (angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate').directive('form', FormResetDirectiveFn); | ||
function parseBooleanAttributeValue(val) { | ||
return val !== undefined && val !== 'false'; | ||
function RegisterCustomFormControlFn() { | ||
var findParentForm = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 50; i += 1) { | ||
if (parent !== undefined && parent.nodeName.toLowerCase() === 'form') { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = angular.element(parent).parent()[0]; | ||
} | ||
} | ||
function parseOptions(ctrl, validator, attrs) { | ||
var opts = ctrl.autoValidateFormOptions = ctrl.autoValidateFormOptions || angular.copy(validator.defaultFormValidationOptions); | ||
opts.forceValidation = false; | ||
opts.disabled = !validator.isEnabled() || parseBooleanAttributeValue(attrs.disableDynamicValidation); | ||
opts.validateNonVisibleControls = parseBooleanAttributeValue(attrs.validateNonVisibleControls); | ||
opts.removeExternalValidationErrorsOnSubmit = attrs.removeExternalValidationErrorsOnSubmit === undefined ? true : parseBooleanAttributeValue(attrs.removeExternalValidationErrorsOnSubmit); | ||
return parent; | ||
}; | ||
if (validator.isEnabled() === false && parseBooleanAttributeValue(attrs.disableDynamicValidation) === false) { | ||
opts.disabled = false; | ||
} | ||
return { | ||
restrict: 'A', | ||
link: function (scope, element) { | ||
var frmEl = findParentForm(element.parent()[0]); | ||
if (frmEl) { | ||
frmEl.customHTMLFormControlsCollection = frmEl.customHTMLFormControlsCollection || []; | ||
frmEl.customHTMLFormControlsCollection.push(element[0]); | ||
} | ||
} | ||
}; | ||
} | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'E', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
angular.module('jcs-autoValidate').directive('registerCustomFormControl', RegisterCustomFormControlFn); | ||
angular.module('jcs-autoValidate').directive('ngForm', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'EA', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
function SubmitDecorator($delegate, $parse, validationManager) { | ||
$delegate[0].compile = function ($element, attrs) { | ||
var fn = $parse(attrs.ngSubmit), | ||
force = attrs.ngSubmitForce === 'true'; | ||
(function (angular) { | ||
'use strict'; | ||
return function (scope, element) { | ||
var formController = element.controller('form'), | ||
resetListenerOffFn; | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validationManager', | ||
function (validationManager) { | ||
return { | ||
restrict: 'E', | ||
link: function (scope, el) { | ||
var formController = el.controller('form'); | ||
function handlerFn(event) { | ||
scope.$apply(function () { | ||
if (formController !== undefined && | ||
formController !== null && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} else { | ||
if (formController.$setSubmitted === undefined) { | ||
// we probably have angular <= 1.2 | ||
formController.$submitted = true; | ||
} | ||
if (formController !== undefined && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === false) { | ||
el.on('reset', function () { | ||
validationManager.resetForm(el); | ||
}); | ||
if (validationManager.validateForm(element) || force === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
scope.$on('$destroy', function () { | ||
el.off('reset'); | ||
}); | ||
} | ||
} | ||
}; | ||
function resetFormFn() { | ||
if (element[0].reset) { | ||
element[0].reset(); | ||
} else { | ||
validationManager.resetForm(element); | ||
} | ||
]); | ||
}(angular)); | ||
} | ||
(function (angular) { | ||
'use strict'; | ||
if (formController && formController.autoValidateFormOptions) { | ||
// allow the form to be reset programatically or via raising the event | ||
// form:formName:reset | ||
formController.autoValidateFormOptions.resetForm = resetFormFn; | ||
if (formController.$name !== undefined && formController.$name !== '') { | ||
resetListenerOffFn = scope.$on('form:' + formController.$name + ':reset', resetFormFn); | ||
} | ||
} | ||
angular.module('jcs-autoValidate').directive('registerCustomFormControl', [ | ||
function () { | ||
var findParentForm = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 50; i += 1) { | ||
if (parent !== undefined && parent.nodeName.toLowerCase() === 'form') { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = angular.element(parent).parent()[0]; | ||
} | ||
} | ||
element.on('submit', handlerFn); | ||
scope.$on('$destroy', function () { | ||
element.off('submit', handlerFn); | ||
if (resetListenerOffFn) { | ||
resetListenerOffFn(); | ||
} | ||
}); | ||
}; | ||
}; | ||
return parent; | ||
}; | ||
return $delegate; | ||
} | ||
return { | ||
restrict: 'A', | ||
link: function (scope, element) { | ||
var frmEl = findParentForm(element.parent()[0]); | ||
if (frmEl) { | ||
frmEl.customHTMLFormControlsCollection = frmEl.customHTMLFormControlsCollection || []; | ||
frmEl.customHTMLFormControlsCollection.push(element[0]); | ||
} | ||
} | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
SubmitDecorator.$inject = [ | ||
'$delegate', | ||
'$parse', | ||
'validationManager' | ||
]; | ||
(function (angular) { | ||
'use strict'; | ||
function ProviderFn($provide) { | ||
$provide.decorator('ngSubmitDirective', SubmitDecorator); | ||
} | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngSubmitDirective', [ | ||
'$delegate', | ||
'$parse', | ||
'validationManager', | ||
function ($delegate, $parse, validationManager) { | ||
$delegate[0].compile = function ($element, attrs) { | ||
var fn = $parse(attrs.ngSubmit), | ||
force = attrs.ngSubmitForce === 'true'; | ||
ProviderFn.$inject = [ | ||
'$provide' | ||
]; | ||
return function (scope, element) { | ||
function handlerFn(event) { | ||
scope.$apply(function () { | ||
var formController = $element.controller('form'); | ||
if (formController !== undefined && | ||
formController !== null && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} else { | ||
if (validationManager.validateForm(element) || force === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
angular.module('jcs-autoValidate').config(ProviderFn); | ||
element.on('submit', handlerFn); | ||
scope.$on('$destroy', function () { | ||
element.off('submit', handlerFn); | ||
}); | ||
}; | ||
}; | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngModelDirective', [ | ||
'$timeout', | ||
'$delegate', | ||
'validationManager', | ||
'jcs-debounce', | ||
function ($timeout, $delegate, validationManager, debounce) { | ||
var directive = $delegate[0], | ||
link = directive.link || directive.compile; | ||
return $delegate; | ||
} | ||
]); | ||
} | ||
]); | ||
}(angular)); | ||
directive.compile = function (el) { | ||
var supportsNgModelOptions = angular.version.major >= 1 && angular.version.minor >= 3, | ||
originalLink = link; | ||
(function (angular) { | ||
'use strict'; | ||
// in the RC of 1.3 there is no directive.link only the directive.compile which | ||
// needs to be invoked to get at the link functions. | ||
if (supportsNgModelOptions && angular.isFunction(link)) { | ||
originalLink = link(el); | ||
} | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngModelDirective', [ | ||
'$timeout', | ||
'$delegate', | ||
'validationManager', | ||
'jcs-debounce', | ||
function ($timeout, $delegate, validationManager, debounce) { | ||
var directive = $delegate[0], | ||
link = directive.link || directive.compile; | ||
return { | ||
pre: function (scope, element, attrs, ctrls) { | ||
var ngModelCtrl = ctrls[0], | ||
frmCtrl = ctrls[1], | ||
ngModelOptions = attrs.ngModelOptions === undefined ? undefined : scope.$eval(attrs.ngModelOptions), | ||
setValidity = ngModelCtrl.$setValidity, | ||
setPristine = ngModelCtrl.$setPristine, | ||
setValidationState = debounce.debounce(function () { | ||
var validateOptions = frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : undefined; | ||
validationManager.validateElement(ngModelCtrl, element, validateOptions); | ||
}, 100); | ||
directive.compile = function (el) { | ||
return function (scope, element, attrs, ctrls) { | ||
var ngModelCtrl = ctrls[0], | ||
frmCtrl = ctrls[1], | ||
supportsNgModelOptions = angular.version.major >= 1 && angular.version.minor >= 3, | ||
ngModelOptions = attrs.ngModelOptions === undefined ? undefined : scope.$eval(attrs.ngModelOptions), | ||
setValidity = ngModelCtrl.$setValidity, | ||
setPristine = ngModelCtrl.$setPristine, | ||
setValidationState = debounce.debounce(function () { | ||
var validateOptions = frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : undefined; | ||
validationManager.validateElement(ngModelCtrl, element, validateOptions); | ||
}, 100); | ||
if (attrs.formnovalidate === undefined && | ||
(frmCtrl !== undefined && frmCtrl !== null && frmCtrl.autoValidateFormOptions && | ||
frmCtrl.autoValidateFormOptions.disabled === false)) { | ||
if (supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions.updateOn === undefined || ngModelOptions.updateOn === '') { | ||
ngModelCtrl.$setValidity = function (validationErrorKey, isValid) { | ||
setValidity.call(ngModelCtrl, validationErrorKey, isValid); | ||
setValidationState(); | ||
}; | ||
} else { | ||
element.on(ngModelOptions.updateOn, function () { | ||
setValidationState(); | ||
}); | ||
// in the RC of 1.3 there is no directive.link only the directive.compile which | ||
// needs to be invoked to get at the link functions. | ||
if (supportsNgModelOptions && angular.isFunction(link)) { | ||
link = link(el); | ||
} | ||
scope.$on('$destroy', function () { | ||
element.off(ngModelOptions.updateOn); | ||
}); | ||
} | ||
if (link.pre) { | ||
link.pre.apply(this, arguments); | ||
ngModelOptions = ngModelCtrl.$options === undefined ? undefined : ngModelCtrl.$options; | ||
} | ||
// We override this so we can reset the element state when it is called. | ||
ngModelCtrl.$setPristine = function () { | ||
setPristine.call(ngModelCtrl); | ||
validationManager.resetElement(element); | ||
}; | ||
if (attrs.formnovalidate === undefined && | ||
(frmCtrl !== undefined && frmCtrl !== null && frmCtrl.autoValidateFormOptions && | ||
frmCtrl.autoValidateFormOptions.disabled === false)) { | ||
if (supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions.updateOn === undefined || ngModelOptions.updateOn === '') { | ||
ngModelCtrl.$setValidity = function (validationErrorKey, isValid) { | ||
setValidity.call(ngModelCtrl, validationErrorKey, isValid); | ||
setValidationState(); | ||
}; | ||
} else { | ||
element.on(ngModelOptions.updateOn, function () { | ||
setValidationState(); | ||
}); | ||
ngModelCtrl.autoValidated = true; | ||
} | ||
scope.$on('$destroy', function () { | ||
element.off(ngModelOptions.updateOn); | ||
}); | ||
} | ||
ngModelCtrl.setExternalValidation = function (errorMsgKey, errorMessage, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = false; | ||
} | ||
// We override this so we can reset the element state when it is called. | ||
ngModelCtrl.$setPristine = function () { | ||
setPristine.call(ngModelCtrl); | ||
validationManager.resetElement(element); | ||
}; | ||
ngModelCtrl.externalErrors = ngModelCtrl.externalErrors || {}; | ||
ngModelCtrl.externalErrors[errorMsgKey] = false; | ||
validationManager.setElementValidationError(element, errorMsgKey, errorMessage); | ||
}; | ||
ngModelCtrl.autoValidated = true; | ||
} | ||
ngModelCtrl.removeExternalValidation = function (errorMsgKey, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
delete collection[errorMsgKey]; | ||
} | ||
if (link.post) { | ||
link.post.apply(this, arguments); | ||
} else { | ||
link.apply(this, arguments); | ||
} | ||
if (ngModelCtrl.externalErrors) { | ||
delete ngModelCtrl.externalErrors[errorMsgKey]; | ||
} | ||
ngModelCtrl.setExternalValidation = function (errorMsgKey, errorMessage, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = false; | ||
} | ||
validationManager.resetElement(element); | ||
}; | ||
ngModelCtrl.externalErrors = ngModelCtrl.externalErrors || {}; | ||
ngModelCtrl.externalErrors[errorMsgKey] = false; | ||
validationManager.setElementValidationError(element, errorMsgKey, errorMessage); | ||
}; | ||
ngModelCtrl.removeAllExternalValidation = function () { | ||
if (ngModelCtrl.externalErrors) { | ||
var errorCollection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
angular.forEach(ngModelCtrl.externalErrors, function (value, key) { | ||
delete errorCollection[key]; | ||
}); | ||
ngModelCtrl.removeExternalValidation = function (errorMsgKey, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = true; | ||
} | ||
ngModelCtrl.externalErrors = {}; | ||
if (ngModelCtrl.externalErrors) { | ||
delete ngModelCtrl.externalErrors[errorMsgKey]; | ||
} | ||
validationManager.resetElement(element); | ||
} | ||
}; | ||
validationManager.resetElement(element); | ||
}; | ||
if (frmCtrl) { | ||
frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].setExternalValidation(errorMsgKey, errorMessageOverride, addToModelErrors); | ||
success = true; | ||
} | ||
ngModelCtrl.removeAllExternalValidation = function () { | ||
if (ngModelCtrl.externalErrors) { | ||
var errorCollection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
angular.forEach(ngModelCtrl.externalErrors, function (value, key) { | ||
errorCollection[key] = true; | ||
}); | ||
return success; | ||
}; | ||
ngModelCtrl.externalErrors = {}; | ||
frmCtrl.removeExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].removeExternalValidation(errorMsgKey, addToModelErrors); | ||
success = true; | ||
} | ||
validationManager.resetElement(element); | ||
} | ||
}; | ||
return success; | ||
}; | ||
} | ||
if (frmCtrl) { | ||
frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].setExternalValidation(errorMsgKey, errorMessageOverride, addToModelErrors); | ||
success = true; | ||
} | ||
return originalLink.pre ? | ||
originalLink.pre.apply(this, arguments) : | ||
this; | ||
}, | ||
post: function (scope, element, attrs, ctrls) { | ||
return originalLink.post ? | ||
originalLink.post.apply(this, arguments) : | ||
originalLink.apply(this, arguments); | ||
} | ||
}; | ||
}; | ||
return success; | ||
}; | ||
return $delegate; | ||
} | ||
]); | ||
} | ||
]); | ||
frmCtrl.removeExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].removeExternalValidation(errorMsgKey, addToModelErrors); | ||
success = true; | ||
} | ||
function AutoValidateRunFn(validator, defaultErrorMessageResolver, bootstrap3ElementModifier, foundation5ElementModifier) { | ||
validator.setErrorMessageResolver(defaultErrorMessageResolver.resolve); | ||
validator.registerDomModifier(bootstrap3ElementModifier.key, bootstrap3ElementModifier); | ||
validator.registerDomModifier(foundation5ElementModifier.key, foundation5ElementModifier); | ||
validator.setDefaultElementModifier(bootstrap3ElementModifier.key); | ||
} | ||
return success; | ||
}; | ||
} | ||
}; | ||
}; | ||
AutoValidateRunFn.$inject = [ | ||
'validator', | ||
'defaultErrorMessageResolver', | ||
'bootstrap3ElementModifier', | ||
'foundation5ElementModifier' | ||
]; | ||
return $delegate; | ||
} | ||
]); | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').run(AutoValidateRunFn); | ||
(function (angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate') | ||
.run([ | ||
'validator', | ||
'defaultErrorMessageResolver', | ||
'bootstrap3ElementModifier', | ||
'foundation5ElementModifier', | ||
function (validator, defaultErrorMessageResolver, bootstrap3ElementModifier, foundation5ElementModifier) { | ||
validator.setErrorMessageResolver(defaultErrorMessageResolver.resolve); | ||
validator.registerDomModifier(bootstrap3ElementModifier.key, bootstrap3ElementModifier); | ||
validator.registerDomModifier(foundation5ElementModifier.key, foundation5ElementModifier); | ||
validator.setDefaultElementModifier(bootstrap3ElementModifier.key); | ||
} | ||
]); | ||
}(angular)); | ||
}(String, angular)); |
/* | ||
* angular-auto-validate - v1.18.6 - 2015-04-16 | ||
* angular-auto-validate - v1.18.14 - 2015-08-23 | ||
* https://github.com/jonsamwell/angular-auto-validate | ||
* Copyright (c) 2015 Jon Samwell (http://www.jonsamwell.com) | ||
*/ | ||
!function(a){"use strict";a.module("jcs-autoValidate",[])}(angular),function(a){"use strict";a.module("jcs-autoValidate").provider("validator",[function(){var b={},c=!0,d=!0,e=!0,f=function(a){var b;return a&&0!==a.length?(b=a.toLowerCase(),a=!("f"===b||"0"===b||"false"===b)):a=!1,a},g=function(a,b){var c;return void 0!==a&&(c=a.attr(b)||a.attr("data-"+b)),c},h=function(a,b){var c;return void 0!==a&&(c=void 0!==a.attr(b)||void 0!==a.attr("data-"+b)),c},i=function(a,b){return f(g(a,b))},j=function(a){return c&&!i(a,"disable-valid-styling")},k=function(a){return d&&!i(a,"disable-invalid-styling")};this.enable=function(a){e=a},this.isEnabled=function(){return e},this.setDefaultElementModifier=function(a){if(void 0===b[a])throw new Error("Element modifier not registered: "+a);this.defaultElementModifier=a},this.registerDomModifier=function(a,c){b[a]=c},this.setErrorMessageResolver=function(a){this.errorMessageResolver=a},this.getErrorMessage=function(b,c){var d;if(void 0===this.errorMessageResolver)throw new Error("Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.");return h(c,"disable-validation-message")?(d=a.injector(["ng"]).get("$q").defer(),d.resolve(""),d.promise):this.errorMessageResolver(b,c)},this.setValidElementStyling=function(a){c=a},this.setInvalidElementStyling=function(a){d=a},this.getDomModifier=function(a){var c=(void 0!==a?a.attr("element-modifier"):this.defaultElementModifier)||(void 0!==a?a.attr("data-element-modifier"):this.defaultElementModifier)||this.defaultElementModifier;if(void 0===c)throw new Error("Please set a default dom modifier via the setDefaultElementModifier method on the validator class.");return b[c]},this.makeValid=function(a){j(a)?this.getDomModifier(a).makeValid(a):this.makeDefault(a)},this.makeInvalid=function(a,b){k(a)?this.getDomModifier(a).makeInvalid(a,b):this.makeDefault(a)},this.makeDefault=function(a){var b=this.getDomModifier(a);b.makeDefault&&b.makeDefault(a)},this.defaultFormValidationOptions={forceValidation:!1,disabled:!1,validateNonVisibleControls:!1,removeExternalValidationErrorsOnSubmit:!0},this.$get=[function(){return this}]}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").factory("bootstrap3ElementModifier",["$log",function(b){var c=function(b){a.forEach(b.find("span"),function(b){b=a.element(b),(b.hasClass("error-msg")||b.hasClass("form-control-feedback")||b.hasClass("control-feedback"))&&b.remove()}),b.removeClass("has-success has-error has-feedback")},d=function(a,b){for(var c,d=a,e=0;10>=e;e+=1){if(void 0!==d&&d.hasClass(b)){c=d;break}void 0!==d&&(d=d.parent())}return c},e=function(b,c){for(var d,f=0;f<b.children.length&&(d=b.children[f],void 0===d||!a.element(d).hasClass(c))&&!(void 0!==d.children&&(d=e(d,c),d.length>0));f+=1);return a.element(d)},f=function(a){return d(a,"form-group")},g=function(a){return e(a,"input-group")},h=function(a,b){a[0].parentNode.insertBefore(b[0],a[0].nextSibling)},i=!1,j=function(a){i=a},k=function(d){var e,j=f(d);if(j){if(c(j),e=g(j[0]),j.addClass("has-success "+(e.length>0?"":"has-feedback")),i){var k='<span class="glyphicon glyphicon-ok form-control-feedback"></span>';e.length>0&&(k=k.replace("form-",""),k='<span class="input-group-addon control-feedback">'+k+"</span"),h(d,a.element(k))}}else b.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")},l=function(d,e){var j,k=f(d),l=a.element('<span class="help-block has-error error-msg">'+e+"</span>");if(k){if(c(k),j=g(k[0]),k.addClass("has-error "+(j.length>0?"":"has-feedback")),h(j.length>0?j:d,l),i){var m='<span class="glyphicon glyphicon-remove form-control-feedback"></span>';j.length>0&&(m=m.replace("form-",""),m='<span class="input-group-addon control-feedback">'+m+"</span"),h(d,a.element(m))}}else b.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")},m=function(a){var d=f(a);d?c(d):b.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")};return{makeValid:k,makeInvalid:l,makeDefault:m,enableValidationStateIcons:j,key:"bs3"}}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").factory("jcs-debounce",["$timeout",function(b){var c=function(c,d,e){d=a.isUndefined(d)?0:d,e=a.isUndefined(e)?!0:e;var f=0;return function(){var a=this,g=arguments;f+=1;var h=function(b){return function(){return b===f?c.apply(a,g):void 0}}(f);return b(h,d,e)}};return{debounce:c}}])}(angular),function(a,b){"use strict";"format"in a.prototype||(a.prototype.format=function(){var a=arguments;return this.replace(/{(\d+)}/g,function(b,c){return void 0!==typeof a[c]?a[c]:b})}),b.autoValidate=b.autoValidate||{errorMessages:{}},b.autoValidate.errorMessages["en-us"]=b.autoValidate.errorMessages["en-gb"]={defaultMsg:"Please add error message for {0}",email:"Please enter a valid email address",minlength:"Please enter at least {0} characters",maxlength:"You have entered more than the maximum {0} characters",min:"Please enter the minimum number of {0}",max:"Please enter the maximum number of {0}",required:"This field is required",date:"Please enter a valid date",pattern:"Please ensure the entered information adheres to this pattern {0}",number:"Please enter a valid number",url:"Please enter a valid URL in the format of http(s)://www.google.com"},b.module("jcs-autoValidate").factory("defaultErrorMessageResolver",["$q","$http",function(a,c){var d,e="en-gb",f="js/angular-auto-validate/dist/lang",g=function(a){return d=c.get("{0}/jcs-auto-validate_{1}.json".format(f,a.toLowerCase()))},h=function(a){f=a},i=function(c,f){var h=a.defer();return f=f||g,e=c.toLowerCase(),void 0===b.autoValidate.errorMessages[e]?(d=f(c),d.then(function(a){d=void 0,b.autoValidate.errorMessages[e]=a.data,h.resolve(b.autoValidate.errorMessages[e])},function(a){b.autoValidate.errorMessages[e]={defaultMsg:"Loading culture failed!"},d=null,h.reject(a)})):h.resolve(b.autoValidate.errorMessages[e]),h.promise},j=function(c){var f=a.defer();return c=void 0===c?e:c.toLowerCase(),void 0!==d?d.then(function(){f.resolve(b.autoValidate.errorMessages[c])},function(a){f.reject(a)}):f.resolve(b.autoValidate.errorMessages[c]),f.promise},k=function(a,b){var c;return b&&(a+="-err-type",c=b.attr("ng-"+a),void 0===c&&(c=b.attr("data-ng-"+a)||b.attr(a)),c&&(c=c.replace(/[\W]/g,""))),c},l=function(c,f){var g,h,i,j=a.defer(),m=[];if(void 0!==d)d.then(function(){l(c,f).then(function(a){j.resolve(a)})});else{if(g=b.autoValidate.errorMessages[e][c],i=k(c,f),i&&(g=b.autoValidate.errorMessages[e][i]),void 0===g&&(g=b.autoValidate.errorMessages[e].defaultMsg.format(c)),f&&f.attr)try{h=f.attr("ng-"+c),void 0===h&&(h=f.attr("data-ng-"+c)||f.attr(c)),m.push(h||""),g=g.format(m)}catch(n){}j.resolve(g)}return j.promise};return{setI18nFileRootPath:h,setCulture:i,getErrorMessages:j,resolve:l}}])}(String,angular),function(a){"use strict";a.module("jcs-autoValidate").factory("foundation5ElementModifier",[function(){var b=function(b,c){a.forEach(b.find("small"),function(b){a.element(b).hasClass("error")&&a.element(b).remove()}),c.removeClass("error")},c=function(a){for(var b=a,c=0;3>=c&&(void 0===b||!b.hasClass("columns"));c+=1)void 0!==b&&(b=b.parent());return b},d=function(a){var d=c(a);b(d&&d.length>0?d:a,a)},e=function(d,e){var f,g=c(d);b(g||d,d),d.addClass("error"),g&&(f=a.element('<small class="error">'+e+"</small>"),g.append(f))},f=function(a){d(a)};return{makeValid:d,makeInvalid:e,makeDefault:f,key:"foundation5"}}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").factory("jcs-elementUtils",[function(){var a=function(a){return a[0].offsetWidth>0&&a[0].offsetHeight>0};return{isElementVisible:a}}]),a.module("jcs-autoValidate").factory("validationManager",["validator","jcs-elementUtils",function(b,c){var d=["input","textarea","select","form"],e=function(a){return c.isElementVisible(a)},f=function(c){var d=a.element(c).controller("form");return void 0!==d&&null!==d?d.autoValidateFormOptions:b.defaultFormValidationOptions},g=function(a,b){var c=a&&a.length>0&&(e(a)||b.validateNonVisibleControls)&&(d.indexOf(a[0].nodeName.toLowerCase())>-1||a[0].hasAttribute("register-custom-form-control"));return c},h=function(c,d,e){var h,i=!0,j=e||f(d),k=c.$pristine===!1||j.forceValidation,l=function(b){var c,d=!0;return a.forEach(b,function(a,b){d&&a&&(d=!1,c=b)}),c};return j.disabled===!1&&(j.forceValidation||g(d,j)&&c&&k)&&(i=!c.$invalid,j.removeExternalValidationErrorsOnSubmit&&c.removeAllExternalValidation&&c.removeAllExternalValidation(),i?b.makeValid(d):(h=l(c.$errors||c.$error),void 0===h?i=!0:b.getErrorMessage(h,d).then(function(a){b.makeInvalid(d,a)}))),i},i=function(a){b.makeDefault(a)},j=function(b){a.forEach(b[0].all||b[0].elements||b[0],function(b){var c,d=a.element(b);c=d.controller("ngModel"),void 0!==c&&("form"===d[0].nodeName.toLowerCase()?j(d):c.$setPristine())})},k=function(b){var c,d=!0,e=b?a.element(b).controller("form"):void 0,i=function(b,c,e){var i,j,l;b=a.element(b),i=b.controller("ngModel"),void 0!==i&&(c||g(b,e))&&("form"===b[0].nodeName.toLowerCase()?k(b):(l=f(b),l.forceValidation=c,j=h(i,b,l),d=d&&j))};return void 0===b||void 0!==e&&e.autoValidateFormOptions.disabled?void 0!==b:(c=a.copy(e.autoValidateFormOptions),c.forceValidation=!0,a.forEach(b[0].all||b[0].elements||b[0],function(a){i(a,!0,c)}),b[0].customHTMLFormControlsCollection&&a.forEach(b[0].customHTMLFormControlsCollection,function(a){i(a,!0,c)}),d)},l=function(a,c,d){c?b.getErrorMessage(c,a).then(function(c){b.makeInvalid(a,c)}):b.makeInvalid(a,d)};return{setElementValidationError:l,validateElement:h,validateForm:k,resetElement:i,resetForm:j}}])}(angular),function(a){"use strict";function b(a){return void 0!==a&&"false"!==a}function c(c,d,e){var f=c.autoValidateFormOptions=c.autoValidateFormOptions||a.copy(d.defaultFormValidationOptions);f.forceValidation=!1,f.disabled=!d.isEnabled()||b(e.disableDynamicValidation),f.validateNonVisibleControls=b(e.validateNonVisibleControls),f.removeExternalValidationErrorsOnSubmit=void 0===e.removeExternalValidationErrorsOnSubmit?!0:b(e.removeExternalValidationErrorsOnSubmit),d.isEnabled()===!1&&b(e.disableDynamicValidation)===!1&&(f.disabled=!1)}a.module("jcs-autoValidate").directive("form",["validator",function(a){return{restrict:"E",require:"form",priority:9999,compile:function(){return{pre:function(b,d,e,f){c(f,a,e)}}}}}]),a.module("jcs-autoValidate").directive("ngForm",["validator",function(a){return{restrict:"EA",require:"form",priority:9999,compile:function(){return{pre:function(b,d,e,f){c(f,a,e)}}}}}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").directive("form",["validationManager",function(a){return{restrict:"E",link:function(b,c){var d=c.controller("form");void 0!==d&&d.autoValidateFormOptions&&d.autoValidateFormOptions.disabled===!1&&(c.on("reset",function(){a.resetForm(c)}),b.$on("$destroy",function(){c.off("reset")}))}}}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").directive("registerCustomFormControl",[function(){var b=function(b){for(var c=b,d=0;50>=d&&(void 0===c||"form"!==c.nodeName.toLowerCase());d+=1)void 0!==c&&(c=a.element(c).parent()[0]);return c};return{restrict:"A",link:function(a,c){var d=b(c.parent()[0]);d&&(d.customHTMLFormControlsCollection=d.customHTMLFormControlsCollection||[],d.customHTMLFormControlsCollection.push(c[0]))}}}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").config(["$provide",function(a){a.decorator("ngSubmitDirective",["$delegate","$parse","validationManager",function(a,b,c){return a[0].compile=function(a,d){var e=b(d.ngSubmit),f="true"===d.ngSubmitForce;return function(b,d){function g(g){b.$apply(function(){var h=a.controller("form");void 0!==h&&null!==h&&h.autoValidateFormOptions&&h.autoValidateFormOptions.disabled===!0?e(b,{$event:g}):(c.validateForm(d)||f===!0)&&e(b,{$event:g})})}d.on("submit",g),b.$on("$destroy",function(){d.off("submit",g)})}},a}])}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").config(["$provide",function(b){b.decorator("ngModelDirective",["$timeout","$delegate","validationManager","jcs-debounce",function(b,c,d,e){var f=c[0],g=f.link||f.compile;return f.compile=function(b){return function(c,f,h,i){var j=i[0],k=i[1],l=a.version.major>=1&&a.version.minor>=3,m=void 0===h.ngModelOptions?void 0:c.$eval(h.ngModelOptions),n=j.$setValidity,o=j.$setPristine,p=e.debounce(function(){var a=void 0!==k&&null!==k?k.autoValidateFormOptions:void 0;d.validateElement(j,f,a)},100);l&&a.isFunction(g)&&(g=g(b)),g.pre&&(g.pre.apply(this,arguments),m=void 0===j.$options?void 0:j.$options),void 0===h.formnovalidate&&void 0!==k&&null!==k&&k.autoValidateFormOptions&&k.autoValidateFormOptions.disabled===!1&&(l||void 0===m||void 0===m.updateOn||""===m.updateOn?j.$setValidity=function(a,b){n.call(j,a,b),p()}:(f.on(m.updateOn,function(){p()}),c.$on("$destroy",function(){f.off(m.updateOn)})),j.$setPristine=function(){o.call(j),d.resetElement(f)},j.autoValidated=!0),g.post?g.post.apply(this,arguments):g.apply(this,arguments),j.setExternalValidation=function(a,b,c){if(c){var e=j.$error||j.$errors;e[a]=!1}j.externalErrors=j.externalErrors||{},j.externalErrors[a]=!1,d.setElementValidationError(f,a,b)},j.removeExternalValidation=function(a,b){if(b){var c=j.$error||j.$errors;c[a]=!0}j.externalErrors&&delete j.externalErrors[a],d.resetElement(f)},j.removeAllExternalValidation=function(){if(j.externalErrors){var b=j.$error||j.$errors;a.forEach(j.externalErrors,function(a,c){b[c]=!0}),j.externalErrors={},d.resetElement(f)}},k&&(k.setExternalValidation=function(a,b,c,d){var e=!1;return k[a]&&(k[a].setExternalValidation(b,c,d),e=!0),e},k.removeExternalValidation=function(a,b,c,d){var e=!1;return k[a]&&(k[a].removeExternalValidation(b,d),e=!0),e})}},c}])}])}(angular),function(a){"use strict";a.module("jcs-autoValidate").run(["validator","defaultErrorMessageResolver","bootstrap3ElementModifier","foundation5ElementModifier",function(a,b,c,d){a.setErrorMessageResolver(b.resolve),a.registerDomModifier(c.key,c),a.registerDomModifier(d.key,d),a.setDefaultElementModifier(c.key)}])}(angular); | ||
!function(a,b){"use strict";function c(){var a={},c=!0,d=!0,e=!0,f=function(a){var b;return a&&0!==a.length?(b=a.toLowerCase(),a=!("f"===b||"0"===b||"false"===b)):a=!1,a},g=function(a,b){var c;return void 0!==a&&(c=a.attr(b)||a.attr("data-"+b)),c},h=function(a,b){var c;return void 0!==a&&(c=void 0!==a.attr(b)||void 0!==a.attr("data-"+b)),c},i=function(a,b){return f(g(a,b))},j=function(a){return c&&!i(a,"disable-valid-styling")},k=function(a){return d&&!i(a,"disable-invalid-styling")};this.enable=function(a){e=a},this.isEnabled=function(){return e},this.setDefaultElementModifier=function(b){if(void 0===a[b])throw new Error("Element modifier not registered: "+b);this.defaultElementModifier=b},this.registerDomModifier=function(b,c){a[b]=c},this.setErrorMessageResolver=function(a){this.errorMessageResolver=a},this.getErrorMessage=function(a,c){var d;if(void 0===this.errorMessageResolver)throw new Error("Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.");return h(c,"disable-validation-message")?(d=b.injector(["ng"]).get("$q").defer(),d.resolve(""),d.promise):this.errorMessageResolver(a,c)},this.setValidElementStyling=function(a){c=a},this.setInvalidElementStyling=function(a){d=a},this.getDomModifier=function(b){var c=(void 0!==b?b.attr("element-modifier"):this.defaultElementModifier)||(void 0!==b?b.attr("data-element-modifier"):this.defaultElementModifier)||this.defaultElementModifier;if(void 0===c)throw new Error("Please set a default dom modifier via the setDefaultElementModifier method on the validator class.");return a[c]},this.makeValid=function(a){j(a)?this.getDomModifier(a).makeValid(a):this.makeDefault(a)},this.makeInvalid=function(a,b){k(a)?this.getDomModifier(a).makeInvalid(a,b):this.makeDefault(a)},this.makeDefault=function(a){var b=this.getDomModifier(a);b.makeDefault&&b.makeDefault(a)},this.defaultFormValidationOptions={forceValidation:!1,disabled:!1,validateNonVisibleControls:!1,removeExternalValidationErrorsOnSubmit:!0,validateOnFormSubmit:!1},this.$get=[function(){return this}]}function d(a){var c=function(a){b.forEach(a.find("span"),function(a){a=b.element(a),(a.hasClass("error-msg")||a.hasClass("form-control-feedback")||a.hasClass("control-feedback"))&&a.remove()}),a.removeClass("has-success has-error has-feedback")},d=function(a,b){for(var c,d=a,e=0;10>=e;e+=1){if(void 0!==d&&d.hasClass(b)){c=d;break}void 0!==d&&(d=d.parent())}return c},e=function(a,c){for(var d,f=0;f<a.children.length&&(d=a.children[f],void 0===d||!b.element(d).hasClass(c))&&!(void 0!==d.children&&(d=e(d,c),d.length>0));f+=1);return b.element(d)},f=function(a){return d(a,"form-group")},g=function(a){return e(a,"input-group")},h=function(a,b){a[0].parentNode.insertBefore(b[0],a[0].nextSibling)},i=!1,j=function(a){i=a},k=function(d){var e,j=f(d);if(j){if(c(j),e=g(j[0]),j.addClass("has-success "+(e.length>0?"":"has-feedback")),i){var k='<span class="glyphicon glyphicon-ok form-control-feedback"></span>';e.length>0&&(k=k.replace("form-",""),k='<span class="input-group-addon control-feedback">'+k+"</span"),h(d,b.element(k))}}else a.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")},l=function(d,e){var j,k=f(d),l=b.element('<span class="help-block has-error error-msg">'+e+"</span>");if(k){if(c(k),j=g(k[0]),k.addClass("has-error "+(j.length>0?"":"has-feedback")),h(j.length>0?j:d,l),i){var m='<span class="glyphicon glyphicon-remove form-control-feedback"></span>';j.length>0&&(m=m.replace("form-",""),m='<span class="input-group-addon control-feedback">'+m+"</span"),h(d,b.element(m))}}else a.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")},m=function(b){var d=f(b);d?c(d):a.error("Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class")};return{makeValid:k,makeInvalid:l,makeDefault:m,enableValidationStateIcons:j,key:"bs3"}}function e(a){var c=function(c,d,e){d=b.isUndefined(d)?0:d,e=b.isUndefined(e)?!0:e;var f=0;return function(){var b=this,g=arguments;f+=1;var h=function(a){return function(){return a===f?c.apply(b,g):void 0}}(f);return a(h,d,e)}};return{debounce:c}}function f(a,c){var d,e="en-gb",f="js/angular-auto-validate/dist/lang",g=function(a){return d=c.get("{0}/jcs-auto-validate_{1}.json".format(f,a.toLowerCase()))},h=function(a){f=a},i=function(c,f){var h=a.defer();return f=f||g,e=c.toLowerCase(),void 0===b.autoValidate.errorMessages[e]?(d=f(c),d.then(function(a){d=void 0,b.autoValidate.errorMessages[e]=a.data,h.resolve(b.autoValidate.errorMessages[e])},function(a){b.autoValidate.errorMessages[e]={defaultMsg:"Loading culture failed!"},d=null,h.reject(a)})):h.resolve(b.autoValidate.errorMessages[e]),h.promise},j=function(c){var f=a.defer();return c=void 0===c?e:c.toLowerCase(),void 0!==d?d.then(function(){f.resolve(b.autoValidate.errorMessages[c])},function(a){f.reject(a)}):f.resolve(b.autoValidate.errorMessages[c]),f.promise},k=function(a,b){var c;return b&&(a+="-err-type",c=b.attr("ng-"+a),void 0===c&&(c=b.attr("data-ng-"+a)||b.attr(a)),c&&(c=c.replace(/[\W]/g,""))),c},l=function(c,f){var g,h,i,j=a.defer(),m=[];if(void 0!==d)d.then(function(){l(c,f).then(function(a){j.resolve(a)})});else{if(g=b.autoValidate.errorMessages[e][c],i=k(c,f),i&&(g=b.autoValidate.errorMessages[e][i]),void 0===g&&(g=b.autoValidate.errorMessages[e].defaultMsg.format(c)),f&&f.attr)try{h=f.attr("ng-"+c),void 0===h&&(h=f.attr("data-ng-"+c)||f.attr(c)),m.push(h||""),g=g.format(m)}catch(n){}j.resolve(g)}return j.promise};return{setI18nFileRootPath:h,setCulture:i,getErrorMessages:j,resolve:l}}function g(){var a=function(a,c){b.forEach(a.find("small"),function(a){b.element(a).hasClass("error")&&b.element(a).remove()}),c.removeClass("error")},c=function(a){for(var b=a,c=0;3>=c&&(void 0===b||!b.hasClass("columns"));c+=1)void 0!==b&&(b=b.parent());return b},d=function(b){var d=c(b);a(d&&d.length>0?d:b,b)},e=function(d,e){var f,g=c(d);a(g||d,d),d.addClass("error"),g&&(f=b.element('<small class="error">'+e+"</small>"),g.append(f))},f=function(a){d(a)};return{makeValid:d,makeInvalid:e,makeDefault:f,key:"foundation5"}}function h(){var a=function(a){return a[0].offsetWidth>0&&a[0].offsetHeight>0};return{isElementVisible:a}}function i(a,c){var d=["input","textarea","select","form"],e=function(a){return c.isElementVisible(a)},f=function(c){var d,e=b.element(c).controller("form");return d=void 0!==e&&null!==e?e.autoValidateFormOptions:a.defaultFormValidationOptions},g=function(a,b,c){var f,g,h,i=a&&a.length>0;return i&&(f=e(a)||b.validateNonVisibleControls,g=d.indexOf(a[0].nodeName.toLowerCase())>-1||a[0].hasAttribute("register-custom-form-control"),h=b.validateOnFormSubmit===!1||b.validateOnFormSubmit===!0&&c===!0),i&&f&&g&&h},h=function(c,d,e){var h,i=!0,j=e||f(d),k=c.$pristine===!1||j.forceValidation,l=function(a){var c,d=!0;return b.forEach(a,function(a,b){d&&a&&(d=!1,c=b)}),c};return j.disabled===!1&&(j.forceValidation||g(d,j,j.formController.$submitted)&&c&&k)&&(i=!c.$invalid,j.removeExternalValidationErrorsOnSubmit&&c.removeAllExternalValidation&&c.removeAllExternalValidation(),i?a.makeValid(d):(h=l(c.$errors||c.$error),void 0===h?i=!0:a.getErrorMessage(h,d).then(function(b){a.makeInvalid(d,b)}))),i},i=function(b){a.makeDefault(b)},j=function(a){b.forEach(a[0].all||a[0].elements||a[0],function(a){var c,d=b.element(a);c=d.controller("ngModel"),void 0!==c&&("form"===d[0].nodeName.toLowerCase()?j(d):c.$setPristine())})},k=function(a){var c,d=!0,e=a?b.element(a).controller("form"):void 0,i=function(a,c,i){var j,l,m,n;if(a=b.element(a),j=a.controller("ngModel"),void 0!==j&&(c||g(a,i,e.$submitted)))if("form"===a[0].nodeName.toLowerCase())k(a);else{m=f(a),n=m.forceValidation,m.forceValidation=c;try{l=h(j,a,m),d=d&&l}finally{m.forceValidation=n}}};return void 0===a||void 0!==e&&e.autoValidateFormOptions.disabled?void 0!==a:(c=b.copy(e.autoValidateFormOptions),c.forceValidation=!0,b.forEach(a[0].all||a[0].elements||a[0],function(a){i(a,!0,c)}),a[0].customHTMLFormControlsCollection&&b.forEach(a[0].customHTMLFormControlsCollection,function(a){i(a,!0,c)}),d)},l=function(b,c,d){c?a.getErrorMessage(c,b).then(function(c){a.makeInvalid(b,c)}):a.makeInvalid(b,d)};return{setElementValidationError:l,validateElement:h,validateForm:k,resetElement:i,resetForm:j}}function j(a,b){return void 0!==a&&null!==a||void 0===b?"false"!==a:b}function k(a,c,d){var e=a.autoValidateFormOptions=a.autoValidateFormOptions||b.copy(c.defaultFormValidationOptions);e.formController=a,e.forceValidation=!1,e.disabled=!c.isEnabled()||j(d.disableDynamicValidation,e.disabled),e.validateNonVisibleControls=j(d.validateNonVisibleControls,e.validateNonVisibleControls),e.validateOnFormSubmit=j(d.validateOnFormSubmit,e.validateOnFormSubmit),e.removeExternalValidationErrorsOnSubmit=void 0===d.removeExternalValidationErrorsOnSubmit?e.removeExternalValidationErrorsOnSubmit:j(d.removeExternalValidationErrorsOnSubmit,e.removeExternalValidationErrorsOnSubmit),c.isEnabled()===!1&&"false"===d.disableDynamicValidation&&(e.disabled=!1)}function l(a){return{restrict:"E",link:function(b,c){function d(){a.resetForm(c),e.$setPristine&&e.$setPristine(),e.$setUntouched&&e.$setUntouched()}var e=c.controller("form");void 0!==e&&e.autoValidateFormOptions&&e.autoValidateFormOptions.disabled===!1&&(c.on("reset",d),b.$on("$destroy",function(){c.off("reset",d)}))}}}function m(){var a=function(a){for(var c=a,d=0;50>=d&&(void 0===c||"form"!==c.nodeName.toLowerCase());d+=1)void 0!==c&&(c=b.element(c).parent()[0]);return c};return{restrict:"A",link:function(b,c){var d=a(c.parent()[0]);d&&(d.customHTMLFormControlsCollection=d.customHTMLFormControlsCollection||[],d.customHTMLFormControlsCollection.push(c[0]))}}}function n(a,b,c){return a[0].compile=function(a,d){var e=b(d.ngSubmit),f="true"===d.ngSubmitForce;return function(a,b){function d(d){a.$apply(function(){void 0!==i&&null!==i&&i.autoValidateFormOptions&&i.autoValidateFormOptions.disabled===!0?e(a,{$event:d}):(void 0===i.$setSubmitted&&(i.$submitted=!0),(c.validateForm(b)||f===!0)&&e(a,{$event:d}))})}function g(){b[0].reset?b[0].reset():c.resetForm(b)}var h,i=b.controller("form");i&&i.autoValidateFormOptions&&(i.autoValidateFormOptions.resetForm=g,void 0!==i.$name&&""!==i.$name&&(h=a.$on("form:"+i.$name+":reset",g))),b.on("submit",d),a.$on("$destroy",function(){b.off("submit",d),h&&h()})}},a}function o(a){a.decorator("ngSubmitDirective",n)}function p(a,b,c,d){a.setErrorMessageResolver(b.resolve),a.registerDomModifier(c.key,c),a.registerDomModifier(d.key,d),a.setDefaultElementModifier(c.key)}b.module("jcs-autoValidate",[]),b.module("jcs-autoValidate").provider("validator",c),d.$inject=["$log"],b.module("jcs-autoValidate").factory("bootstrap3ElementModifier",d),e.$inject=["$timeout"],b.module("jcs-autoValidate").factory("jcs-debounce",e),"format"in a.prototype||(a.prototype.format=function(){var a=arguments;return this.replace(/{(\d+)}/g,function(b,c){return void 0!==typeof a[c]?a[c]:b})}),b.autoValidate=b.autoValidate||{errorMessages:{}},b.autoValidate.errorMessages["en-us"]=b.autoValidate.errorMessages["en-gb"]={defaultMsg:"Please add error message for {0}",email:"Please enter a valid email address",minlength:"Please enter at least {0} characters",maxlength:"You have entered more than the maximum {0} characters",min:"Please enter the minimum number of {0}",max:"Please enter the maximum number of {0}",required:"This field is required",date:"Please enter a valid date",pattern:"Please ensure the entered information adheres to this pattern {0}",number:"Please enter a valid number",url:"Please enter a valid URL in the format of http(s)://www.google.com"},f.$inject=["$q","$http"],b.module("jcs-autoValidate").factory("defaultErrorMessageResolver",f),b.module("jcs-autoValidate").factory("foundation5ElementModifier",g),i.$inject=["validator","jcs-elementUtils"],b.module("jcs-autoValidate").factory("jcs-elementUtils",h),b.module("jcs-autoValidate").factory("validationManager",i),b.module("jcs-autoValidate").directive("form",["validator",function(a){return{restrict:"E",require:"form",priority:9999,compile:function(){return{pre:function(b,c,d,e){k(e,a,d)}}}}}]),b.module("jcs-autoValidate").directive("ngForm",["validator",function(a){return{restrict:"EA",require:"form",priority:9999,compile:function(){return{pre:function(b,c,d,e){k(e,a,d)}}}}}]),l.$inject=["validationManager"],b.module("jcs-autoValidate").directive("form",l),b.module("jcs-autoValidate").directive("registerCustomFormControl",m),n.$inject=["$delegate","$parse","validationManager"],o.$inject=["$provide"],b.module("jcs-autoValidate").config(o),b.module("jcs-autoValidate").config(["$provide",function(a){a.decorator("ngModelDirective",["$timeout","$delegate","validationManager","jcs-debounce",function(a,c,d,e){var f=c[0],g=f.link||f.compile;return f.compile=function(a){var c=b.version.major>=1&&b.version.minor>=3,f=g;return c&&b.isFunction(g)&&(f=g(a)),{pre:function(a,g,h,i){var j=i[0],k=i[1],l=void 0===h.ngModelOptions?void 0:a.$eval(h.ngModelOptions),m=j.$setValidity,n=j.$setPristine,o=e.debounce(function(){var a=void 0!==k&&null!==k?k.autoValidateFormOptions:void 0;d.validateElement(j,g,a)},100);return void 0===h.formnovalidate&&void 0!==k&&null!==k&&k.autoValidateFormOptions&&k.autoValidateFormOptions.disabled===!1&&(c||void 0===l||void 0===l.updateOn||""===l.updateOn?j.$setValidity=function(a,b){m.call(j,a,b),o()}:(g.on(l.updateOn,function(){o()}),a.$on("$destroy",function(){g.off(l.updateOn)})),j.$setPristine=function(){n.call(j),d.resetElement(g)},j.autoValidated=!0),j.setExternalValidation=function(a,b,c){if(c){var e=j.$error||j.$errors;e[a]=!1}j.externalErrors=j.externalErrors||{},j.externalErrors[a]=!1,d.setElementValidationError(g,a,b)},j.removeExternalValidation=function(a,b){if(b){var c=j.$error||j.$errors;delete c[a]}j.externalErrors&&delete j.externalErrors[a],d.resetElement(g)},j.removeAllExternalValidation=function(){if(j.externalErrors){var a=j.$error||j.$errors;b.forEach(j.externalErrors,function(b,c){delete a[c]}),j.externalErrors={},d.resetElement(g)}},k&&(k.setExternalValidation=function(a,b,c,d){var e=!1;return k[a]&&(k[a].setExternalValidation(b,c,d),e=!0),e},k.removeExternalValidation=function(a,b,c,d){var e=!1;return k[a]&&(k[a].removeExternalValidation(b,d),e=!0),e}),f.pre?f.pre.apply(this,arguments):this},post:function(a,b,c,d){return f.post?f.post.apply(this,arguments):f.apply(this,arguments)}}},c}])}]),p.$inject=["validator","defaultErrorMessageResolver","bootstrap3ElementModifier","foundation5ElementModifier"],b.module("jcs-autoValidate").run(p)}(String,angular); |
@@ -26,3 +26,3 @@ (function (module) { | ||
jshint: { | ||
files: ['<%= srcfolder %>**/*.js', '<%= testsfolder %>**/*.spec.js'], | ||
files: ['<%= srcfolder %>**/*.js','!<%= srcfolder %>**/*-postfix.js', '!<%= srcfolder %>**/*-prefix.js', '<%= testsfolder %>**/*.spec.js'], | ||
options: { | ||
@@ -54,3 +54,3 @@ jshintrc: '.jshintrc' | ||
indentLevel: 0, | ||
indentSize: 4, | ||
indentSize: 2, | ||
indentWithTabs: false, | ||
@@ -156,3 +156,5 @@ jslintHappy: true, | ||
dist: { | ||
src: ['src/jcs-auto-validate.js', | ||
src: [ | ||
'src/jcs-auto-validate-prefix.js', | ||
'src/jcs-auto-validate.js', | ||
'src/providers/validator.js', | ||
@@ -169,3 +171,5 @@ 'src/services/bootstrap3ElementModifier.js', | ||
'src/config/ngModelDecorator.js', | ||
'src/jcs-auto-validate-run.js'], | ||
'src/jcs-auto-validate-run.js', | ||
'src/jcs-auto-validate-postfix.js' | ||
], | ||
dest: 'dist/jcs-auto-validate.js' | ||
@@ -182,3 +186,3 @@ } | ||
files: { | ||
'tests/reports/complexity': ['src/**/*.js'] | ||
'tests/reports/complexity': ['src/**/*.js', '!src/**/*-postfix.js', '!src/**/*-prefix.js'] | ||
} | ||
@@ -185,0 +189,0 @@ } |
{ | ||
"name": "angular-auto-validate", | ||
"version": "1.18.6", | ||
"version": "1.18.14", | ||
"description": "An automatic validation module for AngularJS which gets rid of excess html in favour of dynamic element modification to notify the user of validation errors", | ||
@@ -5,0 +5,0 @@ "main": "angular-auto-validate.min.js", |
@@ -1,138 +0,136 @@ | ||
(function (angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngModelDirective', [ | ||
'$timeout', | ||
'$delegate', | ||
'validationManager', | ||
'jcs-debounce', | ||
function ($timeout, $delegate, validationManager, debounce) { | ||
var directive = $delegate[0], | ||
link = directive.link || directive.compile; | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngModelDirective', [ | ||
'$timeout', | ||
'$delegate', | ||
'validationManager', | ||
'jcs-debounce', | ||
function ($timeout, $delegate, validationManager, debounce) { | ||
var directive = $delegate[0], | ||
link = directive.link || directive.compile; | ||
directive.compile = function (el) { | ||
var supportsNgModelOptions = angular.version.major >= 1 && angular.version.minor >= 3, | ||
originalLink = link; | ||
directive.compile = function (el) { | ||
return function (scope, element, attrs, ctrls) { | ||
var ngModelCtrl = ctrls[0], | ||
frmCtrl = ctrls[1], | ||
supportsNgModelOptions = angular.version.major >= 1 && angular.version.minor >= 3, | ||
ngModelOptions = attrs.ngModelOptions === undefined ? undefined : scope.$eval(attrs.ngModelOptions), | ||
setValidity = ngModelCtrl.$setValidity, | ||
setPristine = ngModelCtrl.$setPristine, | ||
setValidationState = debounce.debounce(function () { | ||
var validateOptions = frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : undefined; | ||
validationManager.validateElement(ngModelCtrl, element, validateOptions); | ||
}, 100); | ||
// in the RC of 1.3 there is no directive.link only the directive.compile which | ||
// needs to be invoked to get at the link functions. | ||
if (supportsNgModelOptions && angular.isFunction(link)) { | ||
originalLink = link(el); | ||
} | ||
// in the RC of 1.3 there is no directive.link only the directive.compile which | ||
// needs to be invoked to get at the link functions. | ||
if (supportsNgModelOptions && angular.isFunction(link)) { | ||
link = link(el); | ||
} | ||
return { | ||
pre: function (scope, element, attrs, ctrls) { | ||
var ngModelCtrl = ctrls[0], | ||
frmCtrl = ctrls[1], | ||
ngModelOptions = attrs.ngModelOptions === undefined ? undefined : scope.$eval(attrs.ngModelOptions), | ||
setValidity = ngModelCtrl.$setValidity, | ||
setPristine = ngModelCtrl.$setPristine, | ||
setValidationState = debounce.debounce(function () { | ||
var validateOptions = frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : undefined; | ||
validationManager.validateElement(ngModelCtrl, element, validateOptions); | ||
}, 100); | ||
if (link.pre) { | ||
link.pre.apply(this, arguments); | ||
ngModelOptions = ngModelCtrl.$options === undefined ? undefined : ngModelCtrl.$options; | ||
} | ||
if (attrs.formnovalidate === undefined && | ||
(frmCtrl !== undefined && frmCtrl !== null && frmCtrl.autoValidateFormOptions && | ||
frmCtrl.autoValidateFormOptions.disabled === false)) { | ||
if (supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions.updateOn === undefined || ngModelOptions.updateOn === '') { | ||
ngModelCtrl.$setValidity = function (validationErrorKey, isValid) { | ||
setValidity.call(ngModelCtrl, validationErrorKey, isValid); | ||
setValidationState(); | ||
}; | ||
} else { | ||
element.on(ngModelOptions.updateOn, function () { | ||
setValidationState(); | ||
}); | ||
if (attrs.formnovalidate === undefined && | ||
(frmCtrl !== undefined && frmCtrl !== null && frmCtrl.autoValidateFormOptions && | ||
frmCtrl.autoValidateFormOptions.disabled === false)) { | ||
if (supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions.updateOn === undefined || ngModelOptions.updateOn === '') { | ||
ngModelCtrl.$setValidity = function (validationErrorKey, isValid) { | ||
setValidity.call(ngModelCtrl, validationErrorKey, isValid); | ||
setValidationState(); | ||
}; | ||
} else { | ||
element.on(ngModelOptions.updateOn, function () { | ||
setValidationState(); | ||
}); | ||
scope.$on('$destroy', function () { | ||
element.off(ngModelOptions.updateOn); | ||
}); | ||
} | ||
scope.$on('$destroy', function () { | ||
element.off(ngModelOptions.updateOn); | ||
}); | ||
} | ||
// We override this so we can reset the element state when it is called. | ||
ngModelCtrl.$setPristine = function () { | ||
setPristine.call(ngModelCtrl); | ||
validationManager.resetElement(element); | ||
}; | ||
// We override this so we can reset the element state when it is called. | ||
ngModelCtrl.$setPristine = function () { | ||
setPristine.call(ngModelCtrl); | ||
validationManager.resetElement(element); | ||
}; | ||
ngModelCtrl.autoValidated = true; | ||
} | ||
ngModelCtrl.autoValidated = true; | ||
} | ||
ngModelCtrl.setExternalValidation = function (errorMsgKey, errorMessage, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = false; | ||
} | ||
if (link.post) { | ||
link.post.apply(this, arguments); | ||
} else { | ||
link.apply(this, arguments); | ||
} | ||
ngModelCtrl.externalErrors = ngModelCtrl.externalErrors || {}; | ||
ngModelCtrl.externalErrors[errorMsgKey] = false; | ||
validationManager.setElementValidationError(element, errorMsgKey, errorMessage); | ||
}; | ||
ngModelCtrl.setExternalValidation = function (errorMsgKey, errorMessage, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = false; | ||
} | ||
ngModelCtrl.removeExternalValidation = function (errorMsgKey, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
delete collection[errorMsgKey]; | ||
} | ||
ngModelCtrl.externalErrors = ngModelCtrl.externalErrors || {}; | ||
ngModelCtrl.externalErrors[errorMsgKey] = false; | ||
validationManager.setElementValidationError(element, errorMsgKey, errorMessage); | ||
}; | ||
if (ngModelCtrl.externalErrors) { | ||
delete ngModelCtrl.externalErrors[errorMsgKey]; | ||
} | ||
ngModelCtrl.removeExternalValidation = function (errorMsgKey, addToModelErrors) { | ||
if (addToModelErrors) { | ||
var collection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
collection[errorMsgKey] = true; | ||
} | ||
validationManager.resetElement(element); | ||
}; | ||
if (ngModelCtrl.externalErrors) { | ||
delete ngModelCtrl.externalErrors[errorMsgKey]; | ||
} | ||
ngModelCtrl.removeAllExternalValidation = function () { | ||
if (ngModelCtrl.externalErrors) { | ||
var errorCollection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
angular.forEach(ngModelCtrl.externalErrors, function (value, key) { | ||
delete errorCollection[key]; | ||
}); | ||
validationManager.resetElement(element); | ||
}; | ||
ngModelCtrl.externalErrors = {}; | ||
ngModelCtrl.removeAllExternalValidation = function () { | ||
if (ngModelCtrl.externalErrors) { | ||
var errorCollection = ngModelCtrl.$error || ngModelCtrl.$errors; | ||
angular.forEach(ngModelCtrl.externalErrors, function (value, key) { | ||
delete errorCollection[key]; | ||
}); | ||
validationManager.resetElement(element); | ||
} | ||
}; | ||
ngModelCtrl.externalErrors = {}; | ||
if (frmCtrl) { | ||
frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].setExternalValidation(errorMsgKey, errorMessageOverride, addToModelErrors); | ||
success = true; | ||
} | ||
validationManager.resetElement(element); | ||
} | ||
}; | ||
return success; | ||
}; | ||
if (frmCtrl) { | ||
frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].setExternalValidation(errorMsgKey, errorMessageOverride, addToModelErrors); | ||
success = true; | ||
} | ||
frmCtrl.removeExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].removeExternalValidation(errorMsgKey, addToModelErrors); | ||
success = true; | ||
} | ||
return success; | ||
}; | ||
return success; | ||
}; | ||
} | ||
frmCtrl.removeExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { | ||
var success = false; | ||
if (frmCtrl[modelProperty]) { | ||
frmCtrl[modelProperty].removeExternalValidation(errorMsgKey, addToModelErrors); | ||
success = true; | ||
} | ||
return originalLink.pre ? | ||
originalLink.pre.apply(this, arguments) : | ||
this; | ||
}, | ||
post: function (scope, element, attrs, ctrls) { | ||
return originalLink.post ? | ||
originalLink.post.apply(this, arguments) : | ||
originalLink.apply(this, arguments); | ||
} | ||
}; | ||
}; | ||
return success; | ||
}; | ||
} | ||
}; | ||
}; | ||
return $delegate; | ||
} | ||
]); | ||
} | ||
return $delegate; | ||
} | ||
]); | ||
}(angular)); | ||
} | ||
]); |
@@ -1,48 +0,78 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function SubmitDecorator($delegate, $parse, validationManager) { | ||
$delegate[0].compile = function ($element, attrs) { | ||
var fn = $parse(attrs.ngSubmit), | ||
force = attrs.ngSubmitForce === 'true'; | ||
angular.module('jcs-autoValidate').config(['$provide', | ||
function ($provide) { | ||
$provide.decorator('ngSubmitDirective', [ | ||
'$delegate', | ||
'$parse', | ||
'validationManager', | ||
function ($delegate, $parse, validationManager) { | ||
$delegate[0].compile = function ($element, attrs) { | ||
var fn = $parse(attrs.ngSubmit), | ||
force = attrs.ngSubmitForce === 'true'; | ||
return function (scope, element) { | ||
var formController = element.controller('form'), | ||
resetListenerOffFn; | ||
return function (scope, element) { | ||
function handlerFn(event) { | ||
scope.$apply(function () { | ||
var formController = $element.controller('form'); | ||
if (formController !== undefined && | ||
formController !== null && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} else { | ||
if (validationManager.validateForm(element) || force === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
function handlerFn(event) { | ||
scope.$apply(function () { | ||
if (formController !== undefined && | ||
formController !== null && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} else { | ||
if (formController.$setSubmitted === undefined) { | ||
// we probably have angular <= 1.2 | ||
formController.$submitted = true; | ||
} | ||
element.on('submit', handlerFn); | ||
scope.$on('$destroy', function () { | ||
element.off('submit', handlerFn); | ||
}); | ||
}; | ||
}; | ||
if (validationManager.validateForm(element) || force === true) { | ||
fn(scope, { | ||
$event: event | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
return $delegate; | ||
} | ||
]); | ||
function resetFormFn() { | ||
if (element[0].reset) { | ||
element[0].reset(); | ||
} else { | ||
validationManager.resetForm(element); | ||
} | ||
]); | ||
}(angular)); | ||
} | ||
if (formController && formController.autoValidateFormOptions) { | ||
// allow the form to be reset programatically or via raising the event | ||
// form:formName:reset | ||
formController.autoValidateFormOptions.resetForm = resetFormFn; | ||
if (formController.$name !== undefined && formController.$name !== '') { | ||
resetListenerOffFn = scope.$on('form:' + formController.$name + ':reset', resetFormFn); | ||
} | ||
} | ||
element.on('submit', handlerFn); | ||
scope.$on('$destroy', function () { | ||
element.off('submit', handlerFn); | ||
if (resetListenerOffFn) { | ||
resetListenerOffFn(); | ||
} | ||
}); | ||
}; | ||
}; | ||
return $delegate; | ||
} | ||
SubmitDecorator.$inject = [ | ||
'$delegate', | ||
'$parse', | ||
'validationManager' | ||
]; | ||
function ProviderFn($provide) { | ||
$provide.decorator('ngSubmitDirective', SubmitDecorator); | ||
} | ||
ProviderFn.$inject = [ | ||
'$provide' | ||
]; | ||
angular.module('jcs-autoValidate').config(ProviderFn); |
@@ -1,55 +0,61 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function parseBooleanAttributeValue(val, defaultValue) { | ||
if ((val === undefined || val === null) && defaultValue !== undefined) { | ||
return defaultValue; | ||
} else { | ||
return val !== 'false'; | ||
} | ||
} | ||
function parseBooleanAttributeValue(val) { | ||
return val !== undefined && val !== 'false'; | ||
} | ||
function parseOptions(ctrl, validator, attrs) { | ||
var opts = ctrl.autoValidateFormOptions = ctrl.autoValidateFormOptions || angular.copy(validator.defaultFormValidationOptions); | ||
opts.formController = ctrl; | ||
opts.forceValidation = false; | ||
opts.disabled = !validator.isEnabled() || parseBooleanAttributeValue(attrs.disableDynamicValidation, opts.disabled); | ||
opts.validateNonVisibleControls = parseBooleanAttributeValue(attrs.validateNonVisibleControls, opts.validateNonVisibleControls); | ||
opts.validateOnFormSubmit = parseBooleanAttributeValue(attrs.validateOnFormSubmit, opts.validateOnFormSubmit); | ||
opts.removeExternalValidationErrorsOnSubmit = attrs.removeExternalValidationErrorsOnSubmit === undefined ? | ||
opts.removeExternalValidationErrorsOnSubmit : | ||
parseBooleanAttributeValue(attrs.removeExternalValidationErrorsOnSubmit, opts.removeExternalValidationErrorsOnSubmit); | ||
function parseOptions(ctrl, validator, attrs) { | ||
var opts = ctrl.autoValidateFormOptions = ctrl.autoValidateFormOptions || angular.copy(validator.defaultFormValidationOptions); | ||
opts.forceValidation = false; | ||
opts.disabled = !validator.isEnabled() || parseBooleanAttributeValue(attrs.disableDynamicValidation); | ||
opts.validateNonVisibleControls = parseBooleanAttributeValue(attrs.validateNonVisibleControls); | ||
opts.removeExternalValidationErrorsOnSubmit = attrs.removeExternalValidationErrorsOnSubmit === undefined ? true : parseBooleanAttributeValue(attrs.removeExternalValidationErrorsOnSubmit); | ||
// the library might be globally disabled but enabled on a particular form so check the | ||
// disableDynamicValidation attribute is on the form | ||
if (validator.isEnabled() === false && attrs.disableDynamicValidation === 'false') { | ||
opts.disabled = false; | ||
} | ||
} | ||
if (validator.isEnabled() === false && parseBooleanAttributeValue(attrs.disableDynamicValidation) === false) { | ||
opts.disabled = false; | ||
} | ||
} | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'E', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'E', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
angular.module('jcs-autoValidate').directive('ngForm', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'EA', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').directive('ngForm', [ | ||
'validator', | ||
function (validator) { | ||
return { | ||
restrict: 'EA', | ||
require: 'form', | ||
priority: 9999, | ||
compile: function () { | ||
return { | ||
pre: function (scope, element, attrs, ctrl) { | ||
parseOptions(ctrl, validator, attrs); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
]); |
@@ -1,27 +0,35 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function FormResetDirectiveFn(validationManager) { | ||
return { | ||
restrict: 'E', | ||
link: function (scope, el) { | ||
var formController = el.controller('form'); | ||
angular.module('jcs-autoValidate').directive('form', [ | ||
'validationManager', | ||
function (validationManager) { | ||
return { | ||
restrict: 'E', | ||
link: function (scope, el) { | ||
var formController = el.controller('form'); | ||
function resetFn() { | ||
validationManager.resetForm(el); | ||
if (formController.$setPristine) { | ||
formController.$setPristine(); | ||
} | ||
if (formController !== undefined && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === false) { | ||
el.on('reset', function () { | ||
validationManager.resetForm(el); | ||
}); | ||
if (formController.$setUntouched) { | ||
formController.$setUntouched(); | ||
} | ||
} | ||
scope.$on('$destroy', function () { | ||
el.off('reset'); | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
if (formController !== undefined && | ||
formController.autoValidateFormOptions && | ||
formController.autoValidateFormOptions.disabled === false) { | ||
el.on('reset', resetFn); | ||
scope.$on('$destroy', function () { | ||
el.off('reset', resetFn); | ||
}); | ||
} | ||
} | ||
}; | ||
} | ||
FormResetDirectiveFn.$inject = [ | ||
'validationManager' | ||
]; | ||
angular.module('jcs-autoValidate').directive('form', FormResetDirectiveFn); |
@@ -1,31 +0,27 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function RegisterCustomFormControlFn() { | ||
var findParentForm = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 50; i += 1) { | ||
if (parent !== undefined && parent.nodeName.toLowerCase() === 'form') { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = angular.element(parent).parent()[0]; | ||
} | ||
} | ||
angular.module('jcs-autoValidate').directive('registerCustomFormControl', [ | ||
function () { | ||
var findParentForm = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 50; i += 1) { | ||
if (parent !== undefined && parent.nodeName.toLowerCase() === 'form') { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = angular.element(parent).parent()[0]; | ||
} | ||
} | ||
return parent; | ||
}; | ||
return parent; | ||
}; | ||
return { | ||
restrict: 'A', | ||
link: function (scope, element) { | ||
var frmEl = findParentForm(element.parent()[0]); | ||
if (frmEl) { | ||
frmEl.customHTMLFormControlsCollection = frmEl.customHTMLFormControlsCollection || []; | ||
frmEl.customHTMLFormControlsCollection.push(element[0]); | ||
} | ||
} | ||
}; | ||
} | ||
return { | ||
restrict: 'A', | ||
link: function (scope, element) { | ||
var frmEl = findParentForm(element.parent()[0]); | ||
if (frmEl) { | ||
frmEl.customHTMLFormControlsCollection = frmEl.customHTMLFormControlsCollection || []; | ||
frmEl.customHTMLFormControlsCollection.push(element[0]); | ||
} | ||
} | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').directive('registerCustomFormControl', RegisterCustomFormControlFn); |
@@ -1,17 +0,15 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function AutoValidateRunFn(validator, defaultErrorMessageResolver, bootstrap3ElementModifier, foundation5ElementModifier) { | ||
validator.setErrorMessageResolver(defaultErrorMessageResolver.resolve); | ||
validator.registerDomModifier(bootstrap3ElementModifier.key, bootstrap3ElementModifier); | ||
validator.registerDomModifier(foundation5ElementModifier.key, foundation5ElementModifier); | ||
validator.setDefaultElementModifier(bootstrap3ElementModifier.key); | ||
} | ||
angular.module('jcs-autoValidate') | ||
.run([ | ||
'validator', | ||
'defaultErrorMessageResolver', | ||
'bootstrap3ElementModifier', | ||
'foundation5ElementModifier', | ||
function (validator, defaultErrorMessageResolver, bootstrap3ElementModifier, foundation5ElementModifier) { | ||
validator.setErrorMessageResolver(defaultErrorMessageResolver.resolve); | ||
validator.registerDomModifier(bootstrap3ElementModifier.key, bootstrap3ElementModifier); | ||
validator.registerDomModifier(foundation5ElementModifier.key, foundation5ElementModifier); | ||
validator.setDefaultElementModifier(bootstrap3ElementModifier.key); | ||
} | ||
]); | ||
}(angular)); | ||
AutoValidateRunFn.$inject = [ | ||
'validator', | ||
'defaultErrorMessageResolver', | ||
'bootstrap3ElementModifier', | ||
'foundation5ElementModifier' | ||
]; | ||
angular.module('jcs-autoValidate').run(AutoValidateRunFn); |
@@ -1,5 +0,1 @@ | ||
(function (angular) { | ||
'use strict'; | ||
angular.module('jcs-autoValidate', []); | ||
}(angular)); | ||
angular.module('jcs-autoValidate', []); |
@@ -1,289 +0,285 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function ValidatorFn() { | ||
var elementStateModifiers = {}, | ||
enableValidElementStyling = true, | ||
enableInvalidElementStyling = true, | ||
validationEnabled = true, | ||
angular.module('jcs-autoValidate') | ||
.provider('validator', [ | ||
function () { | ||
var elementStateModifiers = {}, | ||
enableValidElementStyling = true, | ||
enableInvalidElementStyling = true, | ||
validationEnabled = true, | ||
toBoolean = function (value) { | ||
var v; | ||
if (value && value.length !== 0) { | ||
v = value.toLowerCase(); | ||
value = !(v === 'f' || v === '0' || v === 'false'); | ||
} else { | ||
value = false; | ||
} | ||
toBoolean = function (value) { | ||
var v; | ||
if (value && value.length !== 0) { | ||
v = value.toLowerCase(); | ||
value = !(v === 'f' || v === '0' || v === 'false'); | ||
} else { | ||
value = false; | ||
} | ||
return value; | ||
}, | ||
return value; | ||
}, | ||
getAttributeValue = function (el, attrName) { | ||
var val; | ||
getAttributeValue = function (el, attrName) { | ||
var val; | ||
if (el !== undefined) { | ||
val = el.attr(attrName) || el.attr('data-' + attrName); | ||
} | ||
if (el !== undefined) { | ||
val = el.attr(attrName) || el.attr('data-' + attrName); | ||
} | ||
return val; | ||
}, | ||
return val; | ||
}, | ||
attributeExists = function (el, attrName) { | ||
var exists; | ||
attributeExists = function (el, attrName) { | ||
var exists; | ||
if (el !== undefined) { | ||
exists = el.attr(attrName) !== undefined || el.attr('data-' + attrName) !== undefined; | ||
} | ||
if (el !== undefined) { | ||
exists = el.attr(attrName) !== undefined || el.attr('data-' + attrName) !== undefined; | ||
} | ||
return exists; | ||
}, | ||
return exists; | ||
}, | ||
getBooleanAttributeValue = function (el, attrName) { | ||
return toBoolean(getAttributeValue(el, attrName)); | ||
}, | ||
getBooleanAttributeValue = function (el, attrName) { | ||
return toBoolean(getAttributeValue(el, attrName)); | ||
}, | ||
validElementStylingEnabled = function (el) { | ||
return enableValidElementStyling && !getBooleanAttributeValue(el, 'disable-valid-styling'); | ||
}, | ||
validElementStylingEnabled = function (el) { | ||
return enableValidElementStyling && !getBooleanAttributeValue(el, 'disable-valid-styling'); | ||
}, | ||
invalidElementStylingEnabled = function (el) { | ||
return enableInvalidElementStyling && !getBooleanAttributeValue(el, 'disable-invalid-styling'); | ||
}; | ||
invalidElementStylingEnabled = function (el) { | ||
return enableInvalidElementStyling && !getBooleanAttributeValue(el, 'disable-invalid-styling'); | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#enable | ||
* @methodOf validator | ||
* | ||
* @description | ||
* By default auto validate will validate all forms and elements with an ngModel directive on. By | ||
* setting enabled to false you will explicitly have to opt in to enable validation on forms and child | ||
* elements. | ||
* | ||
* Note: this can be overridden by add the 'auto-validate-enabled="true/false' attribute to a form. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.enable(false); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {Boolean} isEnabled true to enable, false to disable. | ||
*/ | ||
this.enable = function (isEnabled) { | ||
validationEnabled = isEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#enable | ||
* @methodOf validator | ||
* | ||
* @description | ||
* By default auto validate will validate all forms and elements with an ngModel directive on. By | ||
* setting enabled to false you will explicitly have to opt in to enable validation on forms and child | ||
* elements. | ||
* | ||
* Note: this can be overridden by add the 'auto-validate-enabled="true/false' attribute to a form. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.enable(false); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {Boolean} isEnabled true to enable, false to disable. | ||
*/ | ||
this.enable = function (isEnabled) { | ||
validationEnabled = isEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#isEnabled | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Returns true if the library is enabeld. | ||
* | ||
* @return {Boolean} true if enabled, otherwise false. | ||
*/ | ||
this.isEnabled = function () { | ||
return validationEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#isEnabled | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Returns true if the library is enabeld. | ||
* | ||
* @return {Boolean} true if enabled, otherwise false. | ||
*/ | ||
this.isEnabled = function () { | ||
return validationEnabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setDefaultElementModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Sets the default element modifier that will be used by the validator | ||
* to change an elements UI state. Please ensure the modifier has been registered | ||
* before setting it as default. | ||
* | ||
* Note: this can be changed by setting the | ||
* element modifier attribute on the input element 'data-element-modifier="myCustomModifier"' | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setDefaultElementModifier('myCustomModifier'); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier. | ||
*/ | ||
this.setDefaultElementModifier = function (key) { | ||
if (elementStateModifiers[key] === undefined) { | ||
throw new Error('Element modifier not registered: ' + key); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name validator#setDefaultElementModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Sets the default element modifier that will be used by the validator | ||
* to change an elements UI state. Please ensure the modifier has been registered | ||
* before setting it as default. | ||
* | ||
* Note: this can be changed by setting the | ||
* element modifier attribute on the input element 'data-element-modifier="myCustomModifier"' | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setDefaultElementModifier('myCustomModifier'); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier. | ||
*/ | ||
this.setDefaultElementModifier = function (key) { | ||
if (elementStateModifiers[key] === undefined) { | ||
throw new Error('Element modifier not registered: ' + key); | ||
} | ||
this.defaultElementModifier = key; | ||
}; | ||
this.defaultElementModifier = key; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#registerDomModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.registerDomModifier('customDomModifier', { | ||
* makeValid: function (el) { | ||
* el.removeClass(el, 'invalid'); | ||
* el.addClass(el, 'valid'); | ||
* }, | ||
* makeInvalid: function (el, err, domManipulator) { | ||
* el.removeClass(el, 'valid'); | ||
* el.addClass(el, 'invalid'); | ||
* } | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier | ||
* @param {object} modifier An object which implements the elementModifier interface | ||
*/ | ||
this.registerDomModifier = function (key, modifier) { | ||
elementStateModifiers[key] = modifier; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#registerDomModifier | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.registerDomModifier('customDomModifier', { | ||
* makeValid: function (el) { | ||
* el.removeClass(el, 'invalid'); | ||
* el.addClass(el, 'valid'); | ||
* }, | ||
* makeInvalid: function (el, err, domManipulator) { | ||
* el.removeClass(el, 'valid'); | ||
* el.addClass(el, 'invalid'); | ||
* } | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {string} key The key name of the modifier | ||
* @param {object} modifier An object which implements the elementModifier interface | ||
*/ | ||
this.registerDomModifier = function (key, modifier) { | ||
elementStateModifiers[key] = modifier; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setErrorMessageResolver | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setErrorMessageResolver(function (errorKey, el) { | ||
* var defer = $q.defer(); | ||
* // resolve the correct error from the given key and resolve the returned promise. | ||
* return defer.promise(); | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {function} resolver A method that returns a promise with the resolved error message in. | ||
*/ | ||
this.setErrorMessageResolver = function (resolver) { | ||
this.errorMessageResolver = resolver; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setErrorMessageResolver | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Registers an object that adheres to the elementModifier interface and is | ||
* able to modifier an elements dom so that appears valid / invalid for a specific | ||
* scenario i.e. the Twitter Bootstrap css framework, Foundation CSS framework etc. | ||
* | ||
* Example: | ||
* <pre> | ||
* app.config(function (validator) { | ||
* validator.setErrorMessageResolver(function (errorKey, el) { | ||
* var defer = $q.defer(); | ||
* // resolve the correct error from the given key and resolve the returned promise. | ||
* return defer.promise(); | ||
* }); | ||
* }); | ||
* </pre> | ||
* | ||
* @param {function} resolver A method that returns a promise with the resolved error message in. | ||
*/ | ||
this.setErrorMessageResolver = function (resolver) { | ||
this.errorMessageResolver = resolver; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#getErrorMessage | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Resolves the error message for the given error type. | ||
* | ||
* @param {String} errorKey The error type. | ||
* @param {Element} el The UI element that is the focus of the error. | ||
* It is provided as the error message may need information from the element i.e. ng-min (the min allowed value). | ||
*/ | ||
this.getErrorMessage = function (errorKey, el) { | ||
var defer; | ||
if (this.errorMessageResolver === undefined) { | ||
throw new Error('Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name validator#getErrorMessage | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Resolves the error message for the given error type. | ||
* | ||
* @param {String} errorKey The error type. | ||
* @param {Element} el The UI element that is the focus of the error. | ||
* It is provided as the error message may need information from the element i.e. ng-min (the min allowed value). | ||
*/ | ||
this.getErrorMessage = function (errorKey, el) { | ||
var defer; | ||
if (this.errorMessageResolver === undefined) { | ||
throw new Error('Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
} | ||
if (attributeExists(el, 'disable-validation-message')) { | ||
defer = angular.injector(['ng']).get('$q').defer(); | ||
defer.resolve(''); | ||
return defer.promise; | ||
} else { | ||
return this.errorMessageResolver(errorKey, el); | ||
} | ||
}; | ||
if (attributeExists(el, 'disable-validation-message')) { | ||
defer = angular.injector(['ng']).get('$q').defer(); | ||
defer.resolve(''); | ||
return defer.promise; | ||
} else { | ||
return this.errorMessageResolver(errorKey, el); | ||
} | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setValidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables valid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setValidElementStyling = function (enabled) { | ||
enableValidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setValidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables valid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setValidElementStyling = function (enabled) { | ||
enableValidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setInvalidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables invalid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setInvalidElementStyling = function (enabled) { | ||
enableInvalidElementStyling = enabled; | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name validator#setInvalidElementStyling | ||
* @methodOf validator | ||
* | ||
* @description | ||
* Globally enables invalid element visual styling. This is enabled by default. | ||
* | ||
* @param {Boolean} enabled True to enable style otherwise false. | ||
*/ | ||
this.setInvalidElementStyling = function (enabled) { | ||
enableInvalidElementStyling = enabled; | ||
}; | ||
this.getDomModifier = function (el) { | ||
var modifierKey = (el !== undefined ? el.attr('element-modifier') : this.defaultElementModifier) || | ||
(el !== undefined ? el.attr('data-element-modifier') : this.defaultElementModifier) || | ||
this.defaultElementModifier; | ||
this.getDomModifier = function (el) { | ||
var modifierKey = (el !== undefined ? el.attr('element-modifier') : this.defaultElementModifier) || | ||
(el !== undefined ? el.attr('data-element-modifier') : this.defaultElementModifier) || | ||
this.defaultElementModifier; | ||
if (modifierKey === undefined) { | ||
throw new Error('Please set a default dom modifier via the setDefaultElementModifier method on the validator class.'); | ||
} | ||
if (modifierKey === undefined) { | ||
throw new Error('Please set a default dom modifier via the setDefaultElementModifier method on the validator class.'); | ||
} | ||
return elementStateModifiers[modifierKey]; | ||
}; | ||
return elementStateModifiers[modifierKey]; | ||
}; | ||
this.makeValid = function (el) { | ||
if (validElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeValid(el); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeValid = function (el) { | ||
if (validElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeValid(el); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeInvalid = function (el, errorMsg) { | ||
if (invalidElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeInvalid(el, errorMsg); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeInvalid = function (el, errorMsg) { | ||
if (invalidElementStylingEnabled(el)) { | ||
this.getDomModifier(el).makeInvalid(el, errorMsg); | ||
} else { | ||
this.makeDefault(el); | ||
} | ||
}; | ||
this.makeDefault = function (el) { | ||
var dm = this.getDomModifier(el); | ||
if (dm.makeDefault) { | ||
dm.makeDefault(el); | ||
} | ||
}; | ||
this.makeDefault = function (el) { | ||
var dm = this.getDomModifier(el); | ||
if (dm.makeDefault) { | ||
dm.makeDefault(el); | ||
} | ||
}; | ||
this.defaultFormValidationOptions = { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false, | ||
removeExternalValidationErrorsOnSubmit: true, | ||
validateOnFormSubmit: false | ||
}; | ||
this.defaultFormValidationOptions = { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false, | ||
removeExternalValidationErrorsOnSubmit: true | ||
}; | ||
this.$get = [ | ||
function () { | ||
return this; | ||
} | ||
]; | ||
} | ||
this.$get = [ | ||
function () { | ||
return this; | ||
} | ||
]; | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').provider('validator', ValidatorFn); |
@@ -1,183 +0,181 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function Bootstrap3ElementModifierFn($log) { | ||
var reset = function (el) { | ||
angular.forEach(el.find('span'), function (spanEl) { | ||
spanEl = angular.element(spanEl); | ||
if (spanEl.hasClass('error-msg') || spanEl.hasClass('form-control-feedback') || spanEl.hasClass('control-feedback')) { | ||
spanEl.remove(); | ||
} | ||
}); | ||
angular.module('jcs-autoValidate') | ||
.factory('bootstrap3ElementModifier', [ | ||
'$log', | ||
function ($log) { | ||
var reset = function (el) { | ||
angular.forEach(el.find('span'), function (spanEl) { | ||
spanEl = angular.element(spanEl); | ||
if (spanEl.hasClass('error-msg') || spanEl.hasClass('form-control-feedback') || spanEl.hasClass('control-feedback')) { | ||
spanEl.remove(); | ||
} | ||
}); | ||
el.removeClass('has-success has-error has-feedback'); | ||
}, | ||
findWithClassElementAsc = function (el, klass) { | ||
var returnEl, | ||
parent = el; | ||
for (var i = 0; i <= 10; i += 1) { | ||
if (parent !== undefined && parent.hasClass(klass)) { | ||
returnEl = parent; | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
el.removeClass('has-success has-error has-feedback'); | ||
}, | ||
findWithClassElementAsc = function (el, klass) { | ||
var returnEl, | ||
parent = el; | ||
for (var i = 0; i <= 10; i += 1) { | ||
if (parent !== undefined && parent.hasClass(klass)) { | ||
returnEl = parent; | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
return returnEl; | ||
}, | ||
return returnEl; | ||
}, | ||
findWithClassElementDesc = function (el, klass) { | ||
var child; | ||
for (var i = 0; i < el.children.length; i += 1) { | ||
child = el.children[i]; | ||
if (child !== undefined && angular.element(child).hasClass(klass)) { | ||
break; | ||
} else if (child.children !== undefined) { | ||
child = findWithClassElementDesc(child, klass); | ||
if (child.length > 0) { | ||
break; | ||
} | ||
} | ||
} | ||
findWithClassElementDesc = function (el, klass) { | ||
var child; | ||
for (var i = 0; i < el.children.length; i += 1) { | ||
child = el.children[i]; | ||
if (child !== undefined && angular.element(child).hasClass(klass)) { | ||
break; | ||
} else if (child.children !== undefined) { | ||
child = findWithClassElementDesc(child, klass); | ||
if (child.length > 0) { | ||
break; | ||
} | ||
} | ||
} | ||
return angular.element(child); | ||
}, | ||
return angular.element(child); | ||
}, | ||
findFormGroupElement = function (el) { | ||
return findWithClassElementAsc(el, 'form-group'); | ||
}, | ||
findFormGroupElement = function (el) { | ||
return findWithClassElementAsc(el, 'form-group'); | ||
}, | ||
findInputGroupElement = function (el) { | ||
return findWithClassElementDesc(el, 'input-group'); | ||
}, | ||
findInputGroupElement = function (el) { | ||
return findWithClassElementDesc(el, 'input-group'); | ||
}, | ||
insertAfter = function (referenceNode, newNode) { | ||
referenceNode[0].parentNode.insertBefore(newNode[0], referenceNode[0].nextSibling); | ||
}, | ||
insertAfter = function (referenceNode, newNode) { | ||
referenceNode[0].parentNode.insertBefore(newNode[0], referenceNode[0].nextSibling); | ||
}, | ||
/** | ||
* @ngdoc property | ||
* @name bootstrap3ElementModifier#addValidationStateIcons | ||
* @propertyOf bootstrap3ElementModifier | ||
* @returns {bool} True if an state icon will be added to the element in the valid and invalid control | ||
* states. The default is false. | ||
*/ | ||
addValidationStateIcons = false, | ||
/** | ||
* @ngdoc property | ||
* @name bootstrap3ElementModifier#addValidationStateIcons | ||
* @propertyOf bootstrap3ElementModifier | ||
* @returns {bool} True if an state icon will be added to the element in the valid and invalid control | ||
* states. The default is false. | ||
*/ | ||
addValidationStateIcons = false, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#enableValidationStateIcons | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply an icon to the input element. | ||
* | ||
* @param {bool} enable - True to enable the icon otherwise false. | ||
*/ | ||
enableValidationStateIcons = function (enable) { | ||
addValidationStateIcons = enable; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#enableValidationStateIcons | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply an icon to the input element. | ||
* | ||
* @param {bool} enable - True to enable the icon otherwise false. | ||
*/ | ||
enableValidationStateIcons = function (enable) { | ||
addValidationStateIcons = enable; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeValid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
inputGroupEl; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeValid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
inputGroupEl; | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeInvalid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'), | ||
inputGroupEl; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeInvalid | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply bootstrap 3 specific styles and child elements. If the service | ||
* property 'addValidationStateIcons' is true it will also append validation glyphicon to the element. | ||
* See: http://getbootstrap.com/css/#forms-control-validation | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var frmGroupEl = findFormGroupElement(el), | ||
helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'), | ||
inputGroupEl; | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
inputGroupEl = findInputGroupElement(frmGroupEl[0]); | ||
frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); | ||
insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); | ||
if (addValidationStateIcons) { | ||
var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; | ||
if (inputGroupEl.length > 0) { | ||
iconElText = iconElText.replace('form-', ''); | ||
iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; | ||
} | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
insertAfter(el, angular.element(iconElText)); | ||
} | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeDefault | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply bootstrap 3 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
var frmGroupEl = findFormGroupElement(el); | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name bootstrap3ElementModifier#makeDefault | ||
* @methodOf bootstrap3ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply bootstrap 3 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
var frmGroupEl = findFormGroupElement(el); | ||
if (frmGroupEl) { | ||
reset(frmGroupEl); | ||
} else { | ||
$log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); | ||
} | ||
}; | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
enableValidationStateIcons: enableValidationStateIcons, | ||
key: 'bs3' | ||
}; | ||
} | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
enableValidationStateIcons: enableValidationStateIcons, | ||
key: 'bs3' | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
Bootstrap3ElementModifierFn.$inject = [ | ||
'$log' | ||
]; | ||
angular.module('jcs-autoValidate').factory('bootstrap3ElementModifier', Bootstrap3ElementModifierFn); |
@@ -1,35 +0,34 @@ | ||
(function (angular) { | ||
'use strict'; | ||
/* | ||
* Taken from https://github.com/angular/angular.js/issues/2690#issue-14462164 (with added tests of course!) | ||
*/ | ||
function JCSDebounceFn($timeout) { | ||
var debounce = function (fn, timeout, apply) { | ||
timeout = angular.isUndefined(timeout) ? 0 : timeout; | ||
apply = angular.isUndefined(apply) ? true : apply; // !!default is true! most suitable to my experience | ||
var nthCall = 0; | ||
return function () { // intercepting fn | ||
var that = this; | ||
var argz = arguments; | ||
nthCall += 1; | ||
var later = (function (version) { | ||
return function () { | ||
if (version === nthCall) { | ||
return fn.apply(that, argz); | ||
} | ||
}; | ||
})(nthCall); | ||
/* | ||
* Taken from https://github.com/angular/angular.js/issues/2690#issue-14462164 (with added tests of course!) | ||
*/ | ||
angular.module('jcs-autoValidate').factory('jcs-debounce', [ | ||
'$timeout', | ||
function ($timeout) { | ||
var debounce = function (fn, timeout, apply) { | ||
timeout = angular.isUndefined(timeout) ? 0 : timeout; | ||
apply = angular.isUndefined(apply) ? true : apply; // !!default is true! most suitable to my experience | ||
var nthCall = 0; | ||
return function () { // intercepting fn | ||
var that = this; | ||
var argz = arguments; | ||
nthCall += 1; | ||
var later = (function (version) { | ||
return function () { | ||
if (version === nthCall) { | ||
return fn.apply(that, argz); | ||
} | ||
}; | ||
})(nthCall); | ||
return $timeout(later, timeout, apply); | ||
}; | ||
}; | ||
return $timeout(later, timeout, apply); | ||
}; | ||
}; | ||
return { | ||
debounce: debounce | ||
}; | ||
} | ||
return { | ||
debounce: debounce | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
JCSDebounceFn.$inject = [ | ||
'$timeout' | ||
]; | ||
angular.module('jcs-autoValidate').factory('jcs-debounce', JCSDebounceFn); |
@@ -1,202 +0,200 @@ | ||
(function (String, angular) { | ||
'use strict'; | ||
/** | ||
* Replaces string placeholders with corresponding template string | ||
*/ | ||
if (!('format' in String.prototype)) { | ||
String.prototype.format = function () { | ||
var args = arguments; | ||
return this.replace(/{(\d+)}/g, function (match, number) { | ||
return typeof args[number] !== undefined ? args[number] : match; | ||
}); | ||
}; | ||
} | ||
/** | ||
* Replaces string placeholders with corresponding template string | ||
*/ | ||
if (!('format' in String.prototype)) { | ||
String.prototype.format = function () { | ||
var args = arguments; | ||
return this.replace(/{(\d+)}/g, function (match, number) { | ||
return typeof args[number] !== undefined ? args[number] : match; | ||
}); | ||
}; | ||
} | ||
angular.autoValidate = angular.autoValidate || { | ||
errorMessages: {} | ||
}; | ||
angular.autoValidate = angular.autoValidate || { | ||
errorMessages: {} | ||
}; | ||
angular.autoValidate.errorMessages['en-us'] = angular.autoValidate.errorMessages['en-gb'] = { | ||
defaultMsg: 'Please add error message for {0}', | ||
email: 'Please enter a valid email address', | ||
minlength: 'Please enter at least {0} characters', | ||
maxlength: 'You have entered more than the maximum {0} characters', | ||
min: 'Please enter the minimum number of {0}', | ||
max: 'Please enter the maximum number of {0}', | ||
required: 'This field is required', | ||
date: 'Please enter a valid date', | ||
pattern: 'Please ensure the entered information adheres to this pattern {0}', | ||
number: 'Please enter a valid number', | ||
url: 'Please enter a valid URL in the format of http(s)://www.google.com' | ||
}; | ||
angular.autoValidate.errorMessages['en-us'] = angular.autoValidate.errorMessages['en-gb'] = { | ||
defaultMsg: 'Please add error message for {0}', | ||
email: 'Please enter a valid email address', | ||
minlength: 'Please enter at least {0} characters', | ||
maxlength: 'You have entered more than the maximum {0} characters', | ||
min: 'Please enter the minimum number of {0}', | ||
max: 'Please enter the maximum number of {0}', | ||
required: 'This field is required', | ||
date: 'Please enter a valid date', | ||
pattern: 'Please ensure the entered information adheres to this pattern {0}', | ||
number: 'Please enter a valid number', | ||
url: 'Please enter a valid URL in the format of http(s)://www.google.com' | ||
}; | ||
function DefaultErrorMessageResolverFn($q, $http) { | ||
var currentCulture = 'en-gb', | ||
angular.module('jcs-autoValidate') | ||
.factory('defaultErrorMessageResolver', [ | ||
'$q', | ||
'$http', | ||
function ($q, $http) { | ||
var currentCulture = 'en-gb', | ||
i18nFileRootPath = 'js/angular-auto-validate/dist/lang', | ||
i18nFileRootPath = 'js/angular-auto-validate/dist/lang', | ||
cultureRetrievalPromise, | ||
cultureRetrievalPromise, | ||
loadRemoteCulture = function (culture) { | ||
cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase())); | ||
return cultureRetrievalPromise; | ||
}, | ||
loadRemoteCulture = function (culture) { | ||
cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase())); | ||
return cultureRetrievalPromise; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setI18nFileRootPath | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the root path to the il8n files on the server | ||
* | ||
* @param {String} rootPath - The root path on the server to the il8n file - this defaults | ||
* to 'js/angular-auto-validate/lang/' | ||
*/ | ||
setI18nFileRootPath = function (rootPath) { | ||
i18nFileRootPath = rootPath; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setI18nFileRootPath | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the root path to the il8n files on the server | ||
* | ||
* @param {String} rootPath - The root path on the server to the il8n file - this defaults | ||
* to 'js/angular-auto-validate/lang/' | ||
*/ | ||
setI18nFileRootPath = function (rootPath) { | ||
i18nFileRootPath = rootPath; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setCulture | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the culture for the error messages by loading an the correct culture resource file. | ||
* | ||
* @param {String} culture - The new culture in the format of 'en-gb' etc. | ||
* @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should | ||
* return a promise which is resolved with the culture errorMessage object. If a function is not specified | ||
* the culture file is loaded from the **i18nFileRootPath**. | ||
* @returns {Promise} - A promise which is resolved with the loaded culture error messages object. | ||
*/ | ||
setCulture = function (culture, cultureLoadingFn) { | ||
var defer = $q.defer(); | ||
cultureLoadingFn = cultureLoadingFn || loadRemoteCulture; | ||
currentCulture = culture.toLowerCase(); | ||
if (angular.autoValidate.errorMessages[currentCulture] === undefined) { | ||
cultureRetrievalPromise = cultureLoadingFn(culture); | ||
cultureRetrievalPromise.then(function (response) { | ||
cultureRetrievalPromise = undefined; | ||
angular.autoValidate.errorMessages[currentCulture] = response.data; | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
}, function (err) { | ||
angular.autoValidate.errorMessages[currentCulture] = { | ||
defaultMsg: 'Loading culture failed!' | ||
}; | ||
cultureRetrievalPromise = null; | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#setCulture | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Set the culture for the error messages by loading an the correct culture resource file. | ||
* | ||
* @param {String} culture - The new culture in the format of 'en-gb' etc. | ||
* @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should | ||
* return a promise which is resolved with the culture errorMessage object. If a function is not specified | ||
* the culture file is loaded from the **i18nFileRootPath**. | ||
* @returns {Promise} - A promise which is resolved with the loaded culture error messages object. | ||
*/ | ||
setCulture = function (culture, cultureLoadingFn) { | ||
var defer = $q.defer(); | ||
cultureLoadingFn = cultureLoadingFn || loadRemoteCulture; | ||
currentCulture = culture.toLowerCase(); | ||
if (angular.autoValidate.errorMessages[currentCulture] === undefined) { | ||
cultureRetrievalPromise = cultureLoadingFn(culture); | ||
cultureRetrievalPromise.then(function (response) { | ||
cultureRetrievalPromise = undefined; | ||
angular.autoValidate.errorMessages[currentCulture] = response.data; | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
}, function (err) { | ||
angular.autoValidate.errorMessages[currentCulture] = { | ||
defaultMsg: 'Loading culture failed!' | ||
}; | ||
cultureRetrievalPromise = null; | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[currentCulture]); | ||
} | ||
return defer.promise; | ||
}, | ||
return defer.promise; | ||
}, | ||
getErrorMessages = function (culture) { | ||
var defer = $q.defer(); | ||
culture = culture === undefined ? currentCulture : culture.toLowerCase(); | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
}, function (err) { | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
} | ||
return defer.promise; | ||
}, | ||
getErrorMessages = function (culture) { | ||
var defer = $q.defer(); | ||
culture = culture === undefined ? currentCulture : culture.toLowerCase(); | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
}, function (err) { | ||
defer.reject(err); | ||
}); | ||
} else { | ||
defer.resolve(angular.autoValidate.errorMessages[culture]); | ||
} | ||
return defer.promise; | ||
}, | ||
getMessageTypeOverride = function (errorType, el) { | ||
var overrideKey; | ||
getMessageTypeOverride = function (errorType, el) { | ||
var overrideKey; | ||
if (el) { | ||
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey" | ||
errorType += '-err-type'; | ||
if (el) { | ||
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey" | ||
errorType += '-err-type'; | ||
overrideKey = el.attr('ng-' + errorType); | ||
if (overrideKey === undefined) { | ||
overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
overrideKey = el.attr('ng-' + errorType); | ||
if (overrideKey === undefined) { | ||
overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
if (overrideKey) { | ||
overrideKey = overrideKey.replace(/[\W]/g, ''); | ||
} | ||
} | ||
if (overrideKey) { | ||
overrideKey = overrideKey.replace(/[\W]/g, ''); | ||
} | ||
} | ||
return overrideKey; | ||
}, | ||
return overrideKey; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#resolve | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Resolves a validate error type into a user validation error message | ||
* | ||
* @param {String} errorType - The type of validation error that has occurred. | ||
* @param {Element} el - The input element that is the source of the validation error. | ||
* @returns {Promise} A promise that is resolved when the validation message has been produced. | ||
*/ | ||
resolve = function (errorType, el) { | ||
var defer = $q.defer(), | ||
errMsg, | ||
parameters = [], | ||
parameter, | ||
messageTypeOverride; | ||
/** | ||
* @ngdoc function | ||
* @name defaultErrorMessageResolver#resolve | ||
* @methodOf defaultErrorMessageResolver | ||
* | ||
* @description | ||
* Resolves a validate error type into a user validation error message | ||
* | ||
* @param {String} errorType - The type of validation error that has occurred. | ||
* @param {Element} el - The input element that is the source of the validation error. | ||
* @returns {Promise} A promise that is resolved when the validation message has been produced. | ||
*/ | ||
resolve = function (errorType, el) { | ||
var defer = $q.defer(), | ||
errMsg, | ||
parameters = [], | ||
parameter, | ||
messageTypeOverride; | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
resolve(errorType, el).then(function (msg) { | ||
defer.resolve(msg); | ||
}); | ||
}); | ||
} else { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][errorType]; | ||
messageTypeOverride = getMessageTypeOverride(errorType, el); | ||
if (messageTypeOverride) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride]; | ||
} | ||
if (cultureRetrievalPromise !== undefined) { | ||
cultureRetrievalPromise.then(function () { | ||
resolve(errorType, el).then(function (msg) { | ||
defer.resolve(msg); | ||
}); | ||
}); | ||
} else { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][errorType]; | ||
messageTypeOverride = getMessageTypeOverride(errorType, el); | ||
if (messageTypeOverride) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride]; | ||
} | ||
if (errMsg === undefined) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType); | ||
} | ||
if (errMsg === undefined) { | ||
errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType); | ||
} | ||
if (el && el.attr) { | ||
try { | ||
parameter = el.attr('ng-' + errorType); | ||
if (parameter === undefined) { | ||
parameter = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
if (el && el.attr) { | ||
try { | ||
parameter = el.attr('ng-' + errorType); | ||
if (parameter === undefined) { | ||
parameter = el.attr('data-ng-' + errorType) || el.attr(errorType); | ||
} | ||
parameters.push(parameter || ''); | ||
parameters.push(parameter || ''); | ||
errMsg = errMsg.format(parameters); | ||
} catch (e) {} | ||
} | ||
errMsg = errMsg.format(parameters); | ||
} catch (e) {} | ||
} | ||
defer.resolve(errMsg); | ||
} | ||
defer.resolve(errMsg); | ||
} | ||
return defer.promise; | ||
}; | ||
return defer.promise; | ||
}; | ||
return { | ||
setI18nFileRootPath: setI18nFileRootPath, | ||
setCulture: setCulture, | ||
getErrorMessages: getErrorMessages, | ||
resolve: resolve | ||
}; | ||
} | ||
return { | ||
setI18nFileRootPath: setI18nFileRootPath, | ||
setCulture: setCulture, | ||
getErrorMessages: getErrorMessages, | ||
resolve: resolve | ||
}; | ||
} | ||
]); | ||
}(String, angular)); | ||
DefaultErrorMessageResolverFn.$inject = [ | ||
'$q', | ||
'$http' | ||
]; | ||
angular.module('jcs-autoValidate').factory('defaultErrorMessageResolver', DefaultErrorMessageResolverFn); |
@@ -1,90 +0,84 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function Foundation5ElementModifierFn() { | ||
var reset = function (el, inputEl) { | ||
angular.forEach(el.find('small'), function (smallEl) { | ||
if (angular.element(smallEl).hasClass('error')) { | ||
angular.element(smallEl).remove(); | ||
} | ||
}); | ||
angular.module('jcs-autoValidate') | ||
.factory('foundation5ElementModifier', [ | ||
inputEl.removeClass('error'); | ||
}, | ||
findParentColumn = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 3; i += 1) { | ||
if (parent !== undefined && parent.hasClass('columns')) { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
function () { | ||
var reset = function (el, inputEl) { | ||
angular.forEach(el.find('small'), function (smallEl) { | ||
if (angular.element(smallEl).hasClass('error')) { | ||
angular.element(smallEl).remove(); | ||
} | ||
}); | ||
return parent; | ||
}, | ||
inputEl.removeClass('error'); | ||
}, | ||
findParentColumn = function (el) { | ||
var parent = el; | ||
for (var i = 0; i <= 3; i += 1) { | ||
if (parent !== undefined && parent.hasClass('columns')) { | ||
break; | ||
} else if (parent !== undefined) { | ||
parent = parent.parent(); | ||
} | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeValid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var parentColumn = findParentColumn(el); | ||
reset(parentColumn && parentColumn.length > 0 ? parentColumn : el, el); | ||
}, | ||
return parent; | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeInvalid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var parentColumn = findParentColumn(el), | ||
helpTextEl; | ||
reset(parentColumn || el, el); | ||
el.addClass('error'); | ||
if (parentColumn) { | ||
helpTextEl = angular.element('<small class="error">' + errorMsg + '</small>'); | ||
parentColumn.append(helpTextEl); | ||
} | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeValid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear valid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeValid = function (el) { | ||
var parentColumn = findParentColumn(el); | ||
reset(parentColumn && parentColumn.length > 0 ? parentColumn : el, el); | ||
}, | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeDefault | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply foundation 5 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
makeValid(el); | ||
}; | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeInvalid | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear invalid by apply Foundation 5 specific styles and child elements. | ||
* See: http://foundation.zurb.com/docs/components/forms.html | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeInvalid = function (el, errorMsg) { | ||
var parentColumn = findParentColumn(el), | ||
helpTextEl; | ||
reset(parentColumn || el, el); | ||
el.addClass('error'); | ||
if (parentColumn) { | ||
helpTextEl = angular.element('<small class="error">' + errorMsg + '</small>'); | ||
parentColumn.append(helpTextEl); | ||
} | ||
}, | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
key: 'foundation5' | ||
}; | ||
} | ||
/** | ||
* @ngdoc function | ||
* @name foundation5ElementModifier#makeDefault | ||
* @methodOf foundation5ElementModifier | ||
* | ||
* @description | ||
* Makes an element appear in its default visual state by apply foundation 5 specific styles and child elements. | ||
* | ||
* @param {Element} el - The input control element that is the target of the validation. | ||
*/ | ||
makeDefault = function (el) { | ||
makeValid(el); | ||
}; | ||
return { | ||
makeValid: makeValid, | ||
makeInvalid: makeInvalid, | ||
makeDefault: makeDefault, | ||
key: 'foundation5' | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
angular.module('jcs-autoValidate').factory('foundation5ElementModifier', Foundation5ElementModifierFn); |
@@ -1,209 +0,229 @@ | ||
(function (angular) { | ||
'use strict'; | ||
function ElementUtilsFn() { | ||
var isElementVisible = function (el) { | ||
return el[0].offsetWidth > 0 && el[0].offsetHeight > 0; | ||
}; | ||
angular.module('jcs-autoValidate') | ||
.factory('jcs-elementUtils', [ | ||
function () { | ||
var isElementVisible = function (el) { | ||
return el[0].offsetWidth > 0 && el[0].offsetHeight > 0; | ||
}; | ||
return { | ||
isElementVisible: isElementVisible | ||
}; | ||
} | ||
return { | ||
isElementVisible: isElementVisible | ||
}; | ||
} | ||
]); | ||
function ValidationManagerFn(validator, elementUtils) { | ||
var elementTypesToValidate = ['input', 'textarea', 'select', 'form'], | ||
angular.module('jcs-autoValidate') | ||
.factory('validationManager', [ | ||
'validator', | ||
'jcs-elementUtils', | ||
function (validator, elementUtils) { | ||
var elementTypesToValidate = ['input', 'textarea', 'select', 'form'], | ||
elementIsVisible = function (el) { | ||
return elementUtils.isElementVisible(el); | ||
}, | ||
elementIsVisible = function (el) { | ||
return elementUtils.isElementVisible(el); | ||
}, | ||
getFormOptions = function (el) { | ||
var frmCtrl = angular.element(el).controller('form'), | ||
options; | ||
getFormOptions = function (el) { | ||
var frmCtrl = angular.element(el).controller('form'); | ||
return frmCtrl !== undefined && frmCtrl !== null ? frmCtrl.autoValidateFormOptions : validator.defaultFormValidationOptions; | ||
}, | ||
if (frmCtrl !== undefined && frmCtrl !== null) { | ||
options = frmCtrl.autoValidateFormOptions; | ||
} else { | ||
options = validator.defaultFormValidationOptions; | ||
} | ||
/** | ||
* Only validate if the element is present, it is visible | ||
* it is either a valid user input control (input, select, textare, form) or | ||
* it is a custom control register by the developer. | ||
* @param el | ||
* @param formOptions The validation options of the parent form | ||
* @returns {boolean} true to indicate it should be validated | ||
*/ | ||
shouldValidateElement = function (el, formOptions) { | ||
var result = el && | ||
el.length > 0 && | ||
(elementIsVisible(el) || formOptions.validateNonVisibleControls) && | ||
(elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1 || | ||
el[0].hasAttribute('register-custom-form-control')); | ||
return result; | ||
}, | ||
return options; | ||
}, | ||
/** | ||
* @ngdoc validateElement | ||
* @name validation#validateElement | ||
* @param {object} modelCtrl holds the information about the element e.g. $invalid, $valid | ||
* @param {options} | ||
* - forceValidation if set to true forces the validation even if the element is pristine | ||
* - disabled if set to true forces the validation is disabled and will return true | ||
* - validateNonVisibleControls if set to true forces the validation of non visible element i.e. display:block | ||
* @description | ||
* Validate the form element and make invalid/valid element model status. | ||
* | ||
* As of v1.17.22: | ||
* BREAKING CHANGE to validateElement on the validationManger. The third parameter is now the parent form's | ||
* autoValidateFormOptions object on the form controller. This can be left blank and will be found by the | ||
* validationManager. | ||
*/ | ||
validateElement = function (modelCtrl, el, options) { | ||
var isValid = true, | ||
frmOptions = options || getFormOptions(el), | ||
needsValidation = modelCtrl.$pristine === false || frmOptions.forceValidation, | ||
errorType, | ||
findErrorType = function ($errors) { | ||
var keepGoing = true, | ||
errorTypeToReturn; | ||
angular.forEach($errors, function (status, errortype) { | ||
if (keepGoing && status) { | ||
keepGoing = false; | ||
errorTypeToReturn = errortype; | ||
} | ||
}); | ||
/** | ||
* Only validate if the element is present, it is visible | ||
* it is either a valid user input control (input, select, textare, form) or | ||
* it is a custom control register by the developer. | ||
* @param el | ||
* @param formOptions The validation options of the parent form | ||
* @returns {boolean} true to indicate it should be validated | ||
*/ | ||
shouldValidateElement = function (el, formOptions, formSubmitted) { | ||
var elementExists = el && el.length > 0, | ||
correctVisibilityToValidate, | ||
correctTypeToValidate, | ||
correctPhaseToValidate; | ||
return errorTypeToReturn; | ||
}; | ||
if (elementExists) { | ||
correctVisibilityToValidate = elementIsVisible(el) || formOptions.validateNonVisibleControls; | ||
correctTypeToValidate = elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1 || | ||
el[0].hasAttribute('register-custom-form-control'); | ||
correctPhaseToValidate = formOptions.validateOnFormSubmit === false || | ||
(formOptions.validateOnFormSubmit === true && formSubmitted === true); | ||
} | ||
if (frmOptions.disabled === false) { | ||
if ((frmOptions.forceValidation || (shouldValidateElement(el, frmOptions) && modelCtrl && needsValidation))) { | ||
isValid = !modelCtrl.$invalid; | ||
return elementExists && correctVisibilityToValidate && correctTypeToValidate && correctPhaseToValidate; | ||
if (frmOptions.removeExternalValidationErrorsOnSubmit && modelCtrl.removeAllExternalValidation) { | ||
modelCtrl.removeAllExternalValidation(); | ||
} | ||
}, | ||
if (isValid) { | ||
validator.makeValid(el); | ||
} else { | ||
errorType = findErrorType(modelCtrl.$errors || modelCtrl.$error); | ||
if (errorType === undefined) { | ||
/** | ||
* @ngdoc validateElement | ||
* @name validation#validateElement | ||
* @param {object} modelCtrl holds the information about the element e.g. $invalid, $valid | ||
* @param {options} | ||
* - forceValidation if set to true forces the validation even if the element is pristine | ||
* - disabled if set to true forces the validation is disabled and will return true | ||
* - validateNonVisibleControls if set to true forces the validation of non visible element i.e. display:block | ||
* @description | ||
* Validate the form element and make invalid/valid element model status. | ||
* | ||
* As of v1.17.22: | ||
* BREAKING CHANGE to validateElement on the validationManger. The third parameter is now the parent form's | ||
* autoValidateFormOptions object on the form controller. This can be left blank and will be found by the | ||
* validationManager. | ||
*/ | ||
validateElement = function (modelCtrl, el, options) { | ||
var isValid = true, | ||
frmOptions = options || getFormOptions(el), | ||
needsValidation = modelCtrl.$pristine === false || frmOptions.forceValidation, | ||
errorType, | ||
findErrorType = function ($errors) { | ||
var keepGoing = true, | ||
errorTypeToReturn; | ||
angular.forEach($errors, function (status, errortype) { | ||
if (keepGoing && status) { | ||
keepGoing = false; | ||
errorTypeToReturn = errortype; | ||
} | ||
}); | ||
// we have a weird situation some users are encountering where a custom control | ||
// is valid but the ngModel is report it isn't and thus no valid error type can be found | ||
isValid = true; | ||
} else { | ||
validator.getErrorMessage(errorType, el).then(function (errorMsg) { | ||
validator.makeInvalid(el, errorMsg); | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
return errorTypeToReturn; | ||
}; | ||
return isValid; | ||
}, | ||
if (frmOptions.disabled === false) { | ||
if ((frmOptions.forceValidation || | ||
(shouldValidateElement(el, frmOptions, frmOptions.formController.$submitted) && | ||
modelCtrl && | ||
needsValidation))) { | ||
isValid = !modelCtrl.$invalid; | ||
resetElement = function (element) { | ||
validator.makeDefault(element); | ||
}, | ||
if (frmOptions.removeExternalValidationErrorsOnSubmit && modelCtrl.removeAllExternalValidation) { | ||
modelCtrl.removeAllExternalValidation(); | ||
} | ||
resetForm = function (frmElement) { | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (element) { | ||
var controller, | ||
ctrlElement = angular.element(element); | ||
controller = ctrlElement.controller('ngModel'); | ||
if (isValid) { | ||
validator.makeValid(el); | ||
} else { | ||
errorType = findErrorType(modelCtrl.$errors || modelCtrl.$error); | ||
if (errorType === undefined) { | ||
// we have a weird situation some users are encountering where a custom control | ||
// is valid but the ngModel is report it isn't and thus no valid error type can be found | ||
isValid = true; | ||
} else { | ||
validator.getErrorMessage(errorType, el).then(function (errorMsg) { | ||
validator.makeInvalid(el, errorMsg); | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
if (controller !== undefined) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
resetForm(ctrlElement); | ||
} else { | ||
controller.$setPristine(); | ||
} | ||
} | ||
}); | ||
}, | ||
return isValid; | ||
}, | ||
validateForm = function (frmElement) { | ||
var frmValid = true, | ||
frmCtrl = frmElement ? angular.element(frmElement).controller('form') : undefined, | ||
processElement = function (ctrlElement, force, formOptions) { | ||
var controller, isValid, ctrlFormOptions; | ||
resetElement = function (element) { | ||
validator.makeDefault(element); | ||
}, | ||
ctrlElement = angular.element(ctrlElement); | ||
controller = ctrlElement.controller('ngModel'); | ||
resetForm = function (frmElement) { | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (element) { | ||
var controller, | ||
ctrlElement = angular.element(element); | ||
controller = ctrlElement.controller('ngModel'); | ||
if (controller !== undefined && (force || shouldValidateElement(ctrlElement, formOptions))) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
validateForm(ctrlElement); | ||
} else { | ||
// we need to get the options for the element rather than use the passed in as the | ||
// element could be an ng-form and have different options to the parent form. | ||
ctrlFormOptions = getFormOptions(ctrlElement); | ||
ctrlFormOptions.forceValidation = force; | ||
isValid = validateElement(controller, ctrlElement, ctrlFormOptions); | ||
frmValid = frmValid && isValid; | ||
} | ||
} | ||
}, | ||
clonedOptions; | ||
if (controller !== undefined) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
resetForm(ctrlElement); | ||
} else { | ||
controller.$setPristine(); | ||
} | ||
} | ||
}); | ||
}, | ||
if (frmElement === undefined || (frmCtrl !== undefined && frmCtrl.autoValidateFormOptions.disabled)) { | ||
return frmElement !== undefined; | ||
} | ||
validateForm = function (frmElement) { | ||
var frmValid = true, | ||
frmCtrl = frmElement ? angular.element(frmElement).controller('form') : undefined, | ||
processElement = function (ctrlElement, force, formOptions) { | ||
var controller, isValid, ctrlFormOptions, originalForceValue; | ||
//force the validation of controls | ||
clonedOptions = angular.copy(frmCtrl.autoValidateFormOptions); | ||
clonedOptions.forceValidation = true; | ||
ctrlElement = angular.element(ctrlElement); | ||
controller = ctrlElement.controller('ngModel'); | ||
// IE8 holds the child controls collection in the all property | ||
// Firefox in the elements and chrome as a child iterator | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (ctrlElement) { | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
if (controller !== undefined && (force || shouldValidateElement(ctrlElement, formOptions, frmCtrl.$submitted))) { | ||
if (ctrlElement[0].nodeName.toLowerCase() === 'form') { | ||
// we probably have a sub form | ||
validateForm(ctrlElement); | ||
} else { | ||
// we need to get the options for the element rather than use the passed in as the | ||
// element could be an ng-form and have different options to the parent form. | ||
ctrlFormOptions = getFormOptions(ctrlElement); | ||
originalForceValue = ctrlFormOptions.forceValidation; | ||
ctrlFormOptions.forceValidation = force; | ||
try { | ||
isValid = validateElement(controller, ctrlElement, ctrlFormOptions); | ||
frmValid = frmValid && isValid; | ||
} finally { | ||
ctrlFormOptions.forceValidation = originalForceValue; | ||
} | ||
} | ||
} | ||
}, | ||
clonedOptions; | ||
// If you have a custom form control that should be validated i.e. | ||
// <my-custom-element>...</my-custom-element> it will not be part of the forms | ||
// HTMLFormControlsCollection and thus won't be included in the above element iteration although | ||
// it will be on the Angular FormController (if it has a name attribute). So adding the directive | ||
// register-custom-form-control="" to the control root and autoValidate will include it in this | ||
// iteration. | ||
if (frmElement[0].customHTMLFormControlsCollection) { | ||
angular.forEach(frmElement[0].customHTMLFormControlsCollection, function (ctrlElement) { | ||
// need to force the validation as the element might not be a known form input type | ||
// so the normal validation process will ignore it. | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
} | ||
if (frmElement === undefined || (frmCtrl !== undefined && frmCtrl.autoValidateFormOptions.disabled)) { | ||
return frmElement !== undefined; | ||
} | ||
return frmValid; | ||
}, | ||
//force the validation of controls | ||
clonedOptions = angular.copy(frmCtrl.autoValidateFormOptions); | ||
clonedOptions.forceValidation = true; | ||
setElementValidationError = function (element, errorMsgKey, errorMsg) { | ||
if (errorMsgKey) { | ||
validator.getErrorMessage(errorMsgKey, element).then(function (msg) { | ||
validator.makeInvalid(element, msg); | ||
}); | ||
} else { | ||
validator.makeInvalid(element, errorMsg); | ||
} | ||
}; | ||
// IE8 holds the child controls collection in the all property | ||
// Firefox in the elements and chrome as a child iterator | ||
angular.forEach((frmElement[0].all || frmElement[0].elements) || frmElement[0], function (ctrlElement) { | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
return { | ||
setElementValidationError: setElementValidationError, | ||
validateElement: validateElement, | ||
validateForm: validateForm, | ||
resetElement: resetElement, | ||
resetForm: resetForm | ||
}; | ||
} | ||
]); | ||
}(angular)); | ||
// If you have a custom form control that should be validated i.e. | ||
// <my-custom-element>...</my-custom-element> it will not be part of the forms | ||
// HTMLFormControlsCollection and thus won't be included in the above element iteration although | ||
// it will be on the Angular FormController (if it has a name attribute). So adding the directive | ||
// register-custom-form-control="" to the control root and autoValidate will include it in this | ||
// iteration. | ||
if (frmElement[0].customHTMLFormControlsCollection) { | ||
angular.forEach(frmElement[0].customHTMLFormControlsCollection, function (ctrlElement) { | ||
// need to force the validation as the element might not be a known form input type | ||
// so the normal validation process will ignore it. | ||
processElement(ctrlElement, true, clonedOptions); | ||
}); | ||
} | ||
return frmValid; | ||
}, | ||
setElementValidationError = function (element, errorMsgKey, errorMsg) { | ||
if (errorMsgKey) { | ||
validator.getErrorMessage(errorMsgKey, element).then(function (msg) { | ||
validator.makeInvalid(element, msg); | ||
}); | ||
} else { | ||
validator.makeInvalid(element, errorMsg); | ||
} | ||
}; | ||
return { | ||
setElementValidationError: setElementValidationError, | ||
validateElement: validateElement, | ||
validateForm: validateForm, | ||
resetElement: resetElement, | ||
resetForm: resetForm | ||
}; | ||
} | ||
ValidationManagerFn.$inject = [ | ||
'validator', | ||
'jcs-elementUtils' | ||
]; | ||
angular.module('jcs-autoValidate').factory('jcs-elementUtils', ElementUtilsFn); | ||
angular.module('jcs-autoValidate').factory('validationManager', ValidationManagerFn); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
/** | ||
* Since Angular 1.3 SetValidity on the ngModelController is called 2-3 times | ||
* because of the inclusion of async validators hence now the tests only assert the | ||
* methods were called | ||
*/ | ||
/** | ||
* Since Angular 1.3 SetValidity on the ngModelController is called 2-3 times | ||
* because of the inclusion of async validators hence now the tests only assert the | ||
* methods were called | ||
*/ | ||
describe('ngModelDirective decorator', function () { | ||
var sandbox, $rootScope, $q, validationManager, $timeout, | ||
element, $compile, debounce, debounceStub, | ||
compileElement = function (html, includesForm) { | ||
html = includesForm ? html : '<form ng-submit="">' + html + '</form>'; | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
element = includesForm ? element : angular.element(element[0].children[0]); | ||
}, | ||
setNgOptionsNotSupported = function () { | ||
sandbox.stub(angular, 'version', { | ||
major: angular.version.major, | ||
minor: angular.version.minor | ||
}); | ||
}; | ||
describe('ngModelDirective decorator', function () { | ||
var sandbox, $rootScope, $q, validationManager, $timeout, | ||
element, $compile, debounce, debounceStub, | ||
compileElement = function (html, includesForm) { | ||
html = includesForm ? html : '<form ng-submit="">' + html + '</form>'; | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
element = includesForm ? element : angular.element(element[0].children[0]); | ||
}, | ||
setNgOptionsNotSupported = function () { | ||
sandbox.stub(angular, 'version', { | ||
major: angular.version.major, | ||
minor: angular.version.minor | ||
}); | ||
}; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('ngModelDirective', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
$timeout = $injector.get('$timeout'); | ||
debounce = $injector.get('jcs-debounce'); | ||
validationManager = $injector.get('validationManager'); | ||
describe('ngModelDirective', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
$timeout = $injector.get('$timeout'); | ||
debounce = $injector.get('jcs-debounce'); | ||
validationManager = $injector.get('validationManager'); | ||
debounceStub = sandbox.stub(); | ||
debounceStub = sandbox.stub(); | ||
sandbox.stub(validationManager, 'validateElement'); | ||
sandbox.stub(debounce, 'debounce').returns(debounceStub); | ||
})); | ||
sandbox.stub(validationManager, 'validateElement'); | ||
sandbox.stub(debounce, 'debounce').returns(debounceStub); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<input ng-model="model" />'); | ||
expect(element).to.exist; | ||
var ctrl = element.controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(true); | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<input ng-model="model" />'); | ||
expect(element).to.exist; | ||
var ctrl = element.controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(true); | ||
}); | ||
it('should not be autoValidated it the formnovalidate attribute is present on the element', function () { | ||
compileElement('<input ng-model="model" formnovalidate />'); | ||
var ctrl = element.controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(undefined); | ||
}); | ||
it('should not be autoValidated it the formnovalidate attribute is present on the element', function () { | ||
compileElement('<input ng-model="model" formnovalidate />'); | ||
var ctrl = element.controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(undefined); | ||
}); | ||
it('should not be autoValidated it the disable-dynamic-validation attribute is on the parent form', function () { | ||
compileElement('<form disable-dynamic-validation="true"><input ng-model="model" formnovalidate /></form>', true); | ||
var ctrl = angular.element(element.children()[0]).controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(undefined); | ||
}); | ||
it('should not be autoValidated it the disable-dynamic-validation attribute is on the parent form', function () { | ||
compileElement('<form disable-dynamic-validation="true"><input ng-model="model" formnovalidate /></form>', true); | ||
var ctrl = angular.element(element.children()[0]).controller('ngModel'); | ||
expect(ctrl.autoValidated).to.equal(undefined); | ||
}); | ||
it('should called debounced method when $setValidity invoked if angular version in 1.3 and thus supports ngModelOptions', function () { | ||
// As of the changes needed for angular 1.3 RC release this test will no longer pass in angular 1.2x | ||
// setNgOptionsSupported(); | ||
// compileElement('<input ng-model="model" />'); | ||
// var ctrl = element.controller('ngModel'); | ||
// ctrl.$setValidity('error', true); | ||
// | ||
// expect(debounceStub.called).to.equal(true); | ||
}); | ||
it('should called debounced method when $setValidity invoked if angular version in 1.3 and thus supports ngModelOptions', function () { | ||
// As of the changes needed for angular 1.3 RC release this test will no longer pass in angular 1.2x | ||
// setNgOptionsSupported(); | ||
// compileElement('<input ng-model="model" />'); | ||
// var ctrl = element.controller('ngModel'); | ||
// ctrl.$setValidity('error', true); | ||
// | ||
// expect(debounceStub.called).to.equal(true); | ||
}); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is not defined', function () { | ||
compileElement('<input ng-model="model" />'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is not defined', function () { | ||
compileElement('<input ng-model="model" />'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is defined but updateOn is not defined', function () { | ||
compileElement('<input ng-model="model" data-ng-model-options="{}"/>'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is defined but updateOn is not defined', function () { | ||
compileElement('<input ng-model="model" data-ng-model-options="{}"/>'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is defined but updateOn is not empty', function () { | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'\'}"/>'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
it('should called debounced method when $setValidity invoked if ngModelOptions is defined but updateOn is not empty', function () { | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'\'}"/>'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
expect(debounceStub.called).to.equal(true); | ||
}); | ||
it('invoking the debounced method should call validateElement on the validationManager', function () { | ||
compileElement('<input ng-model="model" />'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
it('invoking the debounced method should call validateElement on the validationManager', function () { | ||
compileElement('<input ng-model="model" />'); | ||
var ctrl = element.controller('ngModel'); | ||
ctrl.$setValidity('error', false); | ||
expect(debounce.debounce.args[0][0]).to.not.equal(undefined); | ||
expect(debounce.debounce.args[0][1]).to.equal(100); | ||
debounce.debounce.args[0][0](); | ||
expect(validationManager.validateElement.calledOnce).to.equal(true); | ||
}); | ||
expect(debounce.debounce.args[0][0]).to.not.equal(undefined); | ||
expect(debounce.debounce.args[0][1]).to.equal(100); | ||
debounce.debounce.args[0][0](); | ||
expect(validationManager.validateElement.calledOnce).to.equal(true); | ||
}); | ||
it('should call validate element when element blur event is raised', function () { | ||
if (angular.version.major === 1 && angular.version.minor < 3) { | ||
setNgOptionsNotSupported(); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
element.triggerHandler('blur'); | ||
it('should call validate element when element blur event is raised', function () { | ||
if (angular.version.major === 1 && angular.version.minor < 3) { | ||
setNgOptionsNotSupported(); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
element.triggerHandler('blur'); | ||
expect(debounce.debounce.args[0][0]).to.not.equal(undefined); | ||
expect(debounce.debounce.args[0][1]).to.equal(100); | ||
debounce.debounce.args[0][0](); | ||
expect(validationManager.validateElement.calledOnce).to.equal(true); | ||
} | ||
}); | ||
expect(debounce.debounce.args[0][0]).to.not.equal(undefined); | ||
expect(debounce.debounce.args[0][1]).to.equal(100); | ||
debounce.debounce.args[0][0](); | ||
expect(validationManager.validateElement.calledOnce).to.equal(true); | ||
} | ||
}); | ||
it('should remove element event listener when scope is destroyed', function () { | ||
if (angular.version.major === 1 && angular.version.minor < 3) { | ||
setNgOptionsNotSupported(); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
it('should remove element event listener when scope is destroyed', function () { | ||
if (angular.version.major === 1 && angular.version.minor < 3) { | ||
setNgOptionsNotSupported(); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
$rootScope.$destroy(); | ||
$rootScope.$destroy(); | ||
// How do I mock out the off method of the element? | ||
//expect(element.off.calledOnce).to.equal(true); | ||
} | ||
}); | ||
// How do I mock out the off method of the element? | ||
//expect(element.off.calledOnce).to.equal(true); | ||
} | ||
}); | ||
describe('$setPristine', function () { | ||
it('should override the default $setPristine function and when invoked should call the default method and the validationManager resetElement method', function () { | ||
var ngModelController; | ||
describe('$setPristine', function () { | ||
it('should override the default $setPristine function and when invoked should call the default method and the validationManager resetElement method', function () { | ||
var ngModelController; | ||
sandbox.stub(validationManager, 'resetElement'); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
sandbox.stub(validationManager, 'resetElement'); | ||
compileElement('<input ng-model="model" data-ng-model-options="{updateOn: \'blur\'}" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.$setPristine(); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.$setPristine(); | ||
expect(validationManager.resetElement.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
expect(validationManager.resetElement.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
describe('setExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
describe('setExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
expect(ngModelController.setExternalValidation).to.not.equal(undefined); | ||
}); | ||
expect(ngModelController.setExternalValidation).to.not.equal(undefined); | ||
}); | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
}); | ||
}); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
}); | ||
}); | ||
describe('removeExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
describe('removeExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
expect(ngModelController.removeExternalValidation).to.not.equal(undefined); | ||
}); | ||
expect(ngModelController.removeExternalValidation).to.not.equal(undefined); | ||
}); | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
ngModelController.removeExternalValidation(errorKey, true); | ||
ngModelController.removeExternalValidation(errorKey, true); | ||
expect(ngModelController.$error[errorKey]).to.equal(true); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(undefined); | ||
}); | ||
}); | ||
expect(ngModelController.$error[errorKey]).to.equal(undefined); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(undefined); | ||
}); | ||
}); | ||
describe('removeAllExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
describe('removeAllExternalValidation', function () { | ||
it('should be defined on the ngModelCtrl', function () { | ||
var ngModelController; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
expect(ngModelController.removeAllExternalValidation).to.not.equal(undefined); | ||
}); | ||
expect(ngModelController.removeAllExternalValidation).to.not.equal(undefined); | ||
}); | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
it('should set a key in the errors collection', function () { | ||
var ngModelController, | ||
errorKey = 'errorKey'; | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
compileElement('<input ng-model="model" />'); | ||
ngModelController = element.controller('ngModel'); | ||
ngModelController.setExternalValidation(errorKey, 'msgKey', true); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
expect(ngModelController.$error[errorKey]).to.equal(false); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(false); | ||
ngModelController.removeAllExternalValidation(); | ||
ngModelController.removeAllExternalValidation(); | ||
expect(ngModelController.$error[errorKey]).to.equal(true); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(undefined); | ||
}); | ||
}); | ||
expect(ngModelController.$error[errorKey]).to.equal(undefined); | ||
expect(ngModelController.externalErrors[errorKey]).to.equal(undefined); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (window, angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('ngModelDirective decorator', function () { | ||
var sandbox, $rootScope, $q, validationManager, | ||
element, $compile, submitFnCalled = false, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
}; | ||
describe('ngModelDirective decorator', function () { | ||
var sandbox, $rootScope, $q, validationManager, | ||
element, $compile, submitFnCalled = false, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
}; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('ngSubmitDirective', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
validationManager = $injector.get('validationManager'); | ||
describe('ngSubmitDirective', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
validationManager = $injector.get('validationManager'); | ||
$rootScope.submitFn = function () { | ||
submitFnCalled = true; | ||
}; | ||
})); | ||
$rootScope.submitFn = function () { | ||
submitFnCalled = true; | ||
}; | ||
})); | ||
afterEach(function () { | ||
submitFnCalled = false; | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
submitFnCalled = false; | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
}); | ||
it('should call validate form on the validationManager when the form submit event is raised', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(true); | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
it('should call validate form on the validationManager when the form submit event is raised', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(true); | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
window.browserTrigger(element, 'submit'); | ||
window.browserTrigger(element, 'submit'); | ||
expect(validationManager.validateForm.calledOnce).to.equal(true); | ||
}); | ||
expect(validationManager.validateForm.calledOnce).to.equal(true); | ||
}); | ||
it('should call the submit function on ngSubmit when the form is submitted and is valid', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(true); | ||
compileElement('<form name="frmOne2" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
it('should call the submit function on ngSubmit when the form is submitted and is valid', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(true); | ||
compileElement('<form name="frmOne2" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
expect(submitFnCalled).to.equal(true); | ||
}); | ||
expect(submitFnCalled).to.equal(true); | ||
}); | ||
it('should call the submit function on ngSubmit when the form is submitted, is invalid but the ngSubmitForce attribute is true', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(false); | ||
compileElement('<form name="frmOne2" ng-submit="submitFn()" ng-submit-force="true"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
it('should call the submit function on ngSubmit when the form is submitted, is invalid but the ngSubmitForce attribute is true', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(false); | ||
compileElement('<form name="frmOne2" ng-submit="submitFn()" ng-submit-force="true"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
expect(submitFnCalled).to.equal(true); | ||
}); | ||
expect(submitFnCalled).to.equal(true); | ||
}); | ||
it('should not call the submit function on ngSubmit when the form is submitted and is valid', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(false); | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
it('should not call the submit function on ngSubmit when the form is submitted and is valid', function () { | ||
sandbox.stub(validationManager, 'validateForm').returns(false); | ||
compileElement('<form name="frmOne" ng-submit="submitFn()"><input type="text" ng-model="name"/></form>'); | ||
expect(element).to.exist; | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
window.browserTrigger(element, 'submit'); | ||
$rootScope.$apply(); | ||
expect(submitFnCalled).to.equal(false); | ||
}); | ||
}); | ||
expect(submitFnCalled).to.equal(false); | ||
}); | ||
}); | ||
}); | ||
}(window, angular, sinon)); |
(function (document, angular, sinon) { | ||
'use strict'; | ||
var sandbox, $rootScope, | ||
element, $compile, validator, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
}; | ||
'use strict'; | ||
var sandbox, $rootScope, | ||
element, $compile, validator, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
}; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('autoValidateFormOptions', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
validator = $injector.get('validator'); | ||
})); | ||
describe('autoValidateFormOptions', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
validator = $injector.get('validator'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<form name="test""></form>'); | ||
it('should be defined', function () { | ||
compileElement('<form name="test""></form>'); | ||
expect(element.controller('form').autoValidateFormOptions).to.exist; | ||
expect(element.controller('form').autoValidateFormOptions).to.exist; | ||
}); | ||
describe('disableDynamicValidation', function () { | ||
it('should set the default value if config properties are not on form', function () { | ||
sandbox.stub(validator, 'defaultFormValidationOptions', { | ||
validateNonVisibleControls: 2, | ||
removeExternalValidationErrorsOnSubmit: 3, | ||
validateOnFormSubmit: 4 | ||
}); | ||
describe('disableDynamicValidation', function () { | ||
it('should set the property "disableDynamicValidation" on the form controller to true', function () { | ||
compileElement('<form name="test" disable-dynamic-validation="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
compileElement('<form name="test"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.validateNonVisibleControls).to.equal(2); | ||
expect(controller.autoValidateFormOptions.removeExternalValidationErrorsOnSubmit).to.equal(3); | ||
expect(controller.autoValidateFormOptions.validateOnFormSubmit).to.equal(4); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to true', function () { | ||
compileElement('<form name="test" data-disable-dynamic-validation="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to true', function () { | ||
compileElement('<form name="test" disable-dynamic-validation="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to true if it is used as a boolean attribute', function () { | ||
compileElement('<form name="test" disable-dynamic-validation></form>'); | ||
it('should set the property "disableDynamicValidation" on the form controller to true', function () { | ||
compileElement('<form name="test" data-disable-dynamic-validation="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to true if it is used as a boolean attribute', function () { | ||
compileElement('<form name="test" disable-dynamic-validation></form>'); | ||
it('should set the property "disableDynamicValidation" on the form controller to false', function () { | ||
compileElement('<form name="test" disable-dynamic-validation="false"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(true); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to false', function () { | ||
compileElement('<form name="test" disable-dynamic-validation="false"></form>'); | ||
it('should set the property "disableDynamicValidation" on the form controller to false', function () { | ||
sandbox.stub(validator, 'isEnabled').returns(false); | ||
compileElement('<form name="test" disable-dynamic-validation="false"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to false when validator is disabled', function () { | ||
sandbox.stub(validator, 'isEnabled').returns(false); | ||
compileElement('<form name="test" disable-dynamic-validation="false"></form>'); | ||
it('should set the property "disableDynamicValidation" on the form controller to false if the attribute is not there', function () { | ||
compileElement('<form name="test"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to false if the attribute is not there', function () { | ||
compileElement('<form name="test"></form>'); | ||
describe('validateNonVisibleControls', function () { | ||
it('should set the property "validateNonVisibleControls" on the form controller to true', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
}); | ||
it('should set the property "validateNonVisibleControls" on the form controller to true', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to true if the library is disabled', function () { | ||
validator.enable(false); | ||
compileElement('<form name="test"></form>'); | ||
it('should set the property "validateNonVisibleControls" on the form controller to true if it is used as a boolean attribute', function () { | ||
compileElement('<form name="test" validate-non-visible-controls></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(true); | ||
validator.enable(true); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
it('should set the property "disableDynamicValidation" on the form controller to false if the library is disabled but the form is enabled', function () { | ||
validator.enable(false); | ||
compileElement('<form name="test" disable-dynamic-validation="false"></form>'); | ||
it('should set the property "validateNonVisibleControls" on the form controller to false', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="false"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.disabled).to.equal(false); | ||
validator.enable(true); | ||
}); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(false); | ||
}); | ||
describe('validateNonVisibleControls', function () { | ||
it('should set the property "validateNonVisibleControls" on the form controller to true', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
it('should set the property "validateNonVisibleControls" on the form controller to false if the attribute is not there', function () { | ||
compileElement('<form name="test"></form>'); | ||
it('should set the property "validateNonVisibleControls" on the form controller to true', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="true"></form>'); | ||
var controller = element.controller('form'); | ||
expect(controller.autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(false); | ||
}); | ||
}); | ||
it('should set the property "validateNonVisibleControls" on the form controller to true if it is used as a boolean attribute', function () { | ||
compileElement('<form name="test" validate-non-visible-controls></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(true); | ||
}); | ||
it('should set the property "validateNonVisibleControls" on the form controller to false', function () { | ||
compileElement('<form name="test" validate-non-visible-controls="false"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(false); | ||
}); | ||
it('should set the property "validateNonVisibleControls" on the form controller to false if the attribute is not there', function () { | ||
compileElement('<form name="test"></form>'); | ||
expect(element.controller('form').autoValidateFormOptions.validateNonVisibleControls).to.equal(false); | ||
}); | ||
}); | ||
}); | ||
}(document, angular, sinon)); |
(function (document, angular, sinon) { | ||
'use strict'; | ||
var sandbox, $rootScope, $timeout, | ||
element, $compile, validationManager, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
angular.element(document.body).append(element); | ||
$rootScope.$digest(); | ||
}; | ||
'use strict'; | ||
var sandbox, $rootScope, $timeout, | ||
element, $compile, validationManager, | ||
compileElement = function (html) { | ||
element = angular.element(html); | ||
$compile(element)($rootScope); | ||
angular.element(document.body).append(element); | ||
$rootScope.$digest(); | ||
}; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('formReset', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$timeout = $injector.get('$timeout'); | ||
$compile = $injector.get('$compile'); | ||
validationManager = $injector.get('validationManager'); | ||
})); | ||
describe('formReset', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$timeout = $injector.get('$timeout'); | ||
$compile = $injector.get('$compile'); | ||
validationManager = $injector.get('validationManager'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
compileElement('<form mame="test"></form>'); | ||
it('should be defined', function () { | ||
compileElement('<form mame="test"></form>'); | ||
expect(element).to.exist; | ||
}); | ||
expect(element).to.exist; | ||
}); | ||
it('should add an event listener to the forms reset event which calls the resetForm on the validationManager', function () { | ||
sandbox.stub(validationManager, 'resetForm'); | ||
compileElement('<form mame="test"></form>'); | ||
it('should add an event listener to the forms reset event which calls the resetForm on the validationManager', function () { | ||
sandbox.stub(validationManager, 'resetForm'); | ||
compileElement('<form mame="test"></form>'); | ||
element.triggerHandler('reset'); | ||
element.triggerHandler('reset'); | ||
expect(validationManager.resetForm.calledOnce).to.equal(true); | ||
}); | ||
expect(validationManager.resetForm.calledOnce).to.equal(true); | ||
}); | ||
it('should add an event listener to the scope $destroy event', function () { | ||
sandbox.stub($rootScope, '$on'); | ||
compileElement('<form mame="test"></form>'); | ||
it('should add an event listener to the scope $destroy event', function () { | ||
sandbox.stub($rootScope, '$on'); | ||
compileElement('<form mame="test"></form>'); | ||
expect($rootScope.$on.calledOnce).to.equal(true); | ||
expect($rootScope.$on.getCall(0).args[0]).to.equal('$destroy'); | ||
}); | ||
expect($rootScope.$on.calledOnce).to.equal(true); | ||
expect($rootScope.$on.getCall(0).args[0]).to.equal('$destroy'); | ||
}); | ||
}); | ||
}(document, angular, sinon)); |
@@ -76,3 +76,14 @@ var shared = function (config) { | ||
'src/jcs-auto-validate.js', | ||
'src/**/*.js', | ||
'src/providers/validator.js', | ||
'src/services/bootstrap3ElementModifier.js', | ||
'src/services/debounce.js', | ||
'src/services/defaultErrorMessageResolver.js', | ||
'src/services/foundation5ElementModifier.js', | ||
'src/services/validationManager.js', | ||
'src/directives/autoValidateFormOptions.js', | ||
'src/directives/formReset.js', | ||
'src/directives/registerCustomFormControl.js', | ||
'src/config/ngSubmitDecorator.js', | ||
'src/config/ngModelDecorator.js', | ||
'src/jcs-auto-validate-run.js', | ||
@@ -79,0 +90,0 @@ 'src/jcs-auto-validate-run.js' |
(function (angular, sinon) { | ||
'use strict'; | ||
describe('jcs-autoValidator validator', function () { | ||
var sandbox, $rootScope, $q, validator; | ||
'use strict'; | ||
describe('jcs-autoValidator validator', function () { | ||
var sandbox, $rootScope, $q, validator; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('validator', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$q = $injector.get('$q'); | ||
validator = $injector.get('validator'); | ||
})); | ||
describe('validator', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$q = $injector.get('$q'); | ||
validator = $injector.get('validator'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
expect(validator).to.exist; | ||
}); | ||
it('should be defined', function () { | ||
expect(validator).to.exist; | ||
}); | ||
describe('setDefaultElementModifier', function () { | ||
it('should throw an error when a default modifier is set which does not exist', function () { | ||
expect(function () { | ||
validator.setDefaultElementModifier('missing_key'); | ||
}).to.throws(Error, 'Element modifier not registered: missing_key'); | ||
}); | ||
describe('setDefaultElementModifier', function () { | ||
it('should throw an error when a default modifier is set which does not exist', function () { | ||
expect(function () { | ||
validator.setDefaultElementModifier('missing_key'); | ||
}).to.throws(Error, 'Element modifier not registered: missing_key'); | ||
}); | ||
it('should set default dom modifier when modifier is present', function () { | ||
var key = 'key'; | ||
validator.registerDomModifier(key, {}); | ||
expect(function () { | ||
validator.setDefaultElementModifier(key); | ||
}).to.not.throws(Error); | ||
expect(validator.defaultElementModifier).to.equal(key); | ||
}); | ||
}); | ||
it('should set default dom modifier when modifier is present', function () { | ||
var key = 'key'; | ||
validator.registerDomModifier(key, {}); | ||
expect(function () { | ||
validator.setDefaultElementModifier(key); | ||
}).to.not.throws(Error); | ||
expect(validator.defaultElementModifier).to.equal(key); | ||
}); | ||
}); | ||
describe('getErrorMessage', function () { | ||
it('should throw an error an error message resolver has not been set', function () { | ||
validator.setErrorMessageResolver(undefined); | ||
expect(function () { | ||
validator.getErrorMessage('error_key'); | ||
}).to.throws(Error, 'Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
}); | ||
describe('getErrorMessage', function () { | ||
it('should throw an error an error message resolver has not been set', function () { | ||
validator.setErrorMessageResolver(undefined); | ||
expect(function () { | ||
validator.getErrorMessage('error_key'); | ||
}).to.throws(Error, 'Please set an error message resolver via the setErrorMessageResolver function before attempting to resolve an error message.'); | ||
}); | ||
it('should call get error message on the set error message resolver', function (done) { | ||
var errorMessage = 'error message', | ||
defer = $q.defer(), | ||
invocationCount = 0, | ||
resolverFunc = function () { | ||
invocationCount += 1; | ||
return defer.promise; | ||
}; | ||
it('should call get error message on the set error message resolver', function (done) { | ||
var errorMessage = 'error message', | ||
defer = $q.defer(), | ||
invocationCount = 0, | ||
resolverFunc = function () { | ||
invocationCount += 1; | ||
return defer.promise; | ||
}; | ||
validator.setErrorMessageResolver(resolverFunc); | ||
defer.resolve(errorMessage); | ||
validator.setErrorMessageResolver(resolverFunc); | ||
defer.resolve(errorMessage); | ||
validator.getErrorMessage('error_key').then(function (msg) { | ||
expect(invocationCount).to.equal(1); | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
validator.getErrorMessage('error_key').then(function (msg) { | ||
expect(invocationCount).to.equal(1); | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should not call get error message on the set error message resolver it validation message is disabled', function (done) { | ||
var errorMessage = '', | ||
defer = $q.defer(), | ||
invocationCount = 0, | ||
resolverFunc = function () { | ||
invocationCount += 1; | ||
return defer.promise; | ||
}, | ||
el = angular.element('<input type="text" required="" disable-validation-message=""/>'); | ||
it('should not call get error message on the set error message resolver it validation message is disabled', function (done) { | ||
var errorMessage = '', | ||
defer = $q.defer(), | ||
invocationCount = 0, | ||
resolverFunc = function () { | ||
invocationCount += 1; | ||
return defer.promise; | ||
}, | ||
el = angular.element('<input type="text" required="" disable-validation-message=""/>'); | ||
validator.setErrorMessageResolver(resolverFunc); | ||
defer.resolve(errorMessage); | ||
validator.setErrorMessageResolver(resolverFunc); | ||
defer.resolve(errorMessage); | ||
validator.getErrorMessage('error_key', el).then(function (msg) { | ||
expect(invocationCount).to.equal(0); | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
validator.getErrorMessage('error_key', el).then(function (msg) { | ||
expect(invocationCount).to.equal(0); | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
describe('getDomModifier', function () { | ||
var bs3 = 'bs3', | ||
custom = 'custom', | ||
custom1 = 'custom1'; | ||
describe('getDomModifier', function () { | ||
var bs3 = 'bs3', | ||
custom = 'custom', | ||
custom1 = 'custom1'; | ||
beforeEach(inject(function ($injector) { | ||
validator.registerDomModifier(bs3, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: bs3 | ||
}); | ||
validator.registerDomModifier(custom, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: custom | ||
}); | ||
validator.registerDomModifier(custom1, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: custom1 | ||
}); | ||
validator.setDefaultElementModifier(bs3); | ||
})); | ||
beforeEach(inject(function ($injector) { | ||
validator.registerDomModifier(bs3, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: bs3 | ||
}); | ||
validator.registerDomModifier(custom, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: custom | ||
}); | ||
validator.registerDomModifier(custom1, { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
name: custom1 | ||
}); | ||
validator.setDefaultElementModifier(bs3); | ||
})); | ||
it('should return the default dom modifier if the element has not specify a variant', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" />')); | ||
it('should return the default dom modifier if the element has not specify a variant', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" />')); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
it('should return the custom dom modifier as defined on the element via the attribute data-element-modifier', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" data-element-modifier="custom" />')); | ||
it('should return the custom dom modifier as defined on the element via the attribute data-element-modifier', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" data-element-modifier="custom" />')); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(custom); | ||
}); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(custom); | ||
}); | ||
it('should return the default dom modifier if the defined modifier key on the element attribute data-element-modifier is empty', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" data-element-modifier="" />')); | ||
it('should return the default dom modifier if the defined modifier key on the element attribute data-element-modifier is empty', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" data-element-modifier="" />')); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
it('should return the default dom modifier if the defined modifer key on the element attribute element-modifier is empty', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" element-modifier="" />')); | ||
it('should return the default dom modifier if the defined modifer key on the element attribute element-modifier is empty', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" element-modifier="" />')); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(bs3); | ||
}); | ||
it('should return the custom dom modifier as defined on the element via the attribute element-modifier', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" element-modifier="custom1" />')); | ||
it('should return the custom dom modifier as defined on the element via the attribute element-modifier', function () { | ||
var modifier = validator.getDomModifier(angular.element('<input type="text" element-modifier="custom1" />')); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(custom1); | ||
}); | ||
}); | ||
expect(modifier).to.be.defined; | ||
expect(modifier.name).to.be.equal(custom1); | ||
}); | ||
}); | ||
describe('setDefaultDomModifier', function () { | ||
it('should throw error as no default modifier has been set', function () { | ||
var wrappingFunc = function () { | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
}; | ||
describe('setDefaultDomModifier', function () { | ||
it('should throw error as no default modifier has been set', function () { | ||
var wrappingFunc = function () { | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
}; | ||
validator.defaultElementModifier = undefined; | ||
expect(wrappingFunc).to.throws(Error); | ||
}); | ||
}); | ||
validator.defaultElementModifier = undefined; | ||
expect(wrappingFunc).to.throws(Error); | ||
}); | ||
}); | ||
describe('makeValid', function () { | ||
var bs3 = 'bs3', | ||
makeValidInvocationCount = 0, | ||
domModifier = { | ||
makeValid: function () { | ||
makeValidInvocationCount += 1; | ||
}, | ||
makeInvalid: angular.noop, | ||
name: bs3 | ||
}; | ||
describe('makeValid', function () { | ||
var bs3 = 'bs3', | ||
makeValidInvocationCount = 0, | ||
domModifier = { | ||
makeValid: function () { | ||
makeValidInvocationCount += 1; | ||
}, | ||
makeInvalid: angular.noop, | ||
name: bs3 | ||
}; | ||
beforeEach(inject(function ($injector) { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
})); | ||
beforeEach(inject(function ($injector) { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
})); | ||
afterEach(function () { | ||
makeValidInvocationCount = 0; | ||
}); | ||
afterEach(function () { | ||
makeValidInvocationCount = 0; | ||
}); | ||
it('should call makeValid on the dom modifier once', function () { | ||
validator.makeValid(angular.element('<input type="text"/>')); | ||
expect(makeValidInvocationCount).to.equal(1); | ||
}); | ||
it('should call makeValid on the dom modifier once', function () { | ||
validator.makeValid(angular.element('<input type="text"/>')); | ||
expect(makeValidInvocationCount).to.equal(1); | ||
}); | ||
it('should not call makeValid on the dom modifier if enableValidElementStyling is false', function () { | ||
validator.setValidElementStyling(false); | ||
validator.makeValid(angular.element('<input type="text"/>')); | ||
expect(makeValidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeValid on the dom modifier if enableValidElementStyling is false', function () { | ||
validator.setValidElementStyling(false); | ||
validator.makeValid(angular.element('<input type="text"/>')); | ||
expect(makeValidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeValid on the dom modifier if the element has disabled valid element styling', function () { | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="true"/>')); | ||
expect(makeValidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeValid on the dom modifier if the element has disabled valid element styling', function () { | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="true"/>')); | ||
expect(makeValidInvocationCount).to.equal(0); | ||
}); | ||
it('should call makeDefault on the dom modifier if the element has disabled valid element styling', function () { | ||
sandbox.stub(validator, 'makeDefault'); | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="true"/>')); | ||
it('should call makeDefault on the dom modifier if the element has disabled valid element styling', function () { | ||
sandbox.stub(validator, 'makeDefault'); | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="true"/>')); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
it('should call makeValid on the dom modifier if the element has not disabled valid element styling', function () { | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="false"/>')); | ||
expect(makeValidInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
it('should call makeValid on the dom modifier if the element has not disabled valid element styling', function () { | ||
validator.makeValid(angular.element('<input type="text" disable-valid-styling="false"/>')); | ||
expect(makeValidInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
describe('makeInvalid', function () { | ||
var bs3 = 'bs3', | ||
makeInvalidInvocationCount = 0, | ||
domModifier = { | ||
makeValid: angular.noop, | ||
makeInvalid: function () { | ||
makeInvalidInvocationCount += 1; | ||
}, | ||
name: bs3 | ||
}; | ||
describe('makeInvalid', function () { | ||
var bs3 = 'bs3', | ||
makeInvalidInvocationCount = 0, | ||
domModifier = { | ||
makeValid: angular.noop, | ||
makeInvalid: function () { | ||
makeInvalidInvocationCount += 1; | ||
}, | ||
name: bs3 | ||
}; | ||
beforeEach(function () { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
}); | ||
beforeEach(function () { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
}); | ||
afterEach(function () { | ||
makeInvalidInvocationCount = 0; | ||
}); | ||
afterEach(function () { | ||
makeInvalidInvocationCount = 0; | ||
}); | ||
it('should call makeInvalid on the dom modifier once', function () { | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(1); | ||
}); | ||
it('should call makeInvalid on the dom modifier once', function () { | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(1); | ||
}); | ||
it('should not call makeInvalid on the dom modifier if enableInvalidElementStyling is false', function () { | ||
validator.setInvalidElementStyling(false); | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeInvalid on the dom modifier if enableInvalidElementStyling is false', function () { | ||
validator.setInvalidElementStyling(false); | ||
validator.makeInvalid(angular.element('<input type="text"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeInvalid on the dom modifier if the element has disabled invalid element styling', function () { | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="true"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(0); | ||
}); | ||
it('should not call makeInvalid on the dom modifier if the element has disabled invalid element styling', function () { | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="true"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(0); | ||
}); | ||
it('should call makeDefault on the dom modifier if the element has disabled invalid element styling', function () { | ||
sandbox.stub(validator, 'makeDefault'); | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="true"/>')); | ||
it('should call makeDefault on the dom modifier if the element has disabled invalid element styling', function () { | ||
sandbox.stub(validator, 'makeDefault'); | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="true"/>')); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
it('should call makeInvalid on the dom modifier if the element has not disabled invalid element styling', function () { | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="false"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
it('should call makeInvalid on the dom modifier if the element has not disabled invalid element styling', function () { | ||
validator.makeInvalid(angular.element('<input type="text" disable-invalid-styling="false"/>')); | ||
expect(makeInvalidInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
describe('makeDefault', function () { | ||
var bs3 = 'bs3', | ||
makeDefaultInvocationCount = 0, | ||
domModifier = { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
makeDefault: function () { | ||
makeDefaultInvocationCount += 1; | ||
}, | ||
name: bs3 | ||
}; | ||
describe('makeDefault', function () { | ||
var bs3 = 'bs3', | ||
makeDefaultInvocationCount = 0, | ||
domModifier = { | ||
makeValid: angular.noop, | ||
makeInvalid: angular.noop, | ||
makeDefault: function () { | ||
makeDefaultInvocationCount += 1; | ||
}, | ||
name: bs3 | ||
}; | ||
beforeEach(function () { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
}); | ||
beforeEach(function () { | ||
validator.registerDomModifier(bs3, domModifier); | ||
validator.setDefaultElementModifier(bs3); | ||
}); | ||
afterEach(function () { | ||
makeDefaultInvocationCount = 0; | ||
}); | ||
afterEach(function () { | ||
makeDefaultInvocationCount = 0; | ||
}); | ||
it('should call makeDefault on the dom modifier once', function () { | ||
validator.makeDefault(angular.element('<input type="text"/>')); | ||
expect(makeDefaultInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
it('should call makeDefault on the dom modifier once', function () { | ||
validator.makeDefault(angular.element('<input type="text"/>')); | ||
expect(makeDefaultInvocationCount).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('jcs.autoValidate bootstrap3ElementModifier', function () { | ||
var sandbox, $rootScope, bootstrap3ElementModifier; | ||
describe('jcs.autoValidate bootstrap3ElementModifier', function () { | ||
var sandbox, $rootScope, bootstrap3ElementModifier; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('bootstrap3ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
bootstrap3ElementModifier = $injector.get('bootstrap3ElementModifier'); | ||
})); | ||
describe('bootstrap3ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
bootstrap3ElementModifier = $injector.get('bootstrap3ElementModifier'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
expect(bootstrap3ElementModifier).to.not.equal(undefined); | ||
}); | ||
it('should be defined', function () { | ||
expect(bootstrap3ElementModifier).to.not.equal(undefined); | ||
}); | ||
describe('makeDefault', function () { | ||
it('should remove the .has-error class, .has-success and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-error has-success has-feedback"><input type="text"/></div>'); | ||
describe('makeDefault', function () { | ||
it('should remove the .has-error class, .has-success and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-error has-success has-feedback"><input type="text"/></div>'); | ||
bootstrap3ElementModifier.makeDefault(element); | ||
bootstrap3ElementModifier.makeDefault(element); | ||
expect(element.hasClass('has-error')).to.equal(false); | ||
expect(element.hasClass('has-success')).to.equal(false); | ||
expect(element.hasClass('has-feedback')).to.equal(false); | ||
}); | ||
expect(element.hasClass('has-error')).to.equal(false); | ||
expect(element.hasClass('has-success')).to.equal(false); | ||
expect(element.hasClass('has-feedback')).to.equal(false); | ||
}); | ||
it('should remove the .error-msg element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el9" type="email" class="form-control" required="required" ng-model="model.email"><span class="help-block error-msg">help text</span></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
it('should remove the .error-msg element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el9" type="email" class="form-control" required="required" ng-model="model.email"><span class="help-block error-msg">help text</span></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
bootstrap3ElementModifier.makeDefault(element.find('#el9')); | ||
bootstrap3ElementModifier.makeDefault(element.find('#el9')); | ||
expect(element.find('.help-block').length).to.equal(0); | ||
}); | ||
}); | ||
expect(element.find('.help-block').length).to.equal(0); | ||
}); | ||
}); | ||
describe('makeInvalid', function () { | ||
it('should remove the .has-success class and add the .has-error and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-success"><input type="text"/></div>'); | ||
describe('makeInvalid', function () { | ||
it('should remove the .has-success class and add the .has-error and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-success"><input type="text"/></div>'); | ||
bootstrap3ElementModifier.makeInvalid(element); | ||
bootstrap3ElementModifier.makeInvalid(element); | ||
expect(element.hasClass('has-success')).to.equal(false); | ||
expect(element.hasClass('has-error')).to.equal(true); | ||
expect(element.hasClass('has-feedback')).to.equal(true); | ||
}); | ||
expect(element.hasClass('has-success')).to.equal(false); | ||
expect(element.hasClass('has-error')).to.equal(true); | ||
expect(element.hasClass('has-feedback')).to.equal(true); | ||
}); | ||
it('should add an error icon when property "addValidationStateIcons" is true', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el3" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
it('should add an error icon when property "addValidationStateIcons" is true', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el3" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
bootstrap3ElementModifier.makeInvalid(element.find('#el3')); | ||
bootstrap3ElementModifier.makeInvalid(element.find('#el3')); | ||
expect(element.find('.glyphicon.glyphicon-remove.form-control-feedback').length).to.equal(1); | ||
}); | ||
expect(element.find('.glyphicon.glyphicon-remove.form-control-feedback').length).to.equal(1); | ||
}); | ||
it('should add the .help-block element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el4" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
it('should add the .help-block element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el4" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
bootstrap3ElementModifier.makeInvalid(element.find('#el4')); | ||
bootstrap3ElementModifier.makeInvalid(element.find('#el4')); | ||
expect(element.find('.help-block').length).to.equal(1); | ||
}); | ||
}); | ||
expect(element.find('.help-block').length).to.equal(1); | ||
}); | ||
}); | ||
describe('makeValid', function () { | ||
it('should remove the .has-error class and add the .has-success and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-error"><input type="text"/></div>'); | ||
describe('makeValid', function () { | ||
it('should remove the .has-error class and add the .has-success and .has-feedback classes', function () { | ||
var element = angular.element('<div class="form-group has-error"><input type="text"/></div>'); | ||
bootstrap3ElementModifier.makeValid(element); | ||
bootstrap3ElementModifier.makeValid(element); | ||
expect(element.hasClass('has-error')).to.equal(false); | ||
expect(element.hasClass('has-success')).to.equal(true); | ||
expect(element.hasClass('has-feedback')).to.equal(true); | ||
}); | ||
expect(element.hasClass('has-error')).to.equal(false); | ||
expect(element.hasClass('has-success')).to.equal(true); | ||
expect(element.hasClass('has-feedback')).to.equal(true); | ||
}); | ||
it('should add an OK icon when property "addValidationStateIcons" is true', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el1" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
it('should add an OK icon when property "addValidationStateIcons" is true', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el1" type="email" class="form-control" required="required" ng-model="model.email"></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
bootstrap3ElementModifier.makeValid(element.find('#el1')); | ||
bootstrap3ElementModifier.makeValid(element.find('#el1')); | ||
expect(element.find('.glyphicon.glyphicon-ok.form-control-feedback').length).to.equal(1); | ||
}); | ||
expect(element.find('.glyphicon.glyphicon-ok.form-control-feedback').length).to.equal(1); | ||
}); | ||
it('should remove the .error-msg element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el2" type="email" class="form-control" required="required" ng-model="model.email"><span class="help-block error-msg">help text</span></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
it('should remove the .error-msg element', function () { | ||
var element = angular.element('<div class="form-group"><div class="col-sm-10">' + | ||
'<input id="el2" type="email" class="form-control" required="required" ng-model="model.email"><span class="help-block error-msg">help text</span></div></div>'); | ||
bootstrap3ElementModifier.enableValidationStateIcons(true); | ||
bootstrap3ElementModifier.makeValid(element.find('#el2')); | ||
bootstrap3ElementModifier.makeValid(element.find('#el2')); | ||
expect(element.find('.help-block').length).to.equal(0); | ||
}); | ||
}); | ||
expect(element.find('.help-block').length).to.equal(0); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('jcs.autoValidate debounce', function () { | ||
var sandbox, $rootScope, $timeout, debounce; | ||
describe('jcs.autoValidate debounce', function () { | ||
var sandbox, $rootScope, $timeout, debounce; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('bootstrap3ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$timeout = $injector.get('$timeout'); | ||
debounce = $injector.get('jcs-debounce'); | ||
})); | ||
describe('bootstrap3ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$timeout = $injector.get('$timeout'); | ||
debounce = $injector.get('jcs-debounce'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
expect(debounce).to.not.equal(undefined); | ||
}); | ||
it('should be defined', function () { | ||
expect(debounce).to.not.equal(undefined); | ||
}); | ||
describe('debounce', function () { | ||
it('should return a function', function () { | ||
var debouceFn = debounce.debounce(angular.noop); | ||
describe('debounce', function () { | ||
it('should return a function', function () { | ||
var debouceFn = debounce.debounce(angular.noop); | ||
expect(typeof debouceFn === 'function').to.equal(true); | ||
}); | ||
expect(typeof debouceFn === 'function').to.equal(true); | ||
}); | ||
it('should execute immediately with a specified timeout', function () { | ||
var debouceFnCalledTimes = 0, | ||
debouceFn = debounce.debounce(function () { | ||
debouceFnCalledTimes += 1; | ||
}); | ||
it('should execute immediately with a specified timeout', function () { | ||
var debouceFnCalledTimes = 0, | ||
debouceFn = debounce.debounce(function () { | ||
debouceFnCalledTimes += 1; | ||
}); | ||
debouceFn(); | ||
debouceFn(); | ||
$timeout.flush(); | ||
$timeout.flush(); | ||
expect(debouceFnCalledTimes).to.equal(1); | ||
}); | ||
expect(debouceFnCalledTimes).to.equal(1); | ||
}); | ||
it('should only execute once when called multiple times', function () { | ||
var debouceFnCalledTimes = 0, | ||
debouceFn = debounce.debounce(function () { | ||
debouceFnCalledTimes += 1; | ||
}, 100); | ||
it('should only execute once when called multiple times', function () { | ||
var debouceFnCalledTimes = 0, | ||
debouceFn = debounce.debounce(function () { | ||
debouceFnCalledTimes += 1; | ||
}, 100); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
debouceFn(); | ||
$timeout.flush(); | ||
$timeout.flush(); | ||
expect(debouceFnCalledTimes).to.equal(1); | ||
}); | ||
}); | ||
expect(debouceFnCalledTimes).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('jcs-autoValidate defaultErrorMessageResolver', function () { | ||
var sandbox, $rootScope, $q, $httpBackend, defaultErrorMessageResolver; | ||
describe('jcs-autoValidate defaultErrorMessageResolver', function () { | ||
var sandbox, $rootScope, $q, $httpBackend, defaultErrorMessageResolver; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('defaultErrorMessageResolver', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$httpBackend = $injector.get('$httpBackend'); | ||
$q = $injector.get('$q'); | ||
defaultErrorMessageResolver = $injector.get('defaultErrorMessageResolver'); | ||
})); | ||
describe('defaultErrorMessageResolver', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$httpBackend = $injector.get('$httpBackend'); | ||
$q = $injector.get('$q'); | ||
defaultErrorMessageResolver = $injector.get('defaultErrorMessageResolver'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
expect(defaultErrorMessageResolver).to.exist; | ||
}); | ||
it('should be defined', function () { | ||
expect(defaultErrorMessageResolver).to.exist; | ||
}); | ||
describe('getErrorMessages', function () { | ||
it('should be an object', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages).to.not.equal(undefined); | ||
done(); | ||
}); | ||
describe('getErrorMessages', function () { | ||
it('should be an object', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key defaultMsg', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.defaultMsg).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key defaultMsg', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.defaultMsg).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key email', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.email).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key email', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.email).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key minlength', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.minlength).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key minlength', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.minlength).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key maxlength', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.maxlength).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key maxlength', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.maxlength).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key min', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.min).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key min', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.min).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key max', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.max).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key max', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.max).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key required', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.required).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key required', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.required).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key date', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.date).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key date', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.date).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key pattern', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.pattern).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key pattern', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.pattern).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key number', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.number).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key number', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.number).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should have the key url', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.url).to.not.equal(undefined); | ||
done(); | ||
}); | ||
it('should have the key url', function (done) { | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
expect(errorMessages.url).to.not.equal(undefined); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
describe('setI18nFileRootPath', function () { | ||
it('should be defined', function () { | ||
expect(defaultErrorMessageResolver.setI18nFileRootPath).to.not.equal(undefined); | ||
}); | ||
}); | ||
describe('setI18nFileRootPath', function () { | ||
it('should be defined', function () { | ||
expect(defaultErrorMessageResolver.setI18nFileRootPath).to.not.equal(undefined); | ||
}); | ||
}); | ||
describe('setCulture', function () { | ||
afterEach(function () { | ||
//$httpBackend.verifyNoOutstandingExpectation(); | ||
$httpBackend.verifyNoOutstandingRequest(); | ||
}); | ||
describe('setCulture', function () { | ||
afterEach(function () { | ||
//$httpBackend.verifyNoOutstandingExpectation(); | ||
$httpBackend.verifyNoOutstandingRequest(); | ||
}); | ||
it('should return with calling the loadingFn if the culture is already loaded', function (done) { | ||
var loadingFnCalled = false, | ||
loadingFn = function () { | ||
loadingFnCalled = true; | ||
}; | ||
it('should return with calling the loadingFn if the culture is already loaded', function (done) { | ||
var loadingFnCalled = false, | ||
loadingFn = function () { | ||
loadingFnCalled = true; | ||
}; | ||
defaultErrorMessageResolver.setCulture('en-gb', loadingFn).then(function () { | ||
expect(loadingFnCalled).to.equal(false); | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-gb', loadingFn).then(function () { | ||
expect(loadingFnCalled).to.equal(false); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should call the loading function if it is specified', function (done) { | ||
var loadingFnCalled = false, | ||
loadingFn = function () { | ||
var defer = $q.defer(); | ||
loadingFnCalled = true; | ||
defer.resolve({}); | ||
return defer.promise; | ||
}; | ||
it('should call the loading function if it is specified', function (done) { | ||
var loadingFnCalled = false, | ||
loadingFn = function () { | ||
var defer = $q.defer(); | ||
loadingFnCalled = true; | ||
defer.resolve({}); | ||
return defer.promise; | ||
}; | ||
defaultErrorMessageResolver.setCulture('fr-fr', loadingFn).then(function () { | ||
expect(loadingFnCalled).to.equal(true); | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('fr-fr', loadingFn).then(function () { | ||
expect(loadingFnCalled).to.equal(true); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should call $http to load the culture file with the correct url', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_fr-fr.json').respond(200, {}); | ||
it('should call $http to load the culture file with the correct url', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_fr-fr.json').respond(200, {}); | ||
defaultErrorMessageResolver.setCulture('fr-fr').then(function () { | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('fr-fr').then(function () { | ||
done(); | ||
}); | ||
$httpBackend.flush(); | ||
$httpBackend.flush(); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should call $http to load the culture file with the correct url by lower casing the culture code', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-es.json').respond(200, {}); | ||
it('should call $http to load the culture file with the correct url by lower casing the culture code', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-es.json').respond(200, {}); | ||
defaultErrorMessageResolver.setCulture('en-ES').then(function () { | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-ES').then(function () { | ||
done(); | ||
}); | ||
$httpBackend.flush(); | ||
$httpBackend.flush(); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should return the error in the promise when the load of a remote culture file fails', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-it.json').respond(404, { | ||
data: 'some error' | ||
}); | ||
it('should return the error in the promise when the load of a remote culture file fails', function (done) { | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-it.json').respond(404, { | ||
data: 'some error' | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-it').then(function () {}, function (err) { | ||
done(); | ||
expect(err.data).to.equal('some error'); | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-it').then(function () {}, function (err) { | ||
done(); | ||
expect(err.data).to.equal('some error'); | ||
}); | ||
$httpBackend.flush(); | ||
$httpBackend.flush(); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should call $http with the correct url path when the root has been set', function (done) { | ||
$httpBackend.expectGET('some/made/up/path/jcs-auto-validate_zh-cn.json').respond(200, {}); | ||
it('should call $http with the correct url path when the root has been set', function (done) { | ||
$httpBackend.expectGET('some/made/up/path/jcs-auto-validate_zh-cn.json').respond(200, {}); | ||
defaultErrorMessageResolver.setI18nFileRootPath('some/made/up/path'); | ||
defaultErrorMessageResolver.setI18nFileRootPath('some/made/up/path'); | ||
defaultErrorMessageResolver.setCulture('zh-cn').then(function () { | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('zh-cn').then(function () { | ||
done(); | ||
}); | ||
$httpBackend.flush(); | ||
$httpBackend.flush(); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should resolve the current waiting error message once the culture has been loaded.', function (done) { | ||
var requiredStr = 'required'; | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-fr.json').respond(200, { | ||
required: requiredStr | ||
}); | ||
it('should resolve the current waiting error message once the culture has been loaded.', function (done) { | ||
var requiredStr = 'required'; | ||
$httpBackend.expectGET('js/angular-auto-validate/dist/lang/jcs-auto-validate_en-fr.json').respond(200, { | ||
required: requiredStr | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-fr'); | ||
defaultErrorMessageResolver.resolve('required').then(function (msg) { | ||
expect(msg).to.equal(requiredStr); | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.setCulture('en-fr'); | ||
defaultErrorMessageResolver.resolve('required').then(function (msg) { | ||
expect(msg).to.equal(requiredStr); | ||
done(); | ||
}); | ||
$httpBackend.flush(); | ||
$httpBackend.flush(); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
describe('resolve', function () { | ||
it('should return a promise', function () { | ||
var promise = defaultErrorMessageResolver.resolve('required'); | ||
describe('resolve', function () { | ||
it('should return a promise', function () { | ||
var promise = defaultErrorMessageResolver.resolve('required'); | ||
expect(promise).to.not.equal(undefined); | ||
expect(promise.then).to.not.equal(undefined); | ||
}); | ||
expect(promise).to.not.equal(undefined); | ||
expect(promise.then).to.not.equal(undefined); | ||
}); | ||
it('should return the default error message when the error type is not found', function (done) { | ||
var errorType = 'not_present'; | ||
defaultErrorMessageResolver.resolve(errorType).then(function (msg) { | ||
expect(msg).to.equal('Please add error message for ' + errorType); | ||
done(); | ||
}); | ||
it('should return the default error message when the error type is not found', function (done) { | ||
var errorType = 'not_present'; | ||
defaultErrorMessageResolver.resolve(errorType).then(function (msg) { | ||
expect(msg).to.equal('Please add error message for ' + errorType); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should return only the error message if the element is undefined', function (done) { | ||
var errorType = 'required'; | ||
defaultErrorMessageResolver.resolve(errorType).then(function (msg) { | ||
expect(msg).to.equal('This field is required'); | ||
done(); | ||
}); | ||
it('should return only the error message if the element is undefined', function (done) { | ||
var errorType = 'required'; | ||
defaultErrorMessageResolver.resolve(errorType).then(function (msg) { | ||
expect(msg).to.equal('This field is required'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should replace parameters in error message it element is passed has data-* attribute of errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" data-ng-minlength="2" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter at least 2 characters'); | ||
done(); | ||
}); | ||
it('should replace parameters in error message it element is passed has data-* attribute of errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" data-ng-minlength="2" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter at least 2 characters'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should replace parameters in error message if element is passed has ng-* attribute of errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" ng-minlength="2" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter at least 2 characters'); | ||
done(); | ||
}); | ||
it('should replace parameters in error message if element is passed has ng-* attribute of errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" ng-minlength="2" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter at least 2 characters'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should default to the ng-* version of the attribute when replacing parameters in the meesage', function (done) { | ||
var errorType = 'max', | ||
element = angular.element('<input type="number" ng-max="2" max="2147483647" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter the maximum number of 2'); | ||
done(); | ||
}); | ||
it('should default to the ng-* version of the attribute when replacing parameters in the meesage', function (done) { | ||
var errorType = 'max', | ||
element = angular.element('<input type="number" ng-max="2" max="2147483647" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter the maximum number of 2'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should return an overridden error message type if the attribute is present on the element and contains the correct key', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" data-ng-minlength="2" ng-minlength-err-type="required" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('This field is required'); | ||
done(); | ||
}); | ||
it('should return an overridden error message type if the attribute is present on the element and contains the correct key', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" data-ng-minlength="2" ng-minlength-err-type="required" />'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('This field is required'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should replace parameters in error message if element is is overriding the error message type and using a parameter for the overridden errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" ng-minlength="3" ng-minlength-err-type="max"/>'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter the maximum number of 3'); | ||
done(); | ||
}); | ||
it('should replace parameters in error message if element is is overriding the error message type and using a parameter for the overridden errorType', function (done) { | ||
var errorType = 'minlength', | ||
element = angular.element('<input type="text" ng-minlength="3" ng-minlength-err-type="max"/>'); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal('Please enter the maximum number of 3'); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should return the overridden errorType for a custom validation type', function (done) { | ||
var errorType = 'validator', | ||
errorMessage = 'Please ensure the password you entered match', | ||
element = angular.element('<input type="password" ng-model="vm.confirmPassword" validator-err-type="invalidPassword_Confirmation" />'); | ||
it('should return the overridden errorType for a custom validation type', function (done) { | ||
var errorType = 'validator', | ||
errorMessage = 'Please ensure the password you entered match', | ||
element = angular.element('<input type="password" ng-model="vm.confirmPassword" validator-err-type="invalidPassword_Confirmation" />'); | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
errorMessages.invalidPassword_Confirmation = errorMessage; | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
errorMessages.invalidPassword_Confirmation = errorMessage; | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
it('should return the overridden errorType for a custom validation type which has invalid quote characters', function (done) { | ||
var errorType = 'validator', | ||
errorMessage = 'Please ensure the password you entered match', | ||
element = angular.element('<input type="password" ng-model="vm.confirmPassword" validator-err-type=“invalidPasswordConfirmation“ />'); | ||
it('should return the overridden errorType for a custom validation type which has invalid quote characters', function (done) { | ||
var errorType = 'validator', | ||
errorMessage = 'Please ensure the password you entered match', | ||
element = angular.element('<input type="password" ng-model="vm.confirmPassword" validator-err-type=“invalidPasswordConfirmation“ />'); | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
errorMessages.invalidPasswordConfirmation = errorMessage; | ||
defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) { | ||
errorMessages.invalidPasswordConfirmation = errorMessage; | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
}); | ||
defaultErrorMessageResolver.resolve(errorType, element).then(function (msg) { | ||
expect(msg).to.equal(errorMessage); | ||
done(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
$rootScope.$apply(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('angulartemplates.modules.form foundation5ElementModifier', function () { | ||
var sandbox, $rootScope, foundation5ElementModifier; | ||
describe('angulartemplates.modules.form foundation5ElementModifier', function () { | ||
var sandbox, $rootScope, foundation5ElementModifier; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('foundation5ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
foundation5ElementModifier = $injector.get('foundation5ElementModifier'); | ||
})); | ||
describe('foundation5ElementModifier', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
foundation5ElementModifier = $injector.get('foundation5ElementModifier'); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
it('should be defined', function () { | ||
expect(foundation5ElementModifier).to.not.equal(undefined); | ||
}); | ||
it('should be defined', function () { | ||
expect(foundation5ElementModifier).to.not.equal(undefined); | ||
}); | ||
describe('makeDefault', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
describe('makeDefault', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
it('should remove the error class from the input', function () { | ||
var element = angular.element('<input type="text" class="error"/>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
it('should remove the error class from the input', function () { | ||
var element = angular.element('<input type="text" class="error"/>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
it('should remove the error class from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
it('should remove the error class from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
it('should remove the small.error element from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /><small class="error">error text</small></div>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
it('should remove the small.error element from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /><small class="error">error text</small></div>'); | ||
foundation5ElementModifier.makeDefault(element); | ||
expect(element.find('small.error').length).to.equal(0); | ||
}); | ||
}); | ||
expect(element.find('small.error').length).to.equal(0); | ||
}); | ||
}); | ||
describe('makeValid', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
describe('makeValid', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
it('should remove the error class from the input', function () { | ||
var element = angular.element('<input type="text" class="error"/>'); | ||
foundation5ElementModifier.makeValid(element); | ||
it('should remove the error class from the input', function () { | ||
var element = angular.element('<input type="text" class="error"/>'); | ||
foundation5ElementModifier.makeValid(element); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
it('should remove the error class from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeValid(element); | ||
it('should remove the error class from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeValid(element); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
expect(element.hasClass('error')).to.equal(false); | ||
}); | ||
it('should remove the small.error element from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /><small class="error">error text</small></div>'); | ||
foundation5ElementModifier.makeValid(element); | ||
it('should remove the small.error element from the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns error"><input type="text" /><small class="error">error text</small></div>'); | ||
foundation5ElementModifier.makeValid(element); | ||
expect(element.find('small.error').length).to.equal(0); | ||
}); | ||
}); | ||
expect(element.find('small.error').length).to.equal(0); | ||
}); | ||
}); | ||
describe('makeInvalid', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
describe('makeInvalid', function () { | ||
/** | ||
* Foundation allows the .error class to be on either the element or the parent .column element. | ||
*/ | ||
it('should add the error class to the input element', function () { | ||
var element = angular.element('<input type="text" />'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
it('should add the error class to the input element', function () { | ||
var element = angular.element('<input type="text" />'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
expect(element.hasClass('error')).to.equal(true); | ||
}); | ||
expect(element.hasClass('error')).to.equal(true); | ||
}); | ||
it('should add the error class to the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
it('should add the error class to the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
expect(element.hasClass('error')).to.equal(true); | ||
}); | ||
expect(element.hasClass('error')).to.equal(true); | ||
}); | ||
it('should add the small.error element to the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
it('should add the small.error element to the parent element with .columns class', function () { | ||
var element = angular.element('<div class="columns"><input type="text" /></div>'); | ||
foundation5ElementModifier.makeInvalid(element); | ||
expect(element.find('small.error').length).to.equal(1); | ||
}); | ||
}); | ||
expect(element.find('small.error').length).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
(function (angular, sinon) { | ||
'use strict'; | ||
'use strict'; | ||
describe('jcs-autoValidate validationManager', function () { | ||
var sandbox, $rootScope, $compile, $q, validator, validationManager, modelCtrl, defer, elementUtils, | ||
setModelCtrl = function () { | ||
modelCtrl = { | ||
$parsers: [], | ||
$formatters: [], | ||
$name: 'name' | ||
}; | ||
}, | ||
compileElement = function (html, includesForm) { | ||
html = includesForm ? html : '<form ng-submit="">' + html + '</form>'; | ||
var element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
element = includesForm ? element : angular.element(element[0].children[0]); | ||
return element; | ||
}, | ||
getDefaultFormOptions = function () { | ||
return { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false | ||
}; | ||
}; | ||
describe('jcs-autoValidate validationManager', function () { | ||
var sandbox, $rootScope, $compile, $q, validator, validationManager, modelCtrl, defer, elementUtils, | ||
setModelCtrl = function () { | ||
modelCtrl = { | ||
$parsers: [], | ||
$formatters: [], | ||
$name: 'name' | ||
}; | ||
}, | ||
compileElement = function (html, includesForm) { | ||
html = includesForm ? html : '<form ng-submit="">' + html + '</form>'; | ||
var element = angular.element(html); | ||
$compile(element)($rootScope); | ||
$rootScope.$digest(); | ||
element = includesForm ? element : angular.element(element[0].children[0]); | ||
return element; | ||
}, | ||
getDefaultFormOptions = function () { | ||
return { | ||
forceValidation: false, | ||
disabled: false, | ||
validateNonVisibleControls: false, | ||
validateOnFormSubmit: false, | ||
formController: {} | ||
}; | ||
}; | ||
beforeEach(module('jcs-autoValidate')); | ||
beforeEach(module('jcs-autoValidate')); | ||
describe('validationManager', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
defer = $q.defer(); | ||
validator = $injector.get('validator'); | ||
validationManager = $injector.get('validationManager'); | ||
elementUtils = $injector.get('jcs-elementUtils'); | ||
describe('validationManager', function () { | ||
beforeEach(inject(function ($injector) { | ||
sandbox = sinon.sandbox.create(); | ||
$rootScope = $injector.get('$rootScope'); | ||
$compile = $injector.get('$compile'); | ||
$q = $injector.get('$q'); | ||
defer = $q.defer(); | ||
validator = $injector.get('validator'); | ||
validationManager = $injector.get('validationManager'); | ||
elementUtils = $injector.get('jcs-elementUtils'); | ||
sandbox.stub(validator, 'makeValid'); | ||
sandbox.stub(validator, 'makeInvalid'); | ||
sandbox.stub(validator, 'getErrorMessage').returns(defer.promise); | ||
sandbox.stub(validator, 'makeValid'); | ||
sandbox.stub(validator, 'makeInvalid'); | ||
sandbox.stub(validator, 'getErrorMessage').returns(defer.promise); | ||
setModelCtrl(); | ||
})); | ||
setModelCtrl(); | ||
})); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
setModelCtrl(); | ||
}); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
setModelCtrl(); | ||
}); | ||
it('should be defined', function () { | ||
expect(validationManager).to.exist; | ||
}); | ||
it('should be defined', function () { | ||
expect(validationManager).to.exist; | ||
}); | ||
describe('validateElement', function () { | ||
it('should return true if the control is pristine and not make the element valid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
describe('validateElement', function () { | ||
it('should return true if the control is pristine and not make the element valid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = true; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = true; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
it('should make the element valid and return true if the control is not pristine and has no validation requirements', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
it('should make the element valid and return true if the control is not pristine and has no validation requirements', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = false; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(true); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = false; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(true); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
it('should not validate the element if it is not visible on the screen', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
it('should not validate the element if it is not visible on the screen', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(false); | ||
modelCtrl.$pristine = false; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(false); | ||
modelCtrl.$pristine = false; | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
it('should validate the element if it is not visible on the screen as the form option validateNonVisibleControls is true', function () { | ||
var el = compileElement('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result, | ||
frmOptions = getDefaultFormOptions(); | ||
it('should validate the element if it is not visible on the screen as the form option validateNonVisibleControls is true', function () { | ||
var el = compileElement('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result, | ||
frmOptions = getDefaultFormOptions(); | ||
frmOptions.validateNonVisibleControls = true; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(false); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$errors = { | ||
required: true | ||
}; | ||
result = validationManager.validateElement(modelCtrl, el, frmOptions); | ||
frmOptions.validateNonVisibleControls = true; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(false); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$errors = { | ||
required: true | ||
}; | ||
result = validationManager.validateElement(modelCtrl, el, frmOptions); | ||
defer.resolve('error message'); | ||
$rootScope.$apply(); | ||
defer.resolve('error message'); | ||
$rootScope.$apply(); | ||
expect(result).to.equal(false); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(true); | ||
}); | ||
expect(result).to.equal(false); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(true); | ||
}); | ||
it('should validate the element regardless of whether there is a parent form', function () { | ||
var el = compileElement('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>', true), | ||
result, | ||
frmOptions = getDefaultFormOptions(); | ||
it('should validate the element regardless of whether there is a parent form', function () { | ||
var el = compileElement('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>', true), | ||
result, | ||
frmOptions = getDefaultFormOptions(); | ||
frmOptions.validateNonVisibleControls = true; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(false); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$errors = { | ||
required: true | ||
}; | ||
result = validationManager.validateElement(modelCtrl, el, frmOptions); | ||
frmOptions.validateNonVisibleControls = true; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$errors = { | ||
required: true | ||
}; | ||
result = validationManager.validateElement(modelCtrl, el, frmOptions); | ||
defer.resolve('error message'); | ||
$rootScope.$apply(); | ||
defer.resolve('error message'); | ||
$rootScope.$apply(); | ||
expect(result).to.equal(false); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(true); | ||
}); | ||
expect(result).to.equal(false); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(true); | ||
}); | ||
it('should call validator to make element valid when there are $formatters and the form is valid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne"/>'); | ||
it('should not validate the element if validateOnSubmit is true and the form has not been submitted yet', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" required="" ng-minlength="10"/>'), | ||
result; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = false; | ||
var formOptions = getDefaultFormOptions(); | ||
formOptions.formController.$submitted = false; | ||
formOptions.validateOnFormSubmit = true; | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(validator.makeValid.calledOnce).to.equal(true); | ||
expect(validator.makeValid.calledWith(el)).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$pristine = false; | ||
result = validationManager.validateElement(modelCtrl, el, formOptions); | ||
it('should call validator to make element invalid when there are $formatters and the form is invalid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" />'), | ||
errorMsg = 'msg'; | ||
expect(result).to.equal(true); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(false); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
it('should validate the element if validateOnSubmit is true and the form has been submitted', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne"/>'), | ||
result; | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
var formOptions = getDefaultFormOptions(); | ||
formOptions.formController.$submitted = true; | ||
formOptions.validateOnFormSubmit = true; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
defer.resolve('error message'); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
modelCtrl.$parsers.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
it('should call validator to make element invalid when there are $parsers and the form is invalid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne"/>'), | ||
errorMsg = 'msg'; | ||
result = validationManager.validateElement(modelCtrl, el, formOptions); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$parsers.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
$rootScope.$apply(); | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(result).to.equal(false); | ||
expect(validator.makeValid.called).to.equal(false); | ||
expect(validator.makeInvalid.called).to.equal(true); | ||
}); | ||
$rootScope.$apply(); | ||
it('should call validator to make element valid when there are $formatters and the form is valid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne"/>'); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = false; | ||
it('should return true if the input has no validation specified', function () { | ||
var el = angular.element('<input type="text" ng-model="propertyOne" />'), | ||
result; | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(validator.makeValid.calledOnce).to.equal(true); | ||
expect(validator.makeValid.calledWith(el)).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
it('should call validator to make element invalid when there are $formatters and the form is invalid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne" />'), | ||
errorMsg = 'msg'; | ||
expect(result).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
it('should call validator to make element valid it the control is marked as a custom form control', function () { | ||
var el = angular.element('<div type="text" ng-model="propOne" register-custom-form-control=""></div>'); | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = false; | ||
$rootScope.$apply(); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(validator.makeValid.calledOnce).to.equal(true); | ||
expect(validator.makeValid.calledWith(el)).to.equal(true); | ||
}); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
it('should call validator to make element invalid it the control is marked as a custom form control', function () { | ||
var el = angular.element('<div type="text" ng-model="propOne" register-custom-form-control=""></div>'), | ||
errorMsg = 'msg'; | ||
it('should call validator to make element invalid when there are $parsers and the form is invalid', function () { | ||
var el = angular.element('<input type="text" ng-model="propOne"/>'), | ||
errorMsg = 'msg'; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$parsers.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
}); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
describe('validateForm', function () { | ||
it('should return false it the form element is undefined', function () { | ||
var result = validationManager.validateForm(); | ||
it('should return true if the input has no validation specified', function () { | ||
var el = angular.element('<input type="text" ng-model="propertyOne" />'), | ||
result; | ||
expect(result).to.equal(false); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
result = validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
it('should return true it the form controller is set to not auto validate the form', function () { | ||
var form = compileElement('<form role="form" novalidate="novalidate" ng-submit="submit();" disable-dynamic-validation><input ng-model="name" required /></form>', true), | ||
result = validationManager.validateForm(form); | ||
expect(result).to.equal(true); | ||
}); | ||
expect(result).to.equal(true); | ||
}); | ||
it('should call validator to make element valid if the control is marked as a custom form control', function () { | ||
var el = angular.element('<div type="text" ng-model="propOne" register-custom-form-control=""></div>'); | ||
it('should only validate elements on the parent and not disabled subform', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
subFrm = compileElement('<ng-form name="subFrm1" disable-dynamic-validation></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="surname" ng-minlength="2" />', true), | ||
isValid; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = false; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
subFrm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('minlength', false); | ||
frm.append(subFrm); | ||
$rootScope.$apply(); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
expect(validator.makeValid.calledOnce).to.equal(true); | ||
expect(validator.makeValid.calledWith(el)).to.equal(true); | ||
}); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
it('should call validator to make element invalid it the control is marked as a custom form control', function () { | ||
var el = angular.element('<div type="text" ng-model="propOne" register-custom-form-control=""></div>'), | ||
errorMsg = 'msg'; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
modelCtrl.$formatters.push(angular.noop); | ||
modelCtrl.$pristine = false; | ||
modelCtrl.$invalid = true; | ||
modelCtrl.$error = { | ||
required: true | ||
}; | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
defer.resolve(errorMsg); | ||
validationManager.validateElement(modelCtrl, el, getDefaultFormOptions()); | ||
it('should only validate elements on the parent and not disabled subform where the subform is via an attribute', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
subFrm = compileElement('<div ng-form name="subFrm1" disable-dynamic-validation></div>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="surname" ng-minlength="2" />', true), | ||
isValid; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
subFrm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('minlength', false); | ||
frm.append(subFrm); | ||
$rootScope.$apply(); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
expect(validator.makeInvalid.calledWith(el, errorMsg)).to.equal(true); | ||
}); | ||
}); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
describe('validateForm', function () { | ||
it('should return false it the form element is undefined', function () { | ||
var result = validationManager.validateForm(); | ||
$rootScope.$apply(); | ||
expect(result).to.equal(false); | ||
}); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
it('should return true it the form controller is set to not auto validate the form', function () { | ||
var form = compileElement('<form role="form" novalidate="novalidate" ng-submit="submit();" disable-dynamic-validation><input ng-model="name" required /></form>', true), | ||
result = validationManager.validateForm(form); | ||
it('should call validator makeInvalid once when a single form input element is invalid', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
isValid; | ||
expect(result).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
it('should only validate elements on the parent and not disabled subform', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
subFrm = compileElement('<ng-form name="subFrm1" disable-dynamic-validation></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="surname" ng-minlength="2" />', true), | ||
isValid; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
subFrm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('minlength', false); | ||
frm.append(subFrm); | ||
$rootScope.$apply(); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
it('should call validator makeInvalid twice when a single form input element is invalid', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="name" ng-maxlength="2" />', true), | ||
isValid; | ||
it('should only validate elements on the parent and not disabled subform where the subform is via an attribute', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
subFrm = compileElement('<div ng-form name="subFrm1" disable-dynamic-validation></div>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="surname" ng-minlength="2" />', true), | ||
isValid; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
frm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('maxlength', false); | ||
inpt2.controller('ngModel').$pristine = false; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
subFrm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('minlength', false); | ||
frm.append(subFrm); | ||
$rootScope.$apply(); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledTwice).to.equal(true); | ||
}); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
it('should call validator makeInvalid once when a single form input element is invalid in a child ng-form', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
ngFrm = compileElement('<ng-form name="childFrm"></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
isValid; | ||
it('should call validator makeInvalid once when a single form input element is invalid', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
isValid; | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
ngFrm.append(inpt); | ||
frm.append(ngFrm); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
$rootScope.$apply(); | ||
it('should call validator makeInvalid once when a single form input element is invalid and the form is submitted', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" required="required" ng-minlength="2" />', true); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
$rootScope.$apply(); | ||
it('should call validator makeInvalid twice when a single form input element is invalid', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inpt2 = compileElement('<input type="text" ng-model="name" ng-maxlength="2" />', true), | ||
isValid; | ||
frm.on('submit', function (event) { | ||
event.preventDefault(); | ||
}); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
frm.append(inpt2); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
inpt2.controller('ngModel').$setValidity('maxlength', false); | ||
inpt2.controller('ngModel').$pristine = false; | ||
$rootScope.$apply(); | ||
defer.resolve('errorMsg'); | ||
frm.trigger('submit'); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledTwice).to.equal(true); | ||
}); | ||
describe('resetForm', function () { | ||
it('should call validator.makeDefault for every input type element in the form', function () { | ||
var frm = compileElement('<form name="frm1"><input type="text" ng-model="name" ng-minlength="2" /><input type="text" ng-model="lastname" ng-maxlength="2" /></form>', true); | ||
sandbox.stub(validator, 'makeDefault'); | ||
it('should call validator makeInvalid once when a single form input element is invalid in a child ng-form', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
ngFrm = compileElement('<ng-form name="childFrm"></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
isValid; | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
ngFrm.append(inpt); | ||
frm.append(ngFrm); | ||
inpt.controller('ngModel').$setValidity('minlength', false); | ||
inpt.controller('ngModel').$pristine = false; | ||
$rootScope.$apply(); | ||
validationManager.resetForm(frm); | ||
defer.resolve('errorMsg'); | ||
isValid = validationManager.validateForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(validator.makeDefault.calledTwice).to.equal(true); | ||
}); | ||
expect(isValid).to.equal(false); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
it('should call validator makeDefault once when a single form input element is invalid in a child ng-form', function () { | ||
var frm = compileElement('<form name="frm1"><ng-form name="childFrm"><input type="text" ng-model="name" ng-minlength="2" /></ng-form></form>', true); | ||
sandbox.stub(validator, 'makeDefault'); | ||
it('should call validator makeInvalid once when a single form input element is invalid and the form is submitted', function () { | ||
var frm = compileElement('<form name="frm1" ng-submit=""></form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" required="required" ng-minlength="2" />', true); | ||
$rootScope.$apply(); | ||
sandbox.stub(elementUtils, 'isElementVisible').returns(true); | ||
frm.append(inpt); | ||
$rootScope.$apply(); | ||
validationManager.resetForm(frm); | ||
frm.on('submit', function (event) { | ||
event.preventDefault(); | ||
}); | ||
$rootScope.$apply(); | ||
defer.resolve('errorMsg'); | ||
frm.trigger('submit'); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
$rootScope.$apply(); | ||
it('should set the model controller of the input element to pristine', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
ngFrm = compileElement('<ng-form name="childFrm"></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inptNgModelController = inpt.controller('ngModel'); | ||
expect(validator.makeInvalid.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
sandbox.stub(validator, 'makeDefault'); | ||
describe('resetForm', function () { | ||
it('should call validator.makeDefault for every input type element in the form', function () { | ||
var frm = compileElement('<form name="frm1"><input type="text" ng-model="name" ng-minlength="2" /><input type="text" ng-model="lastname" ng-maxlength="2" /></form>', true); | ||
sandbox.stub(validator, 'makeDefault'); | ||
ngFrm.append(inpt); | ||
frm.append(ngFrm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
inptNgModelController.$setViewValue('123'); | ||
$rootScope.$apply(); | ||
expect(inptNgModelController.$pristine).to.equal(false); | ||
validationManager.resetForm(frm); | ||
validationManager.resetForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
expect(validator.makeDefault.calledTwice).to.equal(true); | ||
}); | ||
expect(inptNgModelController.$pristine).to.equal(true); | ||
}); | ||
}); | ||
it('should call validator makeDefault once when a single form input element is invalid in a child ng-form', function () { | ||
var frm = compileElement('<form name="frm1"><ng-form name="childFrm"><input type="text" ng-model="name" ng-minlength="2" /></ng-form></form>', true); | ||
sandbox.stub(validator, 'makeDefault'); | ||
describe('resetElement', function () { | ||
it('should call validator.makeDefault with the given element', function () { | ||
var inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />'); | ||
$rootScope.$apply(); | ||
sandbox.stub(validator, 'makeDefault'); | ||
validationManager.resetForm(frm); | ||
$rootScope.$apply(); | ||
$rootScope.$apply(); | ||
validationManager.resetElement(inpt); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
$rootScope.$apply(); | ||
it('should set the model controller of the input element to pristine', function () { | ||
var frm = compileElement('<form name="frm1"></form>', true), | ||
ngFrm = compileElement('<ng-form name="childFrm"></ng-form>', true), | ||
inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />', true), | ||
inptNgModelController = inpt.controller('ngModel'); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
sandbox.stub(validator, 'makeDefault'); | ||
ngFrm.append(inpt); | ||
frm.append(ngFrm); | ||
$rootScope.$apply(); | ||
inptNgModelController.$setViewValue('123'); | ||
$rootScope.$apply(); | ||
expect(inptNgModelController.$pristine).to.equal(false); | ||
validationManager.resetForm(frm); | ||
$rootScope.$apply(); | ||
expect(inptNgModelController.$pristine).to.equal(true); | ||
}); | ||
}); | ||
describe('resetElement', function () { | ||
it('should call validator.makeDefault with the given element', function () { | ||
var inpt = compileElement('<input type="text" ng-model="name" ng-minlength="2" />'); | ||
sandbox.stub(validator, 'makeDefault'); | ||
$rootScope.$apply(); | ||
validationManager.resetElement(inpt); | ||
$rootScope.$apply(); | ||
expect(validator.makeDefault.calledOnce).to.equal(true); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}(angular, sinon)); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
63
6.78%4626
3.31%257537
-12.85%