angular-schema-form
Advanced tools
Comparing version 0.8.0 to 0.8.2
@@ -7,3 +7,3 @@ { | ||
], | ||
"version": "0.8.0", | ||
"version": "0.8.2", | ||
"authors": [ | ||
@@ -10,0 +10,0 @@ "Textalk", |
angular.module("schemaForm").run(["$templateCache", function($templateCache) {$templateCache.put("directives/decorators/bootstrap/actions-trcl.html","<div class=\"btn-group schema-form-actions {{form.htmlClass}}\" ng-transclude=\"\"></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/actions.html","<div class=\"btn-group schema-form-actions {{form.htmlClass}}\"><input ng-repeat-start=\"item in form.items\" type=\"submit\" class=\"btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}\" value=\"{{item.title}}\" ng-if=\"item.type === \'submit\'\"> <button ng-repeat-end=\"\" class=\"btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}\" type=\"button\" ng-disabled=\"form.readonly\" ng-if=\"item.type !== \'submit\'\" ng-click=\"buttonClick($event,item)\"><span ng-if=\"item.icon\" class=\"{{item.icon}}\"></span>{{item.title}}</button></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/array.html","<div sf-array=\"form\" class=\"schema-form-array {{form.htmlClass}}\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\"><h3 ng-show=\"form.title && form.notitle !== true\">{{ form.title }}</h3><ol class=\"list-group\" ng-model=\"modelArray\" ui-sortable=\"\"><li class=\"list-group-item {{form.fieldHtmlClass}}\" ng-repeat=\"item in modelArray track by $index\"><button ng-hide=\"form.readonly || form.remove === null\" ng-click=\"deleteFromArray($index)\" style=\"position: relative; z-index: 20;\" type=\"button\" class=\"close pull-right\"><span aria-hidden=\"true\">×</span><span class=\"sr-only\">Close</span></button><sf-decorator ng-init=\"arrayIndex = $index\" form=\"copyWithIndex($index)\"></sf-decorator></li></ol><div class=\"clearfix\" style=\"padding: 15px;\"><button ng-hide=\"form.readonly || form.add === null\" ng-click=\"appendToArray()\" type=\"button\" class=\"btn {{ form.style.add || \'btn-default\' }} pull-right\"><i class=\"glyphicon glyphicon-plus\"></i> {{ form.add || \'Add\'}}</button></div><div class=\"help-block\" ng-show=\"(hasError() && errorMessage(schemaError())) || form.description\" ng-bind-html=\"(hasError() && errorMessage(schemaError())) || form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/checkbox.html","<div class=\"checkbox schema-form-checkbox {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><label><input type=\"checkbox\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" class=\"{{form.fieldHtmlClass}}\" name=\"{{form.key.slice(-1)[0]}}\"> <span ng-bind-html=\"form.title\"></span></label><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/checkboxes.html","<div sf-array=\"form\" ng-model=\"$$value$$\" class=\"form-group schema-form-checkboxes {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><label class=\"control-label\" ng-show=\"showTitle()\">{{form.title}}</label><div class=\"checkbox\" ng-repeat=\"val in titleMapValues track by $index\"><label><input type=\"checkbox\" ng-disabled=\"form.readonly\" sf-changed=\"form\" class=\"{{form.fieldHtmlClass}}\" ng-model=\"titleMapValues[$index]\" schema-vaidate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"> <span ng-bind-html=\"form.titleMap[$index].name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/default.html","<div class=\"form-group schema-form-{{form.type}} {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess(), \'has-feedback\': form.feedback !== false }\"><label class=\"control-label\" ng-class=\"{\'sr-only\': !showTitle()}\" for=\"{{form.key.slice(-1)[0]}}\">{{form.title}}</label> <input ng-if=\"!form.fieldAddonLeft && !form.fieldAddonRight\" ng-show=\"form.key\" type=\"{{form.type}}\" step=\"any\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" ng-model-options=\"form.ngModelOptions\" ng-model=\"$$value$$\" ng-disabled=\"form.readonly\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\" aria-describedby=\"{{form.key.slice(-1)[0] + \'Status\'}}\"><div ng-if=\"form.fieldAddonLeft || form.fieldAddonRight\" ng-class=\"{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}\"><span ng-if=\"form.fieldAddonLeft\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonLeft\"></span> <input ng-show=\"form.key\" type=\"{{form.type}}\" step=\"any\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" ng-model-options=\"form.ngModelOptions\" ng-model=\"$$value$$\" ng-disabled=\"form.readonly\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\" aria-describedby=\"{{form.key.slice(-1)[0] + \'Status\'}}\"> <span ng-if=\"form.fieldAddonRight\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonRight\"></span></div><span ng-if=\"form.feedback !== false\" class=\"form-control-feedback\" ng-class=\"evalInScope(form.feedback) || {\'glyphicon\': true, \'glyphicon-ok\': hasSuccess(), \'glyphicon-remove\': hasError() }\" aria-hidden=\"true\"></span> <span ng-if=\"hasError() || hasSuccess()\" id=\"{{form.key.slice(-1)[0] + \'Status\'}}\" class=\"sr-only\">{{ hasSuccess() ? \'(success)\' : \'(error)\' }}</span><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/checkbox.html","<div class=\"checkbox schema-form-checkbox {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><label class=\"{{form.labelHtmlClass}}\"><input type=\"checkbox\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" class=\"{{form.fieldHtmlClass}}\" name=\"{{form.key.slice(-1)[0]}}\"> <span ng-bind-html=\"form.title\"></span></label><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/checkboxes.html","<div sf-array=\"form\" ng-model=\"$$value$$\" class=\"form-group schema-form-checkboxes {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><label class=\"control-label {{form.labelHtmlClass}}\" ng-show=\"showTitle()\">{{form.title}}</label><div class=\"checkbox\" ng-repeat=\"val in titleMapValues track by $index\"><label><input type=\"checkbox\" ng-disabled=\"form.readonly\" sf-changed=\"form\" class=\"{{form.fieldHtmlClass}}\" ng-model=\"titleMapValues[$index]\" schema-vaidate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"> <span ng-bind-html=\"form.titleMap[$index].name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/default.html","<div class=\"form-group schema-form-{{form.type}} {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess(), \'has-feedback\': form.feedback !== false }\"><label class=\"control-label {{form.labelHtmlClass}}\" ng-class=\"{\'sr-only\': !showTitle()}\" for=\"{{form.key.slice(-1)[0]}}\">{{form.title}}</label> <input ng-if=\"!form.fieldAddonLeft && !form.fieldAddonRight\" ng-show=\"form.key\" type=\"{{form.type}}\" step=\"any\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" ng-model-options=\"form.ngModelOptions\" ng-model=\"$$value$$\" ng-disabled=\"form.readonly\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\" aria-describedby=\"{{form.key.slice(-1)[0] + \'Status\'}}\"><div ng-if=\"form.fieldAddonLeft || form.fieldAddonRight\" ng-class=\"{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}\"><span ng-if=\"form.fieldAddonLeft\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonLeft\"></span> <input ng-show=\"form.key\" type=\"{{form.type}}\" step=\"any\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" ng-model-options=\"form.ngModelOptions\" ng-model=\"$$value$$\" ng-disabled=\"form.readonly\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\" aria-describedby=\"{{form.key.slice(-1)[0] + \'Status\'}}\"> <span ng-if=\"form.fieldAddonRight\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonRight\"></span></div><span ng-if=\"form.feedback !== false\" class=\"form-control-feedback\" ng-class=\"evalInScope(form.feedback) || {\'glyphicon\': true, \'glyphicon-ok\': hasSuccess(), \'glyphicon-remove\': hasError() }\" aria-hidden=\"true\"></span> <span ng-if=\"hasError() || hasSuccess()\" id=\"{{form.key.slice(-1)[0] + \'Status\'}}\" class=\"sr-only\">{{ hasSuccess() ? \'(success)\' : \'(error)\' }}</span><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/fieldset-trcl.html","<fieldset ng-disabled=\"form.readonly\" class=\"schema-form-fieldset {{form.htmlClass}}\"><legend ng-show=\"form.title\">{{ form.title }}</legend><div class=\"help-block\" ng-show=\"form.description\" ng-bind-html=\"form.description\"></div><div ng-transclude=\"\"></div></fieldset>"); | ||
$templateCache.put("directives/decorators/bootstrap/fieldset.html","<fieldset ng-disabled=\"form.readonly\" class=\"schema-form-fieldset {{form.htmlClass}}\"><legend ng-show=\"form.title\">{{ form.title }}</legend><div class=\"help-block\" ng-show=\"form.description\" ng-bind-html=\"form.description\"></div><sf-decorator ng-repeat=\"item in form.items\" form=\"item\"></sf-decorator></fieldset>"); | ||
$templateCache.put("directives/decorators/bootstrap/help.html","<div class=\"helpvalue schema-form-helpvalue {{form.htmlClass}}\" ng-bind-html=\"form.helpvalue\"></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radio-buttons.html","<div class=\"form-group schema-form-radiobuttons {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><div><label class=\"control-label\" ng-show=\"showTitle()\">{{form.title}}</label></div><div class=\"btn-group\"><label class=\"btn {{ (item.value === $$value$$) ? form.style.selected || \'btn-default\' : form.style.unselected || \'btn-default\'; }}\" ng-class=\"{ active: item.value === $$value$$ }\" ng-repeat=\"item in form.titleMap\"><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" style=\"display: none;\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radios-inline.html","<div class=\"form-group schema-form-radios-inline {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><label class=\"control-label\" ng-show=\"showTitle()\">{{form.title}}</label><div><label class=\"radio-inline\" ng-repeat=\"item in form.titleMap\"><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radios.html","<div class=\"form-group schema-form-radios {{form.htmlClass}}\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><label class=\"control-label\" ng-show=\"showTitle()\">{{form.title}}</label><div class=\"radio\" ng-repeat=\"item in form.titleMap\"><label><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radio-buttons.html","<div class=\"form-group schema-form-radiobuttons {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><div><label class=\"control-label {{form.labelHtmlClass}}\" ng-show=\"showTitle()\">{{form.title}}</label></div><div class=\"btn-group\"><label class=\"btn {{ (item.value === $$value$$) ? form.style.selected || \'btn-default\' : form.style.unselected || \'btn-default\'; }}\" ng-class=\"{ active: item.value === $$value$$ }\" ng-repeat=\"item in form.titleMap\"><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" style=\"display: none;\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radios-inline.html","<div class=\"form-group schema-form-radios-inline {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><label class=\"control-label {{form.labelHtmlClass}}\" ng-show=\"showTitle()\">{{form.title}}</label><div><label class=\"radio-inline\" ng-repeat=\"item in form.titleMap\"><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/radios.html","<div class=\"form-group schema-form-radios {{form.htmlClass}}\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><label class=\"control-label {{form.labelHtmlClass}}\" ng-show=\"showTitle()\">{{form.title}}</label><div class=\"radio\" ng-repeat=\"item in form.titleMap\"><label><input type=\"radio\" class=\"{{form.fieldHtmlClass}}\" sf-changed=\"form\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" ng-value=\"item.value\" name=\"{{form.key.join(\'.\')}}\"> <span ng-bind-html=\"item.name\"></span></label></div><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/section.html","<div class=\"schema-form-section {{form.htmlClass}}\"><sf-decorator ng-repeat=\"item in form.items\" form=\"item\"></sf-decorator></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/select.html","<div class=\"form-group {{form.htmlClass}} schema-form-select\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess(), \'has-feedback\': form.feedback !== false}\"><label class=\"control-label\" ng-show=\"showTitle()\">{{form.title}}</label><select ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" ng-disabled=\"form.readonly\" sf-changed=\"form\" class=\"form-control {{form.fieldHtmlClass}}\" schema-validate=\"form\" ng-options=\"item.value as item.name group by item.group for item in form.titleMap\" name=\"{{form.key.slice(-1)[0]}}\"></select><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/select.html","<div class=\"form-group {{form.htmlClass}} schema-form-select\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess(), \'has-feedback\': form.feedback !== false}\"><label class=\"control-label {{form.labelHtmlClass}}\" ng-show=\"showTitle()\">{{form.title}}</label><select ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" ng-disabled=\"form.readonly\" sf-changed=\"form\" class=\"form-control {{form.fieldHtmlClass}}\" schema-validate=\"form\" ng-options=\"item.value as item.name group by item.group for item in form.titleMap\" name=\"{{form.key.slice(-1)[0]}}\"></select><div class=\"help-block\" sf-message=\"form.description\"></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/submit.html","<div class=\"form-group schema-form-submit {{form.htmlClass}}\"><input type=\"submit\" class=\"btn {{ form.style || \'btn-primary\' }} {{form.fieldHtmlClass}}\" value=\"{{form.title}}\" ng-disabled=\"form.readonly\" ng-if=\"form.type === \'submit\'\"> <button class=\"btn {{ form.style || \'btn-default\' }}\" type=\"button\" ng-click=\"buttonClick($event,form)\" ng-disabled=\"form.readonly\" ng-if=\"form.type !== \'submit\'\"><span ng-if=\"form.icon\" class=\"{{form.icon}}\"></span> {{form.title}}</button></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/tabarray.html","<div sf-array=\"form\" ng-init=\"selected = { tab: 0 }\" class=\"clearfix schema-form-tabarray schema-form-tabarray-{{form.tabType || \'left\'}} {{form.htmlClass}}\"><div ng-if=\"!form.tabType || form.tabType !== \'right\'\" ng-class=\"{\'col-xs-3\': !form.tabType || form.tabType === \'left\'}\"><ul class=\"nav nav-tabs\" ng-class=\"{ \'tabs-left\': !form.tabType || form.tabType === \'left\'}\"><li ng-repeat=\"item in modelArray track by $index\" ng-click=\"$event.preventDefault() || (selected.tab = $index)\" ng-class=\"{active: selected.tab === $index}\"><a href=\"#\">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide=\"form.readonly\" ng-click=\"$event.preventDefault() || (selected.tab = appendToArray().length - 1)\"><a href=\"#\"><i class=\"glyphicon glyphicon-plus\"></i> {{ form.add || \'Add\'}}</a></li></ul></div><div ng-class=\"{\'col-xs-9\': !form.tabType || form.tabType === \'left\' || form.tabType === \'right\'}\"><div class=\"tab-content {{form.fieldHtmlClass}}\"><div class=\"tab-pane clearfix\" ng-repeat=\"item in modelArray track by $index\" ng-show=\"selected.tab === $index\" ng-class=\"{active: selected.tab === $index}\"><sf-decorator ng-init=\"arrayIndex = $index\" form=\"copyWithIndex($index)\"></sf-decorator><button ng-hide=\"form.readonly\" ng-click=\"selected.tab = deleteFromArray($index).length - 1\" type=\"button\" class=\"btn {{ form.style.remove || \'btn-default\' }} pull-right\"><i class=\"glyphicon glyphicon-trash\"></i> {{ form.remove || \'Remove\'}}</button></div></div></div><div ng-if=\"form.tabType === \'right\'\" class=\"col-xs-3\"><ul class=\"nav nav-tabs tabs-right\"><li ng-repeat=\"item in modelArray track by $index\" ng-click=\"$event.preventDefault() || (selected.tab = $index)\" ng-class=\"{active: selected.tab === $index}\"><a href=\"#\">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide=\"form.readonly\" ng-click=\"$event.preventDefault() || appendToArray()\"><a href=\"#\"><i class=\"glyphicon glyphicon-plus\"></i> {{ form.add || \'Add\'}}</a></li></ul></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/tabs.html","<div ng-init=\"selected = { tab: 0 }\" class=\"schema-form-tabs {{form.htmlClass}}\"><ul class=\"nav nav-tabs\"><li ng-repeat=\"tab in form.tabs\" ng-disabled=\"form.readonly\" ng-click=\"$event.preventDefault() || (selected.tab = $index)\" ng-class=\"{active: selected.tab === $index}\"><a href=\"#\">{{ tab.title }}</a></li></ul><div class=\"tab-content {{form.fieldHtmlClass}}\"><div class=\"tab-pane\" ng-disabled=\"form.readonly\" ng-repeat=\"tab in form.tabs\" ng-show=\"selected.tab === $index\" ng-class=\"{active: selected.tab === $index}\"><bootstrap-decorator ng-repeat=\"item in tab.items\" form=\"item\"></bootstrap-decorator></div></div></div>"); | ||
$templateCache.put("directives/decorators/bootstrap/textarea.html","<div class=\"form-group has-feedback {{form.htmlClass}} schema-form-textarea\" ng-class=\"{\'has-error\': hasError(), \'has-success\': hasSuccess()}\"><label ng-class=\"{\'sr-only\': !showTitle()}\" for=\"{{form.key.slice(-1)[0]}}\">{{form.title}}</label> <textarea ng-if=\"!form.fieldAddonLeft && !form.fieldAddonRight\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"></textarea><div ng-if=\"form.fieldAddonLeft || form.fieldAddonRight\" ng-class=\"{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}\"><span ng-if=\"form.fieldAddonLeft\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonLeft\"></span> <textarea class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"></textarea> <span ng-if=\"form.fieldAddonRight\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonRight\"></span></div><span class=\"help-block\" sf-message=\"form.description\"></span></div>");}]); | ||
$templateCache.put("directives/decorators/bootstrap/textarea.html","<div class=\"form-group has-feedback {{form.htmlClass}} schema-form-textarea\" ng-class=\"{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}\"><label class=\"{{form.labelHtmlClass}}\" ng-class=\"{\'sr-only\': !showTitle()}\" for=\"{{form.key.slice(-1)[0]}}\">{{form.title}}</label> <textarea ng-if=\"!form.fieldAddonLeft && !form.fieldAddonRight\" class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"></textarea><div ng-if=\"form.fieldAddonLeft || form.fieldAddonRight\" ng-class=\"{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}\"><span ng-if=\"form.fieldAddonLeft\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonLeft\"></span> <textarea class=\"form-control {{form.fieldHtmlClass}}\" id=\"{{form.key.slice(-1)[0]}}\" sf-changed=\"form\" placeholder=\"{{form.placeholder}}\" ng-disabled=\"form.readonly\" ng-model=\"$$value$$\" ng-model-options=\"form.ngModelOptions\" schema-validate=\"form\" name=\"{{form.key.slice(-1)[0]}}\"></textarea> <span ng-if=\"form.fieldAddonRight\" class=\"input-group-addon\" ng-bind-html=\"form.fieldAddonRight\"></span></div><span class=\"help-block\" sf-message=\"form.description\"></span></div>");}]); | ||
angular.module('schemaForm').config(['schemaFormDecoratorsProvider', function(decoratorsProvider) { | ||
@@ -20,0 +20,0 @@ var base = 'directives/decorators/bootstrap/'; |
@@ -1,1 +0,1 @@ | ||
angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'<div class="btn-group schema-form-actions {{form.htmlClass}}" ng-transclude=""></div>'),e.put("directives/decorators/bootstrap/actions.html",'<div class="btn-group schema-form-actions {{form.htmlClass}}"><input ng-repeat-start="item in form.items" type="submit" class="btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}" value="{{item.title}}" ng-if="item.type === \'submit\'"> <button ng-repeat-end="" class="btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}" type="button" ng-disabled="form.readonly" ng-if="item.type !== \'submit\'" ng-click="buttonClick($event,item)"><span ng-if="item.icon" class="{{item.icon}}"></span>{{item.title}}</button></div>'),e.put("directives/decorators/bootstrap/array.html",'<div sf-array="form" class="schema-form-array {{form.htmlClass}}" ng-model="$$value$$" ng-model-options="form.ngModelOptions"><h3 ng-show="form.title && form.notitle !== true">{{ form.title }}</h3><ol class="list-group" ng-model="modelArray" ui-sortable=""><li class="list-group-item {{form.fieldHtmlClass}}" ng-repeat="item in modelArray track by $index"><button ng-hide="form.readonly || form.remove === null" ng-click="deleteFromArray($index)" style="position: relative; z-index: 20;" type="button" class="close pull-right"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button><sf-decorator ng-init="arrayIndex = $index" form="copyWithIndex($index)"></sf-decorator></li></ol><div class="clearfix" style="padding: 15px;"><button ng-hide="form.readonly || form.add === null" ng-click="appendToArray()" type="button" class="btn {{ form.style.add || \'btn-default\' }} pull-right"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</button></div><div class="help-block" ng-show="(hasError() && errorMessage(schemaError())) || form.description" ng-bind-html="(hasError() && errorMessage(schemaError())) || form.description"></div></div>'),e.put("directives/decorators/bootstrap/checkbox.html",'<div class="checkbox schema-form-checkbox {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><label><input type="checkbox" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" class="{{form.fieldHtmlClass}}" name="{{form.key.slice(-1)[0]}}"> <span ng-bind-html="form.title"></span></label><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/checkboxes.html",'<div sf-array="form" ng-model="$$value$$" class="form-group schema-form-checkboxes {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><label class="control-label" ng-show="showTitle()">{{form.title}}</label><div class="checkbox" ng-repeat="val in titleMapValues track by $index"><label><input type="checkbox" ng-disabled="form.readonly" sf-changed="form" class="{{form.fieldHtmlClass}}" ng-model="titleMapValues[$index]" schema-vaidate="form" name="{{form.key.slice(-1)[0]}}"> <span ng-bind-html="form.titleMap[$index].name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/default.html",'<div class="form-group schema-form-{{form.type}} {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess(), \'has-feedback\': form.feedback !== false }"><label class="control-label" ng-class="{\'sr-only\': !showTitle()}" for="{{form.key.slice(-1)[0]}}">{{form.title}}</label> <input ng-if="!form.fieldAddonLeft && !form.fieldAddonRight" ng-show="form.key" type="{{form.type}}" step="any" sf-changed="form" placeholder="{{form.placeholder}}" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" ng-model-options="form.ngModelOptions" ng-model="$$value$$" ng-disabled="form.readonly" schema-validate="form" name="{{form.key.slice(-1)[0]}}" aria-describedby="{{form.key.slice(-1)[0] + \'Status\'}}"><div ng-if="form.fieldAddonLeft || form.fieldAddonRight" ng-class="{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}"><span ng-if="form.fieldAddonLeft" class="input-group-addon" ng-bind-html="form.fieldAddonLeft"></span> <input ng-show="form.key" type="{{form.type}}" step="any" sf-changed="form" placeholder="{{form.placeholder}}" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" ng-model-options="form.ngModelOptions" ng-model="$$value$$" ng-disabled="form.readonly" schema-validate="form" name="{{form.key.slice(-1)[0]}}" aria-describedby="{{form.key.slice(-1)[0] + \'Status\'}}"> <span ng-if="form.fieldAddonRight" class="input-group-addon" ng-bind-html="form.fieldAddonRight"></span></div><span ng-if="form.feedback !== false" class="form-control-feedback" ng-class="evalInScope(form.feedback) || {\'glyphicon\': true, \'glyphicon-ok\': hasSuccess(), \'glyphicon-remove\': hasError() }" aria-hidden="true"></span> <span ng-if="hasError() || hasSuccess()" id="{{form.key.slice(-1)[0] + \'Status\'}}" class="sr-only">{{ hasSuccess() ? \'(success)\' : \'(error)\' }}</span><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'<fieldset ng-disabled="form.readonly" class="schema-form-fieldset {{form.htmlClass}}"><legend ng-show="form.title">{{ form.title }}</legend><div class="help-block" ng-show="form.description" ng-bind-html="form.description"></div><div ng-transclude=""></div></fieldset>'),e.put("directives/decorators/bootstrap/fieldset.html",'<fieldset ng-disabled="form.readonly" class="schema-form-fieldset {{form.htmlClass}}"><legend ng-show="form.title">{{ form.title }}</legend><div class="help-block" ng-show="form.description" ng-bind-html="form.description"></div><sf-decorator ng-repeat="item in form.items" form="item"></sf-decorator></fieldset>'),e.put("directives/decorators/bootstrap/help.html",'<div class="helpvalue schema-form-helpvalue {{form.htmlClass}}" ng-bind-html="form.helpvalue"></div>'),e.put("directives/decorators/bootstrap/radio-buttons.html",'<div class="form-group schema-form-radiobuttons {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><div><label class="control-label" ng-show="showTitle()">{{form.title}}</label></div><div class="btn-group"><label class="btn {{ (item.value === $$value$$) ? form.style.selected || \'btn-default\' : form.style.unselected || \'btn-default\'; }}" ng-class="{ active: item.value === $$value$$ }" ng-repeat="item in form.titleMap"><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" style="display: none;" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/radios-inline.html",'<div class="form-group schema-form-radios-inline {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><label class="control-label" ng-show="showTitle()">{{form.title}}</label><div><label class="radio-inline" ng-repeat="item in form.titleMap"><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/radios.html",'<div class="form-group schema-form-radios {{form.htmlClass}}" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><label class="control-label" ng-show="showTitle()">{{form.title}}</label><div class="radio" ng-repeat="item in form.titleMap"><label><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/section.html",'<div class="schema-form-section {{form.htmlClass}}"><sf-decorator ng-repeat="item in form.items" form="item"></sf-decorator></div>'),e.put("directives/decorators/bootstrap/select.html",'<div class="form-group {{form.htmlClass}} schema-form-select" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess(), \'has-feedback\': form.feedback !== false}"><label class="control-label" ng-show="showTitle()">{{form.title}}</label><select ng-model="$$value$$" ng-model-options="form.ngModelOptions" ng-disabled="form.readonly" sf-changed="form" class="form-control {{form.fieldHtmlClass}}" schema-validate="form" ng-options="item.value as item.name group by item.group for item in form.titleMap" name="{{form.key.slice(-1)[0]}}"></select><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/submit.html",'<div class="form-group schema-form-submit {{form.htmlClass}}"><input type="submit" class="btn {{ form.style || \'btn-primary\' }} {{form.fieldHtmlClass}}" value="{{form.title}}" ng-disabled="form.readonly" ng-if="form.type === \'submit\'"> <button class="btn {{ form.style || \'btn-default\' }}" type="button" ng-click="buttonClick($event,form)" ng-disabled="form.readonly" ng-if="form.type !== \'submit\'"><span ng-if="form.icon" class="{{form.icon}}"></span> {{form.title}}</button></div>'),e.put("directives/decorators/bootstrap/tabarray.html",'<div sf-array="form" ng-init="selected = { tab: 0 }" class="clearfix schema-form-tabarray schema-form-tabarray-{{form.tabType || \'left\'}} {{form.htmlClass}}"><div ng-if="!form.tabType || form.tabType !== \'right\'" ng-class="{\'col-xs-3\': !form.tabType || form.tabType === \'left\'}"><ul class="nav nav-tabs" ng-class="{ \'tabs-left\': !form.tabType || form.tabType === \'left\'}"><li ng-repeat="item in modelArray track by $index" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide="form.readonly" ng-click="$event.preventDefault() || (selected.tab = appendToArray().length - 1)"><a href="#"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</a></li></ul></div><div ng-class="{\'col-xs-9\': !form.tabType || form.tabType === \'left\' || form.tabType === \'right\'}"><div class="tab-content {{form.fieldHtmlClass}}"><div class="tab-pane clearfix" ng-repeat="item in modelArray track by $index" ng-show="selected.tab === $index" ng-class="{active: selected.tab === $index}"><sf-decorator ng-init="arrayIndex = $index" form="copyWithIndex($index)"></sf-decorator><button ng-hide="form.readonly" ng-click="selected.tab = deleteFromArray($index).length - 1" type="button" class="btn {{ form.style.remove || \'btn-default\' }} pull-right"><i class="glyphicon glyphicon-trash"></i> {{ form.remove || \'Remove\'}}</button></div></div></div><div ng-if="form.tabType === \'right\'" class="col-xs-3"><ul class="nav nav-tabs tabs-right"><li ng-repeat="item in modelArray track by $index" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide="form.readonly" ng-click="$event.preventDefault() || appendToArray()"><a href="#"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</a></li></ul></div></div>'),e.put("directives/decorators/bootstrap/tabs.html",'<div ng-init="selected = { tab: 0 }" class="schema-form-tabs {{form.htmlClass}}"><ul class="nav nav-tabs"><li ng-repeat="tab in form.tabs" ng-disabled="form.readonly" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{ tab.title }}</a></li></ul><div class="tab-content {{form.fieldHtmlClass}}"><div class="tab-pane" ng-disabled="form.readonly" ng-repeat="tab in form.tabs" ng-show="selected.tab === $index" ng-class="{active: selected.tab === $index}"><bootstrap-decorator ng-repeat="item in tab.items" form="item"></bootstrap-decorator></div></div></div>'),e.put("directives/decorators/bootstrap/textarea.html",'<div class="form-group has-feedback {{form.htmlClass}} schema-form-textarea" ng-class="{\'has-error\': hasError(), \'has-success\': hasSuccess()}"><label ng-class="{\'sr-only\': !showTitle()}" for="{{form.key.slice(-1)[0]}}">{{form.title}}</label> <textarea ng-if="!form.fieldAddonLeft && !form.fieldAddonRight" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" sf-changed="form" placeholder="{{form.placeholder}}" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" name="{{form.key.slice(-1)[0]}}"></textarea><div ng-if="form.fieldAddonLeft || form.fieldAddonRight" ng-class="{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}"><span ng-if="form.fieldAddonLeft" class="input-group-addon" ng-bind-html="form.fieldAddonLeft"></span> <textarea class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" sf-changed="form" placeholder="{{form.placeholder}}" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" name="{{form.key.slice(-1)[0]}}"></textarea> <span ng-if="form.fieldAddonRight" class="input-group-addon" ng-bind-html="form.fieldAddonRight"></span></div><span class="help-block" sf-message="form.description"></span></div>')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var s="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:s+"textarea.html",fieldset:s+"fieldset.html",array:s+"array.html",tabarray:s+"tabarray.html",tabs:s+"tabs.html",section:s+"section.html",conditional:s+"section.html",actions:s+"actions.html",select:s+"select.html",checkbox:s+"checkbox.html",checkboxes:s+"checkboxes.html",number:s+"default.html",password:s+"default.html",submit:s+"submit.html",button:s+"submit.html",radios:s+"radios.html","radios-inline":s+"radios-inline.html",radiobuttons:s+"radio-buttons.html",help:s+"help.html","default":s+"default.html"},[]),e.createDirectives({textarea:s+"textarea.html",select:s+"select.html",checkbox:s+"checkbox.html",checkboxes:s+"checkboxes.html",number:s+"default.html",submit:s+"submit.html",button:s+"submit.html",text:s+"default.html",date:s+"default.html",password:s+"default.html",datepicker:s+"datepicker.html",input:s+"default.html",radios:s+"radios.html","radios-inline":s+"radios-inline.html",radiobuttons:s+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,s,t){e.title=e.$eval(t.title)}}}); | ||
angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'<div class="btn-group schema-form-actions {{form.htmlClass}}" ng-transclude=""></div>'),e.put("directives/decorators/bootstrap/actions.html",'<div class="btn-group schema-form-actions {{form.htmlClass}}"><input ng-repeat-start="item in form.items" type="submit" class="btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}" value="{{item.title}}" ng-if="item.type === \'submit\'"> <button ng-repeat-end="" class="btn {{ item.style || \'btn-default\' }} {{form.fieldHtmlClass}}" type="button" ng-disabled="form.readonly" ng-if="item.type !== \'submit\'" ng-click="buttonClick($event,item)"><span ng-if="item.icon" class="{{item.icon}}"></span>{{item.title}}</button></div>'),e.put("directives/decorators/bootstrap/array.html",'<div sf-array="form" class="schema-form-array {{form.htmlClass}}" ng-model="$$value$$" ng-model-options="form.ngModelOptions"><h3 ng-show="form.title && form.notitle !== true">{{ form.title }}</h3><ol class="list-group" ng-model="modelArray" ui-sortable=""><li class="list-group-item {{form.fieldHtmlClass}}" ng-repeat="item in modelArray track by $index"><button ng-hide="form.readonly || form.remove === null" ng-click="deleteFromArray($index)" style="position: relative; z-index: 20;" type="button" class="close pull-right"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button><sf-decorator ng-init="arrayIndex = $index" form="copyWithIndex($index)"></sf-decorator></li></ol><div class="clearfix" style="padding: 15px;"><button ng-hide="form.readonly || form.add === null" ng-click="appendToArray()" type="button" class="btn {{ form.style.add || \'btn-default\' }} pull-right"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</button></div><div class="help-block" ng-show="(hasError() && errorMessage(schemaError())) || form.description" ng-bind-html="(hasError() && errorMessage(schemaError())) || form.description"></div></div>'),e.put("directives/decorators/bootstrap/checkbox.html",'<div class="checkbox schema-form-checkbox {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><label class="{{form.labelHtmlClass}}"><input type="checkbox" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" class="{{form.fieldHtmlClass}}" name="{{form.key.slice(-1)[0]}}"> <span ng-bind-html="form.title"></span></label><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/checkboxes.html",'<div sf-array="form" ng-model="$$value$$" class="form-group schema-form-checkboxes {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><label class="control-label {{form.labelHtmlClass}}" ng-show="showTitle()">{{form.title}}</label><div class="checkbox" ng-repeat="val in titleMapValues track by $index"><label><input type="checkbox" ng-disabled="form.readonly" sf-changed="form" class="{{form.fieldHtmlClass}}" ng-model="titleMapValues[$index]" schema-vaidate="form" name="{{form.key.slice(-1)[0]}}"> <span ng-bind-html="form.titleMap[$index].name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/default.html",'<div class="form-group schema-form-{{form.type}} {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess(), \'has-feedback\': form.feedback !== false }"><label class="control-label {{form.labelHtmlClass}}" ng-class="{\'sr-only\': !showTitle()}" for="{{form.key.slice(-1)[0]}}">{{form.title}}</label> <input ng-if="!form.fieldAddonLeft && !form.fieldAddonRight" ng-show="form.key" type="{{form.type}}" step="any" sf-changed="form" placeholder="{{form.placeholder}}" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" ng-model-options="form.ngModelOptions" ng-model="$$value$$" ng-disabled="form.readonly" schema-validate="form" name="{{form.key.slice(-1)[0]}}" aria-describedby="{{form.key.slice(-1)[0] + \'Status\'}}"><div ng-if="form.fieldAddonLeft || form.fieldAddonRight" ng-class="{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}"><span ng-if="form.fieldAddonLeft" class="input-group-addon" ng-bind-html="form.fieldAddonLeft"></span> <input ng-show="form.key" type="{{form.type}}" step="any" sf-changed="form" placeholder="{{form.placeholder}}" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" ng-model-options="form.ngModelOptions" ng-model="$$value$$" ng-disabled="form.readonly" schema-validate="form" name="{{form.key.slice(-1)[0]}}" aria-describedby="{{form.key.slice(-1)[0] + \'Status\'}}"> <span ng-if="form.fieldAddonRight" class="input-group-addon" ng-bind-html="form.fieldAddonRight"></span></div><span ng-if="form.feedback !== false" class="form-control-feedback" ng-class="evalInScope(form.feedback) || {\'glyphicon\': true, \'glyphicon-ok\': hasSuccess(), \'glyphicon-remove\': hasError() }" aria-hidden="true"></span> <span ng-if="hasError() || hasSuccess()" id="{{form.key.slice(-1)[0] + \'Status\'}}" class="sr-only">{{ hasSuccess() ? \'(success)\' : \'(error)\' }}</span><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'<fieldset ng-disabled="form.readonly" class="schema-form-fieldset {{form.htmlClass}}"><legend ng-show="form.title">{{ form.title }}</legend><div class="help-block" ng-show="form.description" ng-bind-html="form.description"></div><div ng-transclude=""></div></fieldset>'),e.put("directives/decorators/bootstrap/fieldset.html",'<fieldset ng-disabled="form.readonly" class="schema-form-fieldset {{form.htmlClass}}"><legend ng-show="form.title">{{ form.title }}</legend><div class="help-block" ng-show="form.description" ng-bind-html="form.description"></div><sf-decorator ng-repeat="item in form.items" form="item"></sf-decorator></fieldset>'),e.put("directives/decorators/bootstrap/help.html",'<div class="helpvalue schema-form-helpvalue {{form.htmlClass}}" ng-bind-html="form.helpvalue"></div>'),e.put("directives/decorators/bootstrap/radio-buttons.html",'<div class="form-group schema-form-radiobuttons {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><div><label class="control-label {{form.labelHtmlClass}}" ng-show="showTitle()">{{form.title}}</label></div><div class="btn-group"><label class="btn {{ (item.value === $$value$$) ? form.style.selected || \'btn-default\' : form.style.unselected || \'btn-default\'; }}" ng-class="{ active: item.value === $$value$$ }" ng-repeat="item in form.titleMap"><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" style="display: none;" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/radios-inline.html",'<div class="form-group schema-form-radios-inline {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><label class="control-label {{form.labelHtmlClass}}" ng-show="showTitle()">{{form.title}}</label><div><label class="radio-inline" ng-repeat="item in form.titleMap"><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/radios.html",'<div class="form-group schema-form-radios {{form.htmlClass}}" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><label class="control-label {{form.labelHtmlClass}}" ng-show="showTitle()">{{form.title}}</label><div class="radio" ng-repeat="item in form.titleMap"><label><input type="radio" class="{{form.fieldHtmlClass}}" sf-changed="form" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" ng-value="item.value" name="{{form.key.join(\'.\')}}"> <span ng-bind-html="item.name"></span></label></div><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/section.html",'<div class="schema-form-section {{form.htmlClass}}"><sf-decorator ng-repeat="item in form.items" form="item"></sf-decorator></div>'),e.put("directives/decorators/bootstrap/select.html",'<div class="form-group {{form.htmlClass}} schema-form-select" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess(), \'has-feedback\': form.feedback !== false}"><label class="control-label {{form.labelHtmlClass}}" ng-show="showTitle()">{{form.title}}</label><select ng-model="$$value$$" ng-model-options="form.ngModelOptions" ng-disabled="form.readonly" sf-changed="form" class="form-control {{form.fieldHtmlClass}}" schema-validate="form" ng-options="item.value as item.name group by item.group for item in form.titleMap" name="{{form.key.slice(-1)[0]}}"></select><div class="help-block" sf-message="form.description"></div></div>'),e.put("directives/decorators/bootstrap/submit.html",'<div class="form-group schema-form-submit {{form.htmlClass}}"><input type="submit" class="btn {{ form.style || \'btn-primary\' }} {{form.fieldHtmlClass}}" value="{{form.title}}" ng-disabled="form.readonly" ng-if="form.type === \'submit\'"> <button class="btn {{ form.style || \'btn-default\' }}" type="button" ng-click="buttonClick($event,form)" ng-disabled="form.readonly" ng-if="form.type !== \'submit\'"><span ng-if="form.icon" class="{{form.icon}}"></span> {{form.title}}</button></div>'),e.put("directives/decorators/bootstrap/tabarray.html",'<div sf-array="form" ng-init="selected = { tab: 0 }" class="clearfix schema-form-tabarray schema-form-tabarray-{{form.tabType || \'left\'}} {{form.htmlClass}}"><div ng-if="!form.tabType || form.tabType !== \'right\'" ng-class="{\'col-xs-3\': !form.tabType || form.tabType === \'left\'}"><ul class="nav nav-tabs" ng-class="{ \'tabs-left\': !form.tabType || form.tabType === \'left\'}"><li ng-repeat="item in modelArray track by $index" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide="form.readonly" ng-click="$event.preventDefault() || (selected.tab = appendToArray().length - 1)"><a href="#"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</a></li></ul></div><div ng-class="{\'col-xs-9\': !form.tabType || form.tabType === \'left\' || form.tabType === \'right\'}"><div class="tab-content {{form.fieldHtmlClass}}"><div class="tab-pane clearfix" ng-repeat="item in modelArray track by $index" ng-show="selected.tab === $index" ng-class="{active: selected.tab === $index}"><sf-decorator ng-init="arrayIndex = $index" form="copyWithIndex($index)"></sf-decorator><button ng-hide="form.readonly" ng-click="selected.tab = deleteFromArray($index).length - 1" type="button" class="btn {{ form.style.remove || \'btn-default\' }} pull-right"><i class="glyphicon glyphicon-trash"></i> {{ form.remove || \'Remove\'}}</button></div></div></div><div ng-if="form.tabType === \'right\'" class="col-xs-3"><ul class="nav nav-tabs tabs-right"><li ng-repeat="item in modelArray track by $index" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{interp(form.title,{\'$index\':$index, value: item}) || $index}}</a></li><li ng-hide="form.readonly" ng-click="$event.preventDefault() || appendToArray()"><a href="#"><i class="glyphicon glyphicon-plus"></i> {{ form.add || \'Add\'}}</a></li></ul></div></div>'),e.put("directives/decorators/bootstrap/tabs.html",'<div ng-init="selected = { tab: 0 }" class="schema-form-tabs {{form.htmlClass}}"><ul class="nav nav-tabs"><li ng-repeat="tab in form.tabs" ng-disabled="form.readonly" ng-click="$event.preventDefault() || (selected.tab = $index)" ng-class="{active: selected.tab === $index}"><a href="#">{{ tab.title }}</a></li></ul><div class="tab-content {{form.fieldHtmlClass}}"><div class="tab-pane" ng-disabled="form.readonly" ng-repeat="tab in form.tabs" ng-show="selected.tab === $index" ng-class="{active: selected.tab === $index}"><bootstrap-decorator ng-repeat="item in tab.items" form="item"></bootstrap-decorator></div></div></div>'),e.put("directives/decorators/bootstrap/textarea.html",'<div class="form-group has-feedback {{form.htmlClass}} schema-form-textarea" ng-class="{\'has-error\': form.disableErrorState !== true && hasError(), \'has-success\': form.disableSuccessState !== true && hasSuccess()}"><label class="{{form.labelHtmlClass}}" ng-class="{\'sr-only\': !showTitle()}" for="{{form.key.slice(-1)[0]}}">{{form.title}}</label> <textarea ng-if="!form.fieldAddonLeft && !form.fieldAddonRight" class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" sf-changed="form" placeholder="{{form.placeholder}}" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" name="{{form.key.slice(-1)[0]}}"></textarea><div ng-if="form.fieldAddonLeft || form.fieldAddonRight" ng-class="{\'input-group\': (form.fieldAddonLeft || form.fieldAddonRight)}"><span ng-if="form.fieldAddonLeft" class="input-group-addon" ng-bind-html="form.fieldAddonLeft"></span> <textarea class="form-control {{form.fieldHtmlClass}}" id="{{form.key.slice(-1)[0]}}" sf-changed="form" placeholder="{{form.placeholder}}" ng-disabled="form.readonly" ng-model="$$value$$" ng-model-options="form.ngModelOptions" schema-validate="form" name="{{form.key.slice(-1)[0]}}"></textarea> <span ng-if="form.fieldAddonRight" class="input-group-addon" ng-bind-html="form.fieldAddonRight"></span></div><span class="help-block" sf-message="form.description"></span></div>')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",array:t+"array.html",tabarray:t+"tabarray.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html","radios-inline":t+"radios-inline.html",radiobuttons:t+"radio-buttons.html",help:t+"help.html","default":t+"default.html"},[]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html","radios-inline":t+"radios-inline.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); |
@@ -0,1 +1,10 @@ | ||
(function(root, factory) { | ||
if (typeof define === 'function' && define.amd) { | ||
define(['angular', 'ObjectPath', 'tv4'], factory); | ||
} else if (typeof exports === 'object') { | ||
module.exports = factory(require('angular'), require('ObjectPath'), require('tv4')); | ||
} else { | ||
root.schemaForm = factory(root.angular, root.ObjectPath, root.tv4); | ||
} | ||
}(this, function(angular, ObjectPath, tv4) { | ||
// Deps is sort of a problem for us, maybe in the future we will ask the user to depend | ||
@@ -23,3 +32,3 @@ // on modules for add-ons | ||
angular.module('schemaForm', deps); | ||
var schemaForm = angular.module('schemaForm', deps); | ||
@@ -163,4 +172,4 @@ angular.module('schemaForm').provider('sfPath', | ||
$compileProvider.directive(name, | ||
['$parse', '$compile', '$http', '$templateCache', '$interpolate', '$q', 'sfErrorMessage', | ||
function($parse, $compile, $http, $templateCache, $interpolate, $q, sfErrorMessage) { | ||
['$parse', '$compile', '$http', '$templateCache', '$interpolate', '$q', 'sfErrorMessage', 'sfPath', | ||
function($parse, $compile, $http, $templateCache, $interpolate, $q, sfErrorMessage, sfPath) { | ||
@@ -292,2 +301,3 @@ return { | ||
(scope.ngModel && scope.ngModel.$modelValue) || '', | ||
(scope.ngModel && scope.ngModel.$viewValue) || '', | ||
scope.form, | ||
@@ -337,2 +347,8 @@ scope.options && scope.options.validationMessage | ||
if (form.condition) { | ||
var evalExpr = 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex})'; | ||
if (form.key) { | ||
evalExpr = 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex, "modelValue": model' + sfPath.stringify(form.key) + '})'; | ||
} | ||
angular.forEach(element.children(), function(child) { | ||
@@ -344,8 +360,7 @@ var ngIf = child.getAttribute('ng-if'); | ||
'(' + ngIf + | ||
') || (evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex }))' | ||
: 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex })' | ||
') || (' + evalExpr +')' | ||
: evalExpr | ||
); | ||
}); | ||
} | ||
$compile(element.contents())(scope); | ||
@@ -380,3 +395,2 @@ }); | ||
} | ||
console.log('settings validationMessage', validationMessage) | ||
form.validationMessage[error] = validationMessage; | ||
@@ -387,5 +401,7 @@ } | ||
// Setting or removing a validity can change the field to believe its valid | ||
// but its not. So lets trigger its validation as well. | ||
scope.$broadcast('schemaFormValidate'); | ||
if (validity === true) { | ||
// Setting or removing a validity can change the field to believe its valid | ||
// but its not. So lets trigger its validation as well. | ||
scope.$broadcast('schemaFormValidate'); | ||
} | ||
} | ||
@@ -558,3 +574,3 @@ }) | ||
'default': 'Field does not validate', | ||
0: 'Invalid type, expected {{schema.type}})', | ||
0: 'Invalid type, expected {{schema.type}}', | ||
1: 'No enum match for: {{value}}', | ||
@@ -566,15 +582,15 @@ 10: 'Data does not match any schemas from "anyOf"', | ||
// Numeric errors | ||
100: 'Value {{value}} is not a multiple of {{schema.multipleOf}}', | ||
101: 'Value {{value}} is less than minimum {{schema.minimum}}', | ||
102: 'Value {{value}} is equal to exclusive minimum {{schema.minimum}}', | ||
103: 'Value {{value}} is greater than maximum {{schema.maximum}}', | ||
104: 'Value {{value}} is equal to exclusive maximum {{schema.maximum}}', | ||
105: 'Value {{value}} is not a valid number', | ||
100: 'Value is not a multiple of {{schema.divisibleBy}}', | ||
101: '{{viewValue}} is less than the allowed minimum of {{schema.minimum}}', | ||
102: '{{viewValue}} is equal to the exclusive minimum {{schema.minimum}}', | ||
103: '{{viewValue}} is greater than the allowed maximum of {{schema.maximum}}', | ||
104: '{{viewValue}} is equal to the exclusive maximum {{schema.maximum}}', | ||
105: 'Value is not a valid number', | ||
// String errors | ||
200: 'String is too short ({{value.length}} chars), minimum {{schema.minimum}}', | ||
201: 'String is too long ({{value.length}} chars), maximum {{schema.maximum}}', | ||
200: 'String is too short ({{viewValue.length}} chars), minimum {{schema.minLength}}', | ||
201: 'String is too long ({{viewValue.length}} chars), maximum {{schema.maxLength}}', | ||
202: 'String does not match pattern: {{schema.pattern}}', | ||
// Object errors | ||
300: 'Too few properties defined, minimum {{schema.minimum}}', | ||
301: 'Too many properties defined, maximum {{schema.maximum}}', | ||
300: 'Too few properties defined, minimum {{schema.minProperties}}', | ||
301: 'Too many properties defined, maximum {{schema.maxProperties}}', | ||
302: 'Required', | ||
@@ -584,4 +600,4 @@ 303: 'Additional properties not allowed', | ||
// Array errors | ||
400: 'Array is too short ({{value.length}}), minimum {{schema.minimum}}', | ||
401: 'Array is too long ({{value.length}}), maximum {{schema.maximum}}', | ||
400: 'Array is too short ({{value.length}}), minimum {{schema.maxItems}}', | ||
401: 'Array is too long ({{value.length}}), maximum {{schema.minItems}}', | ||
402: 'Array items are not unique', | ||
@@ -598,2 +614,11 @@ 403: 'Additional items not allowed', | ||
// In some cases we get hit with an angular validation error | ||
defaultMessages.number = defaultMessages[105]; | ||
defaultMessages.required = defaultMessages[302]; | ||
defaultMessages.min = defaultMessages[101]; | ||
defaultMessages.max = defaultMessages[103]; | ||
defaultMessages.maxlength = defaultMessages[201]; | ||
defaultMessages.minlength = defaultMessages[200]; | ||
defaultMessages.pattern = defaultMessages[202]; | ||
this.setDefaultMessages = function(messages) { | ||
@@ -623,2 +648,3 @@ defaultMessages = messages; | ||
* @param {Any} value the actual model value. | ||
* @param {Any} viewValue the viewValue | ||
* @param {Object} form a form definition object for this field | ||
@@ -629,3 +655,3 @@ * @param {Object} global the global validation messages object (even though its called global | ||
*/ | ||
service.interpolate = function(error, value, form, global) { | ||
service.interpolate = function(error, value, viewValue, form, global) { | ||
global = global || {}; | ||
@@ -656,2 +682,3 @@ var validationMessage = form.validationMessage || {}; | ||
value: value, | ||
viewValue: viewValue, | ||
form: form, | ||
@@ -1512,3 +1539,3 @@ schema: form.schema, | ||
var update = function(valid) { | ||
if (valid && scope.hasError()) { | ||
if (valid && !scope.hasError()) { | ||
element.html(msg); | ||
@@ -1523,16 +1550,4 @@ } else { | ||
// TODO: Make that optional | ||
// tv4- errors take precedence | ||
var error = errors[0]; | ||
if (errors.length > 1) { | ||
error = errors.reduce(function(prev, value) { | ||
if (prev && prev.indexOf('tv4-') === 0) { | ||
return prev; | ||
} | ||
return value; | ||
}); | ||
console.log('reduced',errors, error) | ||
} | ||
if (error) { | ||
@@ -1542,2 +1557,3 @@ element.html(sfErrorMessage.interpolate( | ||
scope.ngModel.$modelValue, | ||
scope.ngModel.$viewValue, | ||
scope.form, | ||
@@ -1772,2 +1788,7 @@ scope.options && scope.options.validationMessage | ||
// Omit TV4 validation | ||
if (scope.options && scope.options.tv4Validation === false) { | ||
return viewValue; | ||
} | ||
var result = sfValidator.validate(form, viewValue); | ||
@@ -1835,1 +1856,4 @@ // Since we might have different tv4 errors we must clear all | ||
}]); | ||
return schemaForm; | ||
})); |
@@ -1,1 +0,1 @@ | ||
var deps=[];try{angular.module("ngSanitize"),deps.push("ngSanitize")}catch(e){}try{angular.module("ui.sortable"),deps.push("ui.sortable")}catch(e){}try{angular.module("angularSpectrumColorpicker"),deps.push("angularSpectrumColorpicker")}catch(e){}angular.module("schemaForm",deps),angular.module("schemaForm").provider("sfPath",[function(){var e={parse:ObjectPath.parse};e.stringify=1===angular.version.major&&angular.version.minor<3?function(e){return Array.isArray(e)?e.join("."):e.toString()}:ObjectPath.stringify,e.normalize=function(r,t){return e.stringify(Array.isArray(r)?r:e.parse(r),t)},this.parse=e.parse,this.stringify=e.stringify,this.normalize=e.normalize,this.$get=function(){return e}}]),angular.module("schemaForm").factory("sfSelect",["sfPath",function(e){var r=/^\d+$/;return function(t,n,a){n||(n=this);var i="string"==typeof t?e.parse(t):t;if("undefined"!=typeof a&&1===i.length)return n[i[0]]=a,n;"undefined"!=typeof a&&"undefined"==typeof n[i[0]]&&(n[i[0]]=i.length>2&&r.test(i[1])?[]:{});for(var o=n[i[0]],l=1;l<i.length;l++){if(""===i[l])return void 0;if("undefined"!=typeof a){if(l===i.length-1)return o[i[l]]=a,a;var u=o[i[l]];("undefined"==typeof u||null===u)&&(u=r.test(i[l+1])?[]:{},o[i[l]]=u),o=u}else o&&(o=o[i[l]])}return o}}]),angular.module("schemaForm").provider("schemaFormDecorators",["$compileProvider","sfPathProvider",function(e,r){var t="",n={},a=function(e,r){"sfDecorator"===e&&(e=t);for(var a=n[e],i=a.rules,o=0;o<i.length;o++){var l=i[o](r);if(l)return l}return a.mappings[r.type]?a.mappings[r.type]:a.mappings["default"]},i=function(t){e.directive(t,["$parse","$compile","$http","$templateCache","$interpolate","$q","sfErrorMessage",function(e,n,i,o,l,u,s){return{restrict:"AE",replace:!1,transclude:!1,scope:!0,require:"?^sfSchema",link:function(e,c,f,m){e.$on("schemaFormPropagateNgModelController",function(r,t){r.stopPropagation(),r.preventDefault(),e.ngModel=t}),e.showTitle=function(){return e.form&&e.form.notitle!==!0&&e.form.title},e.listToCheckboxValues=function(e){var r={};return angular.forEach(e,function(e){r[e]=!0}),r},e.checkboxValuesToList=function(e){var r=[];return angular.forEach(e,function(e,t){e&&r.push(t)}),r},e.buttonClick=function(r,t){angular.isFunction(t.onClick)?t.onClick(r,t):angular.isString(t.onClick)&&(m?m.evalInParentScope(t.onClick,{$event:r,form:t}):e.$eval(t.onClick,{$event:r,form:t}))},e.evalExpr=function(r,t){return m?m.evalInParentScope(r,t):e.$eval(r,t)},e.evalInScope=function(r,t){return r?e.$eval(r,t):void 0},e.interp=function(e,r){return e&&l(e)(r)},e.hasSuccess=function(){return e.ngModel?e.ngModel.$valid&&(!e.ngModel.$pristine||!e.ngModel.$isEmpty(e.ngModel.$modelValue)):!1},e.hasError=function(){return e.ngModel?e.ngModel.$invalid&&!e.ngModel.$pristine:!1},e.errorMessage=function(r){return s.interpolate(r&&r.code+""||"default",e.ngModel&&e.ngModel.$modelValue||"",e.form,e.options&&e.options.validationMessage)};var d=e.$watch(f.form,function(l){if(l){l.ngModelOptions=l.ngModelOptions||{},e.form=l;var s;if("template"===l.type&&l.template)s=u.when(l.template);else{var f="template"===l.type?l.templateUrl:a(t,l);s=i.get(f,{cache:o}).then(function(e){return e.data})}s.then(function(t){if(l.key){var a=l.key?r.stringify(l.key).replace(/"/g,"""):"";t=t.replace(/\$\$value\$\$/g,"model"+("["!==a[0]?".":"")+a)}c.html(t),l.condition&&angular.forEach(c.children(),function(e){var r=e.getAttribute("ng-if");e.setAttribute("ng-if",r?"("+r+') || (evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex }))':'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex })')}),n(c.contents())(e)}),l.key&&e.$on("schemaForm.error."+l.key.join("."),function(r,t,n,a){(n===!0||n===!1)&&(a=n,n=void 0),e.ngModel&&t&&(e.ngModel.$setDirty()?e.ngModel.$setDirty():(e.ngModel.$dirty=!0,e.ngModel.$pristine=!1),n&&(l.validationMessage||(l.validationMessage={}),console.log("settings validationMessage",n),l.validationMessage[t]=n),e.ngModel.$setValidity(t,a===!0),e.$broadcast("schemaFormValidate"))}),d()}})}}}])},o=function(r,t,n){n=angular.isDefined(n)?n:!1,e.directive("sf"+angular.uppercase(r[0])+r.substr(1),function(){return{restrict:"EAC",scope:!0,replace:!0,transclude:n,template:'<sf-decorator form="form"></sf-decorator>',link:function(e,t,n){var a={items:"c",titleMap:"c",schema:"c"},i={type:r},o=!0;angular.forEach(n,function(r,t){if("$"!==t[0]&&0!==t.indexOf("ng")&&"sfField"!==t){var l=function(r){angular.isDefined(r)&&r!==i[t]&&(i[t]=r,o&&i.type&&(i.key||angular.isUndefined(n.key))&&(e.form=i,o=!1))};"model"===t?e.$watch(r,function(r){r&&e.model!==r&&(e.model=r)}):"c"===a[t]?e.$watchCollection(r,l):n.$observe(t,l)}})}}})};this.createDecorator=function(e,r,a){n[e]={mappings:r||{},rules:a||[]},n[t]||(t=e),i(e)},this.createDirective=o,this.createDirectives=function(e){angular.forEach(e,function(e,r){o(r,e)})},this.directive=function(e){return e=e||t,n[e]},this.addMapping=function(e,r,t){n[e]&&(n[e].mappings[r]=t)},this.$get=function(){return{directive:function(e){return n[e]},defaultDecorator:t}},i("sfDecorator")}]),angular.module("schemaForm").provider("sfErrorMessage",function(){var e={"default":"Field does not validate",0:"Invalid type, expected {{schema.type}})",1:"No enum match for: {{value}}",10:'Data does not match any schemas from "anyOf"',11:'Data does not match any schemas from "oneOf"',12:'Data is valid against more than one schema from "oneOf"',13:'Data matches schema from "not"',100:"Value {{value}} is not a multiple of {{schema.multipleOf}}",101:"Value {{value}} is less than minimum {{schema.minimum}}",102:"Value {{value}} is equal to exclusive minimum {{schema.minimum}}",103:"Value {{value}} is greater than maximum {{schema.maximum}}",104:"Value {{value}} is equal to exclusive maximum {{schema.maximum}}",105:"Value {{value}} is not a valid number",200:"String is too short ({{value.length}} chars), minimum {{schema.minimum}}",201:"String is too long ({{value.length}} chars), maximum {{schema.maximum}}",202:"String does not match pattern: {{schema.pattern}}",300:"Too few properties defined, minimum {{schema.minimum}}",301:"Too many properties defined, maximum {{schema.maximum}}",302:"Required",303:"Additional properties not allowed",304:"Dependency failed - key must exist",400:"Array is too short ({{value.length}}), minimum {{schema.minimum}}",401:"Array is too long ({{value.length}}), maximum {{schema.maximum}}",402:"Array items are not unique",403:"Additional items not allowed",500:"Format validation failed",501:'Keyword failed: "{{title}}"',600:"Circular $refs",1e3:"Unknown property (not in schema)"};this.setDefaultMessages=function(r){e=r},this.getDefaultMessages=function(){return e},this.setDefaultMessage=function(r,t){e[r]=t},this.$get=["$interpolate",function(r){var t={};return t.defaultMessages=e,t.interpolate=function(t,n,a,i){i=i||{};var o=a.validationMessage||{};0===t.indexOf("tv4-")&&(t=t.substring(4));var l=o["default"]||i["default"]||"";[o,i,e].some(function(e){return angular.isString(e)||angular.isFunction(e)?(l=e,!0):e&&e[t]?(l=e[t],!0):void 0});var u={error:t,value:n,form:a,schema:a.schema,title:a.title||a.schema&&a.schema.title};return angular.isFunction(l)?l(u):r(l)(u)},t}]}),angular.module("schemaForm").provider("schemaForm",["sfPathProvider",function(e){var r=function(e){if(Array.isArray(e)&&2==e.length){if("null"===e[0])return e[1];if("null"===e[1])return e[0]}return e},t=function(e){var r=[];return e.forEach(function(e){r.push({name:e,value:e})}),r},n=function(e,r){if(!angular.isArray(e)){var t=[];return r?angular.forEach(r,function(r){t.push({name:e[r],value:r})}):angular.forEach(e,function(e,r){t.push({name:e,value:r})}),t}return e},a=function(e,t,n){var a=h[r(t.type)];if(a)for(var i,o=0;o<a.length;o++)if(i=a[o](e,t,n))return i.schema["x-schema-form"]&&angular.isObject(i.schema["x-schema-form"])&&(i=angular.extend(i,i.schema["x-schema-form"])),i},i=function(e,r,t){t=t||{};var a=t.global&&t.global.formDefaults?angular.copy(t.global.formDefaults):{};return a.title=t.global&&t.global.supressPropertyTitles===!0?r.title:r.title||e,r.description&&(a.description=r.description),(t.required===!0||r.required===!0)&&(a.required=!0),r.maxLength&&(a.maxlength=r.maxLength),r.minLength&&(a.minlength=r.maxLength),(r.readOnly||r.readonly)&&(a.readonly=!0),r.minimum&&(a.minimum=r.minimum+(r.exclusiveMinimum?1:0)),r.maximum&&(a.maximum=r.maximum-(r.exclusiveMaximum?1:0)),r.validationMessage&&(a.validationMessage=r.validationMessage),r.enumNames&&(a.titleMap=n(r.enumNames,r["enum"])),a.schema=r,a.ngModelOptions=a.ngModelOptions||{},a},o=function(t,n,a){if("string"===r(n.type)&&!n["enum"]){var o=i(t,n,a);return o.key=a.path,o.type="text",a.lookup[e.stringify(a.path)]=o,o}},l=function(t,n,a){if("number"===r(n.type)){var o=i(t,n,a);return o.key=a.path,o.type="number",a.lookup[e.stringify(a.path)]=o,o}},u=function(t,n,a){if("integer"===r(n.type)){var o=i(t,n,a);return o.key=a.path,o.type="number",a.lookup[e.stringify(a.path)]=o,o}},s=function(t,n,a){if("boolean"===r(n.type)){var o=i(t,n,a);return o.key=a.path,o.type="checkbox",a.lookup[e.stringify(a.path)]=o,o}},c=function(n,a,o){if("string"===r(a.type)&&a["enum"]){var l=i(n,a,o);return l.key=o.path,l.type="select",l.titleMap||(l.titleMap=t(a["enum"])),o.lookup[e.stringify(o.path)]=l,l}},f=function(n,a,o){if("array"===r(a.type)&&a.items&&a.items["enum"]){var l=i(n,a,o);return l.key=o.path,l.type="checkboxes",l.titleMap||(l.titleMap=t(a.items["enum"])),o.lookup[e.stringify(o.path)]=l,l}},m=function(t,n,o){if("object"===r(n.type)){var l=i(t,n,o);return l.type="fieldset",l.items=[],o.lookup[e.stringify(o.path)]=l,angular.forEach(n.properties,function(r,t){var i=o.path.slice();if(i.push(t),o.ignore[e.stringify(i)]!==!0){var u=n.required&&-1!==n.required.indexOf(t),s=a(t,r,{path:i,required:u||!1,lookup:o.lookup,ignore:o.ignore});s&&l.items.push(s)}}),l}},d=function(t,n,o){if("array"===r(n.type)){var l=i(t,n,o);l.type="array",l.key=o.path,o.lookup[e.stringify(o.path)]=l;var u=n.required&&-1!==n.required.indexOf(o.path[o.path.length-1]),s=o.path.slice();return s.push(""),l.items=[a(t,n.items,{path:s,required:u||!1,lookup:o.lookup,ignore:o.ignore,global:o.global})],l}},h={string:[c,o],object:[m],number:[l],integer:[u],"boolean":[s],array:[f,d]},p=function(e){return e};this.defaults=h,this.stdFormObj=i,this.defaultFormDefinition=a,this.postProcess=function(e){p=e},this.appendRule=function(e,r){h[e]||(h[e]=[]),h[e].push(r)},this.prependRule=function(e,r){h[e]||(h[e]=[]),h[e].unshift(r)},this.createStandardForm=i,this.$get=function(){var t={};return t.merge=function(r,a,i,o,l){a=a||["*"],o=o||{},l=l||r.readonly||r.readOnly;var u=t.defaults(r,i,o),s=a.indexOf("*");-1!==s&&(a=a.slice(0,s).concat(u.form).concat(a.slice(s+1)));var c=u.lookup;return p(a.map(function(a){if("string"==typeof a&&(a={key:a}),a.key&&"string"==typeof a.key&&(a.key=e.parse(a.key)),a.titleMap&&(a.titleMap=n(a.titleMap)),a.itemForm){a.items=[];var u=e.stringify(a.key),s=c[u];angular.forEach(s.items,function(e){var r=angular.copy(a.itemForm);r.key=e.key,a.items.push(r)})}if(a.key){var f=e.stringify(a.key);if(c[f]){var m=c[f];angular.forEach(m,function(e,r){void 0===a[r]&&(a[r]=m[r])})}}return l===!0&&(a.readonly=!0),a.items&&(a.items=t.merge(r,a.items,i,o,a.readonly)),a.tabs&&angular.forEach(a.tabs,function(e){e.items=t.merge(r,e.items,i,o,a.readonly)}),"checkbox"===a.type&&angular.isUndefined(a.schema["default"])&&(a.schema["default"]=!1),a}))},t.defaults=function(e,t,n){var i=[],o={};if(t=t||{},n=n||{},"object"!==r(e.type))throw new Error('Not implemented. Only type "object" allowed at root level of schema.');return angular.forEach(e.properties,function(r,l){if(t[l]!==!0){var u=e.required&&-1!==e.required.indexOf(l),s=a(l,r,{path:[l],lookup:o,ignore:t,required:u,global:n});s&&i.push(s)}}),{form:i,lookup:o}},t.traverseSchema=function(e,r,t,n){n=angular.isDefined(n)?n:!0,t=t||[];var a=function(e,r,t){if(r(e,t),angular.forEach(e.properties,function(e,n){var i=t.slice();i.push(n),a(e,r,i)}),!n&&e.items){var i=t.slice();i.push(""),a(e.items,r,i)}};a(e,r,t||[])},t.traverseForm=function(e,r){r(e),angular.forEach(e.items,function(e){t.traverseForm(e,r)}),e.tabs&&angular.forEach(e.tabs,function(e){angular.forEach(e.items,function(e){t.traverseForm(e,r)})})},t}}]),angular.module("schemaForm").factory("sfValidator",[function(){var e={};return e.validate=function(e,r){if(!e)return{valid:!0};var t=e.schema;if(!t)return{valid:!0};""===r&&(r=void 0),"number"===e.type&&null===r&&(r=void 0);var n={type:"object",properties:{}},a=e.key[e.key.length-1];n.properties[a]=t,e.required&&(n.required=[a]);var i={};return angular.isDefined(r)&&(i[a]=r),tv4.validateResult(i,n)},e}]),angular.module("schemaForm").directive("sfArray",["sfSelect","schemaForm","sfValidator","sfPath",function(e,r,t,n){var a=function(e){return function(r){r.key&&(r.key[r.key.indexOf("")]=e)}};return{restrict:"A",scope:!0,require:"?ngModel",link:function(i,o,l,u){var s={};u&&i.$emit("schemaFormPropagateNgModelController",u);var c=i.$watch(l.sfArray,function(o){var l=e(o.key,i.model);if(i.$watch("model"+n.normalize(o.key),function(){l=e(o.key,i.model),i.modelArray=l}),angular.isUndefined(l)&&(l=[],e(o.key,i.model,l)),i.modelArray=l,o.items){var f=o.items[0];o.items.length>1&&(f={type:"section",items:o.items.map(function(e){return e.ngModelOptions=o.ngModelOptions,angular.isUndefined(e.readonly)&&(e.readonly=o.readonly),e})})}if(i.copyWithIndex=function(e){if(!s[e]&&f){var t=angular.copy(f);t.arrayIndex=e,r.traverseForm(t,a(e)),s[e]=t}return s[e]},i.appendToArray=function(){var t=l.length,n=i.copyWithIndex(t);if(r.traverseForm(n,function(r){if(r.key){var t;angular.isDefined(r["default"])&&(t=r["default"]),angular.isDefined(r.schema)&&angular.isDefined(r.schema["default"])&&(t=r.schema["default"]),angular.isDefined(t)&&e(r.key,i.model,t)}}),t===l.length){var a,u=e("schema.items.type",o);"object"===u?a={}:"array"===u&&(a=[]),l.push(a)}return i.validateArray&&i.validateArray(),l},i.deleteFromArray=function(e){return l.splice(e,1),i.validateArray&&i.validateArray(),u&&u.$setDirty&&u.$setDirty(),l},o.titleMap||o.startEmpty===!0||0!==l.length||i.appendToArray(),o.titleMap&&o.titleMap.length>0){i.titleMapValues=[];var m=function(e){i.titleMapValues=[],e=e||[],o.titleMap.forEach(function(r){i.titleMapValues.push(-1!==e.indexOf(r.value))})};m(i.modelArray),i.$watchCollection("modelArray",m),i.$watchCollection("titleMapValues",function(e){if(e){for(var r=i.modelArray;r.length>0;)r.pop();o.titleMap.forEach(function(t,n){e[n]&&r.push(t.value)})}})}if(u){var d;i.validateArray=function(){var e=t.validate(o,i.modelArray.length>0?i.modelArray:void 0);Object.keys(u.$error).filter(function(e){return 0===e.indexOf("tv4-")}).forEach(function(e){u.$setValidity(e,!0)}),e.valid!==!1||!e.error||""!==e.error.dataPath&&e.error.dataPath!=="/"+o.key[o.key.length-1]||(u.$setViewValue(i.modelArray),d=e.error,u.$setValidity("tv4-"+e.error.code,!1))},i.$on("schemaFormValidate",i.validateArray),i.hasSuccess=function(){return u.$valid&&!u.$pristine},i.hasError=function(){return u.$invalid},i.schemaError=function(){return d}}c()})}}}]),angular.module("schemaForm").directive("sfChanged",function(){return{require:"ngModel",restrict:"AC",scope:!1,link:function(e,r,t,n){var a=e.$eval(t.sfChanged);a&&a.onChange&&n.$viewChangeListeners.push(function(){angular.isFunction(a.onChange)?a.onChange(n.$modelValue,a):e.evalExpr(a.onChange,{modelValue:n.$modelValue,form:a})})}}}),angular.module("schemaForm").directive("sfMessage",["$injector","sfErrorMessage",function(e,r){return{scope:!1,restrict:"EA",link:function(t,n,a){var i=e.has("$sanitize")?e.get("$sanitize"):function(e){return e},o="";a.sfMessage&&(o=t.$eval(a.sfMessage)||"",o=i(o));var l=function(e){if(e&&t.hasError())n.html(o);else{var a=Object.keys(t.ngModel&&t.ngModel.$error||{}),i=a[0];a.length>1&&(i=a.reduce(function(e,r){return e&&0===e.indexOf("tv4-")?e:r}),console.log("reduced",a,i)),n.html(i?r.interpolate(i,t.ngModel.$modelValue,t.form,t.options&&t.options.validationMessage):o)}};l(),t.$watchCollection("ngModel.$error",function(){t.ngModel&&l(t.ngModel.$valid)})}}}]),angular.module("schemaForm").directive("sfSchema",["$compile","schemaForm","schemaFormDecorators","sfSelect","sfPath",function(e,r,t,n,a){var i=/[A-Z]/g,o=function(e,r){return r=r||"_",e.replace(i,function(e,t){return(t?r:"")+e.toLowerCase()})};return{scope:{schema:"=sfSchema",initialForm:"=sfForm",model:"=sfModel",options:"=sfOptions"},controller:["$scope",function(e){this.evalInParentScope=function(r,t){return e.$parent.$eval(r,t)}}],replace:!1,restrict:"A",transclude:!0,require:"?form",link:function(i,l,u,s,c){i.formCtrl=s;var f={};c(i,function(e){if(e.addClass("schema-form-ignore"),l.prepend(e),l[0].querySelectorAll){var r=l[0].querySelectorAll("[ng-model]");if(r)for(var t=0;t<r.length;t++){var n=r[t].getAttribute("ng-model");f[n.substring(n.indexOf(".")+1)]=!0}}});var m,d={},h=function(s,c){var d=r.merge(s,c,f,i.options),h=document.createDocumentFragment();m&&m.$destroy(),m=i.$new(),m.schemaForm={form:d,schema:s},l.children(":not(.schema-form-ignore)").remove();for(var p={},g=l[0].querySelectorAll("*[sf-insert-field]"),v=0;v<g.length;v++)p[g[v].getAttribute("sf-insert-field")]=g[v];angular.forEach(d,function(e,r){var n=document.createElement(u.sfUseDecorator||o(t.defaultDecorator,"-"));if(n.setAttribute("form","schemaForm.form["+r+"]"),e.key){var i=p[a.stringify(e.key)];if(i){for(;i.firstChild;)i.removeChild(i.firstChild);return void i.appendChild(n)}}h.appendChild(n)}),l[0].appendChild(h),e(l.children())(m),r.traverseSchema(s,function(e,r){if(angular.isDefined(e["default"])){var t=n(r,i.model);angular.isUndefined(t)&&n(r,i.model,e["default"])}}),i.$emit("sf-render-finished",l)};i.$watch(function(){var e=i.schema,r=i.initialForm||["*"];r&&e&&e.type&&(d.form!==r||d.schema!==e)&&Object.keys(e.properties).length>0&&(d.schema=e,d.form=r,h(e,r))}),i.$on("schemaFormRedraw",function(){var e=i.schema,r=i.initialForm||["*"];e&&h(e,r)})}}}]),angular.module("schemaForm").directive("schemaValidate",["sfValidator","sfSelect",function(e,r){return{restrict:"A",scope:!1,priority:500,require:"ngModel",link:function(t,n,a,i){t.$emit("schemaFormPropagateNgModelController",i);var o=null,l=function(){return u||(u=t.$eval(a.schemaValidate)),u},u=l();u.copyValueTo&&i.$viewChangeListeners.push(function(){var e=u.copyValueTo;angular.forEach(e,function(e){r(e,t.model,i.$modelValue)})});var s=function(r){if(u=l(),!u)return r;var t=e.validate(u,r);return Object.keys(i.$error).filter(function(e){return 0===e.indexOf("tv4-")}).forEach(function(e){i.$setValidity(e,!0)}),t.valid?r:(i.$setValidity("tv4-"+t.error.code,!1),void(o=t.error))};"function"==typeof u.ngModel&&u.ngModel(i),["$parsers","$viewChangeListeners","$formatters"].forEach(function(e){u[e]&&i[e]&&u[e].forEach(function(r){i[e].push(r)})}),["$validators","$asyncValidators"].forEach(function(e){u[e]&&i[e]&&angular.forEach(u[e],function(r,t){i[e][t]=r})}),i.$parsers.push(s),t.$on("schemaFormValidate",function(){i.$setDirty?(i.$setDirty(),s(i.$modelValue)):i.$setViewValue(i.$viewValue)}),t.schemaError=function(){return o}}}}]); | ||
!function(e,t){"function"==typeof define&&define.amd?define(["angular","ObjectPath","tv4"],t):"object"==typeof exports?module.exports=t(require("angular"),require("ObjectPath"),require("tv4")):e.schemaForm=t(e.angular,e.ObjectPath,e.tv4)}(this,function(e,t,r){var n=[];try{e.module("ngSanitize"),n.push("ngSanitize")}catch(i){}try{e.module("ui.sortable"),n.push("ui.sortable")}catch(i){}try{e.module("angularSpectrumColorpicker"),n.push("angularSpectrumColorpicker")}catch(i){}var o=e.module("schemaForm",n);return e.module("schemaForm").provider("sfPath",[function(){var r={parse:t.parse};r.stringify=1===e.version.major&&e.version.minor<3?function(e){return Array.isArray(e)?e.join("."):e.toString()}:t.stringify,r.normalize=function(e,t){return r.stringify(Array.isArray(e)?e:r.parse(e),t)},this.parse=r.parse,this.stringify=r.stringify,this.normalize=r.normalize,this.$get=function(){return r}}]),e.module("schemaForm").factory("sfSelect",["sfPath",function(e){var t=/^\d+$/;return function(r,n,i){n||(n=this);var o="string"==typeof r?e.parse(r):r;if("undefined"!=typeof i&&1===o.length)return n[o[0]]=i,n;"undefined"!=typeof i&&"undefined"==typeof n[o[0]]&&(n[o[0]]=o.length>2&&t.test(o[1])?[]:{});for(var a=n[o[0]],s=1;s<o.length;s++){if(""===o[s])return void 0;if("undefined"!=typeof i){if(s===o.length-1)return a[o[s]]=i,i;var l=a[o[s]];("undefined"==typeof l||null===l)&&(l=t.test(o[s+1])?[]:{},a[o[s]]=l),a=l}else a&&(a=a[o[s]])}return a}}]),e.module("schemaForm").provider("schemaFormDecorators",["$compileProvider","sfPathProvider",function(t,r){var n="",i={},o=function(e,t){"sfDecorator"===e&&(e=n);for(var r=i[e],o=r.rules,a=0;a<o.length;a++){var s=o[a](t);if(s)return s}return r.mappings[t.type]?r.mappings[t.type]:r.mappings["default"]},a=function(n){t.directive(n,["$parse","$compile","$http","$templateCache","$interpolate","$q","sfErrorMessage","sfPath",function(t,i,a,s,l,u,c,f){return{restrict:"AE",replace:!1,transclude:!1,scope:!0,require:"?^sfSchema",link:function(t,m,d,h){t.$on("schemaFormPropagateNgModelController",function(e,r){e.stopPropagation(),e.preventDefault(),t.ngModel=r}),t.showTitle=function(){return t.form&&t.form.notitle!==!0&&t.form.title},t.listToCheckboxValues=function(t){var r={};return e.forEach(t,function(e){r[e]=!0}),r},t.checkboxValuesToList=function(t){var r=[];return e.forEach(t,function(e,t){e&&r.push(t)}),r},t.buttonClick=function(r,n){e.isFunction(n.onClick)?n.onClick(r,n):e.isString(n.onClick)&&(h?h.evalInParentScope(n.onClick,{$event:r,form:n}):t.$eval(n.onClick,{$event:r,form:n}))},t.evalExpr=function(e,r){return h?h.evalInParentScope(e,r):t.$eval(e,r)},t.evalInScope=function(e,r){return e?t.$eval(e,r):void 0},t.interp=function(e,t){return e&&l(e)(t)},t.hasSuccess=function(){return t.ngModel?t.ngModel.$valid&&(!t.ngModel.$pristine||!t.ngModel.$isEmpty(t.ngModel.$modelValue)):!1},t.hasError=function(){return t.ngModel?t.ngModel.$invalid&&!t.ngModel.$pristine:!1},t.errorMessage=function(e){return c.interpolate(e&&e.code+""||"default",t.ngModel&&t.ngModel.$modelValue||"",t.ngModel&&t.ngModel.$viewValue||"",t.form,t.options&&t.options.validationMessage)};var p=t.$watch(d.form,function(l){if(l){l.ngModelOptions=l.ngModelOptions||{},t.form=l;var c;if("template"===l.type&&l.template)c=u.when(l.template);else{var d="template"===l.type?l.templateUrl:o(n,l);c=a.get(d,{cache:s}).then(function(e){return e.data})}c.then(function(n){if(l.key){var o=l.key?r.stringify(l.key).replace(/"/g,"""):"";n=n.replace(/\$\$value\$\$/g,"model"+("["!==o[0]?".":"")+o)}if(m.html(n),l.condition){var a='evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex})';l.key&&(a='evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex, "modelValue": model'+f.stringify(l.key)+"})"),e.forEach(m.children(),function(e){var t=e.getAttribute("ng-if");e.setAttribute("ng-if",t?"("+t+") || ("+a+")":a)})}i(m.contents())(t)}),l.key&&t.$on("schemaForm.error."+l.key.join("."),function(e,r,n,i){(n===!0||n===!1)&&(i=n,n=void 0),t.ngModel&&r&&(t.ngModel.$setDirty()?t.ngModel.$setDirty():(t.ngModel.$dirty=!0,t.ngModel.$pristine=!1),n&&(l.validationMessage||(l.validationMessage={}),l.validationMessage[r]=n),t.ngModel.$setValidity(r,i===!0),i===!0&&t.$broadcast("schemaFormValidate"))}),p()}})}}}])},s=function(r,n,i){i=e.isDefined(i)?i:!1,t.directive("sf"+e.uppercase(r[0])+r.substr(1),function(){return{restrict:"EAC",scope:!0,replace:!0,transclude:i,template:'<sf-decorator form="form"></sf-decorator>',link:function(t,n,i){var o={items:"c",titleMap:"c",schema:"c"},a={type:r},s=!0;e.forEach(i,function(r,n){if("$"!==n[0]&&0!==n.indexOf("ng")&&"sfField"!==n){var l=function(r){e.isDefined(r)&&r!==a[n]&&(a[n]=r,s&&a.type&&(a.key||e.isUndefined(i.key))&&(t.form=a,s=!1))};"model"===n?t.$watch(r,function(e){e&&t.model!==e&&(t.model=e)}):"c"===o[n]?t.$watchCollection(r,l):i.$observe(n,l)}})}}})};this.createDecorator=function(e,t,r){i[e]={mappings:t||{},rules:r||[]},i[n]||(n=e),a(e)},this.createDirective=s,this.createDirectives=function(t){e.forEach(t,function(e,t){s(t,e)})},this.directive=function(e){return e=e||n,i[e]},this.addMapping=function(e,t,r){i[e]&&(i[e].mappings[t]=r)},this.$get=function(){return{directive:function(e){return i[e]},defaultDecorator:n}},a("sfDecorator")}]),e.module("schemaForm").provider("sfErrorMessage",function(){var t={"default":"Field does not validate",0:"Invalid type, expected {{schema.type}}",1:"No enum match for: {{value}}",10:'Data does not match any schemas from "anyOf"',11:'Data does not match any schemas from "oneOf"',12:'Data is valid against more than one schema from "oneOf"',13:'Data matches schema from "not"',100:"Value is not a multiple of {{schema.divisibleBy}}",101:"{{viewValue}} is less than the allowed minimum of {{schema.minimum}}",102:"{{viewValue}} is equal to the exclusive minimum {{schema.minimum}}",103:"{{viewValue}} is greater than the allowed maximum of {{schema.maximum}}",104:"{{viewValue}} is equal to the exclusive maximum {{schema.maximum}}",105:"Value is not a valid number",200:"String is too short ({{viewValue.length}} chars), minimum {{schema.minLength}}",201:"String is too long ({{viewValue.length}} chars), maximum {{schema.maxLength}}",202:"String does not match pattern: {{schema.pattern}}",300:"Too few properties defined, minimum {{schema.minProperties}}",301:"Too many properties defined, maximum {{schema.maxProperties}}",302:"Required",303:"Additional properties not allowed",304:"Dependency failed - key must exist",400:"Array is too short ({{value.length}}), minimum {{schema.maxItems}}",401:"Array is too long ({{value.length}}), maximum {{schema.minItems}}",402:"Array items are not unique",403:"Additional items not allowed",500:"Format validation failed",501:'Keyword failed: "{{title}}"',600:"Circular $refs",1e3:"Unknown property (not in schema)"};t.number=t[105],t.required=t[302],t.min=t[101],t.max=t[103],t.maxlength=t[201],t.minlength=t[200],t.pattern=t[202],this.setDefaultMessages=function(e){t=e},this.getDefaultMessages=function(){return t},this.setDefaultMessage=function(e,r){t[e]=r},this.$get=["$interpolate",function(r){var n={};return n.defaultMessages=t,n.interpolate=function(n,i,o,a,s){s=s||{};var l=a.validationMessage||{};0===n.indexOf("tv4-")&&(n=n.substring(4));var u=l["default"]||s["default"]||"";[l,s,t].some(function(t){return e.isString(t)||e.isFunction(t)?(u=t,!0):t&&t[n]?(u=t[n],!0):void 0});var c={error:n,value:i,viewValue:o,form:a,schema:a.schema,title:a.title||a.schema&&a.schema.title};return e.isFunction(u)?u(c):r(u)(c)},n}]}),e.module("schemaForm").provider("schemaForm",["sfPathProvider",function(t){var r=function(e){if(Array.isArray(e)&&2==e.length){if("null"===e[0])return e[1];if("null"===e[1])return e[0]}return e},n=function(e){var t=[];return e.forEach(function(e){t.push({name:e,value:e})}),t},i=function(t,r){if(!e.isArray(t)){var n=[];return r?e.forEach(r,function(e){n.push({name:t[e],value:e})}):e.forEach(t,function(e,t){n.push({name:e,value:t})}),n}return t},o=function(t,n,i){var o=p[r(n.type)];if(o)for(var a,s=0;s<o.length;s++)if(a=o[s](t,n,i))return a.schema["x-schema-form"]&&e.isObject(a.schema["x-schema-form"])&&(a=e.extend(a,a.schema["x-schema-form"])),a},a=function(t,r,n){n=n||{};var o=n.global&&n.global.formDefaults?e.copy(n.global.formDefaults):{};return o.title=n.global&&n.global.supressPropertyTitles===!0?r.title:r.title||t,r.description&&(o.description=r.description),(n.required===!0||r.required===!0)&&(o.required=!0),r.maxLength&&(o.maxlength=r.maxLength),r.minLength&&(o.minlength=r.maxLength),(r.readOnly||r.readonly)&&(o.readonly=!0),r.minimum&&(o.minimum=r.minimum+(r.exclusiveMinimum?1:0)),r.maximum&&(o.maximum=r.maximum-(r.exclusiveMaximum?1:0)),r.validationMessage&&(o.validationMessage=r.validationMessage),r.enumNames&&(o.titleMap=i(r.enumNames,r["enum"])),o.schema=r,o.ngModelOptions=o.ngModelOptions||{},o},s=function(e,n,i){if("string"===r(n.type)&&!n["enum"]){var o=a(e,n,i);return o.key=i.path,o.type="text",i.lookup[t.stringify(i.path)]=o,o}},l=function(e,n,i){if("number"===r(n.type)){var o=a(e,n,i);return o.key=i.path,o.type="number",i.lookup[t.stringify(i.path)]=o,o}},u=function(e,n,i){if("integer"===r(n.type)){var o=a(e,n,i);return o.key=i.path,o.type="number",i.lookup[t.stringify(i.path)]=o,o}},c=function(e,n,i){if("boolean"===r(n.type)){var o=a(e,n,i);return o.key=i.path,o.type="checkbox",i.lookup[t.stringify(i.path)]=o,o}},f=function(e,i,o){if("string"===r(i.type)&&i["enum"]){var s=a(e,i,o);return s.key=o.path,s.type="select",s.titleMap||(s.titleMap=n(i["enum"])),o.lookup[t.stringify(o.path)]=s,s}},m=function(e,i,o){if("array"===r(i.type)&&i.items&&i.items["enum"]){var s=a(e,i,o);return s.key=o.path,s.type="checkboxes",s.titleMap||(s.titleMap=n(i.items["enum"])),o.lookup[t.stringify(o.path)]=s,s}},d=function(n,i,s){if("object"===r(i.type)){var l=a(n,i,s);return l.type="fieldset",l.items=[],s.lookup[t.stringify(s.path)]=l,e.forEach(i.properties,function(e,r){var n=s.path.slice();if(n.push(r),s.ignore[t.stringify(n)]!==!0){var a=i.required&&-1!==i.required.indexOf(r),u=o(r,e,{path:n,required:a||!1,lookup:s.lookup,ignore:s.ignore});u&&l.items.push(u)}}),l}},h=function(e,n,i){if("array"===r(n.type)){var s=a(e,n,i);s.type="array",s.key=i.path,i.lookup[t.stringify(i.path)]=s;var l=n.required&&-1!==n.required.indexOf(i.path[i.path.length-1]),u=i.path.slice();return u.push(""),s.items=[o(e,n.items,{path:u,required:l||!1,lookup:i.lookup,ignore:i.ignore,global:i.global})],s}},p={string:[f,s],object:[d],number:[l],integer:[u],"boolean":[c],array:[m,h]},v=function(e){return e};this.defaults=p,this.stdFormObj=a,this.defaultFormDefinition=o,this.postProcess=function(e){v=e},this.appendRule=function(e,t){p[e]||(p[e]=[]),p[e].push(t)},this.prependRule=function(e,t){p[e]||(p[e]=[]),p[e].unshift(t)},this.createStandardForm=a,this.$get=function(){var n={};return n.merge=function(r,o,a,s,l){o=o||["*"],s=s||{},l=l||r.readonly||r.readOnly;var u=n.defaults(r,a,s),c=o.indexOf("*");-1!==c&&(o=o.slice(0,c).concat(u.form).concat(o.slice(c+1)));var f=u.lookup;return v(o.map(function(o){if("string"==typeof o&&(o={key:o}),o.key&&"string"==typeof o.key&&(o.key=t.parse(o.key)),o.titleMap&&(o.titleMap=i(o.titleMap)),o.itemForm){o.items=[];var u=t.stringify(o.key),c=f[u];e.forEach(c.items,function(t){var r=e.copy(o.itemForm);r.key=t.key,o.items.push(r)})}if(o.key){var m=t.stringify(o.key);if(f[m]){var d=f[m];e.forEach(d,function(e,t){void 0===o[t]&&(o[t]=d[t])})}}return l===!0&&(o.readonly=!0),o.items&&(o.items=n.merge(r,o.items,a,s,o.readonly)),o.tabs&&e.forEach(o.tabs,function(e){e.items=n.merge(r,e.items,a,s,o.readonly)}),"checkbox"===o.type&&e.isUndefined(o.schema["default"])&&(o.schema["default"]=!1),o}))},n.defaults=function(t,n,i){var a=[],s={};if(n=n||{},i=i||{},"object"!==r(t.type))throw new Error('Not implemented. Only type "object" allowed at root level of schema.');return e.forEach(t.properties,function(e,r){if(n[r]!==!0){var l=t.required&&-1!==t.required.indexOf(r),u=o(r,e,{path:[r],lookup:s,ignore:n,required:l,global:i});u&&a.push(u)}}),{form:a,lookup:s}},n.traverseSchema=function(t,r,n,i){i=e.isDefined(i)?i:!0,n=n||[];var o=function(t,r,n){if(r(t,n),e.forEach(t.properties,function(e,t){var i=n.slice();i.push(t),o(e,r,i)}),!i&&t.items){var a=n.slice();a.push(""),o(t.items,r,a)}};o(t,r,n||[])},n.traverseForm=function(t,r){r(t),e.forEach(t.items,function(e){n.traverseForm(e,r)}),t.tabs&&e.forEach(t.tabs,function(t){e.forEach(t.items,function(e){n.traverseForm(e,r)})})},n}}]),e.module("schemaForm").factory("sfValidator",[function(){var t={};return t.validate=function(t,n){if(!t)return{valid:!0};var i=t.schema;if(!i)return{valid:!0};""===n&&(n=void 0),"number"===t.type&&null===n&&(n=void 0);var o={type:"object",properties:{}},a=t.key[t.key.length-1];o.properties[a]=i,t.required&&(o.required=[a]);var s={};return e.isDefined(n)&&(s[a]=n),r.validateResult(s,o)},t}]),e.module("schemaForm").directive("sfArray",["sfSelect","schemaForm","sfValidator","sfPath",function(t,r,n,i){var o=function(e){return function(t){t.key&&(t.key[t.key.indexOf("")]=e)}};return{restrict:"A",scope:!0,require:"?ngModel",link:function(a,s,l,u){var c={};u&&a.$emit("schemaFormPropagateNgModelController",u);var f=a.$watch(l.sfArray,function(s){var l=t(s.key,a.model);if(a.$watch("model"+i.normalize(s.key),function(){l=t(s.key,a.model),a.modelArray=l}),e.isUndefined(l)&&(l=[],t(s.key,a.model,l)),a.modelArray=l,s.items){var m=s.items[0];s.items.length>1&&(m={type:"section",items:s.items.map(function(t){return t.ngModelOptions=s.ngModelOptions,e.isUndefined(t.readonly)&&(t.readonly=s.readonly),t})})}if(a.copyWithIndex=function(t){if(!c[t]&&m){var n=e.copy(m);n.arrayIndex=t,r.traverseForm(n,o(t)),c[t]=n}return c[t]},a.appendToArray=function(){var n=l.length,i=a.copyWithIndex(n);if(r.traverseForm(i,function(r){if(r.key){var n;e.isDefined(r["default"])&&(n=r["default"]),e.isDefined(r.schema)&&e.isDefined(r.schema["default"])&&(n=r.schema["default"]),e.isDefined(n)&&t(r.key,a.model,n)}}),n===l.length){var o,u=t("schema.items.type",s);"object"===u?o={}:"array"===u&&(o=[]),l.push(o)}return a.validateArray&&a.validateArray(),l},a.deleteFromArray=function(e){return l.splice(e,1),a.validateArray&&a.validateArray(),u&&u.$setDirty&&u.$setDirty(),l},s.titleMap||s.startEmpty===!0||0!==l.length||a.appendToArray(),s.titleMap&&s.titleMap.length>0){a.titleMapValues=[];var d=function(e){a.titleMapValues=[],e=e||[],s.titleMap.forEach(function(t){a.titleMapValues.push(-1!==e.indexOf(t.value))})};d(a.modelArray),a.$watchCollection("modelArray",d),a.$watchCollection("titleMapValues",function(e){if(e){for(var t=a.modelArray;t.length>0;)t.pop();s.titleMap.forEach(function(r,n){e[n]&&t.push(r.value)})}})}if(u){var h;a.validateArray=function(){var e=n.validate(s,a.modelArray.length>0?a.modelArray:void 0);Object.keys(u.$error).filter(function(e){return 0===e.indexOf("tv4-")}).forEach(function(e){u.$setValidity(e,!0)}),e.valid!==!1||!e.error||""!==e.error.dataPath&&e.error.dataPath!=="/"+s.key[s.key.length-1]||(u.$setViewValue(a.modelArray),h=e.error,u.$setValidity("tv4-"+e.error.code,!1))},a.$on("schemaFormValidate",a.validateArray),a.hasSuccess=function(){return u.$valid&&!u.$pristine},a.hasError=function(){return u.$invalid},a.schemaError=function(){return h}}f()})}}}]),e.module("schemaForm").directive("sfChanged",function(){return{require:"ngModel",restrict:"AC",scope:!1,link:function(t,r,n,i){var o=t.$eval(n.sfChanged);o&&o.onChange&&i.$viewChangeListeners.push(function(){e.isFunction(o.onChange)?o.onChange(i.$modelValue,o):t.evalExpr(o.onChange,{modelValue:i.$modelValue,form:o})})}}}),e.module("schemaForm").directive("sfMessage",["$injector","sfErrorMessage",function(e,t){return{scope:!1,restrict:"EA",link:function(r,n,i){var o=e.has("$sanitize")?e.get("$sanitize"):function(e){return e},a="";i.sfMessage&&(a=r.$eval(i.sfMessage)||"",a=o(a));var s=function(e){if(e&&!r.hasError())n.html(a);else{var i=Object.keys(r.ngModel&&r.ngModel.$error||{}),o=i[0];n.html(o?t.interpolate(o,r.ngModel.$modelValue,r.ngModel.$viewValue,r.form,r.options&&r.options.validationMessage):a)}};s(),r.$watchCollection("ngModel.$error",function(){r.ngModel&&s(r.ngModel.$valid)})}}}]),e.module("schemaForm").directive("sfSchema",["$compile","schemaForm","schemaFormDecorators","sfSelect","sfPath",function(t,r,n,i,o){var a=/[A-Z]/g,s=function(e,t){return t=t||"_",e.replace(a,function(e,r){return(r?t:"")+e.toLowerCase()})};return{scope:{schema:"=sfSchema",initialForm:"=sfForm",model:"=sfModel",options:"=sfOptions"},controller:["$scope",function(e){this.evalInParentScope=function(t,r){return e.$parent.$eval(t,r)}}],replace:!1,restrict:"A",transclude:!0,require:"?form",link:function(a,l,u,c,f){a.formCtrl=c;var m={};f(a,function(e){if(e.addClass("schema-form-ignore"),l.prepend(e),l[0].querySelectorAll){var t=l[0].querySelectorAll("[ng-model]");if(t)for(var r=0;r<t.length;r++){var n=t[r].getAttribute("ng-model");m[n.substring(n.indexOf(".")+1)]=!0}}});var d,h={},p=function(c,f){var h=r.merge(c,f,m,a.options),p=document.createDocumentFragment();d&&d.$destroy(),d=a.$new(),d.schemaForm={form:h,schema:c},l.children(":not(.schema-form-ignore)").remove();for(var v={},y=l[0].querySelectorAll("*[sf-insert-field]"),g=0;g<y.length;g++)v[y[g].getAttribute("sf-insert-field")]=y[g];e.forEach(h,function(e,t){var r=document.createElement(u.sfUseDecorator||s(n.defaultDecorator,"-"));if(r.setAttribute("form","schemaForm.form["+t+"]"),e.key){var i=v[o.stringify(e.key)];if(i){for(;i.firstChild;)i.removeChild(i.firstChild);return void i.appendChild(r)}}p.appendChild(r)}),l[0].appendChild(p),t(l.children())(d),r.traverseSchema(c,function(t,r){if(e.isDefined(t["default"])){var n=i(r,a.model);e.isUndefined(n)&&i(r,a.model,t["default"])}}),a.$emit("sf-render-finished",l)};a.$watch(function(){var e=a.schema,t=a.initialForm||["*"];t&&e&&e.type&&(h.form!==t||h.schema!==e)&&Object.keys(e.properties).length>0&&(h.schema=e,h.form=t,p(e,t))}),a.$on("schemaFormRedraw",function(){var e=a.schema,t=a.initialForm||["*"];e&&p(e,t)})}}}]),e.module("schemaForm").directive("schemaValidate",["sfValidator","sfSelect",function(t,r){return{restrict:"A",scope:!1,priority:500,require:"ngModel",link:function(n,i,o,a){n.$emit("schemaFormPropagateNgModelController",a);var s=null,l=function(){return u||(u=n.$eval(o.schemaValidate)),u},u=l();u.copyValueTo&&a.$viewChangeListeners.push(function(){var t=u.copyValueTo;e.forEach(t,function(e){r(e,n.model,a.$modelValue)})});var c=function(e){if(u=l(),!u)return e;if(n.options&&n.options.tv4Validation===!1)return e;var r=t.validate(u,e);return Object.keys(a.$error).filter(function(e){return 0===e.indexOf("tv4-")}).forEach(function(e){a.$setValidity(e,!0)}),r.valid?e:(a.$setValidity("tv4-"+r.error.code,!1),void(s=r.error))};"function"==typeof u.ngModel&&u.ngModel(a),["$parsers","$viewChangeListeners","$formatters"].forEach(function(e){u[e]&&a[e]&&u[e].forEach(function(t){a[e].push(t)})}),["$validators","$asyncValidators"].forEach(function(t){u[t]&&a[t]&&e.forEach(u[t],function(e,r){a[t][r]=e})}),a.$parsers.push(c),n.$on("schemaFormValidate",function(){a.$setDirty?(a.$setDirty(),c(a.$modelValue)):a.$setViewValue(a.$viewValue)}),n.schemaError=function(){return s}}}}]),o}); |
@@ -252,4 +252,4 @@ Documentation | ||
### Message Interpolation | ||
Having a good validation message is hard, sometimes you need to reference the actual value, title | ||
och constraint that you hit. Schema Form supports interpolation of error messages to make this a | ||
Having a good validation message is hard, sometimes you need to reference the actual value, title, | ||
or constraint that you hit. Schema Form supports interpolation of error messages to make this a | ||
little bit easier. | ||
@@ -264,2 +264,3 @@ | ||
| value | The model value | | ||
| viewValue | The view value (probably the one you want) | | ||
| form | form definition object for this field | | ||
@@ -627,2 +628,4 @@ | schema | schema for this field | | ||
feedback: false, // Inline feedback icons | ||
disableSuccessState: false, // Set true to NOT apply 'has-success' class to a field that was validated successfully | ||
disableErrorState: false, // Set true to NOT apply 'has-error' class to a field that failed validation | ||
placeholder: "Input...", // placeholder on inputs and textarea | ||
@@ -634,2 +637,3 @@ ngModelOptions: { ... }, // Passed along to ng-model-options | ||
fieldHtmlClass: "street" // CSS Class(es) to be added to field input (or similar) | ||
labelHtmlClass: "street" // CSS Class(es) to be added to the label of the field (or similar) | ||
copyValueTo: ["address.street"], // Copy values to these schema keys. | ||
@@ -733,5 +737,5 @@ condition: "person.age < 18" // Show or hide field depending on an angular expression | ||
the field will be rendered into the DOM otherwise not. The expression is evaluated in the parent scope of | ||
the `sf-schema` directive (the same as onClick on buttons) but with access to the current model | ||
and current array index under the name `model` and `arrayIndex`. This is useful for hiding/showing | ||
parts of a form depending on another form control. | ||
the `sf-schema` directive (the same as onClick on buttons) but with access to the current model, | ||
current model value and current array index under the name `model`, `modelValue` and `arrayIndex`. | ||
This is useful for hiding/showing parts of a form depending on another form control. | ||
@@ -766,4 +770,4 @@ ex. A checkbox that shows an input field for a code when checked | ||
{ | ||
key: "code", | ||
condition: "person.eligible", //or "model.eligable" | ||
"key": "code", | ||
"condition": "person.eligible", //or "model.eligible" | ||
} | ||
@@ -770,0 +774,0 @@ ] |
var gulp = require('gulp'), | ||
concat = require('gulp-concat'), | ||
rename = require('gulp-rename'), | ||
umd = require('gulp-umd'), | ||
uglify = require('gulp-uglify'); | ||
@@ -14,2 +15,13 @@ | ||
.pipe(concat('schema-form.js')) | ||
.pipe(umd({ | ||
dependencies: function() { | ||
return [ | ||
{name: 'angular'}, | ||
{name: 'ObjectPath'}, | ||
{name: 'tv4'}, | ||
] | ||
}, | ||
exports: function() {return 'schemaForm';}, | ||
namespace: function() {return 'schemaForm';} | ||
})) | ||
.pipe(gulp.dest('./dist/')) | ||
@@ -16,0 +28,0 @@ .pipe(uglify()) |
{ | ||
"name": "angular-schema-form", | ||
"version": "0.8.0", | ||
"version": "0.8.2", | ||
"description": "Create complex forms from a JSON schema with angular.", | ||
@@ -14,5 +14,5 @@ "repository": "Textalk/angular-schema-form", | ||
"David Jensen <david.lgj@gmail.com> (https://github.com/davidlgj)", | ||
"Denis Dervisevic <denis@dervisevic.se> (https://github.com/Dervisevic)", | ||
"Cameron Edwards (https://github.com/cameronprattedwards)", | ||
"Mike Marcacci (https://github.com/mike-marcacci)", | ||
"Denis Dervisevic <denis@dervisevic.se> (https://github.com/Dervisevic)" | ||
"Mike Marcacci (https://github.com/mike-marcacci)" | ||
], | ||
@@ -42,4 +42,6 @@ "license": "MIT", | ||
"gulp-minify-html": "^0.1.1", | ||
"gulp-protractor": "^1.0.0", | ||
"gulp-rename": "^1.2.0", | ||
"gulp-uglify": "^0.2.1", | ||
"gulp-umd": "^0.1.3", | ||
"karma": "^0.12.0", | ||
@@ -54,2 +56,3 @@ "karma-chai-sinon": "^0.1.3", | ||
"mocha-lcov-reporter": "0.0.1", | ||
"protractor": "^2.0.0", | ||
"sinon": "^1.9.0", | ||
@@ -56,0 +59,0 @@ "sinon-chai": "^2.5.0", |
@@ -1,2 +0,2 @@ | ||
Angular Schema Form [![alt text][1.1]][1] | ||
Angular Schema Form | ||
=================== | ||
@@ -11,11 +11,12 @@ [![Build Status](https://travis-ci.org/Textalk/angular-schema-form.svg?branch=master)](https://travis-ci.org/Textalk/angular-schema-form) | ||
Web Page | ||
Web Page / Twitter | ||
-------- | ||
[schemaform.io](http://schemaform.io) | ||
[schemaform.io](http://schemaform.io) / [@SchemaFormIO](http://twitter.com/SchemaFormIO) | ||
Demo Time! | ||
---------- | ||
[Try out the example page](http://textalk.github.io/angular-schema-form/examples/bootstrap-example.html). | ||
Try editing the schema or form definition and see what comes out! | ||
[Try out the example page](http://schemaform.io/examples/bootstrap-example.html). Try editing the schema or form definition and see what comes out! | ||
Now you can save your code and share it! | ||
What is it? | ||
@@ -204,6 +205,1 @@ ---------- | ||
``` | ||
<!-- Please don't remove this: Grab your social icons from https://github.com/carlsednaoui/gitsocial --> | ||
[1.1]: http://i.imgur.com/tXSoThF.png (twitter icon with padding) | ||
[1]: http://www.twitter.com/ngSchemaForm | ||
[1.2]: http://i.imgur.com/wWzX9uB.png (twitter icon without padding) |
@@ -20,3 +20,3 @@ angular.module('schemaForm').directive('sfMessage', | ||
var update = function(valid) { | ||
if (valid && scope.hasError()) { | ||
if (valid && !scope.hasError()) { | ||
element.html(msg); | ||
@@ -31,16 +31,4 @@ } else { | ||
// TODO: Make that optional | ||
// tv4- errors take precedence | ||
var error = errors[0]; | ||
if (errors.length > 1) { | ||
error = errors.reduce(function(prev, value) { | ||
if (prev && prev.indexOf('tv4-') === 0) { | ||
return prev; | ||
} | ||
return value; | ||
}); | ||
console.log('reduced',errors, error) | ||
} | ||
if (error) { | ||
@@ -50,2 +38,3 @@ element.html(sfErrorMessage.interpolate( | ||
scope.ngModel.$modelValue, | ||
scope.ngModel.$viewValue, | ||
scope.form, | ||
@@ -52,0 +41,0 @@ scope.options && scope.options.validationMessage |
@@ -44,2 +44,7 @@ angular.module('schemaForm').directive('schemaValidate', ['sfValidator', 'sfSelect', function(sfValidator, sfSelect) { | ||
// Omit TV4 validation | ||
if (scope.options && scope.options.tv4Validation === false) { | ||
return viewValue; | ||
} | ||
var result = sfValidator.validate(form, viewValue); | ||
@@ -46,0 +51,0 @@ // Since we might have different tv4 errors we must clear all |
@@ -23,2 +23,2 @@ // Deps is sort of a problem for us, maybe in the future we will ask the user to depend | ||
angular.module('schemaForm', deps); | ||
var schemaForm = angular.module('schemaForm', deps); |
@@ -34,4 +34,4 @@ angular.module('schemaForm').provider('schemaFormDecorators', | ||
$compileProvider.directive(name, | ||
['$parse', '$compile', '$http', '$templateCache', '$interpolate', '$q', 'sfErrorMessage', | ||
function($parse, $compile, $http, $templateCache, $interpolate, $q, sfErrorMessage) { | ||
['$parse', '$compile', '$http', '$templateCache', '$interpolate', '$q', 'sfErrorMessage', 'sfPath', | ||
function($parse, $compile, $http, $templateCache, $interpolate, $q, sfErrorMessage, sfPath) { | ||
@@ -163,2 +163,3 @@ return { | ||
(scope.ngModel && scope.ngModel.$modelValue) || '', | ||
(scope.ngModel && scope.ngModel.$viewValue) || '', | ||
scope.form, | ||
@@ -208,2 +209,8 @@ scope.options && scope.options.validationMessage | ||
if (form.condition) { | ||
var evalExpr = 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex})'; | ||
if (form.key) { | ||
evalExpr = 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex, "modelValue": model' + sfPath.stringify(form.key) + '})'; | ||
} | ||
angular.forEach(element.children(), function(child) { | ||
@@ -215,8 +222,7 @@ var ngIf = child.getAttribute('ng-if'); | ||
'(' + ngIf + | ||
') || (evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex }))' | ||
: 'evalExpr(form.condition,{ model: model, "arrayIndex": arrayIndex })' | ||
') || (' + evalExpr +')' | ||
: evalExpr | ||
); | ||
}); | ||
} | ||
$compile(element.contents())(scope); | ||
@@ -251,3 +257,2 @@ }); | ||
} | ||
console.log('settings validationMessage', validationMessage) | ||
form.validationMessage[error] = validationMessage; | ||
@@ -258,5 +263,7 @@ } | ||
// Setting or removing a validity can change the field to believe its valid | ||
// but its not. So lets trigger its validation as well. | ||
scope.$broadcast('schemaFormValidate'); | ||
if (validity === true) { | ||
// Setting or removing a validity can change the field to believe its valid | ||
// but its not. So lets trigger its validation as well. | ||
scope.$broadcast('schemaFormValidate'); | ||
} | ||
} | ||
@@ -263,0 +270,0 @@ }) |
@@ -10,3 +10,3 @@ angular.module('schemaForm').provider('sfErrorMessage', function() { | ||
'default': 'Field does not validate', | ||
0: 'Invalid type, expected {{schema.type}})', | ||
0: 'Invalid type, expected {{schema.type}}', | ||
1: 'No enum match for: {{value}}', | ||
@@ -18,15 +18,15 @@ 10: 'Data does not match any schemas from "anyOf"', | ||
// Numeric errors | ||
100: 'Value {{value}} is not a multiple of {{schema.multipleOf}}', | ||
101: 'Value {{value}} is less than minimum {{schema.minimum}}', | ||
102: 'Value {{value}} is equal to exclusive minimum {{schema.minimum}}', | ||
103: 'Value {{value}} is greater than maximum {{schema.maximum}}', | ||
104: 'Value {{value}} is equal to exclusive maximum {{schema.maximum}}', | ||
105: 'Value {{value}} is not a valid number', | ||
100: 'Value is not a multiple of {{schema.divisibleBy}}', | ||
101: '{{viewValue}} is less than the allowed minimum of {{schema.minimum}}', | ||
102: '{{viewValue}} is equal to the exclusive minimum {{schema.minimum}}', | ||
103: '{{viewValue}} is greater than the allowed maximum of {{schema.maximum}}', | ||
104: '{{viewValue}} is equal to the exclusive maximum {{schema.maximum}}', | ||
105: 'Value is not a valid number', | ||
// String errors | ||
200: 'String is too short ({{value.length}} chars), minimum {{schema.minimum}}', | ||
201: 'String is too long ({{value.length}} chars), maximum {{schema.maximum}}', | ||
200: 'String is too short ({{viewValue.length}} chars), minimum {{schema.minLength}}', | ||
201: 'String is too long ({{viewValue.length}} chars), maximum {{schema.maxLength}}', | ||
202: 'String does not match pattern: {{schema.pattern}}', | ||
// Object errors | ||
300: 'Too few properties defined, minimum {{schema.minimum}}', | ||
301: 'Too many properties defined, maximum {{schema.maximum}}', | ||
300: 'Too few properties defined, minimum {{schema.minProperties}}', | ||
301: 'Too many properties defined, maximum {{schema.maxProperties}}', | ||
302: 'Required', | ||
@@ -36,4 +36,4 @@ 303: 'Additional properties not allowed', | ||
// Array errors | ||
400: 'Array is too short ({{value.length}}), minimum {{schema.minimum}}', | ||
401: 'Array is too long ({{value.length}}), maximum {{schema.maximum}}', | ||
400: 'Array is too short ({{value.length}}), minimum {{schema.maxItems}}', | ||
401: 'Array is too long ({{value.length}}), maximum {{schema.minItems}}', | ||
402: 'Array items are not unique', | ||
@@ -50,2 +50,11 @@ 403: 'Additional items not allowed', | ||
// In some cases we get hit with an angular validation error | ||
defaultMessages.number = defaultMessages[105]; | ||
defaultMessages.required = defaultMessages[302]; | ||
defaultMessages.min = defaultMessages[101]; | ||
defaultMessages.max = defaultMessages[103]; | ||
defaultMessages.maxlength = defaultMessages[201]; | ||
defaultMessages.minlength = defaultMessages[200]; | ||
defaultMessages.pattern = defaultMessages[202]; | ||
this.setDefaultMessages = function(messages) { | ||
@@ -75,2 +84,3 @@ defaultMessages = messages; | ||
* @param {Any} value the actual model value. | ||
* @param {Any} viewValue the viewValue | ||
* @param {Object} form a form definition object for this field | ||
@@ -81,3 +91,3 @@ * @param {Object} global the global validation messages object (even though its called global | ||
*/ | ||
service.interpolate = function(error, value, form, global) { | ||
service.interpolate = function(error, value, viewValue, form, global) { | ||
global = global || {}; | ||
@@ -108,2 +118,3 @@ var validationMessage = form.validationMessage || {}; | ||
value: value, | ||
viewValue: viewValue, | ||
form: form, | ||
@@ -110,0 +121,0 @@ schema: form.schema, |
@@ -1826,3 +1826,172 @@ chai.should(); | ||
//generate disableSuccessState, disableErrorState tests for each field | ||
var fields = [ | ||
{ | ||
name: 'default', | ||
property: { | ||
type: 'string', | ||
pattern: "^[a-zA-Z]+$" | ||
}, | ||
form: { | ||
key: ['field'] | ||
} | ||
}, | ||
{ | ||
name: 'textarea', | ||
property: { | ||
type: 'string', | ||
pattern: "^[a-zA-Z]+$" | ||
}, | ||
form: { | ||
key: ['field'], | ||
type: 'textarea' | ||
} | ||
}, | ||
{ | ||
name: 'checkbox', | ||
property: { | ||
type: 'boolean' | ||
}, | ||
form: { | ||
key: ["field"] | ||
} | ||
}, | ||
{ | ||
name: 'radio buttons', | ||
property: { | ||
type: 'boolean', | ||
}, | ||
form: { | ||
key: ["field"], | ||
type: "radiobuttons", | ||
titleMap: [ | ||
{ | ||
"value": false, | ||
"name": "No way" | ||
}, | ||
{ | ||
"value": true, | ||
"name": "OK" | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
name: 'radios inline', | ||
property: { | ||
type: 'boolean', | ||
}, | ||
form: { | ||
key: ["field"], | ||
type: "radios-inline", | ||
titleMap: [ | ||
{ | ||
"value": false, | ||
"name": "No way" | ||
}, | ||
{ | ||
"value": true, | ||
"name": "OK" | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
name: 'radios', | ||
property: { | ||
type: 'boolean', | ||
}, | ||
form: { | ||
key: ["field"], | ||
type: "radios", | ||
titleMap: [ | ||
{ | ||
"value": false, | ||
"name": "No way" | ||
}, | ||
{ | ||
"value": true, | ||
"name": "OK" | ||
} | ||
] | ||
} | ||
}, | ||
{ | ||
name: 'select', | ||
property: { | ||
type: 'boolean', | ||
}, | ||
form: { | ||
key: ["field"], | ||
type: "select", | ||
titleMap: [ | ||
{ | ||
"value": false, | ||
"name": "No way" | ||
}, | ||
{ | ||
"value": true, | ||
"name": "OK" | ||
} | ||
] | ||
} | ||
} | ||
]; | ||
}); | ||
fields.forEach(function (field) { | ||
it('should not add "has-success" class to ' + field.name + " field if a correct value is entered, but disableSuccessState is set on form", function () { | ||
inject(function($compile, $rootScope){ | ||
var scope = $rootScope.$new(); | ||
scope.model = {} | ||
scope.schema = { | ||
type: 'object', | ||
properties: { | ||
field: field.property | ||
} | ||
}; | ||
scope.form = [field.form]; | ||
var tmpl = angular.element('<form name="theForm" sf-schema="schema" sf-form="form" sf-model="model"></form>'); | ||
$compile(tmpl)(scope); | ||
$rootScope.$apply(); | ||
var ngModelCtrl = scope.theForm['{{form.key.slice(-1)[0]}}'] || scope.theForm['{{form.key.join(\'.\')}}']; | ||
ngModelCtrl.$valid = true; | ||
ngModelCtrl.$pristine = false; | ||
$rootScope.$apply(); | ||
tmpl.children().eq(0).children().eq(0).hasClass('has-success').should.be.true; | ||
scope.form[0].disableSuccessState = true; | ||
$rootScope.$apply(); | ||
tmpl.children().eq(0).children().eq(0).hasClass('has-success').should.be.false; | ||
}); | ||
}); | ||
it('should not add "has-error" class to ' + field.name + " field if invalid value is entered, but disableErrorState is set on form", function () { | ||
inject(function($compile, $rootScope){ | ||
var scope = $rootScope.$new(); | ||
scope.model = { | ||
field: field.errorValue | ||
} | ||
scope.schema = { | ||
type: 'object', | ||
properties: { | ||
field: field.property | ||
} | ||
}; | ||
scope.form = [field.form]; | ||
var tmpl = angular.element('<form name="theForm" sf-schema="schema" sf-form="form" sf-model="model"></form>'); | ||
$compile(tmpl)(scope); | ||
$rootScope.$apply(); | ||
var ngModelCtrl = scope.theForm['{{form.key.slice(-1)[0]}}'] || scope.theForm['{{form.key.join(\'.\')}}']; | ||
ngModelCtrl.$invalid = true; | ||
ngModelCtrl.$pristine = false; | ||
$rootScope.$apply(); | ||
tmpl.children().eq(0).children().eq(0).hasClass('has-error').should.be.true; | ||
scope.form[0].disableErrorState = true; | ||
$rootScope.$apply(); | ||
tmpl.children().eq(0).children().eq(0).hasClass('has-error').should.be.false; | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -13,2 +13,3 @@ chai.should(); | ||
'foobar', //value | ||
'foobar', //view value | ||
{schema: {title: 'Foo'}}, //form | ||
@@ -29,2 +30,3 @@ {'default': 'Oh noes!'} | ||
'foobar', //value | ||
'foobar', //view value | ||
{validationMessage: {'default': 'Oh yes!'}, schema: {title: 'Foo'}}, //form | ||
@@ -45,2 +47,3 @@ {'default': 'Oh noes!'} | ||
'foobar', //value | ||
'foobar', //view value | ||
{schema: {title: 'Foo'}}, //form | ||
@@ -60,2 +63,3 @@ {'default': 'Oh noes!', 'foobar-error': 'Aw chucks!'} | ||
'foobar', //value | ||
'foobar', //view value | ||
{schema: {title: 'Foo'}, validationMessage: {'foobar-error': 'Noooooo!'}}, //form | ||
@@ -75,2 +79,3 @@ {'default': 'Oh noes!', 'foobar-error': 'Aw chucks!'} | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -95,2 +100,3 @@ schema: {title: 'Foo'}, | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -110,2 +116,3 @@ schema: {title: 'Foo'}, | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -131,2 +138,3 @@ title: 'Bar', | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -151,2 +159,3 @@ schema: {title: 'Foo'}, | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -166,2 +175,3 @@ schema: {title: 'Foo'}, | ||
value: 'foobar', | ||
viewValue: 'foobar', | ||
form: { | ||
@@ -187,2 +197,3 @@ schema: {title: 'Foo'}, | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -200,2 +211,3 @@ schema: {title: 'Foo'}, | ||
value: 'foobar', | ||
viewValue: 'foobar', | ||
form: { | ||
@@ -216,3 +228,4 @@ schema: {title: 'Foo'}, | ||
'tv4-302', //error | ||
'foobar', //value | ||
'foobar', //value | ||
'foobar', //view value | ||
{ | ||
@@ -219,0 +232,0 @@ schema: {title: 'Foo'}, |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 6 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5046129
281
75311
24
1
5
204
23
7