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.2.16 to 1.3.0

dist/form-for.bootstrap-templates.js

2

bower.json
{
"name": "angular-form-for",
"version": "1.2.16",
"version": "1.3.0",
"main": [

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

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

angular.module("formFor.templates",[]).run(["$templateCache",function(e){e.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" left-aligned="true"></field-error>\n\n <label>\n <div class="checkbox-field-input" ng-class="{\'is-checked\': model.bindable}"></div>\n\n <input type="checkbox" ng-model="model.bindable"\n class="field-input"\n ng-disabled="disable || model.disabled">\n\n <field-label ng-if="label"\n label="{{label}}"\n help="{{help}}"\n ng-click="toggle()">\n </field-label>\n </label>\n</div>\n'),e.put("form-for/templates/collection-label.html",'<div class="collection-label" ng-class="{\'text-danger field-error\': 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 field-error" ng-bind="model.error"></small>\n</div>\n'),e.put("form-for/templates/field-error.html",'<p ng-if="error" class="text-danger field-error" ng-class="{\'left-aligned\': leftAligned}" ng-bind="error"></p>\n'),e.put("form-for/templates/field-label.html",'<label class="field-label"\n popover="{{help}}"\n popover-trigger="mouseenter"\n popover-placement="right">\n\n <span ng-bind-html="bindableLabel"></span>\n\n <span ng-if="help" class="fa-stack help-icon-stack">\n <i class="fa fa-stack-2x fa-circle help-background-icon"></i>\n <i class="fa fa-stack-1x fa-inverse fa-question help-foreground-icon"></i>\n </span>\n\n <span class="label label-default field-label-required-label" ng-if="requiredLabel" ng-bind="requiredLabel"></span>\n</label>\n'),e.put("form-for/templates/radio-field.html",'<span class="field radio-field"\n ng-class="{disabled: disable || model.disabled, \'has-error\': model.error}">\n\n <field-error error="model.error" left-aligned="true"></field-error>\n\n <label>\n <span class="radio-field-input" ng-class="{\'is-selected\': checked}"\n ng-click="click()"></span>\n\n <input type="radio" ng-model="model.bindable" ng-value="value"\n class="field-input"\n ng-checked="checked"\n ng-disabled="disable || model.disabled">\n\n <field-label ng-if="label"\n label="{{label}}"\n help="{{help}}"\n ng-click="click()">\n </field-label>\n </label>\n</span>\n'),e.put("form-for/templates/select-field-loading-indicator.html",'<i class="fa fa-circle-o-notch fa-spin"></i>\nLoading...\n'),e.put("form-for/templates/select-field.html",'<div class="form-group field select-field"\n ng-class="{ \'direction-down\': !dropUp,\n \'direction-up\': dropUp,\n \'disabled\': disable || model.disabled,\n \'has-error\': model.error,\n \'open\': isOpen }">\n\n <field-label ng-if="label"\n label="{{label}}"\n help="{{help}}"\n required="{{model.required}}">\n </field-label>\n\n <field-error error="model.error"></field-error>\n\n <div class="form-control select-field-toggle-button"\n ng-class="{open: isOpen, disabled: disable || model.disabled}"\n ng-disabled="disable || model.disabled">\n\n <span ng-if="selectedOptionLabel" ng-bind="selectedOptionLabel"></span>\n\n <span ng-if="!selectedOptionLabel">\n <span ng-if="placeholder" ng-bind="placeholder"></span>\n <span ng-if="!placeholder">Select</span>\n </span>\n\n <span class="fa fa-caret-down pull-right select-field-toggle-caret"></span>\n </div>\n\n <div ng-show="isOpen" class="list-group-container">\n <div class="list-group">\n <div ng-show="enableFiltering" class="input-group filter-input-group"\n ng-click="$event.stopPropagation()">\n <input type="text"\n class="form-control text-field-input filter-text-input"\n ng-model="filter"\n ng-keydown="keyDown($event)"\n form-for-debounce="{{filterDebounce}}" />\n\n <span class="input-group-addon input-group-addon-after">\n <i class="fa fa-search text-field-icon"></i>\n </span>\n </div>\n\n <div class="list-group-scrollable">\n <a class="list-group-item"\n ng-repeat="option in filteredOptions"\n ng-value="option[valueAttribute]"\n ng-click="selectOption(option)"\n ng-mouseenter="mouseOver($index)"\n ng-class="{active: option === selectedOption, hover: $index === mouseOverIndex}">\n\n <!-- Bootstrap leaves us no way to style a non-:hover element so we fall back to <strong> -->\n <strong ng-if="$index === mouseOverIndex" ng-bind="option[labelAttribute]"></strong>\n <span ng-if="$index !== mouseOverIndex" ng-bind="option[labelAttribute]"></span>\n <spgn ng-if="!option[labelAttribute]">&nbsp;</spgn> <!-- Gracefully handle empty/null names -->\n </a>\n\n <a ng-if="!options" class="list-group-item"\n ng-include src="\'form-for/templates/select-field-loading-indicator.html\'"></a>\n </div>\n </div>\n </div>\n</div>\n'),e.put("form-for/templates/submit-button.html",'<button class="submit-button" ng-class="buttonClass || \'btn btn-default\'" ng-disabled="disable || model.disabled">\n <i ng-if="icon" class="submit-button-icon" ng-class="icon"></i>\n\n <span ng-bind-html="bindableLabel"></span>\n</button>\n'),e.put("form-for/templates/text-field.html",'<div class="form-group field text-field"\n ng-class="{disabled: disable || model.disabled, \'has-error\': model.error}">\n\n <field-label ng-if="label"\n label="{{label}}"\n help="{{help}}"\n required="{{model.required}}">\n </field-label>\n\n <field-error error="model.error"></field-error>\n\n <div ng-class="{\'input-group\': iconBefore || iconAfter}">\n <span ng-if="iconBefore" class="input-group-addon input-group-addon-before"\n ng-click="onIconBeforeClick()">\n <i class="text-field-icon" ng-class="iconBefore"></i>\n </span>\n\n <input ng-if="!multiline"\n type="{{type}}"\n class="form-control text-field-input"\n ng-class="{\'has-icon-before\': iconBefore, \'has-icon-after\': iconAfter}"\n ng-disabled="disable || model.disabled"\n placeholder="{{placeholder}}"\n ng-model="model.bindable"\n form-for-debounce="{{debounce}}"\n ng-click="onFocus()" />\n\n\n <textarea ng-if="multiline"\n class="form-control text-field-input"\n ng-class="{\'has-icon-before\': iconBefore, \'has-icon-after\': iconAfter}"\n ng-disabled="disable || model.disabled"\n placeholder="{{placeholder}}"\n ng-model="model.bindable"\n form-for-debounce="{{debounce}}"\n ng-click="onFocus()">\n </textarea>\n\n <span ng-if="iconAfter" class="input-group-addon input-group-addon-after"\n ng-click="onIconAfterClick()">\n <i class="text-field-icon" ng-class="iconAfter"></i>\n </span>\n </div>\n</div>\n'),e.put("form-for/templates/type-ahead-field.html",'<div class="form-group field type-ahead-field"\n ng-class="{disabled: disable || model.disabled, \'has-error\': model.error}">\n\n <field-label ng-if="label"\n label="{{label}}"\n help="{{help}}"\n required="{{model.required}}">\n </field-label>\n\n <field-error error="model.error"></field-error>\n\n <input type="text"\n class="form-control type-ahead-field-input"\n placeholder="{{placeholder}}"\n ng-model="model.selectedOption"\n ng-change="changeHandler()"\n typeahead="option as option[labelAttribute] for option in filteredOptions"\n typeahead-wait-ms="debounce || 1000">\n</div>\n')}]);
angular.module("formFor",["formFor.templates"]),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(i,r,o,a){if(!i.attribute)return void e.error('Missing required field "attribute"');i.label=t.getLabel(o,i.attribute);r.find("input");i.toggle=function(){i.disable||i.model.disabled||(i.model.bindable=!i.model.bindable)},t.manageFieldRegistration(i,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,i,r,o){t.$watch("label",function(i){t.bindableLabel=e.trustAsHtml(i)}),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:"@?"}}}]),angular.module("formFor").directive("fieldLabel",["$sce","FormForConfiguration",function(e,t){return{restrict:"EA",templateUrl:"form-for/templates/field-label.html",scope:{help:"@?",label:"@",required:"@?"},controller:["$scope",function(i){i.$watch("label",function(t){i.bindableLabel=e.trustAsHtml(t)}),i.$watch("required",function(e){i.requiredLabel=i.$eval(e)?t.requiredLabel:null})}]}}]),angular.module("formFor").directive("formForDebounce",["$log","$sniffer","$timeout","FormForConfiguration",function(e,t,i,r){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=r.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(){i.cancel(u),u=i(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&&i.cancel(u)})}}}]),angular.module("formFor").directive("formFor",["$injector","$parse","$q","$sce","FormForConfiguration","$FormForStateHelper","NestedObjectHelper","ModelValidator",function(e,t,i,r,o,a,n,l){return{require:"form",restrict:"A",scope:{controller:"=?",disable:"=?",formFor:"=",service:"@",submitComplete:"&?",submitError:"&?",submitWith:"&?",valid:"=?",validationFailed:"&?",validationRules:"=?"},controller:["$scope",function(o){o.fields={},o.collectionLabels={},o.buttons=[],o.service&&(o.$service=e.get(o.service)),o.$validationRules=o.$service?o.$service.validationRules:o.validationRules;var u=this;u.registerFormField=function(e){var i=n.flattenAttribute(e),r=(n.readAttribute(o.$validationRules,e),{bindableWrapper:{bindable:null,disabled:!1,error:null,pristine:!0,required:l.isFieldRequired(e,o.$validationRules)},fieldName:e,unwatchers:[],validationAttribute:e.split("[")[0]});o.fields[i]=r;var a=t(e),s=a.assign;r.unwatchers.push(o.$watch("fields."+i+".bindableWrapper.bindable",function(e,t){e!==t&&s(o.formFor,e)}));var d;return r.unwatchers.push(o.$watch("formFor."+e,function(t,a){(t!==r.bindableWrapper.bindable||void 0===a&&""===t||void 0===t)&&(d=!1),r.bindableWrapper.bindable=t,u.validateField(e),d||(d=!0,o.formForStateHelper.setFieldHasBeenModified(i,!1)),r.bindableWrapper.pristine=!o.formForStateHelper.hasFieldBeenModified(i)})),r.bindableWrapper},this.unregisterFormField=function(e){var t=n.flattenAttribute(e);angular.forEach(o.fields[t].unwatchers,function(e){e()}),delete o.fields[t]},u.registerSubmitButton=function(){var e={disabled:!1};return o.buttons.push(e),e},u.registerCollectionLabel=function(e){var t=n.flattenAttribute(e),i={error:null,required:l.isCollectionRequired(e,o.$validationRules)};o.collectionLabels[t]=i;var r=!1;return o.$watch("formFor."+e+".length",function(){r?l.validateCollection(o.formFor,e,o.$validationRules).then(function(){o.formForStateHelper.setFieldError(t,null)},function(e){o.formForStateHelper.setFieldError(t,e)}):r=!0}),i},u.resetField=function(e){var t=n.flattenAttribute(e);o.formForStateHelper.getFieldError(t)&&(o.formForStateHelper.setFieldHasBeenModified(t,!1),o.fields[t].bindableWrapper.pristine=!0),o.formForStateHelper.setFieldError(t,null)},u.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()},u.resetFields=u.resetErrors,u.validateField=function(e){{var i=n.flattenAttribute(e);o.fields[i],t(e)(o.formFor)}o.formForStateHelper.setFieldHasBeenModified(i,!0),o.$validationRules&&l.validateField(o.formFor,e,o.$validationRules).then(function(){o.formForStateHelper.setFieldError(i,null)},function(e){o.formForStateHelper.setFieldError(i,e)})},u.validateForm=function(){o.updateCollectionErrors({}),o.updateFieldErrors({});var e,t;if(o.$validationRules){var r=[];angular.forEach(o.fields,function(e){r.push(e.fieldName)}),t=l.validateFields(o.formFor,r,o.$validationRules),t.then(angular.noop,o.updateFieldErrors),r=[],angular.forEach(o.collectionLabels,function(e,t){r.push(t)}),e=l.validateFields(o.formFor,r,o.$validationRules),e.then(angular.noop,o.updateCollectionErrors)}else e=i.resolve(),t=i.resolve();var a=i.defer();return i.waitForAll([e,t]).then(a.resolve,function(e){angular.isArray(e[0])&&0===e[0].length&&e.splice(0,1),a.reject(e)}),a.promise},o.controller=o.controller||{},angular.copy(u,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 a(o),o.$watch("formForStateHelper.watchable",function(){var e=o.formForStateHelper.hasFormBeenSubmitted();angular.forEach(o.fields,function(t,i){if(e||o.formForStateHelper.hasFieldBeenModified(i)){var a=o.formForStateHelper.getFieldError(i);t.bindableWrapper.error=a?r.trustAsHtml(a):null}else t.bindableWrapper.error=null}),angular.forEach(o.collectionLabels,function(e,t){var i=o.formForStateHelper.getFieldError(t);e.error=i?r.trustAsHtml(i):null})}),o.updateCollectionErrors=function(e){angular.forEach(o.collectionLabels,function(t,i){var r=n.readAttribute(e,i);o.formForStateHelper.setFieldError(i,r)})},o.updateFieldErrors=function(e){angular.forEach(o.fields,function(t,i){var r=n.readAttribute(e,t.fieldName);o.formForStateHelper.setFieldError(i,r)})}}],link:function(e,t,r){t.on("submit",function(){return e.formForStateHelper.setFormSubmitted(!0),e.disable=!0,e.controller.validateForm().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)&&(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","FieldHelper",function(e,t){var i={};return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/radio-field.html",scope:{attribute:"@",disable:"=",help:"@?",value:"@"},link:function(r,o,a,n){if(!r.attribute)return void e.error('Missing required field "attribute"');if(!i[r.attribute]){var l={defaultScope:r,scopes:[]};t.manageFieldRegistration(r,n),i[r.attribute]=l}var u=i[r.attribute];u.scopes.push(r),r.label=t.getLabel(a,r.value);o.find("input");r.click=function(){r.disable||r.model.disabled||(r.model.bindable=r.value)},u.defaultScope.$watch("model",function(e){r.model=e}),u.defaultScope.$watch("disable",function(e){r.disable=e}),u.defaultScope.$watch("model.disabled",function(e){r.model&&(r.model.disabled=e)}),r.$watch("model.bindable",function(e){r.checked=void 0!==e&&null!==e&&void 0!==r.value&&null!==r.value&&e.toString()===r.value.toString()}),r.$on("$destroy",function(){u.scopes.splice(u.scopes.indexOf(r),1),0===u.scopes.length&&delete i[r.attribute]})}}}]),angular.module("formFor").directive("selectField",["$document","$log","$timeout","$window","FieldHelper",function(e,t,i,r,o){var a=250;return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/select-field.html",scope:{attribute:"@",disable:"=",filter:"=?",filterDebounce:"@?",help:"@?",options:"=",placeholder:"@?"},link:function(n,l,u,s){if(r=$(r),!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.label=o.getLabel(u,n.attribute),o.manageFieldRegistration(n,s),n.emptyOption={},n.filteredOptions=[];var d=function(e){return e&&e.toLowerCase()},c=function(){var e=n.options||[];if(n.filteredOptions.splice(0),n.enableFiltering&&n.filter){var t=d(n.filter);angular.forEach(e,function(e){var i=d(e[n.labelAttribute]).indexOf(t);i>=0&&n.filteredOptions.push(e)})}else angular.copy(e,n.filteredOptions);n.allowBlank&&n.filteredOptions.unshift(n.emptyOption)};n.$watch("filter",c),n.$watch("options.length",c);var f=function(){var e,t=n.selectedOption&&n.selectedOption[[n.valueAttribute]];return n.model.bindable===t?void(!n.allowBlank&&!n.preventDefaultOption&&n.options&&n.options.length&&(n.model.bindable=n.options[0][n.valueAttribute])):(angular.forEach(n.options,function(t){t[n.valueAttribute]===n.model.bindable&&(e=t)}),n.selectedOption=e,void(n.selectedOptionLabel=e&&e[n.labelAttribute]))};n.$watch("model.bindable",f),n.$watch("options.length",f),n.$watch("model.bindable",function(e){for(var t,i=0;i<n.filteredOptions.length;i++){var r=n.filteredOptions[i];if(r[n.valueAttribute]===e){t=r;break}}n.selectedOption=t,n.selectedOptionLabel=t&&t[n.labelAttribute]});var p=function(e,t){i(function(){e.one("click",t)},1)},m=function(){e.off("click",F)},b=function(){p(l.find(".select-field-toggle-button"),M)};n.selectOption=function(e){n.model.bindable=e&&e[n.valueAttribute],n.isOpen=!1,m(),b()};var F=function(){n.isOpen=!1,n.$apply(),m(),b()},v=l.find(".list-group-container"),g=l.find(".list-group-scrollable"),h=l.find(".list-group"),M=function(){if(n.disable||n.model.disabled)return void b();if(n.isOpen=!n.isOpen,n.isOpen){A(),p(e,F);var t=n.model.bindable;i(angular.bind(l,function(){for(var e,i=this.find(".list-group-item"),r=0;r<i.length;r++){var o=i[r],a=$(o).scope().option;if(a&&a[n.valueAttribute]===t){e=o;break}}if(e){g.scrollTop(0);var l=$(e).offset().top-g.offset().top;g.scrollTop(l)}}))}};b();var O=l.find(".select-field-toggle-button"),y={position:"absolute",width:"100%",zIndex:1050},w=function(){switch(u.direction){case"up":return!0;case"down":return!1;case"auto":default:var e=O.offset().top-r.scrollTop();return e+O.outerHeight()+a>r.height()}},A=function(){w()?(n.dropUp=!0,y.top="auto",y.bottom=O.outerHeight()-1+"px"):(n.dropUp=!1,y.bottom="auto",y.top="100%"),v.css(y)};h.css({marginBottom:0}),g.css({maxHeight:a,overflowY:"scroll"}),l.css("position","relative"),n.mouseOver=function(e){n.mouseOverIndex=e,n.mouseOverOption=e>=0?n.filteredOptions[e]:null},n.keyDown=function(e){switch(e.keyCode){case 27:n.isOpen=!1;break;case 13:n.selectOption(n.mouseOverOption),n.isOpen=!1,e.preventDefault(),e.stopPropagation();break;case 38:n.mouseOver(n.mouseOverIndex>0?n.mouseOverIndex-1:n.filteredOptions.length-1);break;case 40:n.mouseOver(n.mouseOverIndex<n.filteredOptions.length-1?n.mouseOverIndex+1:0)}},n.$watchCollection("[isOpen, filteredOptions.length]",function(){n.mouseOver(-1)}),n.$on("$destroy",function(){m()})}}}]),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,i,r,o){e.buttonClass=r.buttonClass,e.$watch("label",function(i){e.bindableLabel=t.trustAsHtml(i)}),e.model=o.registerSubmitButton(e)}}}]),angular.module("formFor").directive("textField",["$log","$timeout","FieldHelper",function(e,t,i){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/text-field.html",scope:{attribute:"@",debounce:"@?",disable:"=",focused:"&?",help:"@?",iconAfterClicked:"&?",iconBeforeClicked:"&?",placeholder:"@?"},link:function(r,o,a,n){if(!r.attribute)return void e.error('Missing required field "attribute"');if(r.label=i.getLabel(a,r.attribute),r.type=a.type||"text",r.multiline=a.hasOwnProperty("multiline")&&"false"!==a.multiline,a.hasOwnProperty("autofocus")&&t(function(){o.find(r.multiline?"textarea":"input").focus()}),i.manageFieldRegistration(r,n),a.iconAfter){var l=function(){if(r.model){var e="{"===a.iconAfter.charAt(0)?r.$eval(a.iconAfter):a.iconAfter;r.iconAfter=angular.isObject(e)?r.model.error?e.invalid:r.model.pristine?e.pristine:e.valid:e}};a.$observe("iconAfter",l),r.$watch("model.error",l),r.$watch("model.pristine",l)}if(a.iconBefore){var u=function(){if(r.model){var e="{"===a.iconBefore.charAt(0)?r.$eval(a.iconBefore):a.iconBefore;r.iconBefore=angular.isObject(e)?r.model.error?e.invalid:r.model.pristine?e.pristine:e.valid:e}};a.$observe("iconBefore",u),r.$watch("model.error",u),r.$watch("model.pristine",u)}r.onIconAfterClick=function(){a.hasOwnProperty("iconAfterClicked")&&r.iconAfterClicked()},r.onIconBeforeClick=function(){a.hasOwnProperty("iconBeforeClicked")&&r.iconBeforeClicked()},r.onFocus=function(){a.hasOwnProperty("focused")&&r.focused()}}}}]),angular.module("formFor").directive("typeAheadField",["$log","$filter","$timeout","FieldHelper","FormForConfiguration",function(e,t,i,r,o){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/type-ahead-field.html",scope:{attribute:"@",disable:"=",filter:"=?",help:"@?",options:"=",placeholder:"@?"},link:function(a,n,l,u){if(!a.attribute)return void e.error('Missing required field "attribute"');l.hasOwnProperty("autofocus")&&i(function(){n.find("input").focus()}),a.debounce=l.debounce||o.defaultDebounceDuration,a.labelAttribute=l.labelAttribute||"label",a.valueAttribute=l.valueAttribute||"value",a.filteredOptions=a.options||[],a.changeHandler=function(){a.filter=n.find("input").val()};var s=function(){var e=a.options||[],i={};i[a.labelAttribute]=a.filter,a.filteredOptions=t("filter")(e,i)};a.$watch("filter",s),a.$watch("options",s),a.label=r.getLabel(l,a.attribute),r.manageFieldRegistration(a,u);var d=function(){var e,t=a.model.selectedOption&&a.model.selectedOption[[a.valueAttribute]];a.model.bindable!==t&&(angular.forEach(a.options,function(t){t[a.valueAttribute]===a.model.bindable&&(e=t)}),a.model.selectedOption=e)};a.$watch("model.bindable",d),a.$watch("options",d);var c;a.$watch("model.selectedOption",function(e){return c?void(a.model.bindable=e&&e[a.valueAttribute]):void(c=!0)})}}}]),angular.module("formFor").service("FieldHelper",["FormForConfiguration","StringUtil",function(e,t){this.getLabel=function(i,r){return i.hasOwnProperty("label")?i.label:e.autoGenerateLabels?t.humanize(r):void 0},this.manageFieldRegistration=function(e,t){e.$watch("attribute",function(i,r){e.model&&t.unregisterFormField(r),e.model=t.registerFormField(e.attribute)}),e.$on("$destroy",function(){t.unregisterFormField(e.attribute)})}}]),angular.module("formFor").service("FormForConfiguration",function(){return{autoGenerateLabels:!1,defaultDebounceDuration:1e3,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").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,i){var r=e.flattenAttribute(t);e.writeAttribute(this.formScope.errorMap,t,i),i?this.shallowErrorMap[r]=i:delete this.shallowErrorMap[r],this.formScope.valid=this.isFormValid(),this.watchable++},t.prototype.setFieldHasBeenModified=function(t,i){e.writeAttribute(this.fieldNameToModificationMap,t,i),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,i,r){return this.$getRulesForFieldName=function(e,t){return t=t.replace(/\[[^\]]+\]/g,".collection.fields"),r.readAttribute(e,t)},this.isCollectionRequired=function(e,t){var i=this.$getRulesForFieldName(t,e);return i&&i.collection&&i.collection.min&&(angular.isObject(i.collection.min)?i.collection.min.rule:i.collection.min)},this.isFieldRequired=function(e,t){var i=this.$getRulesForFieldName(t,e);return i&&i.required&&(angular.isObject(i.required)?i.required.rule:i.required)},this.validateAll=function(e,t){var i=r.flattenObjectKeys(t);return this.validateFields(e,i,t)},this.validateFields=function(e,i,o){var a=t.defer(),n=[],l={};return angular.forEach(i,function(t){var i=this.$getRulesForFieldName(o,t);if(i){var a;a=i.collection?this.validateCollection(e,t,o):this.validateField(e,t,o),a.then(angular.noop,function(e){r.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=r.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(i.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(i.validationFailedForMaxCollectionSizeMessage)({num:c}))}}return t.resolve()},this.validateField=function(o,a,n){var l=this.$getRulesForFieldName(n,a),u=r.readAttribute(o,a);if(l){if(u=u||"",l.required){var s=angular.isObject(l.required)?l.required.rule:l.required;if(!!u!==s)return t.reject(angular.isObject(l.required)?l.required.message:i.validationFailedForRequiredMessage)}if(l.minlength){var d=angular.isObject(l.minlength)?l.minlength.rule:l.minlength;if(u.length<d)return t.reject(angular.isObject(l.minlength)?l.minlength.message:e(i.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(i.validationFailedForMaxLengthMessage)({num:c}))}if(l.type){var f=angular.isObject(l.type)?l.type.rule:l.type,p=u.toString();if(f.indexOf("integer")>=0&&!p.match(/^\-*[0-9]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForIntegerTypeMessage);if(f.indexOf("number")>=0&&!p.match(/^\-*[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForNumericTypeMessage);if(f.indexOf("negative")>=0&&!p.match(/^\-[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForNegativeTypeMessage);if(f.indexOf("positive")>=0&&!p.match(/^[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForPositiveTypeMessage);if(f.indexOf("email")>=0&&!p.match(/^[\w\.\+]+@\w+\.\w+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForEmailTypeMessage)}if(l.pattern){var m=l.pattern instanceof RegExp,b=m?l.pattern:l.pattern.rule;if(!b.exec(u))return t.reject(m?i.validationFailedForPatternMessage:l.pattern.message)}if(l.custom){var F=angular.isFunction(l.custom)?i.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 i=0;;){if(i=t.indexOf("[",i),0>i)break;var r=t.substr(0,i),o=this.readAttribute(e,r);o||(o=[],this.writeAttribute(e,r,o));var a=t.substr(i).match(/([0-9]+)\]\./);if(a){var n=parseInt(a[1]);o[n]||(o[n]={})}i++}},flattenAttribute:function(e){return e=e.replace(/\[([^\]]+)\]\.{0,1}/g,"___$1___"),e=e.replace(/\./g,"___")},flattenObjectKeys:function(e){for(var t=[],i=[{object:e,prefix:null}];;){if(0===i.length)break;var r=i.pop(),o=r.prefix?r.prefix+".":"";if("object"==typeof r.object)for(var a in r.object){var n=o+a;t.push(n),i.push({object:r.object[a],prefix:n})}}return t},readAttribute:function(t,i){return e(i)(t)},writeAttribute:function(t,i,r){this.$createEmptyArrays(t,i),e(i).assign(t,r)}}}]);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(),i=[],r=0,o=!1,a=function(e,t){i.hasOwnProperty(e)||(i[e]=t,r--),n()},n=function(){0===r&&(o?t.reject(i):t.resolve(i))};return angular.forEach(e,function(e,t){r++,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("checkboxField",["$log","FieldHelper",function(e,t){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/checkbox-field.html",scope:{attribute:"@",disable:"=",help:"@?"},link:function(i,r,o,a){if(!i.attribute)return void e.error('Missing required field "attribute"');i.label=t.getLabel(o,i.attribute),i.tabIndex=o.tabIndex||0;r.find("input");i.toggle=function(){i.disable||i.model.disabled||(i.model.bindable=!i.model.bindable)},t.manageFieldRegistration(i,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,i,r,o){t.$watch("label",function(i){t.bindableLabel=e.trustAsHtml(i)}),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:"@?"}}}]),angular.module("formFor").directive("fieldLabel",["$sce","FormForConfiguration",function(e,t){return{restrict:"EA",templateUrl:"form-for/templates/field-label.html",scope:{help:"@?",label:"@",required:"@?"},controller:["$scope",function(i){i.$watch("label",function(t){i.bindableLabel=e.trustAsHtml(t)}),i.$watch("required",function(e){i.requiredLabel=i.$eval(e)?t.requiredLabel:null})}]}}]),angular.module("formFor").directive("formForDebounce",["$log","$sniffer","$timeout","FormForConfiguration",function(e,t,i,r){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 s,u=n.formForDebounce,d=r.defaultDebounceDuration;if(void 0!==u&&("false"===u.toString()?d=!1:(u=parseInt(u),angular.isNumber(u)&&!isNaN(u)&&(d=u))),t.hasEvent("input")?a.off("input"):(a.off("keydown"),t.hasEvent("paste")&&a.off("paste")),d!==!1){var c=function(){i.cancel(s),s=i(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(){s&&i.cancel(s)})}}}]),angular.module("formFor").directive("formFor",["$injector","$log","$parse","$q","$sce","FormForConfiguration","$FormForStateHelper","NestedObjectHelper","ModelValidator",function(e,t,i,r,o,a,n,l,s){return{require:"form",restrict:"A",scope:{controller:"=?",disable:"=?",formFor:"=",service:"@",submitComplete:"&?",submitError:"&?",submitWith:"&?",valid:"=?",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 u=this;u.registerFormField=function(e){if(!e)throw Error('Invalid field name "'+e+'" provided.');var t=l.flattenAttribute(e);if(a.fields.hasOwnProperty(t))throw Error('Field "'+e+'" has already eben registered. Field names must be unique.');var r=(l.readAttribute(a.$validationRules,e),{bindableWrapper:{bindable:null,disabled:!1,error:null,pristine:!0,required:s.isFieldRequired(e,a.$validationRules)},fieldName:e,unwatchers:[],validationAttribute:e.split("[")[0]});a.fields[t]=r;var o=i(e),n=o.assign;r.unwatchers.push(a.$watch("fields."+t+".bindableWrapper.bindable",function(e,t){e!==t&&n(a.formFor,e)}));var d;return r.unwatchers.push(a.$watch("formFor."+e,function(i,o){(i!==r.bindableWrapper.bindable||void 0===o&&""===i||void 0===i)&&(d=!1),r.bindableWrapper.bindable=i,u.validateField(e),d||(d=!0,a.formForStateHelper.setFieldHasBeenModified(t,!1)),r.bindableWrapper.pristine=!a.formForStateHelper.hasFieldBeenModified(t)})),r.bindableWrapper},this.unregisterFormField=function(e){var t=l.flattenAttribute(e);angular.forEach(a.fields[t].unwatchers,function(e){e()}),delete a.fields[t]},u.registerSubmitButton=function(){var e={disabled:!1};return a.buttons.push(e),e},u.registerCollectionLabel=function(e){var t=l.flattenAttribute(e),i={error:null,required:s.isCollectionRequired(e,a.$validationRules)};a.collectionLabels[t]=i;var r=!1;return a.$watch("formFor."+e+".length",function(){r?s.validateCollection(a.formFor,e,a.$validationRules).then(function(){a.formForStateHelper.setFieldError(t,null)},function(e){a.formForStateHelper.setFieldError(t,e)}):r=!0}),i},u.resetField=function(e){var t=l.flattenAttribute(e);a.formForStateHelper.getFieldError(t)&&(a.formForStateHelper.setFieldHasBeenModified(t,!1),a.fields[t].bindableWrapper.pristine=!0),a.formForStateHelper.setFieldError(t,null)},u.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()},u.resetFields=u.resetErrors,u.validateField=function(e){{var t=l.flattenAttribute(e);a.fields[t],i(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)})},u.validateForm=function(){a.updateCollectionErrors({}),a.updateFieldErrors({});var e,t;if(a.$validationRules){var i=[];angular.forEach(a.fields,function(e){i.push(e.fieldName)}),t=s.validateFields(a.formFor,i,a.$validationRules),t.then(angular.noop,a.updateFieldErrors),i=[],angular.forEach(a.collectionLabels,function(e,t){i.push(t)}),e=s.validateFields(a.formFor,i,a.$validationRules),e.then(angular.noop,a.updateCollectionErrors)}else e=r.resolve(),t=r.resolve();var o=r.defer();return r.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(u,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,i){if(e||a.formForStateHelper.hasFieldBeenModified(i)){var r=a.formForStateHelper.getFieldError(i);t.bindableWrapper.error=r?o.trustAsHtml(r):null}else t.bindableWrapper.error=null}),angular.forEach(a.collectionLabels,function(e,t){var i=a.formForStateHelper.getFieldError(t);e.error=i?o.trustAsHtml(i):null})}),a.updateCollectionErrors=function(e){angular.forEach(a.collectionLabels,function(t,i){var r=l.readAttribute(e,i);a.formForStateHelper.setFieldError(i,r)})},a.updateFieldErrors=function(e){angular.forEach(a.fields,function(t,i){var r=l.readAttribute(e,t.fieldName);a.formForStateHelper.setFieldError(i,r)})}}],link:function(e,t,i){t.on("submit",function(){return e.formForStateHelper.setFormSubmitted(!0),e.disable=!0,e.controller.validateForm().then(function(){var t;t=i.submitWith?e.submitWith({data:e.formFor}):e.$service&&e.$service.submit?e.$service.submit(e.formFor):r.reject("No submit function provided"),t||(t=r.reject("Submit function did not return a promise")),t.then(function(t){i.submitComplete?e.submitComplete({data:t}):a.defaultSubmitComplete(t)},function(t){angular.isObject(t)&&(e.updateCollectionErrors(t),e.updateFieldErrors(t)),i.submitError?e.submitError({error:t}):a.defaultSubmitError(t)}),t["finally"](function(){e.disable=!1})},function(){e.disable=!1,i.validationFailed?e.validationFailed():a.defaultValidationFailed()}),!1})}}}]),angular.module("formFor").directive("radioField",["$log","FieldHelper",function(e,t){var i={};return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/radio-field.html",scope:{attribute:"@",disable:"=",help:"@?",value:"@"},link:function(r,o,a,n){if(!r.attribute)return void e.error('Missing required field "attribute"');if(i[r.attribute])r.hideErrorMessage=!0;else{var l={defaultScope:r,scopes:[]};t.manageFieldRegistration(r,n),i[r.attribute]=l}var s=i[r.attribute];s.scopes.push(r),r.label=t.getLabel(a,r.value),r.tabIndex=a.tabIndex||0;o.find("input");r.click=function(){r.disable||r.model.disabled||(r.model.bindable=r.value)},s.defaultScope.$watch("model",function(e){r.model=e}),s.defaultScope.$watch("disable",function(e){r.disable=e}),s.defaultScope.$watch("model.disabled",function(e){r.model&&(r.model.disabled=e)}),r.$watch("model.bindable",function(e){r.checked=void 0!==e&&null!==e&&void 0!==r.value&&null!==r.value&&e.toString()===r.value.toString()}),r.$on("$destroy",function(){s.scopes.splice(s.scopes.indexOf(r),1),0===s.scopes.length&&delete i[r.attribute]})}}}]),angular.module("formFor").directive("selectField",["$document","$log","$timeout","$window","FieldHelper",function(e,t,i,r,o){var a=250,n=10;return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/select-field.html",scope:{attribute:"@",disable:"=",filter:"=?",filterDebounce:"@?",help:"@?",options:"="},link:function(l,s,u,d){if(r=$(r),!l.attribute)return void t.error('Missing required field "attribute"');l.allowBlank=u.hasOwnProperty("allowBlank"),l.enableFiltering=u.hasOwnProperty("enableFiltering"),l.preventDefaultOption=u.hasOwnProperty("preventDefaultOption"),l.labelAttribute=u.labelAttribute||"label",l.valueAttribute=u.valueAttribute||"value",l.placeholder=u.placeholder||"Select",l.tabIndex=u.tabIndex||0,l.label=o.getLabel(u,l.attribute),o.manageFieldRegistration(l,d),l.emptyOption={},l.emptyOption[l.labelAttribute]="",l.emptyOption[l.valueAttribute]=void 0,l.filteredOptions=[];var c=function(e){return e&&e.toLowerCase()},f=function(){var e=l.options||[];if(l.filteredOptions.splice(0),l.enableFiltering&&l.filter){var t=c(l.filter);angular.forEach(e,function(e){var i=c(e[l.labelAttribute]).indexOf(t);i>=0&&l.filteredOptions.push(e)})}else angular.copy(e,l.filteredOptions);l.allowBlank&&l.filteredOptions.unshift(l.emptyOption)};l.$watch("filter",f),l.$watch("options.length",f);var p=function(){var e=l.selectedOption&&l.selectedOption[[l.valueAttribute]];return l.model.bindable===e?void(!l.allowBlank&&!l.preventDefaultOption&&l.options&&l.options.length&&(l.model.bindable=l.options[0][l.valueAttribute])):void 0};l.$watch("model.bindable",p),l.$watch("options.length",p);var m=s.find("[toggle-button]");l.close=function(){i(function(){l.isOpen=!1},n)},l.open=function(){i(function(){l.isOpen=!0},n)},l.$watch("model.bindable",function(){var e;angular.forEach(l.options,function(t){t[l.valueAttribute]===l.model.bindable&&(e=t)}),l.selectedOption=e,l.selectedOptionLabel=e&&e[l.labelAttribute],l.filter=l.selectedOptionLabel}),l.selectOption=function(e){l.model.bindable=e&&e[l.valueAttribute],l.isOpen=!1};var b=function(){l.isOpen=!1,l.$apply()},F=s.find(".select-field-list-container"),v=s.find(".select-field-list-scrollable"),g=(s.find(".select-field-list"),function(e){i(function(){for(var t,i=this.find(".select-field-list-item"),r=0;r<i.length;r++){var o=i[r],a=$(o).scope().option;if(a&&a[l.valueAttribute]===e){t=o;break}}if(t){v.scrollTop(0);var n=v.scrollTop(),s=v.outerHeight(),u=$(t).position().top,d=$(t).outerHeight();0===s?v.scrollTop(u):n>u?v.scrollTop(u):u+d>n+s&&v.scrollTop(u-s+d)}}.bind(s),n)}),h=function(){l.disable||l.model.disabled||(l.isOpen=!0,l.isOpen&&(M(),g(l.model.bindable)),l.$$phase||l.$digest())};l.$watch("isOpen",function(){i(function(){l.isOpen?(m.off("click",h),e.on("click",b)):(m.on("click",h),e.off("click",b))},n)});var O=function(){switch(u.direction){case"up":return!0;case"down":return!1;case"auto":default:var e=m.offset().top-r.scrollTop();return e+m.outerHeight()+a>r.height()}},M=function(){O()?(l.dropUp=!0,F.css({bottom:m.outerHeight()-1+"px",top:"auto"})):(l.dropUp=!1,F.css({bottom:"auto",top:"100%"}))},y=s.find(".filter-text-input");l.mouseOver=function(e){l.mouseOverIndex=e,l.mouseOverOption=e>=0?l.filteredOptions[e]:null},l.keyDown=function(e){switch(e.keyCode){case 27:l.isOpen=!1,i(m.focus.bind(m));break;case 13:l.isOpen?(l.selectOption(l.mouseOverOption),l.isOpen=!1,i(m.focus.bind(m))):(l.isOpen=!0,M()),e.preventDefault();break;case 38:l.isOpen?(l.mouseOver(l.mouseOverIndex>0?l.mouseOverIndex-1:l.filteredOptions.length-1),g(l.mouseOverOption&&l.mouseOverOption.value)):l.isOpen=!0,e.preventDefault();break;case 40:l.isOpen?(l.mouseOver(l.mouseOverIndex<l.filteredOptions.length-1?l.mouseOverIndex+1:0),g(l.mouseOverOption&&l.mouseOverOption.value)):l.isOpen=!0,e.preventDefault();break;case 9:case 16:l.isOpen=!1;break;default:l.isOpen=!0}},l.$watchCollection("[isOpen, filteredOptions.length]",function(){l.mouseOver(-1),l.isOpen&&l.enableFiltering&&i(y.focus.bind(y))}),l.$on("$destroy",function(){e.off("click",b)})}}}]),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,i,r,o){e.buttonClass=r.buttonClass,e.tabIndex=r.tabIndex||0,e.$watch("label",function(i){e.bindableLabel=t.trustAsHtml(i)}),e.model=o.registerSubmitButton(e)}}}]),angular.module("formFor").directive("textField",["$log","$timeout","FieldHelper",function(e,t,i){return{require:"^formFor",restrict:"EA",templateUrl:"form-for/templates/text-field.html",scope:{attribute:"@",debounce:"@?",disable:"=",focused:"&?",help:"@?",iconAfterClicked:"&?",iconBeforeClicked:"&?",placeholder:"@?"},link:function(r,o,a,n){if(!r.attribute)return void e.error('Missing required field "attribute"');if(r.label=i.getLabel(a,r.attribute),r.type=a.type||"text",r.multiline=a.hasOwnProperty("multiline")&&"false"!==a.multiline,r.tabIndex=a.tabIndex||0,a.hasOwnProperty("autofocus")&&t(function(){o.find(r.multiline?"textarea":"input").focus()}),i.manageFieldRegistration(r,n),a.iconAfter){var l=function(){if(r.model){var e="{"===a.iconAfter.charAt(0)?r.$eval(a.iconAfter):a.iconAfter;r.iconAfter=angular.isObject(e)?r.model.error?e.invalid:r.model.pristine?e.pristine:e.valid:e}};a.$observe("iconAfter",l),r.$watch("model.error",l),r.$watch("model.pristine",l)}if(a.iconBefore){var s=function(){if(r.model){var e="{"===a.iconBefore.charAt(0)?r.$eval(a.iconBefore):a.iconBefore;r.iconBefore=angular.isObject(e)?r.model.error?e.invalid:r.model.pristine?e.pristine:e.valid:e}};a.$observe("iconBefore",s),r.$watch("model.error",s),r.$watch("model.pristine",s)}r.onIconAfterClick=function(){a.hasOwnProperty("iconAfterClicked")&&r.iconAfterClicked()},r.onIconBeforeClick=function(){a.hasOwnProperty("iconBeforeClicked")&&r.iconBeforeClicked()},r.onFocus=function(){a.hasOwnProperty("focused")&&r.focused()}}}}]),angular.module("formFor").service("FieldHelper",["FormForConfiguration","StringUtil",function(e,t){this.getLabel=function(i,r){return i.hasOwnProperty("label")?i.label:e.autoGenerateLabels?t.humanize(r):void 0},this.manageFieldRegistration=function(e,t){e.$watch("attribute",function(i,r){e.model&&t.unregisterFormField(r),e.model=t.registerFormField(e.attribute)}),e.$on("$destroy",function(){t.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").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,i){var r=e.flattenAttribute(t);e.writeAttribute(this.formScope.errorMap,t,i),i?this.shallowErrorMap[r]=i:delete this.shallowErrorMap[r],this.formScope.valid=this.isFormValid(),this.watchable++},t.prototype.setFieldHasBeenModified=function(t,i){e.writeAttribute(this.fieldNameToModificationMap,t,i),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,i,r){return this.$getRulesForFieldName=function(e,t){return t=t.replace(/\[[^\]]+\]/g,".collection.fields"),r.readAttribute(e,t)},this.isCollectionRequired=function(e,t){var i=this.$getRulesForFieldName(t,e);return i&&i.collection&&i.collection.min&&(angular.isObject(i.collection.min)?i.collection.min.rule:i.collection.min)},this.isFieldRequired=function(e,t){var i=this.$getRulesForFieldName(t,e);return i&&i.required&&(angular.isObject(i.required)?i.required.rule:i.required)},this.validateAll=function(e,t){var i=r.flattenObjectKeys(t);return this.validateFields(e,i,t)},this.validateFields=function(e,i,o){var a=t.defer(),n=[],l={};return angular.forEach(i,function(t){var i=this.$getRulesForFieldName(o,t);if(i){var a;a=i.collection?this.validateCollection(e,t,o):this.validateField(e,t,o),a.then(angular.noop,function(e){r.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),s=r.readAttribute(o,a);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(i.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(i.validationFailedForMaxCollectionSizeMessage)({num:c}))}}return t.resolve()},this.validateField=function(o,a,n){var l=this.$getRulesForFieldName(n,a),s=r.readAttribute(o,a);if(l){if(s=s||"",l.required){var u=angular.isObject(l.required)?l.required.rule:l.required;if(!!s!==u)return t.reject(angular.isObject(l.required)?l.required.message:i.validationFailedForRequiredMessage)}if(l.minlength){var d=angular.isObject(l.minlength)?l.minlength.rule:l.minlength;if(s.length<d)return t.reject(angular.isObject(l.minlength)?l.minlength.message:e(i.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(i.validationFailedForMaxLengthMessage)({num:c}))}if(l.type){var f=angular.isObject(l.type)?l.type.rule:l.type,p=s.toString();if(f.indexOf("integer")>=0&&!p.match(/^\-*[0-9]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForIntegerTypeMessage);if(f.indexOf("number")>=0&&!p.match(/^\-*[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForNumericTypeMessage);if(f.indexOf("negative")>=0&&!p.match(/^\-[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForNegativeTypeMessage);if(f.indexOf("positive")>=0&&!p.match(/^[0-9\.]+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForPositiveTypeMessage);if(f.indexOf("email")>=0&&!p.match(/^[\w\.\+]+@\w+\.\w+$/))return t.reject(angular.isObject(l.type)?l.type.message:i.validationFailedForEmailTypeMessage)}if(l.pattern){var m=l.pattern instanceof RegExp,b=m?l.pattern:l.pattern.rule;if(!b.exec(s))return t.reject(m?i.validationFailedForPatternMessage:l.pattern.message)}if(l.custom){var F=angular.isFunction(l.custom)?i.validationFailedForCustomMessage:l.custom.message,v=angular.isFunction(l.custom)?l.custom:l.custom.rule;try{var g=v(s,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 i=0;;){if(i=t.indexOf("[",i),0>i)break;var r=t.substr(0,i),o=this.readAttribute(e,r);o||(o=[],this.writeAttribute(e,r,o));var a=t.substr(i).match(/([0-9]+)\]\./);if(a){var n=parseInt(a[1]);o[n]||(o[n]={})}i++}},flattenAttribute:function(e){return e=e.replace(/\[([^\]]+)\]\.{0,1}/g,"___$1___"),e=e.replace(/\./g,"___")},flattenObjectKeys:function(e){for(var t=[],i=[{object:e,prefix:null}];;){if(0===i.length)break;var r=i.pop(),o=r.prefix?r.prefix+".":"";if("object"==typeof r.object)for(var a in r.object){var n=o+a;t.push(n),i.push({object:r.object[a],prefix:n})}}return t},readAttribute:function(t,i){return e(i)(t)},writeAttribute:function(t,i,r){this.$createEmptyArrays(t,i),e(i).assign(t,r)}}}]);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(),i=[],r=0,o=!1,a=function(e,t){i.hasOwnProperty(e)||(i[e]=t,r--),n()},n=function(){0===r&&(o?t.reject(i):t.resolve(i))};return angular.forEach(e,function(e,t){r++,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)):""}});

@@ -6,2 +6,3 @@ var gulp = require('gulp');

var shell = require('gulp-shell');
var ngAnnotate = require('gulp-ng-annotate');

@@ -38,27 +39,29 @@ var CONFIG = {

var concatJS = function() {
var order = require('gulp-order');
var getTemplates = function(templatesDirectory, moduleName, outputFile) {
var templateCache = require('gulp-angular-templatecache');
var ngAnnotate = require('gulp-ng-annotate');
var sources =
es.merge(
gulp.src('templates/**/*.html')
.pipe(templateCache('templates.js', {
module: 'formFor.templates',
standalone: true,
root: 'form-for/templates/'
})),
jsSources.pipe(concat('form-for.js')));
return sources
.pipe(order([
'templates.js',
'form-for.js'
]))
.pipe(ngAnnotate());
return gulp.src(templatesDirectory)
.pipe(
templateCache('templates.js',
{
module: moduleName,
standalone: true,
root: 'form-for/templates/' // Relative path for Directive :templateUrls
}))
.pipe(ngAnnotate())
.pipe(concat(outputFile))
.pipe(gulp.dest(CONFIG.distDir))
};
gulp.task('createBootstrapTemplates', function() {
return getTemplates('templates/bootstrap/**/*.html', 'formFor.bootstrapTemplates', 'form-for.bootstrap-templates.js');
});
gulp.task('createDefaultTemplates', function() {
return getTemplates('templates/default/**/*.html', 'formFor.defaultTemplates', 'form-for.default-templates.js');
});
gulp.task('createUncompressedJs', function() {
return concatJS()
return jsSources.pipe(concat('form-for.js'))
.pipe(ngAnnotate())
.pipe(concat('form-for.js'))

@@ -71,3 +74,4 @@ .pipe(gulp.dest(CONFIG.distDir));

return concatJS()
return jsSources.pipe(concat('form-for.js'))
.pipe(ngAnnotate())
.pipe(uglify())

@@ -92,3 +96,3 @@ .pipe(concat('form-for.min.js'))

action: 'run'
}))
}));
});

@@ -104,2 +108,12 @@

gulp.task('build', ['clean', 'lintJs', 'test', 'createCompressedJs', 'createUncompressedJs', 'compileCss', 'docs']);
gulp.task('build', [
'clean',
'lintJs',
'test',
'createCompressedJs',
'createUncompressedJs',
'createBootstrapTemplates',
'createDefaultTemplates',
'compileCss',
'docs'
]);

@@ -13,3 +13,2 @@ 'use strict';

ngHtml2JsPreprocessor: {
moduleName: 'formFor.templates'
},

@@ -16,0 +15,0 @@ files: [

{
"name": "angular-form-for",
"version": "1.2.16",
"version": "1.3.0",
"description": "Set of Angular directives to simplify creating and validating HTML forms.",

@@ -26,3 +26,2 @@ "keywords": [

"gulp-karma": "0.0.4",
"gulp-order": "^1.1.1",
"gulp-rimraf": "^0.1.0",

@@ -29,0 +28,0 @@ "gulp-stylus": "^1.3.0",

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

* (Although not required, it is strongly suggested that you specify a value for this attribute.) HTML is allowed for this attribute.
* @param {int} tabIndex Optional custom tab index for input; by default this is 0 (tab order chosen by the browser)
*

@@ -45,2 +46,3 @@ * @example

$scope.label = FieldHelper.getLabel($attributes, $scope.attribute);
$scope.tabIndex = $attributes.tabIndex || 0;

@@ -47,0 +49,0 @@ var $input = $element.find('input');

@@ -36,3 +36,3 @@ /**

angular.module('formFor').directive('formFor',
function($injector, $parse, $q, $sce, FormForConfiguration, $FormForStateHelper, NestedObjectHelper, ModelValidator) {
function($injector, $log, $parse, $q, $sce, FormForConfiguration, $FormForStateHelper, NestedObjectHelper, ModelValidator) {
return {

@@ -54,2 +54,5 @@ require: 'form', // We don't need the ngForm controller, but we do rely on the form-submit hook

controller: function($scope) {
if (!$scope.formFor) {
$log.error('The form data object specified by <form form-for=""> is null or undefined.');
}

@@ -108,3 +111,12 @@ // Map of safe (bindable, $scope.$watch-able) field names to objects containing the following keys:

controller.registerFormField = function(fieldName) {
if (!fieldName) {
throw Error('Invalid field name "' + fieldName + '" provided.');
}
var bindableFieldName = NestedObjectHelper.flattenAttribute(fieldName);
if ($scope.fields.hasOwnProperty(bindableFieldName)) {
throw Error('Field "' + fieldName + '" has already eben registered. Field names must be unique.');
}
var rules = NestedObjectHelper.readAttribute($scope.$validationRules, fieldName);

@@ -111,0 +123,0 @@

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

* HTML is allowed for this attribute
* @param {int} tabIndex Optional custom tab index for input; by default this is 0 (tab order chosen by the browser)
* @param {Object} Value to be assigned to model if this radio component is selected.

@@ -57,2 +58,5 @@ *

nameToActiveRadioMap[$scope.attribute] = mainRadioDatum;
} else {
// Only the primary <radio> input should show error message text
$scope.hideErrorMessage = true;
}

@@ -67,2 +71,3 @@

$scope.label = FieldHelper.getLabel($attributes, $scope.value);
$scope.tabIndex = $attributes.tabIndex || 0;

@@ -69,0 +74,0 @@ var $input = $element.find('input');

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

* Without this attribute, lists with `allow-blank` will default select the first option in the options array.
* @param {int} tabIndex Optional custom tab index for input; by default this is 0 (tab order chosen by the browser)
* @param {String} valueAttribute Optional override for value key in options array.

@@ -59,2 +60,3 @@ * Defaults to "value".

var MAX_HEIGHT = 250;
var MIN_TIMEOUT_INTERVAL = 10;

@@ -71,4 +73,3 @@ return {

help: '@?',
options: '=',
placeholder: '@?'
options: '='
},

@@ -90,2 +91,4 @@ link: function($scope, $element, $attributes, formForController) {

$scope.valueAttribute = $attributes.valueAttribute || 'value';
$scope.placeholder = $attributes.placeholder || 'Select';
$scope.tabIndex = $attributes.tabIndex || 0;

@@ -101,2 +104,5 @@ $scope.label = FieldHelper.getLabel($attributes, $scope.attribute);

$scope.emptyOption = {};
$scope.emptyOption[$scope.labelAttribute] = '';
$scope.emptyOption[$scope.valueAttribute] = undefined;
$scope.filteredOptions = [];

@@ -153,12 +159,2 @@

}
angular.forEach($scope.options,
function(option) {
if (option[$scope.valueAttribute] === $scope.model.bindable) {
matchingOption = option;
}
});
$scope.selectedOption = matchingOption;
$scope.selectedOptionLabel = matchingOption && matchingOption[$scope.labelAttribute];
};

@@ -173,40 +169,36 @@

var toggleButton = $element.find('[toggle-button]');
$scope.close = function() {
$timeout(function() {
$scope.isOpen = false;
}, MIN_TIMEOUT_INTERVAL);
};
$scope.open = function() {
$timeout(function() {
$scope.isOpen = true;
}, MIN_TIMEOUT_INTERVAL);
};
$scope.$watch('model.bindable', function(value) {
var matchingOption;
for (var index = 0; index < $scope.filteredOptions.length; index++) {
var option = $scope.filteredOptions[index];
angular.forEach($scope.options,
function(option) {
if (option[$scope.valueAttribute] === $scope.model.bindable) {
matchingOption = option;
}
});
if (option[$scope.valueAttribute] === value) {
matchingOption = option;
break;
}
};
$scope.selectedOption = matchingOption;
$scope.selectedOptionLabel = matchingOption && matchingOption[$scope.labelAttribute];
// Make sure our filtered text reflects the currently selected label (important for Bootstrap styles).
$scope.filter = $scope.selectedOptionLabel;
});
var oneClick = function(target, handler) {
$timeout(function() { // Delay to avoid processing the same click event that trigger the toggle-open
target.one('click', handler);
}, 1);
};
var removeClickWatch = function() {
$document.off('click', clickWatcher);
};
var addClickToOpen = function() {
oneClick($element.find('.select-field-toggle-button'), clickToOpen);
};
$scope.selectOption = function(option) {
$scope.model.bindable = option && option[$scope.valueAttribute];
$scope.isOpen = false;
removeClickWatch();
addClickToOpen();
};

@@ -217,60 +209,70 @@

$scope.$apply();
removeClickWatch();
addClickToOpen();
};
var listContainer = $element.find('.list-group-container');
var listScroller = $element.find('.list-group-scrollable');
var list = $element.find('.list-group');
var listContainer = $element.find('.select-field-list-container');
var listScroller = $element.find('.select-field-list-scrollable');
var list = $element.find('.select-field-list');
var clickToOpen = function() {
if ($scope.disable || $scope.model.disabled) {
addClickToOpen();
var scrollToValue = function(value) {
$timeout(
function() {
var listItems = this.find('.select-field-list-item');
var matchingListItem;
return;
}
for (var index = 0; index < listItems.length; index++) {
var listItem = listItems[index];
var option = $(listItem).scope().option;
$scope.isOpen = !$scope.isOpen;
if (option && option[$scope.valueAttribute] === value) {
matchingListItem = listItem;
if ($scope.isOpen) {
// TODO Auto-focus input field if filterable
break;
}
}
setListVerticalDirection();
if (matchingListItem) {
listScroller.scrollTop(0);
oneClick($document, clickWatcher);
var scrollerTop = listScroller.scrollTop();// + listScroller.offset().top;
var scrollerHeight = listScroller.outerHeight();
var itemTop = $(matchingListItem).position().top;
var itemHeight = $(matchingListItem).outerHeight();
var value = $scope.model.bindable;
if (scrollerHeight === 0) {
listScroller.scrollTop(itemTop);
} else if (itemTop < scrollerTop) {
listScroller.scrollTop(itemTop);
} else if (scrollerTop + scrollerHeight < itemTop + itemHeight) {
listScroller.scrollTop(itemTop - scrollerHeight + itemHeight);
}
}
}.bind($element), MIN_TIMEOUT_INTERVAL);
};
$timeout(
angular.bind(
$element,
function() {
var listItems = this.find('.list-group-item');
var matchingListItem;
var clickToOpen = function(event) {
if ($scope.disable || $scope.model.disabled) {
return;
}
for (var index = 0; index < listItems.length; index++) {
var listItem = listItems[index];
var option = $(listItem).scope().option;
$scope.isOpen = true;
if (option && option[$scope.valueAttribute] === value) {
matchingListItem = listItem;
if ($scope.isOpen) {
setListVerticalDirection();
scrollToValue($scope.model.bindable);
}
break;
}
}
if (matchingListItem) {
listScroller.scrollTop(0);
var top = $(matchingListItem).offset().top - listScroller.offset().top;
listScroller.scrollTop(top);
}
}));
}
$scope.$$phase || $scope.$digest();
};
addClickToOpen();
$scope.$watch('isOpen', function(value) {
$timeout(function() {
if ($scope.isOpen) {
toggleButton.off('click', clickToOpen);
$document.on('click', clickWatcher);
} else {
toggleButton.on('click', clickToOpen);
$document.off('click', clickWatcher);
}
}, MIN_TIMEOUT_INTERVAL);
});

@@ -281,10 +283,2 @@ /*****************************************************************************************

var toggleButton = $element.find('.select-field-toggle-button');
var css = {
position: 'absolute',
width: '100%',
zIndex: 1050
};
var shouldDropUp = function() {

@@ -311,25 +305,16 @@ switch ($attributes.direction) {

css.top = 'auto';
css.bottom = (toggleButton.outerHeight() - 1) + 'px';
listContainer.css({
bottom: (toggleButton.outerHeight() - 1) + 'px',
top: 'auto'
});
} else {
$scope.dropUp = false;
css.bottom = 'auto';
css.top = '100%';
listContainer.css({
bottom: 'auto',
top: '100%'
});
}
listContainer.css(css);
};
list.css({
marginBottom: 0 // Override Bootstrap's default marginBottom: 20px
});
listScroller.css({
maxHeight: MAX_HEIGHT,
overflowY: 'scroll'
});
$element.css('position', 'relative');
/*****************************************************************************************

@@ -339,2 +324,4 @@ * The following code responds to keyboard events when the drop-down is visible

var filterText = $element.find('.filter-text-input');
$scope.mouseOver = function(index) {

@@ -350,17 +337,58 @@ $scope.mouseOverIndex = index;

$scope.isOpen = false;
// Return focus to toggle button on close (to prevent interrupting tab order)
$timeout(toggleButton.focus.bind(toggleButton));
break;
case 13: // Enter key
$scope.selectOption($scope.mouseOverOption);
$scope.isOpen = false;
if ($scope.isOpen) {
$scope.selectOption($scope.mouseOverOption);
$scope.isOpen = false;
// Return focus to toggle button on close (to prevent interrupting tab order)
$timeout(toggleButton.focus.bind(toggleButton));
} else {
$scope.isOpen = true;
setListVerticalDirection();
}
// Don't bubble up and submit the parent form
event.preventDefault();
event.stopPropagation();
break;
case 38: // Up arrow
$scope.mouseOver( $scope.mouseOverIndex > 0 ? $scope.mouseOverIndex - 1 : $scope.filteredOptions.length - 1 );
if ($scope.isOpen) {
$scope.mouseOver( $scope.mouseOverIndex > 0 ? $scope.mouseOverIndex - 1 : $scope.filteredOptions.length - 1 );
scrollToValue($scope.mouseOverOption && $scope.mouseOverOption.value);
} else {
$scope.isOpen = true;
}
// Don't allow up/down arrows to scroll the window
event.preventDefault();
break;
case 40: // Down arrow
$scope.mouseOver( $scope.mouseOverIndex < $scope.filteredOptions.length - 1 ? $scope.mouseOverIndex + 1 : 0 );
if ($scope.isOpen) {
$scope.mouseOver( $scope.mouseOverIndex < $scope.filteredOptions.length - 1 ? $scope.mouseOverIndex + 1 : 0 );
scrollToValue($scope.mouseOverOption && $scope.mouseOverOption.value);
} else {
$scope.isOpen = true;
}
// Don't allow up/down arrows to scroll the window
event.preventDefault();
break;
// Tabbing (in or out) should close the menu.
case 9:
case 16:
$scope.isOpen = false;
break;
// But all other key events should (they potentially indicate a changed type-ahead filter value).
default:
$scope.isOpen = true;
break;
}

@@ -371,6 +399,11 @@ };

$scope.mouseOver(-1); // Reset hover anytime our list opens/closes or our collection is refreshed.
// Pass focus through to filter field when select is opened
if ($scope.isOpen && $scope.enableFiltering) {
$timeout(filterText.focus.bind(filterText));
}
});
$scope.$on('$destroy', function() {
removeClickWatch();
$document.off('click', clickWatcher);
});

@@ -377,0 +410,0 @@ }

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

* HTML is allowed for this attribute.
* @param {int} tabIndex Optional custom tab index for input; by default this is 0 (tab order chosen by the browser)
*

@@ -40,2 +41,3 @@ * @example

$scope['buttonClass'] = $attributes.buttonClass;
$scope.tabIndex = $attributes.tabIndex || 0;

@@ -42,0 +44,0 @@ $scope.$watch('label', function(value) {

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

* @param {String} placeholder Optional placeholder text to display if input is empty.
* @param {int} tabIndex Optional custom tab index for input; by default this is 0 (tab order chosen by the browser)
* @param {String} type Optional HTML input-type (ex.

@@ -82,2 +83,3 @@ * text, password, etc.).

$scope.multiline = $attributes.hasOwnProperty('multiline') && $attributes.multiline !== 'false';
$scope.tabIndex = $attributes.tabIndex || 0;

@@ -84,0 +86,0 @@ if ($attributes.hasOwnProperty('autofocus')) {

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

angular.module('formFor', ['formFor.templates']);
angular.module('formFor', []);

@@ -13,3 +13,3 @@ /**

autoGenerateLabels: false,
defaultDebounceDuration: 1000,
defaultDebounceDuration: 500,
defaultSubmitComplete: angular.noop,

@@ -56,3 +56,3 @@ defaultSubmitError: angular.noop,

* @param {int} duration Debounce duration (in ms).
* Defaults to 1000ms.
* Defaults to 500ms.
* To disable debounce (update only on blur) pass false.

@@ -59,0 +59,0 @@ */

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 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

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

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