Socket
Socket
Sign inDemoInstall

angular-form-for

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-form-for - npm Package Compare versions

Comparing version 1.6.1 to 1.7.2

templates/bootstrap/select-field/_multi-select.html

2

bower.json
{
"name": "angular-form-for",
"version": "1.6.1",
"version": "1.7.2",
"main": [

@@ -5,0 +5,0 @@ "./dist/form-for.css",

@@ -1,2 +0,2 @@

angular.module("formFor.bootstrapTemplates", []).run(["$templateCache", function($templateCache) {$templateCache.put("form-for/templates/checkbox-field.html","<div class=\"field checkbox-field\"\n ng-class=\"{disabled: disable || model.disabled, \'has-error\': model.error}\">\n\n <field-error error=\"model.error\"\n left-aligned=\"true\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <input aria-manager\n id=\"{{model.uid}}\"\n type=\"checkbox\"\n tabindex=\"{{tabIndex}}\"\n ng-model=\"model.bindable\"\n ng-disabled=\"disable || model.disabled\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n uid=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\">\n </field-label>\n</div>\n");
angular.module("formFor.bootstrapTemplates", []).run(["$templateCache", function($templateCache) {$templateCache.put("form-for/templates/checkbox-field.html","<div class=\"field checkbox-field\"\n ng-class=\"{disabled: disable || model.disabled, \'has-error\': model.error}\">\n\n <field-error error=\"model.error\"\n left-aligned=\"true\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <input aria-manager\n id=\"{{model.uid}}\"\n type=\"checkbox\"\n tabindex=\"{{tabIndex}}\"\n ng-model=\"model.bindable\"\n ng-disabled=\"disable || model.disabled\"\n ng-change=\"changed()\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n uid=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\">\n </field-label>\n</div>\n");
$templateCache.put("form-for/templates/collection-label.html","<div class=\"collection-label\" ng-class=\"{\'text-danger\': model.error}\">\n <field-label ng-if=\"label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <small ng-if=\"model.error\" class=\"text-danger\" ng-bind=\"model.error\"></small>\n</div>\n");

@@ -7,6 +7,8 @@ $templateCache.put("form-for/templates/field-error.html","<p ng-if=\"error\"\n id=\"{{uid}}\"\n class=\"text-danger\"\n ng-bind=\"error\">\n</p>\n");

$templateCache.put("form-for/templates/select-field-loading-indicator.html","<i class=\"fa fa-circle-o-notch fa-spin\"></i>\nLoading...\n");
$templateCache.put("form-for/templates/select-field.html","<div class=\"form-group\"\n ng-class=\"{ \'disabled\': disable || model.disabled,\n \'has-error\': model.error }\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{enableFiltering ? model.uid + \'-filter\' : model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error error=\"model.error\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <!-- Filtered dropdowns use a type-ahead style component -->\n <div ng-show=\"enableFiltering\" class=\"input-group\">\n <input aria-manager\n id=\"{{model.uid}}-filter\"\n type=\"search\" class=\"form-control filter-text-input\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"filter\"\n ng-click=\"filterTextClick($event)\"\n ng-focus=\"open()\"\n ng-keydown=\"keyDown($event)\">\n\n <ul class=\"dropdown-menu\" ng-class=\"{show: isOpen}\">\n <li ng-repeat=\"option in filteredOptions\"\n ng-class=\"{active: option === selectedOption || $index === mouseOverIndex}\">\n\n <a ng-bind=\"option[labelAttribute]\"\n ng-click=\"selectOption(option)\"\n ng-mouseenter=\"mouseOver($index)\">\n </a>\n </li>\n </ul>\n\n <span class=\"input-group-addon\" ng-click=\"setFilterFocus()\">\n <i class=\"caret\"></i>\n </span>\n </div>\n\n <!-- Unfiltered dropdowns use a regular [Bootstrap] select -->\n <select aria-manager\n ng-if=\"!enableFiltering && filteredOptions.length\"\n id=\"{{model.uid}}\"\n class=\"form-control\"\n tabindex=\"{{tabIndex}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n</div>\n");
$templateCache.put("form-for/templates/select-field.html","<div class=\"form-group\"\n ng-class=\"{ \'disabled\': disable || model.disabled,\n \'has-error\': model.error }\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{enableFiltering ? model.uid + \'-filter\' : model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error error=\"model.error\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <!-- Filtered dropdowns use a type-ahead style component -->\n <div ng-show=\"enableFiltering\" class=\"input-group\">\n <input aria-manager\n id=\"{{model.uid}}-filter\"\n type=\"search\" class=\"form-control filter-text-input\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"filter\"\n ng-click=\"filterTextClick($event)\"\n ng-focus=\"open()\"\n ng-keydown=\"keyDown($event)\">\n\n <ul class=\"dropdown-menu\" ng-class=\"{show: isOpen}\">\n <li ng-repeat=\"option in filteredOptions\"\n ng-class=\"{active: option === selectedOption || $index === mouseOverIndex}\">\n\n <a ng-bind=\"option[labelAttribute]\"\n ng-click=\"selectOption(option)\"\n ng-mouseenter=\"mouseOver($index)\">\n </a>\n </li>\n </ul>\n\n <span class=\"input-group-addon\" ng-click=\"setFilterFocus()\">\n <i class=\"caret\"></i>\n </span>\n </div>\n\n <!-- Unfiltered dropdowns use a regular [Bootstrap] select -->\n <select aria-manager\n ng-if=\"!enableFiltering && filteredOptions.length && !multiple\"\n id=\"{{model.uid}}\"\n class=\"form-control\"\n tabindex=\"{{tabIndex}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n\n <!-- Binding to the \'multiple\' attribute is not supported, even with ng-attr-multiple. -->\n <select aria-manager multiple\n ng-if=\"!enableFiltering && filteredOptions.length && multiple\"\n id=\"{{model.uid}}\"\n class=\"form-control\"\n tabindex=\"{{tabIndex}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n</div>\n");
$templateCache.put("form-for/templates/submit-button.html","<button ng-class=\"buttonClass || \'btn btn-default\'\"\n ng-disabled=\"disable || model.disabled\"\n tabindex=\"{{tabIndex}}\">\n\n <i ng-if=\"icon\" ng-class=\"icon\"></i>\n\n <span ng-bind-html=\"bindableLabel\"></span>\n</button>\n");
$templateCache.put("form-for/templates/text-field.html","<div class=\"form-group\"\n ng-class=\"{disabled: disable || model.disabled, \'has-error\': model.error}\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error error=\"model.error\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <div ng-class=\"{\'input-group\': iconBefore || iconAfter}\">\n <span ng-if=\"iconBefore\" class=\"input-group-addon\"\n ng-click=\"onIconBeforeClick()\">\n <i class=\"text-field-icon\" ng-class=\"iconBefore\"></i>\n </span>\n\n <span ng-if=\"!multiline\" ng-include src=\"\'form-for/templates/text-field/_input.html\'\"></span>\n\n <span ng-if=\"multiline\" ng-include src=\"\'form-for/templates/text-field/_textarea.html\'\"></span>\n\n <span ng-if=\"iconAfter\" class=\"input-group-addon\"\n ng-click=\"onIconAfterClick()\">\n <i class=\"text-field-icon\" ng-class=\"iconAfter\"></i>\n </span>\n </div>\n</div>\n");
$templateCache.put("form-for/templates/select-field/_multi-select.html","");
$templateCache.put("form-for/templates/select-field/_select.html","");
$templateCache.put("form-for/templates/text-field/_input.html","<input aria-manager\n\n id=\"{{model.uid}}\"\n class=\"form-control\"\n ng-disabled=\"disable || model.disabled\"\n\n type=\"{{type}}\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-model=\"model.bindable\"\n form-for-debounce=\"{{debounce}}\"\n ng-click=\"onFocus()\"\n ng-blur=\"onBlur()\" />\n");
$templateCache.put("form-for/templates/text-field/_textarea.html","<textarea aria-manager\n id=\"{{model.uid}}\"\n class=\"form-control\"\n ng-disabled=\"disable || model.disabled\"\n tabindex=\"{{tabIndex}}\"\n ng-attr-placeholder=\"{{placeholder}}\"\n rows=\"{{rows}}\"\n ng-model=\"model.bindable\"\n form-for-debounce=\"{{debounce}}\"\n ng-click=\"onFocus()\"\n ng-blur=\"onBlur()\">\n</textarea>\n");}]);

@@ -1,2 +0,2 @@

angular.module("formFor.defaultTemplates", []).run(["$templateCache", function($templateCache) {$templateCache.put("form-for/templates/checkbox-field.html","<div class=\"form-for-field\" ng-class=\"{\'invalid\': model.error}\">\n <field-error error=\"model.error\"\n left-aligned=\"true\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <input aria-manager\n id=\"{{model.uid}}\"\n type=\"checkbox\"\n tabindex=\"{{tabIndex}}\"\n ng-model=\"model.bindable\"\n ng-checked=\"checked\"\n ng-disabled=\"disable || model.disabled\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n uid=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\">\n </field-label>\n</div>\n");
angular.module("formFor.defaultTemplates", []).run(["$templateCache", function($templateCache) {$templateCache.put("form-for/templates/checkbox-field.html","<div class=\"form-for-field\" ng-class=\"{\'invalid\': model.error}\">\n <field-error error=\"model.error\"\n left-aligned=\"true\"\n uid=\"{{model.uid}}-error\">\n </field-error>\n\n <input aria-manager\n id=\"{{model.uid}}\"\n type=\"checkbox\"\n tabindex=\"{{tabIndex}}\"\n ng-model=\"model.bindable\"\n ng-checked=\"checked\"\n ng-disabled=\"disable || model.disabled\"\n ng-change=\"changed()\">\n\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n uid=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\">\n </field-label>\n</div>\n");
$templateCache.put("form-for/templates/collection-label.html","<div class=\"collection-label\">\n <field-label ng-if=\"label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <small field-error error=\"model.error\" left-aligned=\"true\"></small>\n</div>\n");

@@ -7,6 +7,8 @@ $templateCache.put("form-for/templates/field-error.html","<p ng-if=\"error\"\n id=\"{{uid}}\"\n class=\"field-error\" ng-class=\"{\'left-aligned\': leftAligned}\"\n ng-bind=\"error\">\n</p>\n");

$templateCache.put("form-for/templates/select-field-loading-indicator.html","<i class=\"fa fa-circle-o-notch fa-spin\"></i>\nLoading...\n");
$templateCache.put("form-for/templates/select-field.html","<div class=\"form-for-field with-icon-after\" ng-class=\"{\'invalid\': model.error}\">\n <field-label ng-if=\"label\"\n input-uid=\"{{enableFiltering ? model.uid + \'-filter\' : model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error uid=\"{{model.uid}}-error\" error=\"model.error\"></field-error>\n\n <!-- Unfiltered dropdowns use a regular <select> -->\n <select ng-if=\"!enableFiltering\" aria-manager\n id=\"{{model.uid}}\"\n class=\"select-field-select\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n\n <i ng-if=\"!enableFiltering\" class=\"form-for-select-arrows\"></i>\n\n <!-- Filtered dropdowns use a type-ahead style component -->\n <input ng-show=\"enableFiltering\"\n aria-manager\n id=\"{{model.uid}}-filter\"\n type=\"search\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"filter\"\n ng-click=\"filterTextClick($event)\"\n ng-focus=\"open()\"\n ng-keydown=\"keyDown($event)\">\n\n <ul ng-if=\"enableFiltering\">\n <li ng-repeat=\"option in filteredOptions\"\n ng-class=\"{ \'form-for-typeahead-list-item-active\': option === selectedOption,\n \'form-for-typeahead-list-item-hover\': $index === mouseOverIndex}\"\n ng-bind=\"option[labelAttribute]\"\n ng-click=\"selectOption(option)\"\n ng-mouseenter=\"mouseOver($index)\">\n </li>\n </ul>\n\n <i ng-if=\"enableFiltering\" class=\"form-for-input-icon-right fa fa-search\"></i>\n</div>\n");
$templateCache.put("form-for/templates/select-field.html","<div class=\"form-for-field with-icon-after\" ng-class=\"{\'invalid\': model.error}\">\n <field-label ng-if=\"label\"\n input-uid=\"{{enableFiltering ? model.uid + \'-filter\' : model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error uid=\"{{model.uid}}-error\" error=\"model.error\"></field-error>\n\n <!-- Unfiltered dropdowns use a regular <select> -->\n <select ng-if=\"!enableFiltering && !multiple\" aria-manager\n id=\"{{model.uid}}\"\n class=\"select-field-select\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n\n <!-- Binding to the \'multiple\' attribute is not supported, even with ng-attr-multiple. -->\n <select ng-if=\"!enableFiltering && multiple\" aria-manager multiple\n id=\"{{model.uid}}\"\n class=\"select-field-select\"\n tabindex=\"{{tabIndex}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"model.bindable\"\n ng-options=\"option[valueAttribute] as option[labelAttribute] for option in filteredOptions\">\n </select>\n\n <i ng-if=\"!enableFiltering\" class=\"form-for-select-arrows\"></i>\n\n <!-- Filtered dropdowns use a type-ahead style component -->\n <input ng-show=\"enableFiltering\"\n aria-manager\n id=\"{{model.uid}}-filter\"\n type=\"search\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-disabled=\"disable || model.disabled\"\n ng-model=\"filter\"\n ng-click=\"filterTextClick($event)\"\n ng-focus=\"open()\"\n ng-keydown=\"keyDown($event)\">\n\n <ul ng-if=\"enableFiltering\">\n <li ng-repeat=\"option in filteredOptions\"\n ng-class=\"{ \'form-for-typeahead-list-item-active\': option === selectedOption,\n \'form-for-typeahead-list-item-hover\': $index === mouseOverIndex}\"\n ng-bind=\"option[labelAttribute]\"\n ng-click=\"selectOption(option)\"\n ng-mouseenter=\"mouseOver($index)\">\n </li>\n </ul>\n\n <i ng-if=\"enableFiltering\" class=\"form-for-input-icon-right fa fa-search\"></i>\n</div>\n");
$templateCache.put("form-for/templates/submit-button.html","<button class=\"submit-button\" ng-class=\"buttonClass\"\n ng-disabled=\"disable || model.disabled\"\n role=\"button\"\n tabindex=\"{{tabIndex}}\">\n\n <i ng-if=\"icon\" class=\"submit-button-icon\" ng-class=\"icon\"></i>\n\n <span ng-bind-html=\"bindableLabel\"></span>\n</button>\n");
$templateCache.put("form-for/templates/text-field.html","<div class=\"form-for-field\" ng-class=\"{ \'invalid\': model.error, \'with-icon-after\': iconAfter, \'with-icon-before\': iconBefore }\">\n <field-label ng-if=\"label\"\n input-uid=\"{{model.uid}}\"\n iud=\"{{model.uid}}-label\"\n label=\"{{label}}\"\n help=\"{{help}}\"\n required=\"{{model.required}}\">\n </field-label>\n\n <field-error uid=\"{{model.uid}}-error\" error=\"model.error\"></field-error>\n\n <!-- <input> and <textarea> rendered as partials to allow for easier overrides -->\n <span ng-if=\"!multiline\" ng-include src=\"\'form-for/templates/text-field/_input.html\'\"></span>\n <span ng-if=\"multiline\" ng-include src=\"\'form-for/templates/text-field/_textarea.html\'\"></span>\n\n <i class=\"form-for-input-icon-left\" ng-class=\"iconBefore\"></i>\n <i class=\"form-for-input-icon-right\" ng-class=\"iconAfter\"></i>\n</div>\n");
$templateCache.put("form-for/templates/select-field/_multi-select.html","");
$templateCache.put("form-for/templates/select-field/_select.html","");
$templateCache.put("form-for/templates/text-field/_input.html","<input aria-manager\n id=\"{{model.uid}}\"\n type=\"{{type}}\"\n tabindex=\"{{tabIndex}}\"\n placeholder=\"{{placeholder}}\"\n ng-model=\"model.bindable\"\n ng-disabled=\"disable || model.disabled\"\n form-for-debounce=\"{{debounce}}\"\n ng-click=\"onFocus()\"\n ng-blur=\"onBlur()\" />\n");
$templateCache.put("form-for/templates/text-field/_textarea.html","<textarea aria-manager\n id=\"{{model.uid}}\"\n tabindex=\"{{tabIndex}}\"\n ng-attr-placeholder=\"{{placeholder}}\"\n rows=\"{{rows}}\"\n ng-model=\"model.bindable\"\n ng-disabled=\"disable || model.disabled\"\n form-for-debounce=\"{{debounce}}\"\n ng-click=\"onFocus()\"\n ng-blur=\"onBlur()\">\n</textarea>\n");}]);

@@ -1,1 +0,1 @@

angular.module("formFor",[]),angular.module("formFor").directive("ariaManager",function(){return{restrict:"A",link:function(e,t,r){e.$watch("model.uid",function(e){r.$set("ariaDescribedby",e+"-error"),r.$set("ariaLabelledby",e+"-label")}),e.$watch("model.error",function(e){r.$set("ariaInvalid",!!e)})}}}),angular.module("formFor").directive("checkboxField",["$log","FieldHelper",function(e,t){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/checkbox-field.html",scope:{attribute:"@",disable:"=",help:"@?"},link:function(r,i,o,a){if(!r.attribute)return void e.error('Missing required field "attribute"');r.tabIndex=o.tabIndex||0;i.find("input");r.toggle=function(){r.disable||r.model.disabled||(r.model.bindable=!r.model.bindable)},t.manageLabel(r,o),t.manageFieldRegistration(r,o,a)}}}]),angular.module("formFor").directive("collectionLabel",["$sce","FormForConfiguration",function(e){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/collection-label.html",scope:{attribute:"@",help:"@?",label:"@"},link:function(t,r,i,o){t.$watch("label",function(r){t.bindableLabel=e.trustAsHtml(r)}),t.model=o.registerCollectionLabel(t.attribute)}}}]),angular.module("formFor").directive("fieldError",["$sce","FormForConfiguration",function(){return{restrict:"EA",templateUrl:"form-for/templates/field-error.html",scope:{error:"=",leftAligned:"@?",uid:"@"}}}]),angular.module("formFor").directive("fieldLabel",["$sce","FormForConfiguration",function(e,t){return{restrict:"EA",replace:!0,templateUrl:"form-for/templates/field-label.html",scope:{inputUid:"@",help:"@?",label:"@",required:"@?",uid:"@"},controller:["$scope",function(r){r.$watch("label",function(t){r.bindableLabel=e.trustAsHtml(t)}),r.$watch("required",function(e){r.requiredLabel=r.$eval(e)?t.requiredLabel:null})}]}}]),angular.module("formFor").directive("formForDebounce",["$log","$sniffer","$timeout","FormForConfiguration",function(e,t,r,i){return{restrict:"A",require:"ngModel",priority:99,link:function(o,a,n,l){if("radio"===n.type||"checkbox"===n.type)return void e.warn("formForDebounce should only be used with <input type=text> and <textarea> elements");var u,s=n.formForDebounce,d=i.defaultDebounceDuration;if(void 0!==s&&("false"===s.toString()?d=!1:(s=parseInt(s),angular.isNumber(s)&&!isNaN(s)&&(d=s))),t.hasEvent("input")?a.off("input"):(a.off("keydown"),t.hasEvent("paste")&&a.off("paste")),d!==!1){var c=function(){r.cancel(u),u=r(function(){o.$apply(function(){l.$setViewValue(a.val())})},d)};t.hasEvent("input")?a.on("input",c):(a.on("keydown",c),t.hasEvent("paste")&&a.on("paste",c))}a.on("blur",function(){o.$apply(function(){l.$setViewValue(a.val())})}),o.$on("$destroy",function(){u&&r.cancel(u)})}}}]),angular.module("formFor").directive("formFor",["$injector","$log","$parse","$q","$sce","FormForConfiguration","$FormForStateHelper","$FormForGUID","NestedObjectHelper","ModelValidator",function(e,t,r,i,o,a,n,l,u,s){return{require:"form",restrict:"A",scope:{controller:"=?",disable:"=?",formFor:"=",service:"@",submitComplete:"&?",submitError:"&?",submitWith:"&?",valid:"=?",validateOn:"=?",validationFailed:"&?",validationRules:"=?"},controller:["$scope",function(a){a.formFor||t.error('The form data object specified by <form form-for=""> is null or undefined.'),a.fields={},a.collectionLabels={},a.buttons=[],a.service&&(a.$service=e.get(a.service)),a.$validationRules=a.$service?a.$service.validationRules:a.validationRules;var d=this;d.registerFormField=function(e){if(!e)throw Error('Invalid field name "'+e+'" provided.');var t=u.flattenAttribute(e);if(a.fields.hasOwnProperty(t))throw Error('Field "'+e+'" has already eben registered. Field names must be unique.');var i=(u.readAttribute(a.$validationRules,e),{bindableWrapper:{bindable:null,disabled:a.disable,error:null,pristine:!0,required:s.isFieldRequired(e,a.$validationRules),uid:l.create()},fieldName:e,unwatchers:[],validationAttribute:e.split("[")[0]});a.fields[t]=i;var o=r(e),n=o.assign;i.unwatchers.push(a.$watch("fields."+t+".bindableWrapper.bindable",function(e,t){e!==t&&n(a.formFor,e)}));var c;return i.unwatchers.push(a.$watch("formFor."+e,function(r,o){(r!==i.bindableWrapper.bindable||void 0===o&&""===r||void 0===r)&&(c=!1),i.bindableWrapper.bindable=r,a.validateOn&&"change"!==a.validateOn||d.validateField(e),c||(c=!0,a.formForStateHelper.setFieldHasBeenModified(t,!1)),i.bindableWrapper.pristine=!a.formForStateHelper.hasFieldBeenModified(t)})),i.bindableWrapper},this.unregisterFormField=function(e){var t=u.flattenAttribute(e);angular.forEach(a.fields[t].unwatchers,function(e){e()}),delete a.fields[t]},d.registerSubmitButton=function(){var e={disabled:!1};return a.buttons.push(e),e},d.registerCollectionLabel=function(e){var t=u.flattenAttribute(e),r={error:null,required:s.isCollectionRequired(e,a.$validationRules)};a.collectionLabels[t]=r;var i=!1;return a.$watch("formFor."+e+".length",function(){i?a.validateOn&&"change"!==a.validateOn||s.validateCollection(a.formFor,e,a.$validationRules).then(function(){a.formForStateHelper.setFieldError(t,null)},function(e){a.formForStateHelper.setFieldError(t,e)}):i=!0}),r},d.resetField=function(e){var t=u.flattenAttribute(e);a.formForStateHelper.getFieldError(t)&&(a.formForStateHelper.setFieldHasBeenModified(t,!1),a.fields[t].bindableWrapper.pristine=!0),a.formForStateHelper.setFieldError(t,null)},d.resetErrors=function(){for(var e in a.fields)a.formForStateHelper.getFieldError(e)&&(a.formForStateHelper.setFieldHasBeenModified(e,!1),a.fields[e].bindableWrapper.pristine=!0);a.formForStateHelper.setFormSubmitted(!1),a.formForStateHelper.resetFieldErrors()},d.resetFields=d.resetErrors,d.setFieldError=function(e,t){var r=u.flattenAttribute(e);a.formForStateHelper.setFieldHasBeenModified(r,!0),a.formForStateHelper.setFieldError(r,t)},d.validateField=function(e){{var t=u.flattenAttribute(e);a.fields[t],r(e)(a.formFor)}a.formForStateHelper.setFieldHasBeenModified(t,!0),a.$validationRules&&s.validateField(a.formFor,e,a.$validationRules).then(function(){a.formForStateHelper.setFieldError(t,null)},function(e){a.formForStateHelper.setFieldError(t,e)})},d.validateForm=function(){a.updateCollectionErrors({}),a.updateFieldErrors({});var e,t;if(a.$validationRules){var r=[];angular.forEach(a.fields,function(e){r.push(e.fieldName)}),t=s.validateFields(a.formFor,r,a.$validationRules),t.then(angular.noop,a.updateFieldErrors),r=[],angular.forEach(a.collectionLabels,function(e,t){r.push(t)}),e=s.validateFields(a.formFor,r,a.$validationRules),e.then(angular.noop,a.updateCollectionErrors)}else e=i.resolve(),t=i.resolve();var o=i.defer();return i.waitForAll([e,t]).then(o.resolve,function(e){angular.isArray(e[0])&&0===e[0].length&&e.splice(0,1),o.reject(e)}),o.promise},a.controller=a.controller||{},angular.copy(d,a.controller),a.$watch("disable",function(e){angular.forEach(a.fields,function(t){t.bindableWrapper.disabled=e}),angular.forEach(a.buttons,function(t){t.disabled=e})}),a.formForStateHelper=new n(a),a.$watch("formForStateHelper.watchable",function(){var e=a.formForStateHelper.hasFormBeenSubmitted();angular.forEach(a.fields,function(t,r){if(e||a.formForStateHelper.hasFieldBeenModified(r)){var i=a.formForStateHelper.getFieldError(r);t.bindableWrapper.error=i?o.trustAsHtml(i):null}else t.bindableWrapper.error=null}),angular.forEach(a.collectionLabels,function(e,t){var r=a.formForStateHelper.getFieldError(t);e.error=r?o.trustAsHtml(r):null})}),a.updateCollectionErrors=function(e){angular.forEach(a.collectionLabels,function(t,r){var i=u.readAttribute(e,r);a.formForStateHelper.setFieldError(r,i)})},a.updateFieldErrors=function(e){angular.forEach(a.fields,function(t,r){var i=u.readAttribute(e,t.fieldName);a.formForStateHelper.setFieldError(r,i)})}}],link:function(e,t,r){t.on("submit",function(){e.formForStateHelper.setFormSubmitted(!0),e.disable=!0;var t;return t="manual"===e.validateOn?i.resolve():e.controller.validateForm(),t.then(function(){var t;t=r.submitWith?e.submitWith({data:e.formFor}):e.$service&&e.$service.submit?e.$service.submit(e.formFor):i.reject("No submit function provided"),t||(t=i.reject("Submit function did not return a promise")),t.then(function(t){r.submitComplete?e.submitComplete({data:t}):a.defaultSubmitComplete(t)},function(t){angular.isObject(t)&&"manual"!==e.validateOn&&(e.updateCollectionErrors(t),e.updateFieldErrors(t)),r.submitError?e.submitError({error:t}):a.defaultSubmitError(t)}),t["finally"](function(){e.disable=!1})},function(){e.disable=!1,r.validationFailed?e.validationFailed():a.defaultValidationFailed()}),!1})}}}]),angular.module("formFor").directive("radioField",["$log","$FormForGUID","FieldHelper",function(e,t,r){var i={};return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/radio-field.html",scope:{attribute:"@",disable:"=",help:"@?",value:"@"},link:function(o,a,n,l){if(!o.attribute)return void e.error('Missing required field "attribute"');if(i[o.attribute])o.hideErrorMessage=!0;else{var u={defaultScope:o,scopes:[]};r.manageFieldRegistration(o,n,l),i[o.attribute]=u}o.uid=n.uid||t.create();var s=i[o.attribute];s.scopes.push(o),r.manageLabel(o,n,!0),o.tabIndex=n.tabIndex||0;a.find("input");o.click=function(){o.disable||o.model.disabled||(o.model.bindable=o.value)},s.defaultScope.$watch("model",function(e){o.model=e}),s.defaultScope.$watch("disable",function(e){o.disable=e}),s.defaultScope.$watch("model.disabled",function(e){o.model&&(o.model.disabled=e)}),o.$watch("model.bindable",function(e){o.checked=void 0!==e&&null!==e&&void 0!==o.value&&null!==o.value&&e.toString()===o.value.toString()}),o.$on("$destroy",function(){s.scopes.splice(s.scopes.indexOf(o),1),0===s.scopes.length&&delete i[o.attribute]})}}}]),angular.module("formFor").directive("selectField",["$document","$log","$timeout","$window","FieldHelper",function(e,t,r,i,o){var a=10;return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/select-field.html",scope:{attribute:"@",disable:"=",filter:"=?",filterDebounce:"@?",help:"@?",options:"="},link:function(n,l,u,s){if(i=angular.element(i),!n.attribute)return void t.error('Missing required field "attribute"');n.allowBlank=u.hasOwnProperty("allowBlank"),n.enableFiltering=u.hasOwnProperty("enableFiltering"),n.preventDefaultOption=u.hasOwnProperty("preventDefaultOption"),n.labelAttribute=u.labelAttribute||"label",n.valueAttribute=u.valueAttribute||"value",n.placeholder=u.placeholder||"Select",n.tabIndex=u.tabIndex||0,o.manageLabel(n,u),o.manageFieldRegistration(n,u,s);var d=function(e){var t=e[0];r(t.focus.bind(t))};n.close=function(){r(function(){n.isOpen=!1})},n.open=function(){n.disable||n.model.disabled||r(function(){n.isOpen=!0})},n.emptyOption={},n.emptyOption[n.labelAttribute]="",n.emptyOption[n.valueAttribute]=void 0,n.placeholderOption={},n.placeholderOption[n.labelAttribute]=n.placeholder,n.placeholderOption[n.valueAttribute]=void 0,n.filteredOptions=[];var c=function(e){return e&&e.toLowerCase()},f=function(){var e=n.options||[];if(n.filteredOptions.splice(0),n.enableFiltering&&n.filter){var t=c(n.filter);angular.forEach(e,function(e){var r=c(e[n.labelAttribute]).indexOf(t);r>=0&&n.filteredOptions.push(e)})}else angular.copy(e,n.filteredOptions);n.selectedOption?n.allowBlank&&n.filteredOptions.unshift(n.emptyOption):n.filteredOptions.unshift(n.placeholderOption)};n.$watch("filter",f),n.$watch("options.length",f);var m=function(){var e=n.selectedOption&&n.selectedOption[[n.valueAttribute]];return n.model.bindable===e?void(!n.allowBlank&&!n.preventDefaultOption&&n.options&&n.options.length&&(n.model.bindable=n.options[0][n.valueAttribute])):void 0};n.$watch("model.bindable",m),n.$watch("options.length",m),n.$watch("model.bindable",function(){var e;angular.forEach(n.options,function(t){t[n.valueAttribute]===n.model.bindable&&(e=t)}),n.selectedOption=e,n.selectedOptionLabel=e&&e[n.labelAttribute],n.filter=n.selectedOptionLabel});var p=function(e){e.ignoreFor!==n.model.uid&&n.close()};n.filterTextClick=function(){n.isOpen&&(event.ignoreFor=n.model.uid)};var b;n.$watch("isOpen",function(){b&&r.cancel(b),b=r(function(){b=null,n.isOpen?e.on("click",p):e.off("click",p)},a)}),n.$on("$destroy",function(){e.off("click",p)});var F=l.find("input");n.setFilterFocus=function(){d(F)},n.mouseOver=function(e){n.mouseOverIndex=e,n.mouseOverOption=e>=0?n.filteredOptions[e]:null},n.selectOption=function(e){n.model.bindable=e&&e[n.valueAttribute]},n.keyDown=function(e){switch(e.keyCode){case 27:n.close();break;case 13:n.isOpen?(n.selectOption(n.mouseOverOption),n.close()):n.open(),e.preventDefault();break;case 38:n.isOpen?n.mouseOver(n.mouseOverIndex>0?n.mouseOverIndex-1:n.filteredOptions.length-1):n.open();break;case 40:n.isOpen?n.mouseOver(n.mouseOverIndex<n.filteredOptions.length-1?n.mouseOverIndex+1:0):n.open();break;case 9:case 16:n.close();break;default:n.open()}},n.$watchCollection("[isOpen, filteredOptions.length]",function(){n.mouseOver(-1),n.isOpen&&n.enableFiltering&&d(F)})}}}]),angular.module("formFor").directive("submitButton",["$log","$sce",function(e,t){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/submit-button.html",scope:{disable:"=",icon:"@",label:"@"},link:function(e,r,i,o){e.buttonClass=i.buttonClass,e.tabIndex=i.tabIndex||0,e.$watch("label",function(r){e.bindableLabel=t.trustAsHtml(r)}),e.model=o.registerSubmitButton(e)}}}]),angular.module("formFor").directive("textField",["$log","$timeout","FieldHelper",function(e,t,r){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/text-field.html",scope:{attribute:"@",debounce:"@?",disable:"=",focused:"&?",blurred:"&?",help:"@?",iconAfterClicked:"&?",iconBeforeClicked:"&?",placeholder:"@?",rows:"=?"},link:function(i,o,a,n){if(!i.attribute)return void e.error('Missing required field "attribute"');if(i.attributes=a,i.rows=i.rows||3,i.type=a.type||"text",i.multiline=a.hasOwnProperty("multiline")&&"false"!==a.multiline,i.tabIndex=a.tabIndex||0,a.hasOwnProperty("autofocus")&&t(function(){o.find(i.multiline?"textarea":"input")[0].focus()}),r.manageLabel(i,a),r.manageFieldRegistration(i,a,n),a.iconAfter){var l=function(){if(i.model){var e="{"===a.iconAfter.charAt(0)?i.$eval(a.iconAfter):a.iconAfter;i.iconAfter=angular.isObject(e)?i.model.error?e.invalid:i.model.pristine?e.pristine:e.valid:e}};a.$observe("iconAfter",l),i.$watch("model.error",l),i.$watch("model.pristine",l)}if(a.iconBefore){var u=function(){if(i.model){var e="{"===a.iconBefore.charAt(0)?i.$eval(a.iconBefore):a.iconBefore;i.iconBefore=angular.isObject(e)?i.model.error?e.invalid:i.model.pristine?e.pristine:e.valid:e}};a.$observe("iconBefore",u),i.$watch("model.error",u),i.$watch("model.pristine",u)}i.onIconAfterClick=function(){a.hasOwnProperty("iconAfterClicked")&&i.iconAfterClicked()},i.onIconBeforeClick=function(){a.hasOwnProperty("iconBeforeClicked")&&i.iconBeforeClicked()},i.onFocus=function(){a.hasOwnProperty("focused")&&i.focused()},i.onBlur=function(){a.hasOwnProperty("blurred")&&i.blurred()}}}}]),angular.module("formFor").service("FieldHelper",["FormForConfiguration","StringUtil",function(e,t){this.manageLabel=function(r,i,o){i.hasOwnProperty("label")&&i.$observe("label",function(e){r.label=e}),e.autoGenerateLabels&&(r.label=t.humanize(o?r.value:r.attribute))},this.manageFieldRegistration=function(e,t,r){e.$watch("attribute",function(i,o){e.model&&r.unregisterFormField(o),e.model=r.registerFormField(e.attribute),t.uid&&(e.model.uid=t.uid)}),e.$on("$destroy",function(){r.unregisterFormField(e.attribute)})}}]),angular.module("formFor").service("FormForConfiguration",function(){return{autoGenerateLabels:!1,defaultDebounceDuration:500,defaultSubmitComplete:angular.noop,defaultSubmitError:angular.noop,defaultValidationFailed:angular.noop,requiredLabel:null,validationFailedForCustomMessage:"Failed custom validation",validationFailedForPatternMessage:"Invalid format",validationFailedForMaxCollectionSizeMessage:"Must be fewer than {{num}} items",validationFailedForMaxLengthMessage:"Must be fewer than {{num}} characters",validationFailedForMinCollectionSizeMessage:"Must at least {{num}} items",validationFailedForMinLengthMessage:"Must be at least {{num}} characters",validationFailedForRequiredMessage:"Required field",validationFailedForEmailTypeMessage:"Invalid email format",validationFailedForIntegerTypeMessage:"Must be an integer",validationFailedForNegativeTypeMessage:"Must be negative",validationFailedForNumericTypeMessage:"Must be numeric",validationFailedForPositiveTypeMessage:"Must be positive",disableAutoLabels:function(){this.autoGenerateLabels=!1},enableAutoLabels:function(){this.autoGenerateLabels=!0},setDefaultDebounceDuration:function(e){this.defaultDebounceDuration=e},setDefaultSubmitComplete:function(e){this.defaultSubmitComplete=e},setDefaultSubmitError:function(e){this.defaultSubmitError=e},setDefaultValidationFailed:function(e){this.defaultValidationFailed=e},setRequiredLabel:function(e){this.requiredLabel=e},setValidationFailedForCustomMessage:function(e){this.validationFailedForCustomMessage=e},setValidationFailedForMaxCollectionSizeMessage:function(e){this.validationFailedForMaxCollectionSizeMessage=e},setValidationFailedForMaxLengthMessage:function(e){this.validationFailedForMaxLengthMessage=e},setValidationFailedForMinCollectionSizeMessage:function(e){this.validationFailedForMaxCollectionSizeMessage=e},setValidationFailedForMinLengthMessage:function(e){this.validationFailedForMinLengthMessage=e},setValidationFailedForPatternMessage:function(e){this.validationFailedForPatternMessage=e},setValidationFailedForRequiredMessage:function(e){this.validationFailedForRequiredMessage=e},setValidationFailedForEmailTypeMessage:function(e){this.validationFailedForEmailTypeMessage=e},setValidationFailedForIntegerTypeMessage:function(e){this.validationFailedForIntegerTypeMessage=e},setValidationFailedForNegativeTypeMessage:function(e){this.validationFailedForNegativeTypeMessage=e},setValidationFailedForNumericTypeMessage:function(e){this.validationFailedForNumericTypeMessage=e},setValidationFailedForPositiveTypeMessage:function(e){this.validationFailedForPositiveTypeMessage=e}}}),angular.module("formFor").service("$FormForGUID",function(){return{create:function(){return("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)}}}),angular.module("formFor").factory("$FormForStateHelper",["NestedObjectHelper",function(e){var t=function(e){e.errorMap=e.errorMap||{},e.valid=!0,this.formScope=e,this.fieldNameToModificationMap={},this.formSubmitted=!1,this.shallowErrorMap={},this.watchable=0};return t.prototype.getFieldError=function(t){return e.readAttribute(this.formScope.errorMap,t)},t.prototype.hasFieldBeenModified=function(t){return e.readAttribute(this.fieldNameToModificationMap,t)},t.prototype.hasFormBeenSubmitted=function(){return this.formSubmitted},t.prototype.isFieldValid=function(e){return!getFieldError(e)},t.prototype.isFormInvalid=function(){return!this.isFormValid()},t.prototype.isFormValid=function(){for(var e in this.shallowErrorMap)return!1;return!0},t.prototype.resetFieldErrors=function(){this.formScope.errorMap={}},t.prototype.setFieldError=function(t,r){var i=e.flattenAttribute(t);e.writeAttribute(this.formScope.errorMap,t,r),r?this.shallowErrorMap[i]=r:delete this.shallowErrorMap[i],this.formScope.valid=this.isFormValid(),this.watchable++},t.prototype.setFieldHasBeenModified=function(t,r){e.writeAttribute(this.fieldNameToModificationMap,t,r),this.watchable++},t.prototype.setFormSubmitted=function(e){this.formSubmitted=e,this.watchable++},t}]),angular.module("formFor").service("ModelValidator",["$interpolate","$q","FormForConfiguration","NestedObjectHelper",function(e,t,r,i){return this.$getRulesForFieldName=function(e,t){return t=t.replace(/\[[^\]]+\]/g,".collection.fields"),i.readAttribute(e,t)},this.isCollectionRequired=function(e,t){var r=this.$getRulesForFieldName(t,e);return r&&r.collection&&r.collection.min&&(angular.isObject(r.collection.min)?r.collection.min.rule:r.collection.min)},this.isFieldRequired=function(e,t){var r=this.$getRulesForFieldName(t,e);return r&&r.required&&(angular.isObject(r.required)?r.required.rule:r.required)},this.validateAll=function(e,t){var r=i.flattenObjectKeys(t);return this.validateFields(e,r,t)},this.validateFields=function(e,r,o){var a=t.defer(),n=[],l={};return angular.forEach(r,function(t){var r=this.$getRulesForFieldName(o,t);if(r){var a;a=r.collection?this.validateCollection(e,t,o):this.validateField(e,t,o),a.then(angular.noop,function(e){i.writeAttribute(l,t,e)}),n.push(a)}},this),t.waitForAll(n).then(a.resolve,function(){a.reject(l)}),a.promise},this.validateCollection=function(o,a,n){var l=this.$getRulesForFieldName(n,a),u=i.readAttribute(o,a);if(l&&l.collection){u=u||[];var s=l.collection;if(s.min){var d=angular.isObject(s.min)?s.min.rule:s.min;if(u.length<d)return t.reject(angular.isObject(s.min)?s.min.message:e(r.validationFailedForMinCollectionSizeMessage)({num:d}))}if(s.max){var c=angular.isObject(s.max)?s.max.rule:s.max;if(u.length>c)return t.reject(angular.isObject(s.max)?s.max.message:e(r.validationFailedForMaxCollectionSizeMessage)({num:c}))}}return t.resolve()},this.validateField=function(o,a,n){var l=this.$getRulesForFieldName(n,a),u=i.readAttribute(o,a);if(l){if(u=u||"",l.required){var s=angular.isObject(l.required)?l.required.rule:l.required;if(angular.isString(u)&&(u=u.replace(/\s/g,"")),!!u!==s)return t.reject(angular.isObject(l.required)?l.required.message:r.validationFailedForRequiredMessage)}if(l.minlength){var d=angular.isObject(l.minlength)?l.minlength.rule:l.minlength;if(u&&u.length<d)return t.reject(angular.isObject(l.minlength)?l.minlength.message:e(r.validationFailedForMinLengthMessage)({num:d}))}if(l.maxlength){var c=angular.isObject(l.maxlength)?l.maxlength.rule:l.maxlength;if(u.length>c)return t.reject(angular.isObject(l.maxlength)?l.maxlength.message:e(r.validationFailedForMaxLengthMessage)({num:c}))}if(l.type){var f=angular.isObject(l.type)?l.type.rule:l.type,m=u.toString();if(f.indexOf("integer")>=0&&m&&!m.match(/^\-*[0-9]+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForIntegerTypeMessage);if(f.indexOf("number")>=0&&m&&!m.match(/^\-*[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForNumericTypeMessage);if(f.indexOf("negative")>=0&&m&&!m.match(/^\-[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForNegativeTypeMessage);if(f.indexOf("positive")>=0&&m&&!m.match(/^[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForPositiveTypeMessage);if(f.indexOf("email")>=0&&m&&!m.match(/^.+@.+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForEmailTypeMessage)}if(l.pattern){var p=l.pattern instanceof RegExp,b=p?l.pattern:l.pattern.rule;if(!b.exec(u))return t.reject(p?r.validationFailedForPatternMessage:l.pattern.message)}if(l.custom){var F=angular.isFunction(l.custom)?r.validationFailedForCustomMessage:l.custom.message,v=angular.isFunction(l.custom)?l.custom:l.custom.rule;try{var g=v(u,o)}catch(h){return t.reject(h.message||F)}return angular.isObject(g)&&angular.isFunction(g.then)?g.then(function(e){return t.resolve(e)},function(e){return t.reject(e||F)}):g?t.resolve(g):t.reject(F)}}return t.resolve()},this}]),angular.module("formFor").service("NestedObjectHelper",["$parse",function(e){return{$createEmptyArrays:function(e,t){for(var r=0;;){if(r=t.indexOf("[",r),0>r)break;var i=t.substr(0,r),o=this.readAttribute(e,i);o||(o=[],this.writeAttribute(e,i,o));var a=t.substr(r).match(/([0-9]+)\]\./);if(a){var n=parseInt(a[1]);o[n]||(o[n]={})}r++}},flattenAttribute:function(e){return e=e.replace(/\[([^\]]+)\]\.{0,1}/g,"___$1___"),e=e.replace(/\./g,"___")},flattenObjectKeys:function(e){for(var t=[],r=[{object:e,prefix:null}];;){if(0===r.length)break;var i=r.pop(),o=i.prefix?i.prefix+".":"";if("object"==typeof i.object)for(var a in i.object){var n=o+a;t.push(n),r.push({object:i.object[a],prefix:n})}}return t},readAttribute:function(t,r){return e(r)(t)},writeAttribute:function(t,r,i){this.$createEmptyArrays(t,r),e(r).assign(t,i)}}}]);var qDecorator=["$delegate",function(e){return e.resolve=function(e){var t=this.defer();return t.resolve(e),t.promise},e.waitForAll=function(e){var t=this.defer(),r=[],i=0,o=!1,a=function(e,t){r.hasOwnProperty(e)||(r[e]=t,i--),n()},n=function(){0===i&&(o?t.reject(r):t.resolve(r))};return angular.forEach(e,function(e,t){i++,e.then(function(e){a(t,e)},function(e){o=!0,a(t,e)})}),n(),t.promise},e}];angular.module("formFor").config(["$provide",function(e){e.decorator("$q",qDecorator)}]),angular.module("formFor").service("StringUtil",function(){this.humanize=function(e){return e?(e=e.replace(/[A-Z]/g,function(e){return" "+e}),e=e.replace(/_([a-z])/g,function(e,t){return" "+t.toUpperCase()}),e=e.replace(/\s+/g," "),e=e.trim(),e=e.charAt(0).toUpperCase()+e.slice(1)):""}});
angular.module("formFor",[]),angular.module("formFor").directive("ariaManager",function(){return{restrict:"A",link:function(e,t,r){e.$watch("model.uid",function(e){r.$set("ariaDescribedby",e+"-error"),r.$set("ariaLabelledby",e+"-label")}),e.$watch("model.error",function(e){r.$set("ariaInvalid",!!e)})}}}),angular.module("formFor").directive("checkboxField",["$log","FieldHelper",function(e,t){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/checkbox-field.html",scope:{attribute:"@",disable:"=",help:"@?",changed:"@?"},link:function(r,i,a,o){if(!r.attribute)return void e.error('Missing required field "attribute"');r.tabIndex=a.tabIndex||0;i.find("input");r.toggle=function(){r.disable||r.model.disabled||(r.model.bindable=!r.model.bindable)},t.manageLabel(r,a),t.manageFieldRegistration(r,a,o)}}}]),angular.module("formFor").directive("collectionLabel",["$sce","FormForConfiguration",function(e){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/collection-label.html",scope:{attribute:"@",help:"@?",label:"@"},link:function(t,r,i,a){t.$watch("label",function(r){t.bindableLabel=e.trustAsHtml(r)}),t.model=a.registerCollectionLabel(t.attribute)}}}]),angular.module("formFor").directive("fieldError",["$sce","FormForConfiguration",function(){return{restrict:"EA",templateUrl:"form-for/templates/field-error.html",scope:{error:"=",leftAligned:"@?",uid:"@"}}}]),angular.module("formFor").directive("fieldLabel",["$sce","FormForConfiguration",function(e,t){return{restrict:"EA",replace:!0,templateUrl:"form-for/templates/field-label.html",scope:{inputUid:"@",help:"@?",label:"@",required:"@?",uid:"@"},controller:["$scope",function(r){r.$watch("label",function(t){r.bindableLabel=e.trustAsHtml(t)}),r.$watch("required",function(e){r.requiredLabel=r.$eval(e)?t.requiredLabel:null})}]}}]),angular.module("formFor").directive("formForDebounce",["$log","$sniffer","$timeout","FormForConfiguration",function(e,t,r,i){return{restrict:"A",require:"ngModel",priority:99,link:function(a,o,n,l){if("radio"===n.type||"checkbox"===n.type)return void e.warn("formForDebounce should only be used with <input type=text> and <textarea> elements");var s,u=n.formForDebounce,d=i.defaultDebounceDuration;if(void 0!==u&&("false"===u.toString()?d=!1:(u=parseInt(u),angular.isNumber(u)&&!isNaN(u)&&(d=u))),t.hasEvent("input")?o.off("input"):(o.off("keydown"),t.hasEvent("paste")&&o.off("paste")),d!==!1){var c=function(){r.cancel(s),s=r(function(){a.$apply(function(){l.$setViewValue(o.val())})},d)};t.hasEvent("input")?o.on("input",c):(o.on("keydown",c),t.hasEvent("paste")&&o.on("paste",c))}o.on("blur",function(){a.$apply(function(){l.$setViewValue(o.val())})}),a.$on("$destroy",function(){s&&r.cancel(s)})}}}]),angular.module("formFor").directive("formFor",["$injector","$log","$parse","$q","$sce","FormForConfiguration","$FormForStateHelper","$FormForGUID","NestedObjectHelper","ModelValidator",function(e,t,r,i,a,o,n,l,s,u){return{require:"form",restrict:"A",scope:{controller:"=?",disable:"=?",formFor:"=",service:"@",submitComplete:"&?",submitError:"&?",submitWith:"&?",valid:"=?",validateOn:"=?",validationFailed:"&?",validationRules:"=?"},controller:["$scope",function(o){o.formFor||t.error('The form data object specified by <form form-for=""> is null or undefined.'),o.fields={},o.collectionLabels={},o.buttons=[],o.service&&(o.$service=e.get(o.service)),o.$validationRules=o.$service?o.$service.validationRules:o.validationRules;var d=this;d.registerFormField=function(e){if(!e)throw Error('Invalid field name "'+e+'" provided.');var t=s.flattenAttribute(e);if(o.fields.hasOwnProperty(t))throw Error('Field "'+e+'" has already been registered. Field names must be unique.');var i=(s.readAttribute(o.$validationRules,e),{bindableWrapper:{bindable:null,disabled:o.disable,error:null,pristine:!0,required:u.isFieldRequired(e,o.$validationRules),uid:l.create()},fieldName:e,unwatchers:[],validationAttribute:e.split("[")[0]});o.fields[t]=i;var a=r(e),n=a.assign;i.unwatchers.push(o.$watch("fields."+t+".bindableWrapper.bindable",function(e,t){e!==t&&n(o.formFor,e)}));var c;return i.unwatchers.push(o.$watch("formFor."+e,function(r,a){(r!==i.bindableWrapper.bindable||void 0===a&&""===r||void 0===r)&&(c=!1),i.bindableWrapper.bindable=r,o.validateOn&&"change"!==o.validateOn||d.validateField(e),c||(c=!0,o.formForStateHelper.setFieldHasBeenModified(t,!1)),i.bindableWrapper.pristine=!o.formForStateHelper.hasFieldBeenModified(t)})),i.bindableWrapper},this.unregisterFormField=function(e){var t=s.flattenAttribute(e);angular.forEach(o.fields[t].unwatchers,function(e){e()}),delete o.fields[t]},d.registerSubmitButton=function(){var e={disabled:!1};return o.buttons.push(e),e},d.registerCollectionLabel=function(e){var t=s.flattenAttribute(e),r={error:null,required:u.isCollectionRequired(e,o.$validationRules)};o.collectionLabels[t]=r;var i=!1;return o.$watch("formFor."+e+".length",function(){i?o.validateOn&&"change"!==o.validateOn||u.validateCollection(o.formFor,e,o.$validationRules).then(function(){o.formForStateHelper.setFieldError(t,null)},function(e){o.formForStateHelper.setFieldError(t,e)}):i=!0}),r},d.resetField=function(e){var t=s.flattenAttribute(e);o.formForStateHelper.getFieldError(t)&&(o.formForStateHelper.setFieldHasBeenModified(t,!1),o.fields[t].bindableWrapper.pristine=!0),o.formForStateHelper.setFieldError(t,null)},d.resetErrors=function(){for(var e in o.fields)o.formForStateHelper.getFieldError(e)&&(o.formForStateHelper.setFieldHasBeenModified(e,!1),o.fields[e].bindableWrapper.pristine=!0);o.formForStateHelper.setFormSubmitted(!1),o.formForStateHelper.resetFieldErrors()},d.resetFields=d.resetErrors,d.setFieldError=function(e,t){var r=s.flattenAttribute(e);o.formForStateHelper.setFieldHasBeenModified(r,!0),o.formForStateHelper.setFieldError(r,t)},d.validateField=function(e){{var t=s.flattenAttribute(e);o.fields[t],r(e)(o.formFor)}o.formForStateHelper.setFieldHasBeenModified(t,!0),o.$validationRules&&u.validateField(o.formFor,e,o.$validationRules).then(function(){o.formForStateHelper.setFieldError(t,null)},function(e){o.formForStateHelper.setFieldError(t,e)})},d.validateForm=function(e){o.updateCollectionErrors({}),o.updateFieldErrors({});var t,r;if(o.$validationRules){var a=[];angular.forEach(o.fields,function(e){a.push(e.fieldName)}),r=u.validateFields(o.formFor,a,o.$validationRules),r.then(angular.noop,o.updateFieldErrors),a=[],angular.forEach(o.collectionLabels,function(e,t){a.push(t)}),t=u.validateFields(o.formFor,a,o.$validationRules),t.then(angular.noop,o.updateCollectionErrors)}else t=i.resolve(),r=i.resolve();var n=i.defer();return i.waitForAll([t,r]).then(n.resolve,function(t){angular.isArray(t[0])&&0===t[0].length&&t.splice(0,1),e&&angular.forEach(t,function(e){var t=s.flattenObjectKeys(e);angular.forEach(t,function(t){var r=s.readAttribute(e,t);if(r){var i=s.flattenAttribute(t);o.formForStateHelper.setFieldHasBeenModified(i,!0)}})}),n.reject(t)}),n.promise},o.controller=o.controller||{},angular.copy(d,o.controller),o.$watch("disable",function(e){angular.forEach(o.fields,function(t){t.bindableWrapper.disabled=e}),angular.forEach(o.buttons,function(t){t.disabled=e})}),o.formForStateHelper=new n(o),o.$watch("formForStateHelper.watchable",function(){var e=o.formForStateHelper.hasFormBeenSubmitted();angular.forEach(o.fields,function(t,r){if(e||o.formForStateHelper.hasFieldBeenModified(r)){var i=o.formForStateHelper.getFieldError(r);t.bindableWrapper.error=i?a.trustAsHtml(i):null}else t.bindableWrapper.error=null}),angular.forEach(o.collectionLabels,function(e,t){var r=o.formForStateHelper.getFieldError(t);e.error=r?a.trustAsHtml(r):null})}),o.updateCollectionErrors=function(e){angular.forEach(o.collectionLabels,function(t,r){var i=s.readAttribute(e,r);o.formForStateHelper.setFieldError(r,i)})},o.updateFieldErrors=function(e){angular.forEach(o.fields,function(t,r){var i=s.readAttribute(e,t.fieldName);o.formForStateHelper.setFieldError(r,i)})}}],link:function(e,t,r){t.on("submit",function(){e.formForStateHelper.setFormSubmitted(!0),e.disable=!0;var t;return t="manual"===e.validateOn?i.resolve():e.controller.validateForm(),t.then(function(){var t;t=r.submitWith?e.submitWith({data:e.formFor}):e.$service&&e.$service.submit?e.$service.submit(e.formFor):i.reject("No submit function provided"),t||(t=i.reject("Submit function did not return a promise")),t.then(function(t){r.submitComplete?e.submitComplete({data:t}):o.defaultSubmitComplete(t)},function(t){angular.isObject(t)&&"manual"!==e.validateOn&&(e.updateCollectionErrors(t),e.updateFieldErrors(t)),r.submitError?e.submitError({error:t}):o.defaultSubmitError(t)}),t["finally"](function(){e.disable=!1})},function(){e.disable=!1,r.validationFailed?e.validationFailed():o.defaultValidationFailed()}),!1})}}}]),angular.module("formFor").directive("radioField",["$log","$FormForGUID","FieldHelper",function(e,t,r){var i={};return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/radio-field.html",scope:{attribute:"@",disable:"=",help:"@?",value:"@"},link:function(a,o,n,l){if(!a.attribute)return void e.error('Missing required field "attribute"');if(i[a.attribute])a.hideErrorMessage=!0;else{var s={defaultScope:a,scopes:[]};r.manageFieldRegistration(a,n,l),i[a.attribute]=s}a.uid=n.uid||t.create();var u=i[a.attribute];u.scopes.push(a),r.manageLabel(a,n,!0),a.tabIndex=n.tabIndex||0;o.find("input");a.click=function(){a.disable||a.model.disabled||(a.model.bindable=a.value)},u.defaultScope.$watch("model",function(e){a.model=e}),u.defaultScope.$watch("disable",function(e){a.disable=e}),u.defaultScope.$watch("model.disabled",function(e){a.model&&(a.model.disabled=e)}),a.$watch("model.bindable",function(e){a.checked=void 0!==e&&null!==e&&void 0!==a.value&&null!==a.value&&e.toString()===a.value.toString()}),a.$on("$destroy",function(){u.scopes.splice(u.scopes.indexOf(a),1),0===u.scopes.length&&delete i[a.attribute]})}}}]),angular.module("formFor").directive("selectField",["$document","$log","$timeout","$window","FieldHelper",function(e,t,r,i,a){var o=10;return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/select-field.html",scope:{attribute:"@",disable:"=",filter:"=?",filterDebounce:"@?",help:"@?",multiple:"=?",options:"="},link:function(n,l,s,u){if(i=angular.element(i),!n.attribute)return void t.error('Missing required field "attribute"');n.allowBlank=s.hasOwnProperty("allowBlank"),n.enableFiltering=s.hasOwnProperty("enableFiltering"),n.preventDefaultOption=s.hasOwnProperty("preventDefaultOption"),n.labelAttribute=s.labelAttribute||"label",n.valueAttribute=s.valueAttribute||"value",n.placeholder=s.placeholder||"Select",n.tabIndex=s.tabIndex||0,a.manageLabel(n,s),a.manageFieldRegistration(n,s,u);var d=function(e){var t=e[0];r(t.focus.bind(t))};n.close=function(){r(function(){n.isOpen=!1})},n.open=function(){n.disable||n.model.disabled||r(function(){n.isOpen=!0})},n.emptyOption={},n.emptyOption[n.labelAttribute]="",n.emptyOption[n.valueAttribute]=void 0,n.placeholderOption={},n.placeholderOption[n.labelAttribute]=n.placeholder,n.placeholderOption[n.valueAttribute]=void 0,n.filteredOptions=[];var c=function(e){return e&&e.toLowerCase()},f=function(){var e=n.options||[];if(n.filteredOptions.splice(0),n.enableFiltering&&n.filter){var t=c(n.filter);angular.forEach(e,function(e){var r=c(e[n.labelAttribute]).indexOf(t);r>=0&&n.filteredOptions.push(e)})}else angular.copy(e,n.filteredOptions);n.selectedOption||n.multiple?n.allowBlank&&n.filteredOptions.unshift(n.emptyOption):n.filteredOptions.unshift(n.placeholderOption)};n.$watch("filter",f),n.$watch("options.length",f);var m=function(){var e=n.selectedOption&&n.selectedOption[[n.valueAttribute]];return n.model.bindable===e?void(!n.allowBlank&&!n.preventDefaultOption&&n.options&&n.options.length&&(n.model.bindable=n.options[0][n.valueAttribute])):void 0};n.$watch("model.bindable",m),n.$watch("options.length",m),n.$watch("model.bindable",function(){var e;angular.forEach(n.options,function(t){t[n.valueAttribute]===n.model.bindable&&(e=t)}),n.selectedOption=e,n.selectedOptionLabel=e&&e[n.labelAttribute],n.filter=n.selectedOptionLabel});var p=function(e){e.ignoreFor!==n.model.uid&&n.close()};n.filterTextClick=function(){n.isOpen&&(event.ignoreFor=n.model.uid)};var b;n.$watch("isOpen",function(){b&&r.cancel(b),b=r(function(){b=null,n.isOpen?e.on("click",p):e.off("click",p)},o)}),n.$on("$destroy",function(){e.off("click",p)});var F=l.find("input");n.setFilterFocus=function(){d(F)},n.mouseOver=function(e){n.mouseOverIndex=e,n.mouseOverOption=e>=0?n.filteredOptions[e]:null},n.selectOption=function(e){n.model.bindable=e&&e[n.valueAttribute]},n.keyDown=function(e){switch(e.keyCode){case 27:n.close();break;case 13:n.isOpen?(n.selectOption(n.mouseOverOption),n.close()):n.open(),e.preventDefault();break;case 38:n.isOpen?n.mouseOver(n.mouseOverIndex>0?n.mouseOverIndex-1:n.filteredOptions.length-1):n.open();break;case 40:n.isOpen?n.mouseOver(n.mouseOverIndex<n.filteredOptions.length-1?n.mouseOverIndex+1:0):n.open();break;case 9:case 16:n.close();break;default:n.open()}},n.$watchCollection("[isOpen, filteredOptions.length]",function(){n.mouseOver(-1),n.isOpen&&n.enableFiltering&&d(F)})}}}]),angular.module("formFor").directive("submitButton",["$log","$sce",function(e,t){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/submit-button.html",scope:{disable:"=",icon:"@",label:"@"},link:function(e,r,i,a){e.buttonClass=i.buttonClass,e.tabIndex=i.tabIndex||0,e.$watch("label",function(r){e.bindableLabel=t.trustAsHtml(r)}),e.model=a.registerSubmitButton(e)}}}]),angular.module("formFor").directive("textField",["$log","$timeout","FieldHelper",function(e,t,r){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/text-field.html",scope:{attribute:"@",debounce:"@?",disable:"=",focused:"&?",blurred:"&?",help:"@?",iconAfterClicked:"&?",iconBeforeClicked:"&?",placeholder:"@?",rows:"=?"},link:function(i,a,o,n){if(!i.attribute)return void e.error('Missing required field "attribute"');if(i.attributes=o,i.rows=i.rows||3,i.type=o.type||"text",i.multiline=o.hasOwnProperty("multiline")&&"false"!==o.multiline,i.tabIndex=o.tabIndex||0,o.hasOwnProperty("autofocus")&&t(function(){a.find(i.multiline?"textarea":"input")[0].focus()}),r.manageLabel(i,o),r.manageFieldRegistration(i,o,n),o.iconAfter){var l=function(){if(i.model){var e="{"===o.iconAfter.charAt(0)?i.$eval(o.iconAfter):o.iconAfter;i.iconAfter=angular.isObject(e)?i.model.error?e.invalid:i.model.pristine?e.pristine:e.valid:e}};o.$observe("iconAfter",l),i.$watch("model.error",l),i.$watch("model.pristine",l)}if(o.iconBefore){var s=function(){if(i.model){var e="{"===o.iconBefore.charAt(0)?i.$eval(o.iconBefore):o.iconBefore;i.iconBefore=angular.isObject(e)?i.model.error?e.invalid:i.model.pristine?e.pristine:e.valid:e}};o.$observe("iconBefore",s),i.$watch("model.error",s),i.$watch("model.pristine",s)}i.onIconAfterClick=function(){o.hasOwnProperty("iconAfterClicked")&&i.iconAfterClicked()},i.onIconBeforeClick=function(){o.hasOwnProperty("iconBeforeClicked")&&i.iconBeforeClicked()},i.onFocus=function(){o.hasOwnProperty("focused")&&i.focused()},i.onBlur=function(){o.hasOwnProperty("blurred")&&i.blurred()}}}}]),angular.module("formFor").service("FieldHelper",["FormForConfiguration","StringUtil",function(e,t){this.manageLabel=function(r,i,a){i.hasOwnProperty("label")&&i.$observe("label",function(e){r.label=e}),e.autoGenerateLabels&&(r.label=t.humanize(a?r.value:r.attribute))},this.manageFieldRegistration=function(e,t,r){e.$watch("attribute",function(i,a){e.model&&r.unregisterFormField(a),e.model=r.registerFormField(e.attribute),t.uid&&(e.model.uid=t.uid)}),e.$on("$destroy",function(){r.unregisterFormField(e.attribute)})}}]),angular.module("formFor").service("FormForConfiguration",function(){return{autoGenerateLabels:!1,defaultDebounceDuration:500,defaultSubmitComplete:angular.noop,defaultSubmitError:angular.noop,defaultValidationFailed:angular.noop,requiredLabel:null,validationFailedForCustomMessage:"Failed custom validation",validationFailedForPatternMessage:"Invalid format",validationFailedForMaxCollectionSizeMessage:"Must be fewer than {{num}} items",validationFailedForMaxLengthMessage:"Must be fewer than {{num}} characters",validationFailedForMinCollectionSizeMessage:"Must at least {{num}} items",validationFailedForMinLengthMessage:"Must be at least {{num}} characters",validationFailedForRequiredMessage:"Required field",validationFailedForEmailTypeMessage:"Invalid email format",validationFailedForIntegerTypeMessage:"Must be an integer",validationFailedForNegativeTypeMessage:"Must be negative",validationFailedForNonNegativeTypeMessage:"Must be non-negative",validationFailedForNumericTypeMessage:"Must be numeric",validationFailedForPositiveTypeMessage:"Must be positive",disableAutoLabels:function(){this.autoGenerateLabels=!1},enableAutoLabels:function(){this.autoGenerateLabels=!0},setDefaultDebounceDuration:function(e){this.defaultDebounceDuration=e},setDefaultSubmitComplete:function(e){this.defaultSubmitComplete=e},setDefaultSubmitError:function(e){this.defaultSubmitError=e},setDefaultValidationFailed:function(e){this.defaultValidationFailed=e},setRequiredLabel:function(e){this.requiredLabel=e},setValidationFailedForCustomMessage:function(e){this.validationFailedForCustomMessage=e},setValidationFailedForMaxCollectionSizeMessage:function(e){this.validationFailedForMaxCollectionSizeMessage=e},setValidationFailedForMaxLengthMessage:function(e){this.validationFailedForMaxLengthMessage=e},setValidationFailedForMinCollectionSizeMessage:function(e){this.validationFailedForMaxCollectionSizeMessage=e},setValidationFailedForMinLengthMessage:function(e){this.validationFailedForMinLengthMessage=e},setValidationFailedForPatternMessage:function(e){this.validationFailedForPatternMessage=e},setValidationFailedForRequiredMessage:function(e){this.validationFailedForRequiredMessage=e},setValidationFailedForEmailTypeMessage:function(e){this.validationFailedForEmailTypeMessage=e},setValidationFailedForIntegerTypeMessage:function(e){this.validationFailedForIntegerTypeMessage=e},setValidationFailedForNegativeTypeMessage:function(e){this.validationFailedForNegativeTypeMessage=e},setValidationFailedForNonNegativeTypeMessage:function(e){this.validationFailedForNonNegativeTypeMessage=e},setValidationFailedForNumericTypeMessage:function(e){this.validationFailedForNumericTypeMessage=e},setValidationFailedForPositiveTypeMessage:function(e){this.validationFailedForPositiveTypeMessage=e}}}),angular.module("formFor").service("$FormForGUID",function(){return{create:function(){return("0000"+(Math.random()*Math.pow(36,4)<<0).toString(36)).slice(-4)}}}),angular.module("formFor").factory("$FormForStateHelper",["NestedObjectHelper",function(e){var t=function(e){e.errorMap=e.errorMap||{},e.valid=!0,this.formScope=e,this.fieldNameToModificationMap={},this.formSubmitted=!1,this.shallowErrorMap={},this.watchable=0};return t.prototype.getFieldError=function(t){return e.readAttribute(this.formScope.errorMap,t)},t.prototype.hasFieldBeenModified=function(t){return e.readAttribute(this.fieldNameToModificationMap,t)},t.prototype.hasFormBeenSubmitted=function(){return this.formSubmitted},t.prototype.isFieldValid=function(e){return!getFieldError(e)},t.prototype.isFormInvalid=function(){return!this.isFormValid()},t.prototype.isFormValid=function(){for(var e in this.shallowErrorMap)return!1;return!0},t.prototype.resetFieldErrors=function(){this.formScope.errorMap={}},t.prototype.setFieldError=function(t,r){var i=e.flattenAttribute(t);e.writeAttribute(this.formScope.errorMap,t,r),r?this.shallowErrorMap[i]=r:delete this.shallowErrorMap[i],this.formScope.valid=this.isFormValid(),this.watchable++},t.prototype.setFieldHasBeenModified=function(t,r){e.writeAttribute(this.fieldNameToModificationMap,t,r),this.watchable++},t.prototype.setFormSubmitted=function(e){this.formSubmitted=e,this.watchable++},t}]),angular.module("formFor").service("ModelValidator",["$interpolate","$q","FormForConfiguration","NestedObjectHelper",function(e,t,r,i){return this.$getRulesForFieldName=function(e,t){return t=t.replace(/\[[^\]]+\]/g,".collection.fields"),i.readAttribute(e,t)},this.isCollectionRequired=function(e,t){var r=this.$getRulesForFieldName(t,e);return r&&r.collection&&r.collection.min&&(angular.isObject(r.collection.min)?r.collection.min.rule:r.collection.min)},this.isFieldRequired=function(e,t){var r=this.$getRulesForFieldName(t,e);return r&&r.required&&(angular.isObject(r.required)?r.required.rule:r.required)},this.validateAll=function(e,t){var r=i.flattenObjectKeys(t);return this.validateFields(e,r,t)},this.validateFields=function(e,r,a){var o=t.defer(),n=[],l={};return angular.forEach(r,function(t){var r=this.$getRulesForFieldName(a,t);if(r){var o;o=r.collection?this.validateCollection(e,t,a):this.validateField(e,t,a),o.then(angular.noop,function(e){i.writeAttribute(l,t,e)}),n.push(o)}},this),t.waitForAll(n).then(o.resolve,function(){o.reject(l)}),o.promise},this.validateCollection=function(a,o,n){var l=this.$getRulesForFieldName(n,o),s=i.readAttribute(a,o);if(l&&l.collection){s=s||[];var u=l.collection;if(u.min){var d=angular.isObject(u.min)?u.min.rule:u.min;if(s.length<d)return t.reject(angular.isObject(u.min)?u.min.message:e(r.validationFailedForMinCollectionSizeMessage)({num:d}))}if(u.max){var c=angular.isObject(u.max)?u.max.rule:u.max;if(s.length>c)return t.reject(angular.isObject(u.max)?u.max.message:e(r.validationFailedForMaxCollectionSizeMessage)({num:c}))}}return t.resolve()},this.isConsideredNumeric_=function(e,t){return e&&!isNaN(t)},this.validateField=function(a,o,n){var l=this.$getRulesForFieldName(n,o),s=i.readAttribute(a,o);if(l){if(s=void 0===s||null===s?"":s,l.required){var u=angular.isObject(l.required)?l.required.rule:l.required;if(angular.isString(s)&&(s=s.replace(/\s+$/,"")),u&&!s)return t.reject(angular.isObject(l.required)?l.required.message:r.validationFailedForRequiredMessage)}if(l.minlength){var d=angular.isObject(l.minlength)?l.minlength.rule:l.minlength;if(s&&s.length<d)return t.reject(angular.isObject(l.minlength)?l.minlength.message:e(r.validationFailedForMinLengthMessage)({num:d}))}if(l.maxlength){var c=angular.isObject(l.maxlength)?l.maxlength.rule:l.maxlength;if(s.length>c)return t.reject(angular.isObject(l.maxlength)?l.maxlength.message:e(r.validationFailedForMaxLengthMessage)({num:c}))}if(l.type){var f=angular.isObject(l.type)?l.type.rule:l.type,m=s.toString(),p=Number(s);if(f){var b=f.split(" ");for(var F in b)switch(f=b[F]){case"integer":if(m&&(isNaN(p)||p%1!==0))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForIntegerTypeMessage);break;case"number":if(m&&isNaN(p))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForNumericTypeMessage);break;case"negative":if(this.isConsideredNumeric_(m,p)&&p>=0)return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForNegativeTypeMessage);break;case"nonNegative":if(this.isConsideredNumeric_(m,p)&&0>p)return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForNonNegativeTypeMessage);break;case"positive":if(this.isConsideredNumeric_(m,p)&&0>=p)return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForPositiveTypeMessage);break;case"email":if(m&&!m.match(/^.+@.+$/))return t.reject(angular.isObject(l.type)?l.type.message:r.validationFailedForEmailTypeMessage)}}}if(l.pattern){var v=l.pattern instanceof RegExp,g=v?l.pattern:l.pattern.rule;if(!g.exec(s))return t.reject(v?r.validationFailedForPatternMessage:l.pattern.message)}if(l.custom){var h=angular.isFunction(l.custom)?r.validationFailedForCustomMessage:l.custom.message,M=angular.isFunction(l.custom)?l.custom:l.custom.rule;try{var $=M(s,a)}catch(O){return t.reject(O.message||h)}return angular.isObject($)&&angular.isFunction($.then)?$.then(function(e){return t.resolve(e)},function(e){return t.reject(e||h)}):$?t.resolve($):t.reject(h)}}return t.resolve()},this}]),angular.module("formFor").service("NestedObjectHelper",["$parse",function(e){return{$createEmptyArrays:function(e,t){for(var r=0;;){if(r=t.indexOf("[",r),0>r)break;var i=t.substr(0,r),a=this.readAttribute(e,i);a||(a=[],this.writeAttribute(e,i,a));var o=t.substr(r).match(/([0-9]+)\]\./);if(o){var n=parseInt(o[1]);a[n]||(a[n]={})}r++}},flattenAttribute:function(e){return e=e.replace(/\[([^\]]+)\]\.{0,1}/g,"___$1___"),e=e.replace(/\./g,"___")},flattenObjectKeys:function(e){for(var t=[],r=[{object:e,prefix:null}];;){if(0===r.length)break;var i=r.pop(),a=i.prefix?i.prefix+".":"";if("object"==typeof i.object)for(var o in i.object){var n=a+o;t.push(n),r.push({object:i.object[o],prefix:n})}}return t},readAttribute:function(t,r){return e(r)(t)},writeAttribute:function(t,r,i){this.$createEmptyArrays(t,r),e(r).assign(t,i)}}}]);var qDecorator=["$delegate",function(e){return e.resolve=function(e){var t=this.defer();return t.resolve(e),t.promise},e.waitForAll=function(e){var t=this.defer(),r=[],i=0,a=!1,o=function(e,t){r.hasOwnProperty(e)||(r[e]=t,i--),n()},n=function(){0===i&&(a?t.reject(r):t.resolve(r))};return angular.forEach(e,function(e,t){i++,e.then(function(e){o(t,e)},function(e){a=!0,o(t,e)})}),n(),t.promise},e}];angular.module("formFor").config(["$provide",function(e){e.decorator("$q",qDecorator)}]),angular.module("formFor").service("StringUtil",function(){this.humanize=function(e){return e?(e=e.replace(/[A-Z]/g,function(e){return" "+e}),e=e.replace(/_([a-z])/g,function(e,t){return" "+t.toUpperCase()}),e=e.replace(/\s+/g," "),e=e.trim(),e=e.charAt(0).toUpperCase()+e.slice(1)):""}});
{
"name": "angular-form-for",
"version": "1.6.1",
"version": "1.7.2",
"description": "Set of Angular directives to simplify creating and validating HTML forms.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -21,2 +21,3 @@ /**

* A unique ID will be auto-generated if no value is provided.
* @param {Function} changed Optional function to be invoked on checkbox change.
*

@@ -38,3 +39,4 @@ * @example

disable: '=',
help: '@?'
help: '@?',
changed: '@?'
},

@@ -41,0 +43,0 @@ link: function($scope, $element, $attributes, formForController) {

@@ -123,3 +123,3 @@ /**

if ($scope.fields.hasOwnProperty(bindableFieldName)) {
throw Error('Field "' + fieldName + '" has already eben registered. Field names must be unique.');
throw Error('Field "' + fieldName + '" has already been registered. Field names must be unique.');
}

@@ -357,4 +357,5 @@

* @memberof form-for
* @param {Boolean} showErrors Mark fields with errors as invalid (visually) after validation
*/
controller.validateForm = function() {
controller.validateForm = function(showErrors) {
// Reset errors before starting new validation.

@@ -402,2 +403,19 @@ $scope.updateCollectionErrors({});

// Errors won't be shown for clean fields, so mark errored fields as dirty.
if (showErrors) {
angular.forEach(errors, function(errorObjectOrArray) {
var flattenedFields = NestedObjectHelper.flattenObjectKeys(errorObjectOrArray);
angular.forEach(flattenedFields, function(fieldName) {
var error = NestedObjectHelper.readAttribute(errorObjectOrArray, fieldName);
if (error) {
var bindableFieldName = NestedObjectHelper.flattenAttribute(fieldName);
$scope.formForStateHelper.setFieldHasBeenModified(bindableFieldName, true);
}
});
});
}
deferred.reject(errors);

@@ -404,0 +422,0 @@ });

@@ -25,2 +25,3 @@ /**

* Defaults to "label".
* @param {Boolean} multiple Drop-down list should allow multiple selections.
* @param {Array} options Set of options, each containing a label and value key.

@@ -72,2 +73,3 @@ * The label is displayed to the user and the value is assigned to the corresponding model attribute on selection.

help: '@?',
multiple: '=?',
options: '='

@@ -156,3 +158,3 @@ },

if (!$scope.selectedOption) {
if (!$scope.selectedOption && !$scope.multiple) {
$scope.filteredOptions.unshift($scope.placeholderOption);

@@ -159,0 +161,0 @@ } else if ($scope.allowBlank) {

@@ -28,2 +28,3 @@ /**

validationFailedForNegativeTypeMessage: 'Must be negative',
validationFailedForNonNegativeTypeMessage: 'Must be non-negative',
validationFailedForNumericTypeMessage: 'Must be numeric',

@@ -205,2 +206,12 @@ validationFailedForPositiveTypeMessage: 'Must be positive',

/**
* Override the default error message for failed type = 'nonNegative' validations.
* This setting applies to all instances of formFor unless otherwise overridden on a per-rule basis.
* @memberof FormForConfiguration
* @param {String} value Custom error message string
*/
setValidationFailedForNonNegativeTypeMessage: function(value) {
this.validationFailedForNonNegativeTypeMessage = value;
},
/**
* Override the default error message for failed type = 'numeric' validations.

@@ -207,0 +218,0 @@ * This setting applies to all instances of formFor unless otherwise overridden on a per-rule basis.

@@ -152,2 +152,10 @@ /**

/**
* Helper function for determining if numeric input has been provided.
* This is to guard against the fact that `new Number('') == 0`.
*/
this.isConsideredNumeric_ = function(stringValue, numericValue) {
return stringValue && !isNaN(numericValue);
};
/**
* Validates a value against the related rule-set (within validationRules).

@@ -167,3 +175,8 @@ * This method returns a promise to be resolved on successful validation.

if (rules) {
value = value || '';
// Don't turn falsy (but non-null) values like 0 or false to ''
if (value === undefined || value === null) {
value = "";
} else {
value = value;
}

@@ -174,6 +187,6 @@ if (rules.required) {

if (angular.isString(value)) {
value = value.replace(/\s/g, ''); // Disallow an all-whitespace string for required fields
value = value.replace(/\s+$/, ''); // Disallow an all-whitespace at the end of the string
}
if (!!value !== required) {
if (required && !value) {
return $q.reject(

@@ -211,36 +224,65 @@ angular.isObject(rules.required) ?

var stringValue = value.toString();
var numericValue = Number(value);
if (type.indexOf('integer') >= 0 && stringValue && !stringValue.match(/^\-*[0-9]+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForIntegerTypeMessage);
}
if (type) {
var types = type.split(' ');
if (type.indexOf('number') >= 0 && stringValue && !stringValue.match(/^\-*[0-9\.]+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForNumericTypeMessage);
}
for (var index in types) {
type = types[index];
switch (type) {
case 'integer':
if (stringValue && (isNaN(numericValue) || numericValue % 1 !== 0)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForIntegerTypeMessage);
}
break;
if (type.indexOf('negative') >= 0 && stringValue && !stringValue.match(/^\-[0-9\.]+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForNegativeTypeMessage);
}
case 'number':
if (stringValue && isNaN(numericValue)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForNumericTypeMessage);
}
break;
if (type.indexOf('positive') >= 0 && stringValue && !stringValue.match(/^[0-9\.]+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForPositiveTypeMessage);
}
case 'negative':
if (this.isConsideredNumeric_(stringValue, numericValue) && numericValue >= 0) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForNegativeTypeMessage);
}
break;
if (type.indexOf('email') >= 0 && stringValue && !stringValue.match(/^.+@.+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForEmailTypeMessage);
case 'nonNegative':
if (this.isConsideredNumeric_(stringValue, numericValue) && numericValue < 0) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForNonNegativeTypeMessage);
}
break;
case 'positive':
if (this.isConsideredNumeric_(stringValue, numericValue) && numericValue <= 0) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForPositiveTypeMessage);
}
break;
case 'email':
if (stringValue && !stringValue.match(/^.+@.+$/)) {
return $q.reject(
angular.isObject(rules.type) ?
rules.type.message :
FormForConfiguration.validationFailedForEmailTypeMessage);
}
break;
}
}
}

@@ -247,0 +289,0 @@ }

@@ -119,2 +119,16 @@ describe('ModelValidator', function() {

});
it('should not reject a truthy value when required is false', function() {
model.rules = {
requiredField: {
required: {
rule: false,
message: 'foobar'
}
}
};
expect(ModelValidator.validateField({requiredField: '1'}, 'requiredField', model.rules)).toBeResolved();
expect(ModelValidator.validateField({requiredField: ''}, 'requiredField', model.rules)).toBeResolved();
});
});

@@ -214,2 +228,3 @@

negative: { type: 'negative' },
nonNegative: { type: 'nonNegative' },
number: { type: 'number' },

@@ -274,7 +289,9 @@ positive: { type: 'positive' }

it('positive should reject negative numeric input', function() {
it('positive should reject non-positive numeric input', function() {
expect(ModelValidator.validateField({positive: -123}, 'positive', model.rules)).toBeRejected();
expect(ModelValidator.validateField({positive: -1.23}, 'positive', model.rules)).toBeRejected();
expect(ModelValidator.validateField({positive: 0}, 'positive', model.rules)).toBeRejected();
expect(ModelValidator.validateField({positive: '-123'}, 'positive', model.rules)).toBeRejected();
expect(ModelValidator.validateField({positive: '-1.23'}, 'positive', model.rules)).toBeRejected();
expect(ModelValidator.validateField({positive: '0'}, 'positive', model.rules)).toBeRejected();
});

@@ -288,2 +305,24 @@

it('non-negative should accept positive numeric input', function() {
expect(ModelValidator.validateField({nonNegative: 123}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: 1.23}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: 0}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: '123'}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: '1.23'}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: '0'}, 'nonNegative', model.rules)).toBeResolved();
});
it('non-negative should reject negative numeric input', function() {
expect(ModelValidator.validateField({nonNegative: -123}, 'nonNegative', model.rules)).toBeRejected();
expect(ModelValidator.validateField({nonNegative: -1.23}, 'nonNegative', model.rules)).toBeRejected();
expect(ModelValidator.validateField({nonNegative: '-123'}, 'nonNegative', model.rules)).toBeRejected();
expect(ModelValidator.validateField({nonNegative: '-1.23'}, 'nonNegative', model.rules)).toBeRejected();
});
it('non-negative should not require input unless the required flag is also present', function() {
expect(ModelValidator.validateField({nonNegative: ''}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: undefined}, 'nonNegative', model.rules)).toBeResolved();
expect(ModelValidator.validateField({nonNegative: null}, 'nonNegative', model.rules)).toBeResolved();
});
it('negative should accept negative numeric input', function() {

@@ -352,3 +391,3 @@ expect(ModelValidator.validateField({negative: -123}, 'negative', model.rules)).toBeResolved();

verifyPromiseRejectedWithMessage(
ModelValidator.validateField({negative: 'invalid'}, 'negative', model.rules),
ModelValidator.validateField({negative: 1}, 'negative', model.rules),
'foobar negative');

@@ -369,3 +408,3 @@ });

verifyPromiseRejectedWithMessage(
ModelValidator.validateField({positive: 'invalid'}, 'positive', model.rules),
ModelValidator.validateField({positive: -1}, 'positive', model.rules),
'foobar positive');

@@ -925,2 +964,8 @@ });

it('should allow overrides for type non-negative', function() {
FormForConfiguration.setValidationFailedForNonNegativeTypeMessage('custom type non-negative');
testCustomValidationFailureMessage('type', 'nonNegative integer', '-1', 'custom type non-negative');
});
it('should allow overrides for type positive', function() {

@@ -927,0 +972,0 @@ FormForConfiguration.setValidationFailedForPositiveTypeMessage('custom type positive');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc