forms-angular 0.12.0-beta.168 → 0.12.0-beta.171

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,17 +111,25 @@ var fng;
111
111
  }
112
112
  var attrib = attrs['fld'];
113
113
  var watchExpression;
114
- if (scope.$parent.subDoc && scope.$parent.subDoc[attrib]) {
114
+ var splitAttrib = attrib.split('.');
115
+ if (scope.$parent.subDoc && (scope.$parent.subDoc[attrib] || scope.$parent.subDoc[splitAttrib[splitAttrib.length - 1]])) {
115
116
  // Support for use in directives in arrays
116
- watchExpression = workString + 'subDoc.' + attrib;
117
+ if (scope.$parent.subDoc[attrib]) {
118
+ watchExpression = workString + 'subDoc.' + attrib;
119
+ }
120
+ else {
121
+ watchExpression = workString + 'subDoc.' + splitAttrib[splitAttrib.length - 1];
122
+ }
117
123
  }
118
124
  else {
119
125
  if (typeof workScope['$index'] !== "undefined") {
120
- var splitAttrib = attrib.split('.');
121
126
  attrib = splitAttrib.pop();
122
127
  attrib = splitAttrib.join('.') + '[' + workScope['$index'] + '].' + attrib;
123
128
  }
124
- watchExpression = workString + 'record.' + attrib;
129
+ else {
130
+ attrib = '.' + attrib;
131
+ }
132
+ watchExpression = workString + 'record' + attrib;
125
133
  }
126
134
  scope.$watch(watchExpression, function (newVal) {
127
135
  if (newVal) {
@@ -708,6 +716,15 @@ var fng;
708
716
  }
709
717
  template += '</div> ';
710
718
  }
719
+ var parts = void 0;
720
+ if (info.subDocContainerType) {
721
+ var containerType = scope[info.subDocContainerType] || info.subDocContainerType;
722
+ var containerProps = Object.assign({ containerType: containerType }, info.subDocContainerProps);
723
+ parts = containerInstructions(containerProps);
724
+ }
725
+ if (parts === null || parts === void 0 ? void 0 : parts.before) {
726
+ template += parts.before;
727
+ }
711
728
  template += processInstructions(info.schema, false, {
712
729
  subschema: 'true',
713
730
  formstyle: info.formStyle,
@@ -715,6 +732,9 @@ var fng;
715
732
  subschemaroot: info.name,
716
733
  suppressNestingWarning: info.suppressNestingWarning
717
734
  });
735
+ if (parts === null || parts === void 0 ? void 0 : parts.after) {
736
+ template += parts.after;
737
+ }
718
738
  if (cssFrameworkService.framework() === 'bs2') {
719
739
  template += ' </div>';
720
740
  }
@@ -727,7 +747,7 @@ var fng;
727
747
  footer = info.customFooter;
728
748
  }
729
749
  var hideCond = '';
730
- var indicatorShowCond = options.model + "." + info.name + ".length == 0";
750
+ var indicatorShowCond = model + ".length == 0";
731
751
  if (info.noAdd === true) {
732
752
  indicatorShowCond = "ng-show=\"" + indicatorShowCond + "\"";
733
753
  }
@@ -739,7 +759,7 @@ var fng;
739
759
  if (info.noneIndicator) {
740
760
  footer += "<span " + indicatorShowCond + " class=\"none_indicator\" id=\"no_" + info.id + "_indicator\">None</span>";
741
761
  // hideCond for the schema-foot is if there's no add button and no indicator
742
- hideCond = options.model + "." + info.name + ".length > 0";
762
+ hideCond = model + ".length > 0";
743
763
  if (info.noAdd === true) {
744
764
  hideCond = "ng-hide=\"" + hideCond + "\"";
745
765
  }
@@ -818,7 +838,8 @@ var fng;
818
838
  var callHandleField = true;
819
839
  if (info.directive) {
820
840
  var directiveName = info.directive;
821
- var newElement = '<' + directiveName + ' model="' + (options.model || 'record') + '"';
841
+ var newElement = info.customHeader || "";
842
+ newElement += '<' + directiveName + ' model="' + (options.model || 'record') + '"';
822
843
  var thisElement = element[0];
823
844
  inferMissingProperties(info, options);
824
845
  for (var i = 0; i < thisElement.attributes.length; i++) {
@@ -897,6 +918,7 @@ var fng;
897
918
  }
898
919
  }
899
920
  newElement += 'ng-model="' + info.name + '"></' + directiveName + '>';
921
+ newElement += (info.customFooter || "");
900
922
  result += newElement;
901
923
  callHandleField = false;
902
924
  }
@@ -4557,5 +4579,5 @@ $templateCache.put('error-display-bs3.html','<div id="display-error" ng-show="er
4557
4579
  $templateCache.put('error-messages.html','<div ng-message="required">A value is required for this field</div>\n<div ng-message="minlength">Too few characters entered</div>\n<div ng-message="maxlength">Too many characters entered</div>\n<div ng-message="min">That value is too small</div>\n<div ng-message="max">That value is too large</div>\n<div ng-message="email">You need to enter a valid email address</div>\n<div ng-message="pattern">This field does not match the expected pattern</div>\n');
4558
4580
  $templateCache.put('form-button-bs2.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-mini btn-primary form-btn" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="icon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-mini btn-warning form-btn" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="icon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-mini btn-success form-btn" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="icon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-mini btn-danger form-btn" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="icon-minus"></i> Delete</button>\n </div>\n</div>\n');
4559
4581
  $templateCache.put('form-button-bs3.html','<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-primary form-btn btn-xs" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="glyphicon glyphicon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-warning form-btn btn-xs" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="glyphicon glyphicon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-success form-btn btn-xs" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="glyphicon glyphicon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-danger form-btn btn-xs" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="glyphicon glyphicon-minus"></i> Delete</button>\n </div>\n</div>\n');
4560
- $templateCache.put('search-bs2.html','<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');
4561
- $templateCache.put('search-bs3.html','<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');}]);
4582
+ $templateCache.put('search-bs2.html','<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');
4583
+ $templateCache.put('search-bs3.html','<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');}]);
@@ -1 +1 @@
1
- var fng;!function(e){(e.directives||(e.directives={})).modelControllerDropdown=function(){return{restrict:"AE",replace:!0,template:'<li ng-show="items.length > 0" class="mcdd" uib-dropdown> <a href="#" uib-dropdown-toggle> {{contextMenu}} <b class="caret"></b> </a> <ul class="uib-dropdown-menu dropdown-menu"> <li ng-repeat="choice in items" ng-hide="isHidden($index)" ng-class="dropdownClass($index)"> <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event)"> {{choice.text}} </a> </li> </ul></li>'}}}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"E",templateUrl:"error-display-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.errorDisplay=n}(fng=fng||{}),function(e){var t;function n(a){a.checkNotModal=function(){for(var e,t=a.element[0],n=!1,r={preventDefault:angular.noop,stopPropagation:angular.noop,target:1,currentTarget:1};(e=t.parentNode)?"function"==typeof e.getAttribute&&e.getAttribute("uib-modal-window")?(angular.element(t).scope().close(r),n=!0):t=e:n=!0,!n;);}}t=e.controllers||(e.controllers={}),n.$inject=["$scope"],t.LinkCtrl=n}(fng=fng||{}),function(e){var t;function n(p,m){return{restrict:"E",scope:{dataSrc:"&model"},link:function(n,e,r){var a=r.ref,t=r.text&&unescape(r.text)!==r.text,o=r.form,i=r.linktab;if(n.readonly=r.readonly,n.element=e,o=o?o+"/":"",i=i?"/"+i:"",t){for(var s=n,l="";"function"!=typeof s.baseSchema&&s.$parent;){if(void 0!==s.$index)throw new Error("No support for $index at this level - "+l);s=s.$parent,l+="$parent."}var c,d=r.fld;if(n.$parent.subDoc&&n.$parent.subDoc[d])c=l+"subDoc."+d;else{if(void 0!==s.$index){var u=d.split(".");d=u.pop(),d=u.join(".")+"["+s.$index+"]."+d}c=l+"record."+d}n.$watch(c,function(e){if(e){if(/^[a-f0-9]{24}/.test(e.toString()))e=e.slice(0,24);else if(e.id&&/^[a-f0-9]{24}/.test(e.id))e=e.id.slice(0,24);else if(n.$parent["f_"+r.fld+"Options"]){var t=n.$parent["f_"+r.fld+"Options"].indexOf(e);e=-1<t?n.$parent["f_"+r.fld+"_ids"][t]:void 0}else e=void 0;n.link=e?p.buildUrl(a+"/"+o+(e.id||e)+"/edit"+i):void 0}else n.link=void 0},!0)}else{r.text&&0<r.text.length&&(n.text=r.text);var f=n.$parent.$index;n.$watch("dataSrc()",function(e){e&&(void 0!==f&&angular.isArray(e)&&(e=e[f]),n.link=p.buildUrl(a+"/"+o+e+"/edit"+i),n.text||m.getListAttributes(a,e).then(function(e){var t=e.data;!1===t.success?n.text=t.err:n.text=t.list},function(e){n.text="Error "+e.status+": "+e.data}))},!0)}},controller:"LinkCtrl",template:function(e,t){function n(e){return'<a ng-click="checkNotModal()" ng-href="{{ link || \'#\' }}" class="fng-link">'+e+"</a>"}return t.readonly?'<span class="fng-link">{{text}}</span>':t.text&&unescape(t.text)!==t.text?n(unescape(t.text)):n("{{text}}")}}}t=e.directives||(e.directives={}),n.$inject=["routingService","SubmissionsService"],t.fngLink=n}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"A",templateUrl:"form-button-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.formButtons=n}(fng=fng||{}),function(e){var t,O,n;function r(c,d,N,E,L,u,A){return{restrict:"EA",link:function(k,x,s){function h(t,e,n,r,a){function o(){var e;if(angular.isArray(k[t.options]))e={repeat:t.options,value:"option"};else{if(!k[t.options]||!angular.isArray(k[t.options].values))throw new Error("Invalid enumeration setup in field "+t.name);e=angular.isArray(k[t.options].labels)?{repeat:t.options+".values",value:t.options+".values[$index]",label:t.options+".labels[$index]"}:{repeat:t.options+".values",value:t.options+".values[$index]"}}return e}var i;if(!e){var s=(a.model||"record")+".";if(e=s,a.subschema&&-1!==t.name.indexOf(".")){var l=t.name,c=a.subschemaroot,d=l.slice(c.length+1);a.index?r="f_"+(e+=c+"["+a.index+"]."+d).slice(s.length).replace(/(\.|\[|]\.)/g,"-"):(e+=c,a.subkey?(r=e.slice(s.length).replace(/\./g,"-")+"-subkey"+a.subkeyno+"-"+d,e+="[$_arrayOffset_"+c.replace(/\./g,"_")+"_"+a.subkeyno+"]."+d):(e+="[$index]."+d,r=null,i=l.replace(/\./g,"-")))}else e+=t.name}var u,f,p=A.allInputsVars(k,t,a,e,r,i),m=p.common,h=(n=n||t.required)?" required ":"";function v(e){var t="";return e&&(t="boolean"==typeof e?" disabled ":' ng-disabled="'+e+'" '),t}switch(t.type){case"select":t.select2?u='<input placeholder="fng-select2 has been removed" readonly>':(m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",m+=' aria-label="'+(t.label&&""!==t.label?t.label:t.name)+'" ',u="<select "+m+'class="'+p.formControl.trim()+p.compactClass+p.sizeClassBS2+'" '+h+">",n||(u+="<option></option>"),angular.isArray(t.options)?angular.forEach(t.options,function(e){_.isObject(e)?u+='<option value="'+(e.val||e.id)+'">'+(e.label||e.text)+"</option>":u+="<option>"+e+"</option>"}):(f=o(),u+='<option ng-repeat="option in '+f.repeat+'"',f.label?u+=' value="{{'+f.value+'}}"> {{ '+f.label+" }} </option> ":u+=">{{"+f.value+"}}</option> "),u+="</select>");break;case"link":u='<fng-link model="'+e+'" ref="'+t.ref+'"',t.form&&(u+=' form="'+t.form+'"'),t.linktab&&(u+=' linktab="'+t.linktab+'"'),t.linktext&&(u+=' text="'+t.linktext+'"'),t.readonly&&("boolean"==typeof t.readonly?u+=' readonly="true"':u+=' ng-readonly="'+t.readonly+'"'),u+="></fng-link>";break;case"radio":u="",m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"";var g="vertical"===a.formstyle||"inline"!==a.formstyle&&!t.inlineRadio;if(angular.isArray(t.options)){var b;a.subschema&&(m=(m=m.replace('name="','name="{{$index}}-')).replace('id="','id="{{$index}}-')),angular.forEach(t.options,function(e,t){b=m.replace('id="','id="'+t+"-"),u+="<input "+b+' type="radio" aria-label="'+e+'" value="'+e+'">'+e,g&&(u+="<br />")})}else{var y=g?"div":"span";a.subschema&&(m=m.replace("$index","$parent.$index").replace('name="','name="{{$parent.$index}}-').replace('id="','id="{{$parent.$index}}-')),f=o(),u+="<"+y+' ng-repeat="option in '+f.repeat+'">',u+="<input "+m.replace('id="','id="{{$index}}-')+' type="radio" aria-label="'+f.value+'" value="{{ '+f.value+' }}"> {{ '+(f.label||f.value)+" }} </"+y+"> "}break;case"checkbox":m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",u=A.generateSimpleInput(m,t,a),"bs3"===L.framework()&&(u='<div class="checkbox">'+u+"</div>");break;default:m+=A.addTextInputMarkup(p,t,h),u="textarea"===t.type?(t.rows&&("auto"===t.rows?m+='msd-elastic="\n" class="ng-animate" ':m+='rows = "'+t.rows+'" '),"ckEditor"===t.editor&&(console.log('Deprecation Warning: "editor" property deprecated - use "add"'),m+='ckeditor = "" ',"bs3"===L.framework()&&(p.sizeClassBS3="col-xs-12")),"<textarea "+m+"></textarea>"):A.generateSimpleInput(m,t,a)}return A.inputChrome(u,t,a,p)}function v(e){var t;switch(e){case"horizontal":t="form-horizontal";break;case"vertical":t="";break;case"inline":t="form-inline";break;case"stacked":t="form-stacked";break;case"horizontalCompact":default:t="form-horizontal compact"}return t}function $(e){var t={before:"",after:""};if("function"==typeof e.containerType)t=e.containerType(e);else switch(e.containerType){case"tab":for(var n=-1,r=0;r<k.tabs.length;r++)if(k.tabs[r].title===e.title){n=r;break}0<=n?(t.before='<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\''+e.title+'\')" heading="'+e.title+'"',0<n&&(t.before+='active="tabs['+n+'].active"'),t.before+=">",t.after="</uib-tab>"):(t.before="<p>Error! Tab "+e.title+" not found in tab list</p>",t.after="");break;case"tabset":t.before="<uib-tabset>",t.after="</uib-tabset>";break;case"well":t.before='<div class="well">',e.title&&(t.before+="<h4>"+e.title+"</h4>"),t.after="</div>";break;case"well-large":t.before='<div class="well well-lg well-large">',t.after="</div>";break;case"well-small":t.before='<div class="well well-sm well-small">',t.after="</div>";break;case"fieldset":t.before="<fieldset>",e.title&&(t.before+="<legend>"+e.title+"</legend>"),t.after="</fieldset>";break;case void 0:case null:case"":break;default:if(t.before='<div class="'+e.containerType+'">',e.title){var a=e.titleTagOrClass||"h4";a.match(/h[1-6]/)?t.before+="<"+a+">"+e.title+"</"+a+">":t.before+='<p class="'+a+'">'+e.title+"</p>"}t.after="</div>"}return t}function C(e,t){var n=A.fieldChrome(k,e,t),r=n.template;if(e.schema){var a=e.name.replace(/\./g,"_"),o="$_schema_"+a;if(k[o]=e.schema,e.schema)if(e.subkey){e.subkey.path=e.name,k[o+"_subkey"]=e.subkey;for(var i=angular.isArray(e.subkey)?e.subkey:[e.subkey],s=0;s<i.length;s++){var l=$(i[s]);r+=l.before,r+=F(e.schema,null,{subschema:"true",formstyle:t.formstyle,subkey:o+"_subkey",subkeyno:s,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),r+=l.after}w.push(e)}else if(t.subschema)t.suppressNestingWarning||console.log("Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date");else{var c=(t.model||"record")+"."+e.name;if("string"==typeof e.customHeader)r+=e.customHeader;else{var d="";e.unshift&&(d='<button id="unshift_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini form-btn" ng-click="unshift(\''+e.name+'\',$event)"><i class="'+A.glyphClass()+'-plus"></i> Add</button>'),"bs3"===L.framework()?r+='<div class="row schema-head"><div class="col-sm-offset-3">'+e.label+d+"</div></div>":r+='<div class="schema-head">'+e.label+d+"</div>"}if("inline"===e.formStyle&&e.inlineHeaders&&(r+=function(e,t,n,r){for(var a='<div class="inline-col-headers" style="display:flex" '+(r?"":'ng-hide="!'+n+" || "+n+'.length === 0"')+">",o=0,i=e;o<i.length;o++){var s=i[o];D(s,t),a+="<div ",s.showWhen=s.showWhen||s.showwhen,s.showWhen&&("string"==typeof s.showWhen?a+='ng-show="'+s.showWhen+'"':a+='ng-show="'+A.generateNgShow(s.showWhen,n)+'"'),s.id&&"function"==typeof s.id.replace&&(a+=' id="col_label_'+s.id.replace(/\./g,"-")+'"'),a+=' class="inline-col-header"><label for="'+s.id+'" class="control-label">'+s.label+"</label></div>"}return a+="</div>"}(e.schema,t,c,"always"===e.inlineHeaders)),r+='<ol class="sub-doc"'+(e.sortable?' ui-sortable="sortableOptions" ng-model="'+c+'"':"")+">",r+='<li ng-form class="'+("bs2"===L.framework()?"row-fluid ":"")+(e.inlineHeaders?"width-controlled ":"")+v(e.formStyle)+" "+(e.ngClass?"ng-class:"+e.ngClass:"")+'" name="form_'+a+'{{$index}}" class="sub-doc well" id="'+e.id+'List_{{$index}}" ng-repeat="subDoc in '+c+' track by $index">',"bs2"===L.framework()&&(r+='<div class="row-fluid sub-doc">'),!0===e.noRemove&&!e.customSubDoc||(r+=' <div class="sub-doc-btns">',"string"==typeof e.customSubDoc&&(r+=e.customSubDoc),!0!==e.noRemove&&(r+="<button "+(e.noRemove?'ng-hide="'+e.noRemove+'"':"")+' name="remove_'+e.id+'_btn" ng-click="remove(\''+e.name+"', $index, $event)\"",e.remove?r+=' class="remove-btn btn btn-mini btn-default btn-xs form-btn"><i class="'+A.glyphClass()+'-minus"></i> Remove':(r+=' style="position: relative; z-index: 20;" type="button" class="close pull-right">',"bs3"===L.framework()?r+='<span aria-hidden="true">×</span><span class="sr-only">Close</span>':r+="<span>×</span>"),r+="</button>"),r+="</div> "),r+=F(e.schema,!1,{subschema:"true",formstyle:e.formStyle,model:t.model,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),"bs2"===L.framework()&&(r+=" </div>"),r+="</li>",r+="</ol>",!0!==e.noAdd||"string"==typeof e.customFooter||e.noneIndicator){var u="";"string"==typeof e.customFooter&&(u=e.customFooter);var f="",p=t.model+"."+e.name+".length == 0";!0===e.noAdd?p='ng-show="'+p+'"':(f=e.noAdd?'ng-hide="'+e.noAdd+'"':"",p=e.noAdd?'ng-show="'+e.noAdd+" && "+p+'"':"",u+="<button "+f+' id="add_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini" ng-click="add(\''+e.name+"',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>"),e.noneIndicator&&(u+="<span "+p+' class="none_indicator" id="no_'+e.id+'_indicator">None</span>',f=t.model+"."+e.name+".length > 0",f=!0===e.noAdd?'ng-hide="'+f+'"':e.noAdd?'ng-hide="'+e.noAdd+" && "+f+'"':""),""!==u&&("bs3"===L.framework()?r+="<div "+f+' class="row schema-foot"><div class="col-sm-offset-3">'+u+"</div></div>":r+="<div "+f+' class = "schema-foot ">'+u+"</div>")}}}else{var m=A.controlDivClasses(t);if(e.array){if(m.push("fng-array"),"inline"===t.formstyle||"stacked"===t.formstyle)throw new Error("Cannot use arrays in an inline or stacked form");r+=A.label(k,e,"link"!==e.type,t),r+=A.handleArrayInputAndControlDiv(h(e,"link"===e.type?null:"arrayItem.x",!0,e.id+"_{{$index}}",t),m,e,t)}else r+=A.label(k,e,null,t),r+=A.handleInputAndControlDiv(h(e,null,t.required,e.id,t),m)}return r+=n.closeTag}var w=[],S=O.N,D=function(e,t){e.type=e.type||"text",e.id?"number"!=typeof e.id&&!e.id.match(/^[0-9]/)||(e.id="_"+e.id):t&&t.noid?e.id=null:e.id="f_"+e.name.replace(/\./g,"_"),e.label=void 0!==e.label?null===e.label?"":e.label:N("titleCase")(e.name.split(".").slice(-1)[0])},F=function(e,t,n){var r="";if(e)for(var a=0;a<e.length;a++){var o=e[a];n.viewform&&((o=angular.copy(o)).readonly=!0),0===a&&t&&!n.schema.match(/\$_schema_/)&&"object"!=typeof o.add&&(o.add=o.add?" "+o.add+" ":"",-1!==o.add.indexOf("ui-date")||n.noautofocus||o.containerType||(o.add=o.add+"autofocus "));var i=!0;if(o.directive){var s=o.directive,l="<"+s+' model="'+(n.model||"record")+'"',c=x[0];D(o,n);for(var d=0;d<c.attributes.length;d++){var u=c.attributes[d];switch(u.nodeName){case"class":var f=u.value.replace("ng-scope","");0<f.length&&(l+=' class="'+f+'"');break;case"schema":var p=("bespoke_"+o.name).replace(/\./g,"_");k[p]=angular.copy(o),delete k[p].directive,l+=' schema="'+p+'"';break;default:l+=" "+u.nodeName+'="'+u.value+'"'}}l+=" ";var m=N("camelCase")(o.directive);for(var h in o)if(o.hasOwnProperty(h))switch(h){case"directive":case"schema":break;case"add":switch(typeof o.add){case"string":l+=" "+o.add;break;case"object":for(var v in o.add)o.add.hasOwnProperty(v)&&(l+=" "+v+'="'+o.add[v].toString().replace(/"/g,"&quot;")+'"');break;default:throw new Error("Invalid add property of type "+typeof o.add+" in directive "+o.name)}break;case m:for(var g in o[h])o[h].hasOwnProperty(g)&&(l+=" "+o.directive+"-"+g+'="',"string"==typeof o[h][g]?l+=o[h][g].replace(/"/g,"&quot;")+'"':l+=JSON.stringify(o[h][g]).replace(/"/g,"&quot;")+'"');break;default:o[h]&&("string"==typeof o[h]?l+=" fng-fld-"+h+'="'+o[h].replace(/"/g,"&quot;")+'"':l+=" fng-fld-"+h+'="'+JSON.stringify(o[h]).replace(/"/g,"&quot;")+'"')}for(h in n)n.hasOwnProperty(h)&&"$"!==h[0]&&void 0!==n[h]&&(l+=" fng-opt-"+h+'="'+n[h].toString().replace(/"/g,"&quot;")+'"');r+=l+='ng-model="'+o.name+'"></'+s+">",i=!1}else if(o.containerType){var b=$(o);switch(o.containerType){case"tab":if(S===O.N){S=O.Forced,r+='<uib-tabset active="activeTabNo">';var y=_.findIndex(k.tabs,function(e){return e.active});k.activeTabNo=0<=y?y:0}r+=b.before,r+=F(o.content,null,n),r+=b.after;break;case"tabset":S=O.Y,r+=b.before,r+=F(o.content,null,n),r+=b.after;break;default:r+=b.before,r+=F(o.content,null,n),r+=b.after}i=!1}else if(n.subkey){var w=angular.isArray(k[n.subkey])?k[n.subkey][0].keyList:k[n.subkey].keyList;_.find(w,function(e,t){return k[n.subkey].path+"."+t===o.name})&&(i=!1)}i&&(D(o,n),r+=C(o,n))}else console.log("Empty array passed to processInstructions"),r="";return r},l=k.$watch(s.schema,function(e){if(e){var t=angular.isArray(e)?e:[e];if(0<t.length&&"function"==typeof l){l(),l=null;var n="",r=s.model||"record",g=k[r];if(g=g||{},!s.subschema&&!s.model||s.forceform){k.topLevelFormName=s.name||"myForm";var a="";for(var o in s)s.hasOwnProperty(o)&&"$"!==o[0]&&-1===["name","formstyle","schema","subschema","model","viewform"].indexOf(o)&&(a+=" "+s.$attr[o]+'="'+s[o]+'"');n="<"+(s.forceform?"ng-form":"form")+' name="'+k.topLevelFormName+'" class="'+v(s.formstyle)+'" novalidate '+a+">"}else n="";if(g===k.topLevelFormName)throw new Error("Model and Name must be distinct - they are both "+g);n+=F(t,!0,s),S===O.Forced&&(n+="</uib-tabset>"),n+=s.subschema?"":"</form>",x.replaceWith(c(n)(k));var i=k[s.shared||"sharedData"],b=i?i.modelControllers:[];if((0<w.length||0<b.length)&&!k.phaseWatcher)var y=k.$watch("phase",function(e){if(k.phaseWatcher=!0,"ready"===e&&"function"==typeof y){y(),y=null;for(var t=0;t<b.length;t++)b[t].onAllReady&&b[t].onAllReady(k);for(var n=0;n<w.length;n++){for(var r,a,o=w[n],i=angular.isArray(o.subkey)?o.subkey:[o.subkey],s=o.name.split("."),l=g;1<s.length;)l=l[s.shift()]||{};l=l[s[0]]=l[s[0]]||[];for(var c=0;c<i.length;c++){if(i[c].selectFunc){if(!k[i[c].selectFunc]||"function"!=typeof k[i[c].selectFunc])throw new Error("Subkey function "+i[c].selectFunc+" is not properly set up");r=k[i[c].selectFunc](g,o)}else{if(!i[c].keyList)throw new Error("Invalid subkey setup for "+o.name);var d=i[c].keyList;for(r=0;r<l.length;r++){for(var u in a=!0,d)if(d.hasOwnProperty(u)&&l[r][u]!==d[u]&&(void 0===l[r][u]||!l[r][u].text||l[r][u].text!==d[u])){a=!1;break}if(a)break}if(!a)switch(i[c].onNotFound){case"error":var f="Cannot find matching "+(i[c].title||i[c].path);E(function(){k.showError(f,"Unable to set up form correctly")}),r=-1;break;case"create":default:var p=o.name.split("."),m=p.pop(),h=p.join("."),v=g;h&&(v=v[h]),r=v[m].push(d)-1}}k["$_arrayOffset_"+o.name.replace(/\./g,"_")+"_"+c]=r}}}});d.$broadcast("formInputDone",s.name),u.updateDataDependentDisplay&&g&&0<Object.keys(g).length&&u.updateDataDependentDisplay(g,null,!0,k)}}},!0)}}}t=e.directives||(e.directives={}),r.$inject=["$compile","$rootScope","$filter","$timeout","cssFrameworkService","formGenerator","formMarkupHelper"],(n=O=O||{})[n.Y=0]="Y",n[n.N=1]="N",n[n.Forced=2]="Forced",t.formInput=r}(fng=fng||{}),function(e){(e.directives||(e.directives={})).fngNakedDate=function(){return{restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$parsers.push(function(e){if(e)return e.toString()}),r.$formatters.push(function(e){if(e)return new Date(e)})}}}}(fng=fng||{}),function(e){var t;function n(r,t,a,o){var n,e,i,s;s=!1,i=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(i)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(i.substr(0,4)))&&(s=!0),e=!s,r.searchPlaceholder=e?"Ctrl + / to Search":"Search",r.handleKey=function(e){if(27===e.keyCode&&r.searchTarget&&0<r.searchTarget.length)r.searchTarget="";else if(0<r.results.length)switch(e.keyCode){case 38:0<r.focus&&r.setFocus(r.focus-1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 40:r.results.length>r.focus+1&&r.setFocus(r.focus+1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 13:null!=r.focus&&r.selectResult(r.focus)}},r.setFocus=function(e){null!==r.focus&&delete r.results[r.focus].focussed,r.results[e].focussed=!0,r.focus=e},r.selectResult=function(e){var t,n=r.results[e];n.url?t=n.url.replace("|id|",n.id):(t=o.prefix()+"/"+n.resource+"/"+n.id+"/edit",n.resourceTab&&(t+="/"+n.resourceTab)),a.url(t)},r.resultClass=function(e){var t="search-result";return r.results&&r.results[e].focussed&&(t+=" focus"),t};function l(){r.moreCount=0,r.errorClass="",r.results=[],r.focus=null}r.$watch("searchTarget",function(e){e&&0<e.length?(n=r.testTime||(new Date).valueOf(),t.get("/api/search?q="+e+"&sentAt="+n).then(function(e){var t=e.data;t.timestamps&&t.timestamps.sentAt&&Number.parseInt(t.timestamps.sentAt)!==n||(0<r.searchTarget.length?(r.results=t.results,r.moreCount=t.moreCount,0<t.results.length&&(r.errorClass="",r.setFocus(0)),r.errorClass=0===r.results.length?"error has-error":""):l())},function(e){console.log("Error in searchbox.js : "+e.data+" (status="+e.status+")")})):l()},!0),r.$on("$routeChangeStart",function(){r.searchTarget=""})}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.SearchCtrl=n}(fng=fng||{}),function(t){var e;function n(e){return{restrict:"AE",templateUrl:"search-"+e.framework()+".html",controller:t.controllers.SearchCtrl}}e=t.directives||(t.directives={}),n.$inject=["cssFrameworkService"],e.globalSearch=n}(fng=fng||{}),function(e){(e.filters||(e.filters={})).camelCase=function(){return function(e){return e.replace(/([\:\-\_]+(.))/g,function(e,t,n,r){return r?n.toUpperCase():n})}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).extractTimestampFromMongoID=function(){return function(e){var t=e.substring(0,8);return new Date(1e3*parseInt(t,16))}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).titleCase=function(){return function(e,t){return e&&(e=e.replace(/(_|\.)/g," ").replace(/[A-Z]/g," $&").trim().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}),e=t?e.replace(/\s/g,""):e.replace(/\s{2,}/g," ")),e}}}(fng=fng||{}),function(e){(e.services||(e.services={})).addAllService=function(){function r(e,t,r,n){var a,o,i=[],s=[];if(r="addAll"+r,"string"==typeof n)for(a=n.split(" "),o=0;o<a.length;o++)s.push(a[o]);if(!function e(t){for(var n in t)n===r&&i.push(t[n]),"$parent"===n&&e(t[n])}(e),void 0!==t[r]&&"string"==typeof t[r])for(a=t[r].split(" "),o=0;o<a.length;o++)0===a[o].indexOf("class=")?s.push(a[o].substring(6,a[o].length)):i.push(a[o]);return(n=0<s.length?' class="'+s.join(" ")+'" ':" ")+(0<i.length?i.join(" ")+" ":"")}this.getAddAllGroupOptions=function(e,t,n){return r(e,t,"Group",n)},this.getAddAllFieldOptions=function(e,t,n){return r(e,t,"Field",n)},this.getAddAllLabelOptions=function(e,t,n){return r(e,t,"Label",n)},this.addAll=function(e,t,n,r){return this["getAddAll"+t+"Options"](e,r,n)||[]}}}(fng=fng||{}),function(e){(e.services||(e.services={})).cssFrameworkService=function(){var n={framework:"bs3"};return{setOptions:function(e){angular.extend(n,e)},$get:function(){return{framework:function(){return n.framework},setFrameworkForDemoWebsite:function(e){n.framework=e},span:function(e){var t;switch(n.framework){case"bs2":t="span"+Math.floor(e);break;case"bs3":t="col-xs-"+Math.floor(e)}return t},offset:function(e){var t;switch(n.framework){case"bs2":t="offset"+Math.floor(e);break;case"bs3":t="col-lg-offset-"+Math.floor(e)}return t},rowFluid:function(){var e;switch(n.framework){case"bs2":e="row-fluid";break;case"bs3":e="row"}return e}}}}}}(fng=fng||{}),function(e){function t(c){return{loadControllerAndMenu:function(e,t,n,r,a){var o,i={};t+="Ctrl",i.$scope=e.modelControllers[n]=a;var s=a.$parent;s.items=s.items||[];function l(e){angular.forEach(e,function(e){e.divider?r=!0:e[o]&&(r&&(r=!1,s.items.push({divider:!0})),s.items.push(e))})}try{c(t,i),o=s.newRecord?"creating":s.id?"editing":"listing",angular.isObject(i.$scope.contextMenu)&&(l(i.$scope.contextMenu),i.$scope.contextMenuPromise&&i.$scope.contextMenuPromise.then(function(e){return l(e)})),e.modelNameDisplayPromise&&e.modelNameDisplayPromise.then(function(e){s.modelNameDisplay=e})}catch(e){/is not a function, got undefined/.test(e.message)||/\[\$controller:ctrlreg\] The controller with the name/.test(e.message)||console.log("Unable to instantiate "+t+" - "+e.message)}}}}((e.services||(e.services={})).fngModelCtrlService=t).$inject=["$controller"]}(fng=fng||{}),function(e){var t;function n(n,t){var a,r,s={hashPrefix:"",html5Mode:!1,routing:"ngroute",prefix:""},l=["edit","view"],o=[{route:"/analyse/:model/:reportSchemaName",state:"analyse::model::report",templateUrl:"base-analysis.html"},{route:"/analyse/:model",state:"analyse::model",templateUrl:"base-analysis.html"},{route:"/:model/:id/edit",state:"model::edit",templateUrl:"base-edit.html"},{route:"/:model/:id/edit/:tab",state:"model::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:id/view",state:"model::edit",templateUrl:"base-view.html"},{route:"/:model/:id/view/:tab",state:"model::view::tab",templateUrl:"base-view.html"},{route:"/:model/new",state:"model::new",templateUrl:"base-edit.html"},{route:"/:model",state:"model::list",templateUrl:"base-list.html"},{route:"/:model/viewonly",state:"model::view",templateUrl:"base-list-view.html"},{route:"/:model/:form/:id/edit",state:"model::form::edit",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/edit/:tab",state:"model::form::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/view",state:"model::form::view",templateUrl:"base-view.html"},{route:"/:model/:form/:id/view/:tab",state:"model::form::view::tab",templateUrl:"base-view.html"},{route:"/:model/:form/new",state:"model::form::new",templateUrl:"base-edit.html"},{route:"/:model/:form",state:"model::form::list",templateUrl:"base-list.html"},{route:"/:model/:form/viewonly",state:"model::form::list::view",templateUrl:"base-list-view.html"}],c=null,d={};function i(e){var t=e;return s.templateFolder&&(t="/"!==s.templateFolder[s.templateFolder.length-1]?s.templateFolder+"/"+t:s.templateFolder+t),t}function u(e,n,r){void 0===n&&(n=""),n=n||"",angular.forEach(e,function(e){a.when(n+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))}),s.variantsForDemoWebsite&&angular.forEach(s.variantsForDemoWebsite,function(t){angular.forEach(e,function(e){a.when(n+t+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))})})}function f(e,t,n){void 0===t&&(t=""),t=t||"",angular.forEach(e,function(e){r.state(e.state,angular.extend(e.options||{url:t+e.route,templateUrl:e.templateUrl},n))})}function p(e,t,n,r,a,o){var i,s=r?"/"+r:"",l=e+"/"+n,c=o?"/"+o:"";switch(t){case"list":i=l+s;break;case"edit":i=l+s+"/"+a+"/edit"+c;break;case"view":i=l+s+"/"+a+"/view"+c;break;case"read":i=l+s+"/"+a+"/read"+c;break;case"new":i=l+s+"/new"+c}return i}function m(e,t){switch(s.routing){case"ngroute":a=n.get("$routeProvider"),e&&u(e),u(t,s.prefix,s.add2fngRoutes);break;case"uirouter":r=n.get("$stateProvider"),e&&f(s.fixedRoutes),f(t,s.prefix,s.add2fngRoutes)}}return{start:function(e){angular.extend(s,e),s.prefix[0]&&"/"!==s.prefix[0]&&(s.prefix="/"+s.prefix),t.html5Mode(s.html5Mode),""!==s.hashPrefix?t.hashPrefix(s.hashPrefix):s.html5Mode||t.hashPrefix(""),m(s.fixedRoutes,o)},addRoutes:function(e,t){m(e,t)},registerAction:function(e){l.push(e)},$get:function(){return{router:function(){return s.routing},prefix:function(){return s.prefix},parsePathFunc:function(){return function(e){if(e!==c){c=e,d={newRecord:!1},0<s.prefix.length&&0===e.indexOf(s.prefix)&&(e=e.slice(s.prefix.length));var t=e.split("/");s.variants&&-1!==s.variants.indexOf(t[1])&&(d.variant=t[1],t.shift());var n=t.length;if("analyse"===t[1])d.analyse=!0,d.modelName=t[2],d.reportSchemaName=4<=n?t[3]:null;else{d.modelName=t[1];var r=[t[n-1],t[n-2]],a=r.indexOf("new"),o=r.indexOf("viewonly"),i=void 0;-1===a&&-1===o?-1!==(i=l.reduce(function(e,t){var n=r.indexOf(t);return-1<n?n:e},-1))&&(n-=2+i,d.id=t[n]):-1!==a?(d.newRecord=!0,n-=1+a):n-=1+o,1!==i&&1!==a||(d.tab=r[0]),2<n&&(d.formName=t[2])}}return d}},buildUrl:function(e){var t=s.html5Mode?"":"#";return t+=s.hashPrefix,(t+=s.prefix)[0]&&(t+="/"),t+="/"===e[0]?e.slice(1):e},buildOperationUrl:function(e,t,n,r,a){return p(s.prefix,e,t,n,r,a)},redirectTo:function(){return function(e,t,n,r,a){var o;n.search({}),o="onDelete"===e?s.onDelete?"new"===s.onDelete?p(s.prefix,"new",t.modelName,t.formName,r,a):s.onDelete:p(s.prefix,"list",t.modelName,t.formName,r,a):p(s.prefix,e,t.modelName,t.formName,r,a),n.path(o)}}}}}}t=e.services||(e.services={}),n.$inject=["$injector","$locationProvider"],t.routingService=n}(fng=fng||{}),function(e){function t(e,t,o,n,i){function g(e,t,n,r,a,o,i,s){function l(e,t){var n=angular.copy(e),r=_.find(i.tabs,function(e){return e.title===n});if(!r){if(0===i.tabs.length&&0<i.formSchema.length){i.tabs.push({title:"Main",content:[],active:"Main"===i.tab||!i.tab}),r=i.tabs[0];for(var a=0;a<i.formSchema.length;a++)r.content.push(i.formSchema[a])}r=i.tabs[i.tabs.push({title:n,containerType:"tab",content:[],active:n===i.tab})-1]}r.content.push(t)}for(var c in"function"==typeof i.onSchemaFetch&&i.onSchemaFetch(e,t),t)if(t.hasOwnProperty(c))if("_id"===c)r&&t._id.options&&t._id.options.list&&w(r,t._id.options.list,c);else if(t.hasOwnProperty(c)){var d=t[c],u=d.options||{},f=u.form||{};if(d.schema&&!f.hidden){if(o&&n){var p=[];g("Nested "+c,d.schema,p,null,c+".",!0,i,s);var m=y(c,f,a);m.schema=p,f.tab&&l(f.tab,m),void 0!==f.order?n.splice(f.order,0,m):n.push(m)}}else{if(n&&!f.hidden){var h=y(c,f,a);if(x(h.showIf,h.name,i)&&"options"!==c){var v=b(h,d,u,i,s);v.tab&&l(v.tab,v),void 0!==f.order?n.splice(f.order,0,v):n.push(v)}}r&&u.list&&w(r,u.list,c)}}"function"==typeof i.onSchemaProcessed&&i.onSchemaProcessed(e,"Main "===e.slice(0,5)?i.baseSchema():n),r&&0===r.length&&k(e,r,n,t)}function b(t,e,n,r,a){if(e.caster&&(t.array=!0,e=e.caster,angular.extend(n,e.options),e.options&&e.options.form&&angular.extend(t,e.options.form)),"String"===e.instance)n.enum?(t.type=t.type||"select",t.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):(t.options=i.suffixCleanId(t,"Options"),r[t.options]=n.enum)):(t.type||(t.type=-1!==t.name.toLowerCase().indexOf("password")?"password":"text"),n.match&&(t.add='pattern="'+n.match+'" '+(t.add||"")));else if("ObjectID"===e.instance)t.ref=n.ref,t.link&&(t.link.linkOnly?(t.type="link",t.linktext=t.link.text):t.link.label?t.linklabel=!0:console.log("Unsupported link setup"),t.form=t.link.form,t.linktab=t.link.linktab,delete t.link),"link"!==t.type&&(t.type="select",t.select2||n.form&&n.form.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):t.directive&&(t.noLookup||t[o("camelCase")(t.directive)]&&t[o("camelCase")(t.directive)].fngAjax)||function(){if(t.options=i.suffixCleanId(t,"Options"),t.ids=i.suffixCleanId(t,"_ids"),!t.hidden)if(n.ref)i.setUpLookupOptions(n.ref,t,r,a,g);else if(n.lookupListRef)i.setUpLookupListOptions(n.lookupListRef,t,r,a),t.lookupListRef=n.lookupListRef;else if(n.internalRef)i.handleInternalLookup(r,t,n.internalRef),t.internalRef=n.internalRef;else if(!n.customLookupOptions)throw new Error("No supported select lookup type found in "+t.name)}());else if("Date"===e.instance){if(!t.type)if(t.intType="date",t.readonly)t.type="text";else if(t.directive)t.type="text";else try{t.add=t.add||"",angular.module("ui.date").requires,t.type="text",t.add+=" ui-date ui-date-format "}catch(e){t.type="date",t.add+=' fng-naked-date="x" '}}else if("boolean"===e.instance.toLowerCase())t.type=t.type||"checkbox";else{if("Number"!==e.instance)throw new Error("Field "+t.name+" is of unsupported type "+e.instance);t.type=t.type||"number",void 0!==n.min&&(t.add='min="'+n.min+'" '+(t.add||"")),void 0!==n.max&&(t.add='max="'+n.max+'" '+(t.add||"")),t.step&&(t.add='step="'+t.step+'" '+(t.add||""))}return n.required&&(t.required=!0),n.readonly&&(t.readonly=!0),void 0!==e.defaultValue?t.defaultValue=e.defaultValue:e.options&&void 0!==e.options.default&&console.log("No support for default with no value, yet"),t}function c(e,t,n){for(var r=e.split("."),a=n||t.record,o=0,i=r.length;o<i;o++)a[r[o]]||(a[r[o]]=o===i-1?[]:{}),a=a[r[o]];return a}function v(e,r){function t(e){var t=e;if("string"==typeof e&&"$"===e.slice(0,1)){var n=e.split(".");switch(n.length){case 1:t=i.getListData(r,e.slice(1));break;case 2:t=i.getListData(r,n[1]);break;default:throw new Error("Unsupported showIf format")}}return t}var n,a=t(e.lhs),o=t(e.rhs);switch(e.comp){case"eq":n=a===o;break;case"ne":n=a!==o;break;default:throw new Error("Unsupported comparator "+e.comp)}return n}var y=function(e,t,n){return t.name=n+e,t},w=function(e,t,n){"object"==typeof t?(t.name=n,e.push(t)):e.push({name:n})},k=function(e,t,n,r){if(n){for(var a=0,o=n.length;a<o;a++)if("text"===n[a].type){t.push({name:n[a].name});break}0===t.length&&0!==n.length&&t.push({name:n[0].name})}if(0===t.length){for(var i in r)if("_id"!==i&&r.hasOwnProperty(i)){t.push({name:i});break}if(0===t.length)throw new Error("Unable to generate a title for "+e)}},x=function(e,r,a){var o=0;function t(e){if("string"==typeof e&&"$"===e.slice(0,1)){var t=e.slice(1),n=a.dataDependencies[t]||[];n.push(r),a.dataDependencies[t]=n,o+=1}}var n=!0;return e&&(t(e.lhs),t(e.rhs),0!==o||v(e,void 0)||(n=!1)),n};return{generateEditUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/edit")},generateViewUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/view")},generateNewUrl:function(e){return n.buildUrl(e.modelName+"/"+(e.formName?e.formName+"/":"")+"new")},handleFieldType:b,handleSchema:g,updateDataDependentDisplay:function(e,t,n,r){var a,o,i,s,l,c;for(var d in r.dataDependencies)if(r.dataDependencies.hasOwnProperty(d)){var u=d.split(".");if(1===u.length){if(n||!t||e[d]!==t[d])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var f=a[o];for(i=0;i<r.formSchema.length;i+=1)r.formSchema[i].name===f&&(l=angular.element(document.querySelector("#cg_"+r.formSchema[i].id)),v(r.formSchema[i].showIf,e)?l.removeClass("ng-hide"):l.addClass("ng-hide"))}}else{if(2!==u.length)throw new Error("You can only go down one level of subdocument with showIf");if(void 0===c&&(c=!0),e[u[0]])for(s=0;s<e[u[0]].length;s++)if(n||!t||!t[u[0]]||!t[u[0]][s]||e[u[0]][s][u[1]]!==t[u[0]][s][u[1]])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var p=a[o].split(".");if(2!==p.length)throw new Error("Conditional display must control dependent fields at same level ");for(i=0;i<r.formSchema.length;i+=1)if(r.formSchema[i].name===p[0])for(var m=r.formSchema[i].schema,h=0;h<m.length;h++)m[h].name===a[o]&&(0===(l=angular.element(document.querySelector("#f_"+p[0]+"List_"+s+" #cg_f_"+a[o].replace(".","_")))).length?l=angular.element(document.querySelector("#f_elements-"+s+"-"+p[1])):c=!1,0<l.length&&(v(r.formSchema[i].schema[h].showIf,e[u[0]][s])?l.show():l.hide()))}}}return c},add:function(t,e,n,r){var a;if(e.target.offsetParent){var o=c(t,n,r),i=n.formSchema.find(function(e){return e.name===t}),s=i?i.schema:null,l=s?n.setDefaults(s,t+"."):{};"function"==typeof(null===(a=n.dataEventFunctions)||void 0===a?void 0:a.onInitialiseNewSubDoc)&&n.dataEventFunctions.onInitialiseNewSubDoc(t,s,l),o.push(l),n.setFormDirty(e)}},unshift:function(e,t,n,r){c(e,n,r).unshift({}),n.setFormDirty(t)},remove:function(t,e,n,r,a){var o,i=c(t,r,a);if("function"==typeof r.dataEventFunctions.onDeleteSubDoc){var s=r.formSchema.find(function(e){return e.name===t}),l=s?s.schema:null;o=r.dataEventFunctions.onDeleteSubDoc(t,l,i,e)}o?r.showError(o):(i.splice(e,1),r.setFormDirty(n))},hasError:function(e,t,n,r){var a=!1;if(r){var o=r[r.topLevelFormName];if("null"!==e&&(o=o[e.replace("$index",n)]),o){var i=o[t];i&&i.$invalid&&!i.$$attr.readonly&&(i.$dirty?a=!0:angular.forEach(i.$validators,function(e,t){"required"!==t&&i.$error[t]&&(a=!0)}))}}else console.log("hasError called with no scope! ",e,t,n);return a},decorateScope:function(a,o,n,e){a.record=e.record,a.phase="init",a.disableFunctions=e.disableFunctions,a.dataEventFunctions=e.dataEventFunctions,a.topLevelFormName=void 0,a.formSchema=[],a.tabs=[],a.listSchema=[],a.recordList=[],a.dataDependencies={},a.internalLookups=[],a.listLookups=[],a.conversions={},a.pageSize=60,a.pagesLoaded=0,(e.baseScope=a).generateEditUrl=function(e){return o.generateEditUrl(e,a)},a.generateViewUrl=function(e){return o.generateViewUrl(e,a)},a.generateNewUrl=function(){return o.generateNewUrl(a)},a.scrollTheList=function(){return n.scrollTheList(a)},a.getListData=function(e,t){return n.getListData(e,t,a.listSchema,a)},a.setPristine=function(e){e&&a.dismissError(),a[a.topLevelFormName]&&a[a.topLevelFormName].$setPristine()},a.skipCols=function(e){return 0<e?"col-md-offset-3":""},a.setFormDirty=function(e){e?angular.element(e.target).inheritedData("$formController").$setDirty():console.log("setFormDirty called without an event (fine in a unit test)")},a.add=function(e,t,n){return o.add(e,t,a,n)},a.hasError=function(e,t,n){return o.hasError(e,t,n,a)},a.unshift=function(e,t,n){return o.unshift(e,t,a,n)},a.remove=function(e,t,n,r){return o.remove(e,t,n,a,r)},a.baseSchema=function(){return a.tabs.length?a.tabs:a.formSchema}}}}((e.services||(e.services={})).formGenerator=t).$inject=["$location","$timeout","$filter","routingService","recordHandler"]}(fng=fng||{}),function(e){var t;function n(f,p,m,a){function d(e,t){var n=["vertical","inline"];return t||n.push("stacked"),!e||"undefined"===e||!n.includes(e)}function s(){return"bs2"===f.framework()?"icon":"glyphicon glyphicon"}return{isHorizontalStyle:d,fieldChrome:function(e,t,n){var r=t.classes||"",a="",o="",i="";if(t.showWhen=t.showWhen||t.showwhen,t.showWhen&&("string"==typeof t.showWhen?i+='ng-show="'+t.showWhen+'"':i+='ng-show="'+function(e,a){function t(e){var t=e;if("string"==typeof e)if("$"===e.slice(0,1)){t=(a||"record")+".";var n=e.slice(1).split(".");if(1<n.length){var r=n.pop();t+=n.join(".")+"[$index]."+r}else t+=e.slice(1)}else t="'"+e+"'";return t}var n=["eq","ne","gt","gte","lt","lte"].indexOf(e.comp);if(-1===n)throw new Error("Invalid comparison in showWhen");return t(e.lhs)+["===","!==",">",">=","<","<="][n]+t(e.rhs)}(t.showWhen,n.model)+'"'),t.id&&"function"==typeof t.id.replace&&(i+=' id="cg_'+t.id.replace(/\./g,"-")+'"'),"bs3"===f.framework()){var s;r+=" form-group","vertical"===n.formstyle&&"block-level"!==t.size&&(a+='<div class="row">',r+=" col-sm-"+p.sizeAsNumber(t.size),o+="</div>");var l=null,c=t.name.split(".");s=n&&void 0!==n.subkeyno?n.subschemaroot.replace(/\./g,"-")+"-subkey"+n.subkeyno+"-"+c[c.length-1]:n.subschema?(l="form_"+c.slice(0,-1).join("_")+"$index",t.name.replace(/\./g,"-")):"f_"+t.name.replace(/\./g,"_"),a+="<div"+m.addAll(e,"Group",r,n)+" ng-class=\"{'has-error': hasError('"+l+"','"+s+"', $index)}\"",o+="</div>"}else o=d(n.formstyle,!0)?(a+="<div"+m.addAll(e,"Group","control-group",n),"</div>"):(a+="<span ","</span>");return{template:a+=(i||"")+">",closeTag:o}},label:function(e,t,n,r){var a="";if("bs3"===f.framework()||!["inline","stacked"].includes(r.formstyle)&&""!==t.label||n){a="<label";var o="control-label";if(d(r.formstyle,!1)?(t.linklabel||(a+=' for="'+t.id+'"'),void 0!==t.labelDefaultClass?o+=" "+t.labelDefaultClass:"bs3"===f.framework()&&(o+=" col-sm-3")):["inline","stacked"].includes(r.formstyle)&&(a+=' for="'+t.id+'"',o+=" sr-only"),a+=m.addAll(e,"Label",null,r)+' class="'+o+'">'+t.label,n&&(a+=' <i id="add_'+t.id+'" ng-click="add(\''+t.name+'\',$event)" class="'+s()+'-plus-sign"></i>'),a+="</label>",t.linklabel){var i='<fng-link fld="'+t.name+'" ref="'+t.ref+'" text="'+escape(a)+'"';t.form&&(i+=' form="'+t.form+'"'),t.linktab&&(i+=' linktab="'+t.linktab+'"'),a=i+="></fng-link>"}}return a},glyphClass:s,allInputsVars:function(e,t,n,r,a,o){var i,s=t.placeHolder,l="",c="",d="",u="";return"bs3"===f.framework()?(l=-1===["horizontal","vertical","inline"].indexOf(n.formstyle)?" input-sm":"",c="col-sm-"+p.sizeAsNumber(t.size),u=" form-control"):d=t.size?" input-"+t.size:"",["inline","stacked"].includes(n.formstyle)&&(s=s||t.label),i='data-ng-model="'+r+'"'+(a?' id="'+a+'" name="'+a+'" ':' name="'+o+'" '),i+=s?'placeholder="'+s+'" ':"",t.popup&&(i+='title="'+t.popup+'" '),t.ariaLabel&&(i+='aria-label="'+t.ariaLabel+'" '),{common:i+=m.addAll(e,"Field",null,n),sizeClassBS3:c,sizeClassBS2:d,compactClass:l,formControl:u}},inputChrome:function(e,t,n,r){"bs3"===f.framework()&&d(n.formstyle,!0)&&"checkbox"!==t.type&&(e='<div class="bs3-input '+r.sizeClassBS3+'">'+e+"</div>");var a=(t.helpInline||"")+(t.helpinline||"");if(0<a.length){var o="bs2"===f.framework()?{el:"span",cl:"help-inline"}:{el:"div",cl:"help-block"};e+="<"+o.el+' class="'+o.cl+'">'+a+"</"+o.el+">"}return n.noid||(e+='<div ng-if="'+(n.name||"myForm")+"['"+t.id+'\'].$dirty" class="help-block"> <div ng-messages="'+(n.name||"myForm")+"['"+t.id+'\'].$error"> <div ng-messages-include="error-messages.html"> </div> </div></div>'),t.help&&(e+='<div class="help-block">'+t.help+"</div>"),e},generateSimpleInput:function(e,t,n){var r="<input "+e+'type="'+t.type+'" ';return t.label||t.ariaLabel?n.subschema&&(r+='aria-label="'+(t.label?a("titleCase")(n.subschemaroot)+" "+t.label:t.popup||t.name.replace(/\./g," "))+'" '):r+='aria-label="'+t.name.replace(/\./g," ")+'" ',"inline"!==n.formstyle||"bs2"!==f.framework()||t.size||(r+='class="input-small"'),r+=" />"},controlDivClasses:function(e){var t=[];return d(e.formstyle,!1)&&t.push("bs2"===f.framework()?"controls":"col-sm-9"),t},handleInputAndControlDiv:function(e,t){return 0<t.length&&(e='<div class="'+t.join(" ")+'">'+e+"</div>"),e},handleArrayInputAndControlDiv:function(e,t,n,r){var a="<div ";return"bs3"===f.framework()&&(a+='ng-class="skipCols($index)" '),a+='class="'+t.join(" ")+'" id="'+n.id+'List" ',a+='ng-repeat="arrayItem in '+(r.model||"record")+"."+n.name+' track by $index">',a+=e,"link"!==n.type&&(a+="<i ng-click=\"remove('"+n.name+'\',$index,$event)" id="remove_'+n.id+'_{{$index}}" class="'+s()+'-minus-sign"></i>'),a+="</div>"},addTextInputMarkup:function(e,t,n){var r="",a=e.formControl.trim()+e.compactClass+e.sizeClassBS2+(t.class?" "+t.class:"");return 0!==a.length&&(r+='class="'+a+'"'),t.add&&(r+=" "+t.add+" "),r+=n,t.readonly?r+=" "+("boolean"==typeof t.readOnly?"readonly":'ng-readonly="'+t.readonly+'"')+" ":r+=" ",r}}}t=e.services||(e.services={}),n.$inject=["cssFrameworkService","inputSizeHelper","addAllService","$filter"],t.formMarkupHelper=n}(fng=fng||{}),function(e){(e.services||(e.services={})).inputSizeHelper=function(){var t=[1,2,4,6,8,10,12],n=["mini","small","medium","large","xlarge","xxlarge","block-level"];return{sizeMapping:t,sizeDescriptions:n,defaultSizeOffset:2,sizeAsNumber:function(e){return t[e?n.indexOf(e):2]}}}}(fng=fng||{}),function(e){var t;function n(b){return{extractFromAttr:function(e,t){function n(e){var t=e.replace(/&quot;/g,'"');return"true"===t?t=!0:"false"===t?t=!1:!isNaN(parseFloat(t))&&isFinite(t)&&(t=parseFloat(t)),t}var r={},a={formStyle:e.formstyle},o={},i=t?t.length:0;for(var s in e)e.hasOwnProperty(s)&&("fngFld"===s.slice(0,6)?r[s.slice(6).toLowerCase()]=n(e[s]):"fngOpt"===s.slice(0,6)?a[s.slice(6).toLowerCase()]=n(e[s]):t&&s.slice(0,i)===t&&(o[_.kebabCase(s.slice(i))]=n(e[s])));return{info:r,options:a,directiveOptions:o}},buildInputMarkup:function(e,t,n,r,a,o,i){var s,l,c,d=b.fieldChrome(e,n,r,' id="cg_'+n.id+'"'),u=b.controlDivClasses(r),f=d.template+b.label(e,n,a,r);if(c=a?(s="arrayItem"+(o?".x":""),l=n.id+"_{{$index}}",n.name+"_{{$index}}"):(s=t+"."+n.name,l=n.id,n.name),r.subschema&&-1!==n.name.indexOf(".")){var p=t+".",m=n.name,h=r.subschemaroot,v=m.slice(h.length+1);s=p,r.index?l="f_"+(s+=h+"["+r.index+"]."+v).slice(p.length).replace(/(\.|\[|\]\.)/g,"-"):(s+=h,r.subkey?(l=s.slice(p.length).replace(/\./g,"-")+"-subkey"+r.subkeyno+"-"+v,s+="[$_arrayOffset_"+h.replace(/\./g,"_")+"_"+r.subkeyno+"]."+v):(s+="[$index]."+v,l=null,c=m.replace(/\./g,"-")))}var g=b.allInputsVars(e,n,r,s,l,c);return g.modelString=s,f+=b["handle"+(a?"Array":"")+"InputAndControlDiv"](b.inputChrome(i(g),n,r,g),u,n,r),f+=d.closeTag},findIdInSchemaAndFlagNeedX:function e(t,n){for(var r=!1,a=0;a<t.length;a++){var o=t[a];if(o.id===n){r=o.needsX=!0;break}if(o.schema&&e(o.schema,n)){r=!0;break}}return r}}}t=e.services||(e.services={}),n.$inject=["formMarkupHelper"],t.pluginHelper=n}(fng=fng||{}),function(e){var t;function n(l,o,a,d,i,s,p,e){var c=function(e){return void 0===e&&(e=function(e){return Math.floor(e).toString(16)}),e(Date.now()/1e3)+" ".repeat(16).replace(/./g,function(){return e(16*Math.random())})};function u(e){if(-1===["cancel","backdrop click","escape key press"].indexOf(e))throw e}function b(e,t){return(e.id||"f_"+e.name).replace(/\./g,"_")+t}function f(e,t,n,r){void 0===r&&(r=!1);for(var a=t.split("."),o=a.length-1,i=e,s=0;s<o;s++){if(!i)throw new Error("walkTree failed: Object = "+e+", fieldname = "+t+", i = "+s);if(i=angular.isArray(i)?_.map(i,function(e){return e[a[s]]}):(r&&!i[a[s]]&&(i[a[s]]={}),i[a[s]]),angular.isArray(i)&&void 0!==n)if(n.scope&&"function"==typeof n.scope)i=i[n.scope().$index];else{if("number"!=typeof n)throw new Error("Unsupported element type in walkTree "+t);i=i[n]}if(!i)break}return{lastObject:i,key:i?a[o]:void 0}}function y(e,t,n,r){var a=f(e,t,n,!!r);if(a.lastObject&&a.key)if(r)if(angular.isArray(a.lastObject))for(var o=0;o<a.lastObject.length;o++)a.lastObject[o][a.key]=r[o];else a.lastObject[a.key]=r;else delete a.lastObject[a.key]}function m(t,n,e,r){if(void 0===r&&(r=!1),!n.topLevelFormName||n[n.topLevelFormName]&&(r||n[n.topLevelFormName].$pristine)){x(t.name,e.master,function(e){return"object"==typeof e&&e.id?e:S(t,e,n[b(t,"Options")],n[b(t,"_ids")])});var a=w(e.master,t.name);a&&y(n.record,t.name,void 0,a)}}var w=function(e,t,n){var r,a=f(e,t,n);return a.lastObject&&a.key&&(r=angular.isArray(a.lastObject)?_.map(a.lastObject,function(e){return e[a.key]}):a.lastObject[a.key]),r};function k(e,t,n,r){void 0===n&&(n=null);var a=w(e,t)||"";if(a&&n){var o=_.find(n,function(e){return e.name===t});if(o)switch(o.params){case void 0:break;case"timestamp":var i=a.toString().substring(0,8),s=new Date(1e3*parseInt(i,16));a=s.toLocaleDateString()+" "+s.toLocaleTimeString();break;default:a=r.dataEventFunctions[o.params](e)}}return a}function x(e,t,n){var r,a,o=(r=e.split("."),a=[r[0]],1<r.length&&a.push(r.slice(1).join(".")),a);if(1<o.length)!function(e,t,n){if(void 0!==t)if(angular.isArray(t))for(var r=0;r<t.length;r++)x(e,t[r],n);else x(e,t,n)}(o[1],t[o[0]],n);else if(t[o[0]]){var i=t[o[0]];if(angular.isArray(i))for(var s=i.length-1;0<=s;s--){var l=typeof i[s];("undefined"==l||"object"==l&&0===Object.keys(i[s]).length)&&i.splice(s,1)}t[o[0]]=n(i)}}function v(e,t,n,r,a){var o="string"==typeof t?e[t]:t,i="string"==typeof n?e[n]:n;o.length=0,i.length=0,r&&0<r.length&&r.forEach(function(e){var t=e[a];t&&0<t.length&&(o.push(t),e._id||(e._id=c()),i.push(e._id))})}var $=function(e){var t=!1;return e.needsX?t=!0:e.directive||("text"===e.type?t=!0:"select"!==e.type||e.ids||(t=!0)),t};function C(e,t,n){var r=e.conversions;return n&&(r=w(r,n)||{}),r[t]}var g=function(e,t,n,r,a,o,i){o=o||t;for(var s=0;s<e.length;s++){var l=e[s],c=l.name.slice(n);c.length||(c=l.name.split(".").pop());var d=w(t,c);if("date"===l.intType&&"string"==typeof d&&y(t,c,null,new Date(d)),l.schema){if(d)for(var u=0;u<d.length;u++)d[u]=g(l.schema,d[u],1+c.length,r,c,o,u)}else{l.internalRef&&v(r,l.options,l.ids,o[l.internalRef.property],l.internalRef.value);var f=k(t,c,null,r);if(l.array&&$(l)&&f&&!(0<f.length&&f[0].x))for(var p=0;p<f.length;p++)f[p]={x:f[p]};var m=r[b(l,"_ids")],h=void 0;if(d&&m&&0<m.length){if(-1!==c.indexOf("."))throw new Error("Trying to directly assign to a nested field 332");!d.toString().match(/^[a-f0-9]{24}$/)||l.internalRef&&l.internalRef.noConvert||(t[c]=S(l,d,r[b(l,"Options")],m))}else l.select2?(console.log("fng-select2 is deprecated - use fng-ui-select instead"),l.select2):d&&(h=C(r,c,a))&&h.fngajax&&!h.noconvert&&h.fngajax(d,l,function(e,t){y(o,e.name,i,t),F(angular.element("#"+e.id),function(){y(r.record,e.name,i,t)})})}}return t};function S(e,t,n,r){if(e.array){for(var a=[],o=!e.directive||$(e),i=0;i<t.length;i++){var s=t[i];s&&s.x&&(s=s.x);var l=N(s,r,n,e.name);o&&(l={x:l}),a.push(l)}return a}return e.select2?{id:t,text:N(t,r,n,e.name)}:N(t,r,n,e.name)}function D(e,t,n,r){var a=_.isObject(e)?e.x||e.text:e;if(a&&a.match(/^[0-9a-f]{24}$/))return a;var o=t.indexOf(a);if(-1===o)throw new Error("convertListValueToId: Invalid data - value "+a+" not found in "+t+" processing "+r);return n[o]}function h(e,t,n){n.master=g(t.formSchema,e,0,t),t.phase="ready",t.cancel()}var F=function(e,t){var n=e.inheritedData("$ngModelController"),r=n&&n.$pristine;r&&(n.$pristine=!1),t(),r&&(n.$pristine=!0)},N=function(e,t,n,r){"object"==typeof e&&(e=e.id);var a=t.indexOf(e);if(-1===a&&-1===(a=n.indexOf(e)))throw new Error("convertIdToListValue: Invalid data - id "+e+" not found in "+t+" processing "+r);return n[a]};function E(t,n,r,e,a){if(a&&0<a.length&&a.length===e.length&&n[r]){var o=a.findIndex(function(e){return e[t.value]===n[r]});if(-1<o){var i=e[o][t.value];i&&(n[r]=i)}}}function L(e,u,n,t,f){var r=!u.id&&!u.newRecord;function a(o,d){u.internalLookups.forEach(function(n){var r=o[n.ref.property],a=d[n.ref.property];v(u,n.lookupOptions,n.lookupIds,r,n.ref.value),(r&&0<r.length||a&&0<a.length)&&n.handlers.forEach(function(t){if(t.possibleArray){var e=w(u.record,t.possibleArray,null);e&&0<e.length&&e.forEach(function(e){return E(n.ref,e,t.lastPart,r,a)})}else angular.isArray(u.record[t.lastPart])?u.record[t.lastPart].forEach(function(e){E(n.ref,e,"x",r,a)}):E(n.ref,u.record,t.lastPart,r,a)})}),u.listLookups.forEach(function(l){function e(e,t){var n=e[t];return n&&n.id&&(n=n.id),n}function c(e){y(u.record,e.name)}var t=l.ref.id.slice(1);if(t.includes("."))throw new Error("No support for nested list lookups yet - "+JSON.stringify(l.ref));var n=e(o,t);n!==e(d,t)&&(l.handlers.forEach(function(e){u[e.formInstructions.options].length=0,u[e.formInstructions.ids].length=0}),n?p.readRecord(l.ref.collection,n).then(function(s){l.handlers.forEach(function(e){for(var t=u[e.formInstructions.options],n=u[e.formInstructions.ids],r=s.data[l.ref.property]||[],a=0;a<r.length;a++){var o=r[a][l.ref.value],i=_.sortedIndex(t,o);t[i]===o&&(o=o+" ("+r[a]._id+")",i=_.sortedIndex(t,o)),t.splice(i,0,o),n.splice(i,0,r[a]._id)}0===Object.keys(d).length?m(e.formInstructions,u,f,!0):c(e.formInstructions)})}):l.handlers.forEach(function(e){c(e.formInstructions)}))})}function o(){u.phase="ready",u.cancel(),a(u.record,{})}if(n.handleSchema("Main "+u.modelName,e,r?null:u.formSchema,u.listSchema,"",!0,u,f),r)f.allowLocationChange=!0;else{var i=!0;if(u.newRecord||(u.dropConversionWatcher=u.$watchCollection("conversions",function(e,t){e!==t&&u.originalData&&h(u.originalData,u,f)})),u.$watch("record",function(e,t){e!==t&&(0<Object.keys(t).length&&u.dropConversionWatcher&&(u.dropConversionWatcher(),u.dropConversionWatcher=null),i=n.updateDataDependentDisplay(e,t,i,u),a(e,t))},!0),u.id)"function"==typeof u.dataEventFunctions.onBeforeRead?u.dataEventFunctions.onBeforeRead(u.id,function(e){e?u.showError(e):t.readRecord(u,f)}):t.readRecord(u,f);else{f.allowLocationChange=!1,f.master=u.setDefaults(u.formSchema);var s=u.initialiseNewRecord||l.$$search.r;if(s)try{Object.assign(f.master,JSON.parse(s)),u.newRecordsStartPristine||u.$on("fngCancel",function(){d(function(){u[u.topLevelFormName]&&u[u.topLevelFormName].$setDirty()},1e3)})}catch(e){console.log("Error parsing specified record : "+e.message)}"function"==typeof u.dataEventFunctions.onInitialiseNewRecord&&(console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)"),u.dataEventFunctions.onInitialiseNewRecord(f.master)),"function"==typeof u.dataEventFunctions.onNewRecordInit?u.dataEventFunctions.onNewRecordInit(f.master,function(e){e?u.showError(e):o()}):o()}}}function t(r){return function(e){if(-1!==[200,400].indexOf(e.status)){var t="";for(var n in e.data.errors)if(e.data.errors.hasOwnProperty(n)){switch(t+="<li><b>"+a("titleCase")(n)+": </b> ",e.data.errors[n].type){case"enum":t+="You need to select from the list of values";break;default:t+=e.data.errors[n].message}t+="</li>"}t=0<t.length?e.data.message+"<br /><ul>"+t+"</ul>":e.data.message||e.data.err||"Error! Sorry - No further details available.",r.showError(t)}else r.showError(e.status+" "+JSON.stringify(e.data))}}function A(e,t,n){n.allowLocationChange=!1,t.phase="reading","function"==typeof t.dataEventFunctions.onAfterRead&&t.dataEventFunctions.onAfterRead(e),t.originalData=e,h(e,t,n)}function r(e,t,n,r){var a=t.name.split("."),o=r.find(function(e){return e.ref.property===n.property&&e.ref.value===n.value}),i={formInstructions:t,lastPart:a.pop(),possibleArray:a.join(".")};o||(o={ref:n,lookupOptions:[],lookupIds:[],handlers:[]},r.push(o)),o.handlers.push(i),e[t.options]=o.lookupOptions,e[t.ids]=o.lookupIds}return{readRecord:function(t,n){t.readingRecord=p.readRecord(t.modelName,t.id),t.readingRecord.then(function(e){A(angular.copy(e.data),t,n)},function(e){404===e.status?l.path("/404"):t.handleHttpError(e)})},scrollTheList:function(n){var r=n.pagesLoaded;p.getPagedAndFilteredList(n.modelName,{aggregate:l.$$search.a,find:l.$$search.f,limit:n.pageSize,skip:r*n.pageSize,order:l.$$search.o}).then(function(e){var t=e.data;angular.isArray(t)?r===n.pagesLoaded?(n.pagesLoaded++,n.recordList=n.recordList.concat(t)):console.log("DEBUG: infinite scroll component asked for a page twice - the model was "+n.modelName):n.showError(t,"Invalid query")},n.handleHttpError)},deleteRecord:function(e,t,n){p.deleteRecord(t.modelName,e).then(function(){"function"==typeof t.dataEventFunctions.onAfterDelete&&t.dataEventFunctions.onAfterDelete(n.master),i.redirectTo()("onDelete",t,l)},function(e){404===e.status?i.redirectTo()("onDelete",t,l):t.showError(e.statusText+" ("+e.status+") while deleting record<br />"+e.data,"Error deleting record")})},updateDocument:function(e,n,r,a){r.phase="updating",p.updateRecord(r.modelName,r.id,e).then(function(e){var t=e.data;!1!==t.success?("function"==typeof r.dataEventFunctions.onAfterUpdate&&r.dataEventFunctions.onAfterUpdate(t,a.master),n.redirect?(n.allowChange&&(a.allowLocationChange=!0),o.location=n.redirect):(A(t,r,a),r.setPristine(!1))):r.showError(t)},r.handleHttpError)},createNew:function(e,n,r,a){p.createRecord(r.modelName,e).then(function(e){var t=e.data;!1!==t.success?(a.allowLocationChange=!0,"function"==typeof r.dataEventFunctions.onAfterCreate&&r.dataEventFunctions.onAfterCreate(t),n.redirect?o.location=n.redirect:i.redirectTo()("edit",r,l,t._id)):r.showError(t)},r.handleHttpError)},getListData:k,suffixCleanId:b,setData:y,setUpLookupOptions:function(n,l,c,d,r){var u=c[l.options]=[],f=c[l.ids]=[];e.getSchema(n).then(function(e){var t=e.data,s=[];r("Lookup "+n,t,null,s,"",!1,c,d),(void 0!==l.filter&&l.filter?p.getPagedAndFilteredList(n,l.filter):p.getAll(n)).then(function(e){var t=angular.copy(e.data);if(t){for(var n=0;n<t.length;n++){for(var r="",a=0;a<s.length;a++){var o=t[n][s[a].name];r+=o?o+" ":""}r=r.trim();var i=_.sortedIndex(u,r);u[i]===r&&(r=r+" ("+t[n]._id+")",i=_.sortedIndex(u,r)),u.splice(i,0,r),f.splice(i,0,t[n]._id)}c.readingRecord&&c.readingRecord.then(function(){m(l,c,d)})}})})},setUpLookupListOptions:function(o,i,s,l){var c=s[i.options]=[],d=s[i.ids]=[];"$"===o.id[0]?r(s,i,o,s.listLookups):p.readRecord(o.collection,s.$eval(o.id)).then(function(e){for(var t=e.data[o.property],n=0;n<t.length;n++){var r=t[n][o.value],a=_.sortedIndex(c,r);c[a]===r&&(r=r+" ("+t[n]._id+")",a=_.sortedIndex(c,r)),c.splice(a,0,r),d.splice(a,0,t[n]._id)}m(i,s,l)})},handleInternalLookup:function(e,t,n){r(e,t,n,e.internalLookups)},preservePristine:F,convertToMongoModel:function d(u,f,p,m,h){function v(e,t){var n;return t&&t.fngajax?e&&(n=e.id||e):e&&(n=e.text||(e.x?e.x.text:e)),n}function e(){var t=u[g],e=t.name.slice(p),n=k(f,e,null,m);if(t.schema){if(n)for(var r=0;r<n.length;r++)n[r]=d(t.schema,n[r],1+e.length,m,e)}else{if(t.array&&$(t)&&n)for(var a=0;a<n.length;a++)n[a]=n[a].x;var o=m[b(t,"_ids")];if(o&&0<o.length)x(e,f,function(e){return function(e,t,n,r){if(e.array){for(var a=[],o=0;o<t.length;o++)a.push(D(t[o],n,r,e.name));return a}return D(t,n,r,e.name)}(t,e,m[b(t,"Options")],o)});else{var i=C(m,e,h);if(i){var s=w(f,e,null),l=void 0;if(t.array){if(l=[],s)for(var c=0;c<s.length;c++)l[c]=v(s[c],i)}else l=v(s,i);y(f,e,null,l)}}}}for(var g=0;g<u.length;g++)e();return f},convertIdToListValue:N,handleError:t,decorateScope:function(c,n,r,a){c.handleHttpError=t(c),c.cancel=function(){angular.copy(a.master,c.record),c.$broadcast("fngCancel",c),d(c.setPristine)},c.$on("showErrorMessage",function(e,t){e.defaultPrevented||(e.defaultPrevented=!0,c.showError(t.body,t.title))}),c.showError=function(t,e){if(c.alertTitle=e||"Error!","string"==typeof t)c.errorMessage=t;else if(t)if(t.message&&"string"==typeof t.message)c.errorMessage=t.message;else if(t.data&&t.data.message)c.errorMessage=t.data.message;else try{c.errorMessage=JSON.stringify(t)}catch(e){c.errorMessage=t}else c.errorMessage="An error occurred - that's all we got. Sorry.";c.errorHideTimer=window.setTimeout(function(){c.dismissError(),c.$digest()},3500+1e3*(c.alertTitle+c.errorMessage).length/50),c.errorVisible=!0,window.setTimeout(function(){c.$digest()})},c.clearTimeout=function(){c.errorHideTimer&&(clearTimeout(c.errorHideTimer),delete c.errorHideTimer)},c.dismissError=function(){c.clearTimeout,c.errorVisible=!1,delete c.errorMessage,delete c.alertTitle},c.stickError=function(){clearTimeout(c.errorHideTimer)},c.prepareForSave=function(t){var n=r.convertToMongoModel(c.formSchema,angular.copy(c.record),0,c);c.id?"function"==typeof c.dataEventFunctions.onBeforeUpdate?c.dataEventFunctions.onBeforeUpdate(n,a.master,function(e){e?t(e):t(null,n)}):t(null,n):"function"==typeof c.dataEventFunctions.onBeforeCreate?c.dataEventFunctions.onBeforeCreate(n,function(e){e?t(e):t(null,n)}):t(null,n)},c.save=function(n){n=n||{},c.prepareForSave(function(e,t){e?"_update_handled_"!==e&&d(function(){c.showError(e)}):c.id?r.updateDocument(t,n,c,a):r.createNew(t,n,c,a)})},c.newClick=function(){i.redirectTo()("new",c,l)},c.$on("$locationChangeStart",function(e,t){a.allowLocationChange||c.isCancelDisabled()||(e.preventDefault(),n.open({template:'<div class="modal-header">\n <h3>Record modified</h3>\n</div>\n<div class="modal-body">\n <p>Would you like to save your changes?</p>\n</div>\n<div class="modal-footer">\n <button class="btn btn-primary dlg-yes" ng-click="yes()">Yes</button>\n <button class="btn btn-warning dlg-no" ng-click="no()">No</button>\n <button class="btn dlg-cancel" ng-click="cancel()">Cancel</button>\n</div>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result.then(function(e){e?c.save({redirect:t,allowChange:!0}):(a.allowLocationChange=!0,o.location=t)}).catch(u))}),c.deleteClick=function(){if(c.record._id){var e=void 0;if(c.unconfirmedDelete)e=Promise.resolve(!0);else e=n.open({template:'<div class="modal-header">\n <h3>Delete Item</h3>\n</div>\n<div class="modal-body">\n <p>Are you sure you want to delete this record?</p>\n</div>\n<div class="modal-footer">\n <button class="btn btn-primary dlg-no" ng-click="cancel()">No</button>\n <button class="btn btn-warning dlg-yes" ng-click="yes()">Yes</button>\n</div>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result;e.then(function(e){function t(){r.deleteRecord(c.id,c,a)}e&&("function"==typeof c.dataEventFunctions.onBeforeDelete?c.dataEventFunctions.onBeforeDelete(a.master,function(e){e?"_delete_handled_"!==e&&c.showError(e):t()}):t())}).catch(u)}},c.isCancelDisabled=function(){return!(!c[c.topLevelFormName]||!c[c.topLevelFormName].$pristine)||"function"==typeof c.disableFunctions.isCancelDisabled&&c.disableFunctions.isCancelDisabled(c.record,a.master,c[c.topLevelFormName])},c.isSaveDisabled=function(){c.whyDisabled=void 0;var e=!1;if(c[c.topLevelFormName]?c[c.topLevelFormName].$invalid?(c.whyDisabled="The form data is invalid:",function n(e,r){e.$$controls.forEach(function(e){if(e.$invalid)if(e.$$controls)n(e,e.$name);else if(c.whyDisabled+="<br /><strong>",r&&(c.whyDisabled+=r+" "),"bs2"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().find("label")&&e.$$element.parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().find("label").text():"bs3"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().parent()&&e.$$element.parent().parent().parent().find("label")&&e.$$element.parent().parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().parent().find("label").text():c.whyDisabled+=e.$name,c.whyDisabled+="</strong>: ",e.$error)for(var t in e.$error)if(e.$error.hasOwnProperty(t))switch(t){case"required":c.whyDisabled+="Field missing required value. ";break;case"pattern":c.whyDisabled+="Field does not match required pattern. ";break;default:c.whyDisabled+=t+". "}})}(c[c.topLevelFormName])):c[c.topLevelFormName].$pristine&&(e=!0):c.whyDisabled="Top level form name invalid",e||c.whyDisabled)return!0;if("function"!=typeof c.disableFunctions.isSaveDisabled)return!1;var t=c.disableFunctions.isSaveDisabled(c.record,a.master,c[c.topLevelFormName]);return c.whyDisabled="string"==typeof t?t:"An application level user-specified function is inhibiting saving the record",!!t},c.isDeleteDisabled=function(){return!c.id||"function"==typeof c.disableFunctions.isDeleteDisabled&&c.disableFunctions.isDeleteDisabled(c.record,a.master,c[c.topLevelFormName])},c.isNewDisabled=function(){return"function"==typeof c.disableFunctions.isNewDisabled&&c.disableFunctions.isNewDisabled(c.record,a.master,c[c.topLevelFormName])},c.setDefaults=function(e,t){void 0===t&&(t="");var n={};return e.forEach(function(e){void 0!==e.defaultValue&&(n[e.name.replace(t,"")]=e.defaultValue)}),n},c.getVal=function(e,t){if(-1===e.indexOf("$index")||void 0!==t)return e=e.replace(/\$index/g,t),c.$eval("record."+e)},c.sortableOptions={update:function(){c.topLevelFormName&&c[c.topLevelFormName].$setDirty()}},c.setUpCustomLookupOptions=function(e,t,n,r){for(var a=0,o=[c,r];a<o.length;a++){var i=o[a];i&&(i[e.ids]=t,i[e.options]=n)}var s=w(c.record,e.name);if(s){if(angular.isArray(s))for(var l=0;l<s.length;l++)s[l]=N(s[l],t,n,e.name);else s=N(s,t,n,e.name);y(c.record,e.name,void 0,s)}}},fillFormFromBackendCustomSchema:L,fillFormWithBackendSchema:function(t,n,r,a){e.getSchema(t.modelName,t.formName).then(function(e){L(e.data,t,n,r,a)},t.handleHttpError)}}}t=e.services||(e.services={}),n.$inject=["$location","$window","$filter","$timeout","routingService","cssFrameworkService","SubmissionsService","SchemasService"],t.recordHandler=n}(fng=fng||{}),function(e){var t;function n(n){return{getSchema:function(e,t){return n.get("/api/schema/"+e+(t?"/"+t:""),{cache:!0})}}}t=e.services||(e.services={}),n.$inject=["$http"],t.SchemasService=n}(fng=fng||{}),function(e){var t;function n(r,a){function n(e){function t(e,t){void 0!==t&&""!==t&&("object"==typeof t&&(t=JSON.stringify(t)),""===n?n="?":n+="&",n+=e+"="+t)}var n="";return t("l",e.limit),t("f",e.find),t("a",e.aggregate),t("o",e.order),t("s",e.skip),n}var o=!0;return{getListAttributes:function(e,t){return r.get("/api/"+e+"/"+t+"/list")},readRecord:function(e,t){return r.get("/api/"+e+"/"+t)},getAll:function(e,t){var n=angular.extend({cache:o},t);return r.get("/api/"+e,n)},getPagedAndFilteredList:function(e,t){return r.get("/api/"+e+n(t))},deleteRecord:function(e,t){return r.delete("/api/"+e+"/"+t)},updateRecord:function(e,t,n){return a.get("$http").remove("/api/"+e),r.post("/api/"+e+"/"+t,n)},createRecord:function(e,t){return a.get("$http").remove("/api/"+e),r.post("/api/"+e,t)},useCache:function(e){o=e},getCache:function(){return!!a.get("$http")},clearCache:function(){a.get("$http").removeAll()}}}t=e.services||(e.services={}),n.$inject=["$http","$cacheFactory"],t.SubmissionsService=n}(fng=fng||{}),function(f){var e;function t(t,n,e,r,a,o,i,s,l){t.sharedData={record:{},disableFunctions:{},dataEventFunctions:{},modelControllers:[]};var c={master:{},fngInvalidRequired:"fng-invalid-required",allowLocationChange:!0};t.errorVisible=!1,angular.extend(t,i.parsePathFunc()(e.$$path));var d=r("titleCase")(t.modelName,!0);function u(){l.fillFormWithBackendSchema(t,s,l,c);for(var e=0;e<t.sharedData.modelControllers.length;e++)t.sharedData.modelControllers[e].onBaseCtrlReady&&t.sharedData.modelControllers[e].onBaseCtrlReady(t);t.$on("$destroy",function(){t.sharedData.modelControllers.forEach(function(e){return e.$destroy()}),n.$broadcast("fngControllersUnloaded")})}o.loadControllerAndMenu(t.sharedData,d,0,!1,t.$new()),t.formName&&o.loadControllerAndMenu(t.sharedData,d+r("titleCase")(t.formName,!0),1,!1,t.$new()),n.$broadcast("fngControllersLoaded",t.sharedData,t.modelName),t.modelNameDisplay=t.sharedData.modelNameDisplay||r("titleCase")(t.modelName),n.$broadcast("fngFormLoadStart",t),s.decorateScope(t,s,l,t.sharedData),l.decorateScope(t,a,l,c),"function"==typeof f.formsAngular.beforeProcess?f.formsAngular.beforeProcess(t,function(e){e?t.showError(e.message,"Error preparing to process form"):u()}):u()}e=f.controllers||(f.controllers={}),t.$inject=["$scope","$rootScope","$location","$filter","$uibModal","fngModelCtrlService","routingService","formGenerator","recordHandler"],e.BaseCtrl=t}(fng=fng||{}),function(e){var t;function n(e,t){e.yes=function(){t.close(!0)},e.no=function(){t.close(!1)},e.cancel=function(){t.dismiss("cancel")}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$uibModalInstance"],t.SaveChangesModalCtrl=n}(fng=fng||{}),function(e){var t;function n(t,e,n,r){t.models=[],e.get("/api/models").then(function(e){t.models=e.data},function(){n.path("/404")}),t.newUrl=function(e){return r.buildUrl(e+"/new")},t.listUrl=function(e){return r.buildUrl(e)}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.ModelCtrl=n}(fng=fng||{}),function(e){var t;function n(e,i,t,r,n,a){function o(){i.items=[],i.contextMenu=void 0}e.navScope=i,o(),i.toggleCollapsed=function(){i.collapsed=!i.collapsed},i.isCollapsed=!0,i.showShortcuts=!1,i.shortcuts=[{key:"?",act:"Show shortcuts"},{key:"/",act:"Jump to search"},{key:"Ctrl+Shift+S",act:"Save the current record"},{key:"Ctrl+Shift+Esc",act:"Cancel changes on the current record"},{key:"Ctrl+Shift+Ins",act:"Create a new record"},{key:"Ctrl+Shift+X",act:"Delete the current record"}],i.markupShortcut=function(e){return'<span class="key">'+e.split("+").join('</span> + <span class="key">')+"</span>"},i.globalShortcuts=function(n){function e(e){var t=document.getElementById(e);t&&(t.disabled||setTimeout(function(){t.click()}),n.preventDefault())}if(191===n.keyCode&&(!("INPUT"==(a=(r=n).target.tagName)||"SELECT"==a||"TEXTAREA"==a||"DIV"==a&&r.target.classList.contains("ck-editor__editable"))||n.ctrlKey&&!n.altKey&&!n.metaKey))if(n.ctrlKey||!n.shiftKey){var t=document.getElementById("searchinput");t&&(t.focus(),n.preventDefault())}else i.showShortcuts=!0;else 83===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("saveButton"):27===n.keyCode&&(n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey||i.showShortcuts)?n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("cancelButton"):i.showShortcuts=!1:45===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("newButton"):88===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey&&e("deleteButton");var r,a},i.css=function(e,t){return"function"==typeof a[e]?a[e](t):"error text-error"},i.$on("fngControllersLoaded",function(e,t,n){i.contextMenu=t.dropDownDisplay||t.modelNameDisplay||r("titleCase")(n,!1),t.dropDownDisplayPromise&&t.dropDownDisplayPromise.then(function(e){i.contextMenu=e})}),i.$on("fngControllersUnloaded",function(e){o()}),i.doClick=function(e,t){var n=angular.element(t.target),r=i.items[e];if(r.divider||n.parent().hasClass("disabled"))t.preventDefault();else if(r.broadcast)i.$broadcast(r.broadcast);else{var a=r.args||[],o=r.fn;if("function"==typeof o)switch(a.length){case 0:o();break;case 1:o(a[0]);break;case 2:o(a[0],a[1]);break;case 3:o(a[0],a[1],a[2]);break;case 4:o(a[0],a[1],a[2],a[3])}else if(o)throw new Error("Incorrect menu setup")}},i.isHidden=function(e){function t(e){return!!e.isHidden&&e.isHidden()}var n=!1;if(i.items[e].divider)if(0===e)n=!0;else for(var r=!1,a=e-1;0<=a&&!n&&!r;)i.items[a].divider?n=!0:t(i.items[a])?--a:r=!0;return n||t(i.items[e])},i.isDisabled=function(e){return!!i.items[e].isDisabled&&i.items[e].isDisabled()},i.buildUrl=function(e){return n.buildUrl(e)},i.dropdownClass=function(e){var t="";return i.items[e].divider?t="divider":i.isDisabled(e)&&(t="disabled"),t}}t=e.controllers||(e.controllers={}),n.$inject=["$rootScope","$scope","$location","$filter","routingService","cssFrameworkService"],t.NavCtrl=n}(fng=fng||{}),function(e){e.formsAngular=angular.module("formsAngular",["ngSanitize","ngMessages","ui.bootstrap","infinite-scroll","monospaced.elastic"]).controller("BaseCtrl",e.controllers.BaseCtrl).controller("SaveChangesModalCtrl",e.controllers.SaveChangesModalCtrl).controller("LinkCtrl",e.controllers.LinkCtrl).controller("ModelCtrl",e.controllers.ModelCtrl).controller("NavCtrl",e.controllers.NavCtrl).directive("modelControllerDropdown",e.directives.modelControllerDropdown).directive("errorDisplay",e.directives.errorDisplay).directive("fngLink",e.directives.fngLink).directive("formInput",e.directives.formInput).directive("formButtons",e.directives.formButtons).directive("globalSearch",e.directives.globalSearch).directive("fngNakedDate",e.directives.fngNakedDate).filter("camelCase",e.filters.camelCase).filter("titleCase",e.filters.titleCase).filter("extractTimestampFromMongoID",e.filters.extractTimestampFromMongoID).service("addAllService",e.services.addAllService).provider("cssFrameworkService",e.services.cssFrameworkService).provider("routingService",e.services.routingService).factory("fngModelCtrlService",e.services.fngModelCtrlService).factory("formGenerator",e.services.formGenerator).factory("formMarkupHelper",e.services.formMarkupHelper).factory("inputSizeHelper",e.services.inputSizeHelper).factory("pluginHelper",e.services.pluginHelper).factory("recordHandler",e.services.recordHandler).factory("SchemasService",e.services.SchemasService).factory("SubmissionsService",e.services.SubmissionsService)}(fng=fng||{});var formsAngular=fng.formsAngular;angular.module("formsAngular").run(["$templateCache",function(e){e.put("base-analysis.html",'<div ng-controller="AnalysisCtrl">\n <error-display></error-display>\n <div class="container-fluid page-header report-header">\n <div ng-class="css(\'rowFluid\')">\n <div class="header-lhs col-xs-7 span7">\n <h1>{{ titleWithSubstitutions }}</h1>\n </div>\n <div class="header-rhs col-xs-5 span5">\n <form-input schema="paramSchema" name="paramForm" ng-show="paramSchema" formstyle="horizontalCompact"></form-input>\n </div>\n </div>\n </div>\n <div class="container-fluid page-body report-body">\n <div class="row-fluid report-grow">\n <div class="gridStyle" style="height:100%;" ui-grid="gridOptions" ui-grid-selection ui-grid-resize-columns></div>\n </div>\n </div>\n</div>\n'),e.put("base-edit.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span id="header-data-desc">\n <span ng-show="!!editFormHeader" >{{ editFormHeader() }}</span>\n <span ng-hide="!!editFormHeader" ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </span>\n </h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <div form-buttons></div>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact"></form-input>\n </div>\n\x3c!-- <pre>--\x3e\n \x3c!--Record--\x3e\n \x3c!--{{ record | json }}--\x3e\n \x3c!--formSchema--\x3e\n \x3c!--{{ formSchema | json }}--\x3e\n\x3c!-- </pre>--\x3e\n</div>\n'),e.put("base-list-view.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateViewUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n'),e.put("base-list.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <a ng-href="{{generateNewUrl()}}"><button id="newBtn" class="btn btn-default"><i class="icon-plus"></i> New</button></a>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateEditUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n'),e.put("base-view.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </h1>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact" viewform="true"></form-input>\n </div>\n</div>\n'),e.put("error-display-bs2.html",'<div id="display-error" ng-show="errorVisible" class="row-fluid ng-hide">\n <div class="alert alert-error offset1 span10">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="icon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="icon-eye-open"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n'),e.put("error-display-bs3.html",'<div id="display-error" ng-show="errorVisible" class="row ng-hide">\n <div class="alert alert-error col-md-offset-1 col-md-10 alert-danger">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="glyphicon glyphicon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="glyphicon glyphicon-pushpin"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n'),e.put("error-messages.html",'<div ng-message="required">A value is required for this field</div>\n<div ng-message="minlength">Too few characters entered</div>\n<div ng-message="maxlength">Too many characters entered</div>\n<div ng-message="min">That value is too small</div>\n<div ng-message="max">That value is too large</div>\n<div ng-message="email">You need to enter a valid email address</div>\n<div ng-message="pattern">This field does not match the expected pattern</div>\n'),e.put("form-button-bs2.html",'<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-mini btn-primary form-btn" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="icon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-mini btn-warning form-btn" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="icon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-mini btn-success form-btn" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="icon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-mini btn-danger form-btn" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="icon-minus"></i> Delete</button>\n </div>\n</div>\n'),e.put("form-button-bs3.html",'<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-primary form-btn btn-xs" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="glyphicon glyphicon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-warning form-btn btn-xs" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="glyphicon glyphicon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-success form-btn btn-xs" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="glyphicon glyphicon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-danger form-btn btn-xs" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="glyphicon glyphicon-minus"></i> Delete</button>\n </div>\n</div>\n'),e.put("search-bs2.html",'<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n'),e.put("search-bs3.html",'<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n')}]);
1
+ var fng;!function(e){(e.directives||(e.directives={})).modelControllerDropdown=function(){return{restrict:"AE",replace:!0,template:'<li ng-show="items.length > 0" class="mcdd" uib-dropdown> <a href="#" uib-dropdown-toggle> {{contextMenu}} <b class="caret"></b> </a> <ul class="uib-dropdown-menu dropdown-menu"> <li ng-repeat="choice in items" ng-hide="isHidden($index)" ng-class="dropdownClass($index)"> <a ng-show="choice.text" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event)"> {{choice.text}} </a> </li> </ul></li>'}}}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"E",templateUrl:"error-display-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.errorDisplay=n}(fng=fng||{}),function(e){var t;function n(a){a.checkNotModal=function(){for(var e,t=a.element[0],n=!1,r={preventDefault:angular.noop,stopPropagation:angular.noop,target:1,currentTarget:1};(e=t.parentNode)?"function"==typeof e.getAttribute&&e.getAttribute("uib-modal-window")?(angular.element(t).scope().close(r),n=!0):t=e:n=!0,!n;);}}t=e.controllers||(e.controllers={}),n.$inject=["$scope"],t.LinkCtrl=n}(fng=fng||{}),function(e){var t;function n(p,m){return{restrict:"E",scope:{dataSrc:"&model"},link:function(n,e,r){var a=r.ref,t=r.text&&unescape(r.text)!==r.text,o=r.form,i=r.linktab;if(n.readonly=r.readonly,n.element=e,o=o?o+"/":"",i=i?"/"+i:"",t){for(var s=n,l="";"function"!=typeof s.baseSchema&&s.$parent;){if(void 0!==s.$index)throw new Error("No support for $index at this level - "+l);s=s.$parent,l+="$parent."}var c,d=r.fld,u=d.split(".");c=n.$parent.subDoc&&(n.$parent.subDoc[d]||n.$parent.subDoc[u[u.length-1]])?n.$parent.subDoc[d]?l+"subDoc."+d:l+"subDoc."+u[u.length-1]:l+"record"+(d=void 0!==s.$index?(d=u.pop(),u.join(".")+"["+s.$index+"]."+d):"."+d),n.$watch(c,function(e){if(e){if(/^[a-f0-9]{24}/.test(e.toString()))e=e.slice(0,24);else if(e.id&&/^[a-f0-9]{24}/.test(e.id))e=e.id.slice(0,24);else if(n.$parent["f_"+r.fld+"Options"]){var t=n.$parent["f_"+r.fld+"Options"].indexOf(e);e=-1<t?n.$parent["f_"+r.fld+"_ids"][t]:void 0}else e=void 0;n.link=e?p.buildUrl(a+"/"+o+(e.id||e)+"/edit"+i):void 0}else n.link=void 0},!0)}else{r.text&&0<r.text.length&&(n.text=r.text);var f=n.$parent.$index;n.$watch("dataSrc()",function(e){e&&(void 0!==f&&angular.isArray(e)&&(e=e[f]),n.link=p.buildUrl(a+"/"+o+e+"/edit"+i),n.text||m.getListAttributes(a,e).then(function(e){var t=e.data;!1===t.success?n.text=t.err:n.text=t.list},function(e){n.text="Error "+e.status+": "+e.data}))},!0)}},controller:"LinkCtrl",template:function(e,t){function n(e){return'<a ng-click="checkNotModal()" ng-href="{{ link || \'#\' }}" class="fng-link">'+e+"</a>"}return t.readonly?'<span class="fng-link">{{text}}</span>':t.text&&unescape(t.text)!==t.text?n(unescape(t.text)):n("{{text}}")}}}t=e.directives||(e.directives={}),n.$inject=["routingService","SubmissionsService"],t.fngLink=n}(fng=fng||{}),function(e){var t;function n(e){return{restrict:"A",templateUrl:"form-button-"+e.framework()+".html"}}t=e.directives||(e.directives={}),n.$inject=["cssFrameworkService"],t.formButtons=n}(fng=fng||{}),function(e){var t,I,n;function r(c,d,E,L,A,u,O){return{restrict:"EA",link:function(k,x,s){function b(t,e,n,r,a){function o(){var e;if(angular.isArray(k[t.options]))e={repeat:t.options,value:"option"};else{if(!k[t.options]||!angular.isArray(k[t.options].values))throw new Error("Invalid enumeration setup in field "+t.name);e=angular.isArray(k[t.options].labels)?{repeat:t.options+".values",value:t.options+".values[$index]",label:t.options+".labels[$index]"}:{repeat:t.options+".values",value:t.options+".values[$index]"}}return e}var i;if(!e){var s=(a.model||"record")+".";if(e=s,a.subschema&&-1!==t.name.indexOf(".")){var l=t.name,c=a.subschemaroot,d=l.slice(c.length+1);a.index?r="f_"+(e+=c+"["+a.index+"]."+d).slice(s.length).replace(/(\.|\[|]\.)/g,"-"):(e+=c,a.subkey?(r=e.slice(s.length).replace(/\./g,"-")+"-subkey"+a.subkeyno+"-"+d,e+="[$_arrayOffset_"+c.replace(/\./g,"_")+"_"+a.subkeyno+"]."+d):(e+="[$index]."+d,r=null,i=l.replace(/\./g,"-")))}else e+=t.name}var u,f,p=O.allInputsVars(k,t,a,e,r,i),m=p.common,h=(n=n||t.required)?" required ":"";function v(e){var t="";return e&&(t="boolean"==typeof e?" disabled ":' ng-disabled="'+e+'" '),t}switch(t.type){case"select":t.select2?u='<input placeholder="fng-select2 has been removed" readonly>':(m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",m+=' aria-label="'+(t.label&&""!==t.label?t.label:t.name)+'" ',u="<select "+m+'class="'+p.formControl.trim()+p.compactClass+p.sizeClassBS2+'" '+h+">",n||(u+="<option></option>"),angular.isArray(t.options)?angular.forEach(t.options,function(e){_.isObject(e)?u+='<option value="'+(e.val||e.id)+'">'+(e.label||e.text)+"</option>":u+="<option>"+e+"</option>"}):(f=o(),u+='<option ng-repeat="option in '+f.repeat+'"',f.label?u+=' value="{{'+f.value+'}}"> {{ '+f.label+" }} </option> ":u+=">{{"+f.value+"}}</option> "),u+="</select>");break;case"link":u='<fng-link model="'+e+'" ref="'+t.ref+'"',t.form&&(u+=' form="'+t.form+'"'),t.linktab&&(u+=' linktab="'+t.linktab+'"'),t.linktext&&(u+=' text="'+t.linktext+'"'),t.readonly&&("boolean"==typeof t.readonly?u+=' readonly="true"':u+=' ng-readonly="'+t.readonly+'"'),u+="></fng-link>";break;case"radio":u="",m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"";var g="vertical"===a.formstyle||"inline"!==a.formstyle&&!t.inlineRadio;if(angular.isArray(t.options)){var b;a.subschema&&(m=(m=m.replace('name="','name="{{$index}}-')).replace('id="','id="{{$index}}-')),angular.forEach(t.options,function(e,t){b=m.replace('id="','id="'+t+"-"),u+="<input "+b+' type="radio" aria-label="'+e+'" value="'+e+'">'+e,g&&(u+="<br />")})}else{var y=g?"div":"span";a.subschema&&(m=m.replace("$index","$parent.$index").replace('name="','name="{{$parent.$index}}-').replace('id="','id="{{$parent.$index}}-')),f=o(),u+="<"+y+' ng-repeat="option in '+f.repeat+'">',u+="<input "+m.replace('id="','id="{{$index}}-')+' type="radio" aria-label="'+f.value+'" value="{{ '+f.value+' }}"> {{ '+(f.label||f.value)+" }} </"+y+"> "}break;case"checkbox":m+=h,m+=v(t.readonly),m+=t.add?" "+t.add+" ":"",u=O.generateSimpleInput(m,t,a),"bs3"===A.framework()&&(u='<div class="checkbox">'+u+"</div>");break;default:m+=O.addTextInputMarkup(p,t,h),u="textarea"===t.type?(t.rows&&("auto"===t.rows?m+='msd-elastic="\n" class="ng-animate" ':m+='rows = "'+t.rows+'" '),"ckEditor"===t.editor&&(console.log('Deprecation Warning: "editor" property deprecated - use "add"'),m+='ckeditor = "" ',"bs3"===A.framework()&&(p.sizeClassBS3="col-xs-12")),"<textarea "+m+"></textarea>"):O.generateSimpleInput(m,t,a)}return O.inputChrome(u,t,a,p)}function w(e){var t;switch(e){case"horizontal":t="form-horizontal";break;case"vertical":t="";break;case"inline":t="form-inline";break;case"stacked":t="form-stacked";break;case"horizontalCompact":default:t="form-horizontal compact"}return t}function $(e){var t={before:"",after:""};if("function"==typeof e.containerType)t=e.containerType(e);else switch(e.containerType){case"tab":for(var n=-1,r=0;r<k.tabs.length;r++)if(k.tabs[r].title===e.title){n=r;break}0<=n?(t.before='<uib-tab deselect="tabDeselect($event, $selectedIndex)" select="updateQueryForTab(\''+e.title+'\')" heading="'+e.title+'"',0<n&&(t.before+='active="tabs['+n+'].active"'),t.before+=">",t.after="</uib-tab>"):(t.before="<p>Error! Tab "+e.title+" not found in tab list</p>",t.after="");break;case"tabset":t.before="<uib-tabset>",t.after="</uib-tabset>";break;case"well":t.before='<div class="well">',e.title&&(t.before+="<h4>"+e.title+"</h4>"),t.after="</div>";break;case"well-large":t.before='<div class="well well-lg well-large">',t.after="</div>";break;case"well-small":t.before='<div class="well well-sm well-small">',t.after="</div>";break;case"fieldset":t.before="<fieldset>",e.title&&(t.before+="<legend>"+e.title+"</legend>"),t.after="</fieldset>";break;case void 0:case null:case"":break;default:if(t.before='<div class="'+e.containerType+'">',e.title){var a=e.titleTagOrClass||"h4";a.match(/h[1-6]/)?t.before+="<"+a+">"+e.title+"</"+a+">":t.before+='<p class="'+a+'">'+e.title+"</p>"}t.after="</div>"}return t}function C(e,t){var n=O.fieldChrome(k,e,t),r=n.template;if(e.schema){var a=e.name.replace(/\./g,"_"),o="$_schema_"+a;if(k[o]=e.schema,e.schema)if(e.subkey){e.subkey.path=e.name,k[o+"_subkey"]=e.subkey;for(var i=angular.isArray(e.subkey)?e.subkey:[e.subkey],s=0;s<i.length;s++){var l=$(i[s]);r+=l.before,r+=N(e.schema,null,{subschema:"true",formstyle:t.formstyle,subkey:o+"_subkey",subkeyno:s,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),r+=l.after}D.push(e)}else if(t.subschema)t.suppressNestingWarning||console.log("Attempts at supporting deep nesting have been removed - will hopefully be re-introduced at a later date");else{var c=(t.model||"record")+"."+e.name;if("string"==typeof e.customHeader)r+=e.customHeader;else{var d="";e.unshift&&(d='<button id="unshift_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini form-btn" ng-click="unshift(\''+e.name+'\',$event)"><i class="'+O.glyphClass()+'-plus"></i> Add</button>'),"bs3"===A.framework()?r+='<div class="row schema-head"><div class="col-sm-offset-3">'+e.label+d+"</div></div>":r+='<div class="schema-head">'+e.label+d+"</div>"}"inline"===e.formStyle&&e.inlineHeaders&&(r+=function(e,t,n,r){for(var a='<div class="inline-col-headers" style="display:flex" '+(r?"":'ng-hide="!'+n+" || "+n+'.length === 0"')+">",o=0,i=e;o<i.length;o++){var s=i[o];F(s,t),a+="<div ",s.showWhen=s.showWhen||s.showwhen,s.showWhen&&("string"==typeof s.showWhen?a+='ng-show="'+s.showWhen+'"':a+='ng-show="'+O.generateNgShow(s.showWhen,n)+'"'),s.id&&"function"==typeof s.id.replace&&(a+=' id="col_label_'+s.id.replace(/\./g,"-")+'"'),a+=' class="inline-col-header"><label for="'+s.id+'" class="control-label">'+s.label+"</label></div>"}return a+="</div>"}(e.schema,t,c,"always"===e.inlineHeaders)),r+='<ol class="sub-doc"'+(e.sortable?' ui-sortable="sortableOptions" ng-model="'+c+'"':"")+">",r+='<li ng-form class="'+("bs2"===A.framework()?"row-fluid ":"")+(e.inlineHeaders?"width-controlled ":"")+w(e.formStyle)+" "+(e.ngClass?"ng-class:"+e.ngClass:"")+'" name="form_'+a+'{{$index}}" class="sub-doc well" id="'+e.id+'List_{{$index}}" ng-repeat="subDoc in '+c+' track by $index">',"bs2"===A.framework()&&(r+='<div class="row-fluid sub-doc">'),!0===e.noRemove&&!e.customSubDoc||(r+=' <div class="sub-doc-btns">',"string"==typeof e.customSubDoc&&(r+=e.customSubDoc),!0!==e.noRemove&&(r+="<button "+(e.noRemove?'ng-hide="'+e.noRemove+'"':"")+' name="remove_'+e.id+'_btn" ng-click="remove(\''+e.name+"', $index, $event)\"",e.remove?r+=' class="remove-btn btn btn-mini btn-default btn-xs form-btn"><i class="'+O.glyphClass()+'-minus"></i> Remove':(r+=' style="position: relative; z-index: 20;" type="button" class="close pull-right">',"bs3"===A.framework()?r+='<span aria-hidden="true">×</span><span class="sr-only">Close</span>':r+="<span>×</span>"),r+="</button>"),r+="</div> ");var u=void 0;if(e.subDocContainerType){var f=k[e.subDocContainerType]||e.subDocContainerType,p=Object.assign({containerType:f},e.subDocContainerProps);u=$(p)}if(null!=u&&u.before&&(r+=u.before),r+=N(e.schema,!1,{subschema:"true",formstyle:e.formStyle,model:t.model,subschemaroot:e.name,suppressNestingWarning:e.suppressNestingWarning}),null!=u&&u.after&&(r+=u.after),"bs2"===A.framework()&&(r+=" </div>"),r+="</li>",r+="</ol>",!0!==e.noAdd||"string"==typeof e.customFooter||e.noneIndicator){var m="";"string"==typeof e.customFooter&&(m=e.customFooter);var h="",v=c+".length == 0";!0===e.noAdd?v='ng-show="'+v+'"':(h=e.noAdd?'ng-hide="'+e.noAdd+'"':"",v=e.noAdd?'ng-show="'+e.noAdd+" && "+v+'"':"",m+="<button "+h+' id="add_'+e.id+'_btn" class="add-btn btn btn-default btn-xs btn-mini" ng-click="add(\''+e.name+"',$event)\">\n <i class=\"' + formMarkupHelper.glyphClass() + '-plus\"></i> \n Add\n </button>"),e.noneIndicator&&(m+="<span "+v+' class="none_indicator" id="no_'+e.id+'_indicator">None</span>',h=c+".length > 0",h=!0===e.noAdd?'ng-hide="'+h+'"':e.noAdd?'ng-hide="'+e.noAdd+" && "+h+'"':""),""!==m&&("bs3"===A.framework()?r+="<div "+h+' class="row schema-foot"><div class="col-sm-offset-3">'+m+"</div></div>":r+="<div "+h+' class = "schema-foot ">'+m+"</div>")}}}else{var g=O.controlDivClasses(t);if(e.array){if(g.push("fng-array"),"inline"===t.formstyle||"stacked"===t.formstyle)throw new Error("Cannot use arrays in an inline or stacked form");r+=O.label(k,e,"link"!==e.type,t),r+=O.handleArrayInputAndControlDiv(b(e,"link"===e.type?null:"arrayItem.x",!0,e.id+"_{{$index}}",t),g,e,t)}else r+=O.label(k,e,null,t),r+=O.handleInputAndControlDiv(b(e,null,t.required,e.id,t),g)}return r+=n.closeTag}var D=[],S=I.N,F=function(e,t){e.type=e.type||"text",e.id?"number"!=typeof e.id&&!e.id.match(/^[0-9]/)||(e.id="_"+e.id):t&&t.noid?e.id=null:e.id="f_"+e.name.replace(/\./g,"_"),e.label=void 0!==e.label?null===e.label?"":e.label:E("titleCase")(e.name.split(".").slice(-1)[0])},N=function(e,t,n){var r="";if(e)for(var a=0;a<e.length;a++){var o=e[a];n.viewform&&((o=angular.copy(o)).readonly=!0),0===a&&t&&!n.schema.match(/\$_schema_/)&&"object"!=typeof o.add&&(o.add=o.add?" "+o.add+" ":"",-1!==o.add.indexOf("ui-date")||n.noautofocus||o.containerType||(o.add=o.add+"autofocus "));var i=!0;if(o.directive){var s=o.directive,l=o.customHeader||"";l+="<"+s+' model="'+(n.model||"record")+'"';var c=x[0];F(o,n);for(var d=0;d<c.attributes.length;d++){var u=c.attributes[d];switch(u.nodeName){case"class":var f=u.value.replace("ng-scope","");0<f.length&&(l+=' class="'+f+'"');break;case"schema":var p=("bespoke_"+o.name).replace(/\./g,"_");k[p]=angular.copy(o),delete k[p].directive,l+=' schema="'+p+'"';break;default:l+=" "+u.nodeName+'="'+u.value+'"'}}l+=" ";var m=E("camelCase")(o.directive);for(var h in o)if(o.hasOwnProperty(h))switch(h){case"directive":case"schema":break;case"add":switch(typeof o.add){case"string":l+=" "+o.add;break;case"object":for(var v in o.add)o.add.hasOwnProperty(v)&&(l+=" "+v+'="'+o.add[v].toString().replace(/"/g,"&quot;")+'"');break;default:throw new Error("Invalid add property of type "+typeof o.add+" in directive "+o.name)}break;case m:for(var g in o[h])o[h].hasOwnProperty(g)&&(l+=" "+o.directive+"-"+g+'="',"string"==typeof o[h][g]?l+=o[h][g].replace(/"/g,"&quot;")+'"':l+=JSON.stringify(o[h][g]).replace(/"/g,"&quot;")+'"');break;default:o[h]&&("string"==typeof o[h]?l+=" fng-fld-"+h+'="'+o[h].replace(/"/g,"&quot;")+'"':l+=" fng-fld-"+h+'="'+JSON.stringify(o[h]).replace(/"/g,"&quot;")+'"')}for(h in n)n.hasOwnProperty(h)&&"$"!==h[0]&&void 0!==n[h]&&(l+=" fng-opt-"+h+'="'+n[h].toString().replace(/"/g,"&quot;")+'"');l+='ng-model="'+o.name+'"></'+s+">",r+=l+=o.customFooter||"",i=!1}else if(o.containerType){var b=$(o);switch(o.containerType){case"tab":if(S===I.N){S=I.Forced,r+='<uib-tabset active="activeTabNo">';var y=_.findIndex(k.tabs,function(e){return e.active});k.activeTabNo=0<=y?y:0}r+=b.before,r+=N(o.content,null,n),r+=b.after;break;case"tabset":S=I.Y,r+=b.before,r+=N(o.content,null,n),r+=b.after;break;default:r+=b.before,r+=N(o.content,null,n),r+=b.after}i=!1}else if(n.subkey){var w=angular.isArray(k[n.subkey])?k[n.subkey][0].keyList:k[n.subkey].keyList;_.find(w,function(e,t){return k[n.subkey].path+"."+t===o.name})&&(i=!1)}i&&(F(o,n),r+=C(o,n))}else console.log("Empty array passed to processInstructions"),r="";return r},l=k.$watch(s.schema,function(e){if(e){var t=angular.isArray(e)?e:[e];if(0<t.length&&"function"==typeof l){l(),l=null;var n="",r=s.model||"record",g=k[r];if(g=g||{},!s.subschema&&!s.model||s.forceform){k.topLevelFormName=s.name||"myForm";var a="";for(var o in s)s.hasOwnProperty(o)&&"$"!==o[0]&&-1===["name","formstyle","schema","subschema","model","viewform"].indexOf(o)&&(a+=" "+s.$attr[o]+'="'+s[o]+'"');n="<"+(s.forceform?"ng-form":"form")+' name="'+k.topLevelFormName+'" class="'+w(s.formstyle)+'" novalidate '+a+">"}else n="";if(g===k.topLevelFormName)throw new Error("Model and Name must be distinct - they are both "+g);n+=N(t,!0,s),S===I.Forced&&(n+="</uib-tabset>"),n+=s.subschema?"":"</form>",x.replaceWith(c(n)(k));var i=k[s.shared||"sharedData"],b=i?i.modelControllers:[];if((0<D.length||0<b.length)&&!k.phaseWatcher)var y=k.$watch("phase",function(e){if(k.phaseWatcher=!0,"ready"===e&&"function"==typeof y){y(),y=null;for(var t=0;t<b.length;t++)b[t].onAllReady&&b[t].onAllReady(k);for(var n=0;n<D.length;n++){for(var r,a,o=D[n],i=angular.isArray(o.subkey)?o.subkey:[o.subkey],s=o.name.split("."),l=g;1<s.length;)l=l[s.shift()]||{};l=l[s[0]]=l[s[0]]||[];for(var c=0;c<i.length;c++){if(i[c].selectFunc){if(!k[i[c].selectFunc]||"function"!=typeof k[i[c].selectFunc])throw new Error("Subkey function "+i[c].selectFunc+" is not properly set up");r=k[i[c].selectFunc](g,o)}else{if(!i[c].keyList)throw new Error("Invalid subkey setup for "+o.name);var d=i[c].keyList;for(r=0;r<l.length;r++){for(var u in a=!0,d)if(d.hasOwnProperty(u)&&l[r][u]!==d[u]&&(void 0===l[r][u]||!l[r][u].text||l[r][u].text!==d[u])){a=!1;break}if(a)break}if(!a)switch(i[c].onNotFound){case"error":var f="Cannot find matching "+(i[c].title||i[c].path);L(function(){k.showError(f,"Unable to set up form correctly")}),r=-1;break;case"create":default:var p=o.name.split("."),m=p.pop(),h=p.join("."),v=g;h&&(v=v[h]),r=v[m].push(d)-1}}k["$_arrayOffset_"+o.name.replace(/\./g,"_")+"_"+c]=r}}}});d.$broadcast("formInputDone",s.name),u.updateDataDependentDisplay&&g&&0<Object.keys(g).length&&u.updateDataDependentDisplay(g,null,!0,k)}}},!0)}}}t=e.directives||(e.directives={}),r.$inject=["$compile","$rootScope","$filter","$timeout","cssFrameworkService","formGenerator","formMarkupHelper"],(n=I=I||{})[n.Y=0]="Y",n[n.N=1]="N",n[n.Forced=2]="Forced",t.formInput=r}(fng=fng||{}),function(e){(e.directives||(e.directives={})).fngNakedDate=function(){return{restrict:"A",require:"ngModel",link:function(e,t,n,r){r.$parsers.push(function(e){if(e)return e.toString()}),r.$formatters.push(function(e){if(e)return new Date(e)})}}}}(fng=fng||{}),function(e){var t;function n(r,t,a,o){var n,e,i,s;s=!1,i=navigator.userAgent||navigator.vendor||window.opera,(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(i)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(i.substr(0,4)))&&(s=!0),e=!s,r.searchPlaceholder=e?"Ctrl + / to Search":"Search",r.handleKey=function(e){if(27===e.keyCode&&r.searchTarget&&0<r.searchTarget.length)r.searchTarget="";else if(0<r.results.length)switch(e.keyCode){case 38:0<r.focus&&r.setFocus(r.focus-1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 40:r.results.length>r.focus+1&&r.setFocus(r.focus+1),"function"==typeof e.preventDefault&&e.preventDefault();break;case 13:null!=r.focus&&r.selectResult(r.focus)}},r.setFocus=function(e){null!==r.focus&&delete r.results[r.focus].focussed,r.results[e].focussed=!0,r.focus=e},r.selectResult=function(e){var t,n=r.results[e];n.url?t=n.url.replace("|id|",n.id):(t=o.prefix()+"/"+n.resource+"/"+n.id+"/edit",n.resourceTab&&(t+="/"+n.resourceTab)),a.url(t)},r.resultClass=function(e){var t="search-result";return r.results&&r.results[e].focussed&&(t+=" focus"),t};function l(){r.moreCount=0,r.errorClass="",r.results=[],r.focus=null}r.$watch("searchTarget",function(e){e&&0<e.length?(n=r.testTime||(new Date).valueOf(),t.get("/api/search?q="+e+"&sentAt="+n).then(function(e){var t=e.data;t.timestamps&&t.timestamps.sentAt&&Number.parseInt(t.timestamps.sentAt)!==n||(0<r.searchTarget.length?(r.results=t.results,r.moreCount=t.moreCount,0<t.results.length&&(r.errorClass="",r.setFocus(0)),r.errorClass=0===r.results.length?"error has-error":""):l())},function(e){console.log("Error in searchbox.js : "+e.data+" (status="+e.status+")")})):l()},!0),r.$on("$routeChangeStart",function(){r.searchTarget=""})}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.SearchCtrl=n}(fng=fng||{}),function(t){var e;function n(e){return{restrict:"AE",templateUrl:"search-"+e.framework()+".html",controller:t.controllers.SearchCtrl}}e=t.directives||(t.directives={}),n.$inject=["cssFrameworkService"],e.globalSearch=n}(fng=fng||{}),function(e){(e.filters||(e.filters={})).camelCase=function(){return function(e){return e.replace(/([\:\-\_]+(.))/g,function(e,t,n,r){return r?n.toUpperCase():n})}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).extractTimestampFromMongoID=function(){return function(e){var t=e.substring(0,8);return new Date(1e3*parseInt(t,16))}}}(fng=fng||{}),function(e){(e.filters||(e.filters={})).titleCase=function(){return function(e,t){return e&&(e=e.replace(/(_|\.)/g," ").replace(/[A-Z]/g," $&").trim().replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()}),e=t?e.replace(/\s/g,""):e.replace(/\s{2,}/g," ")),e}}}(fng=fng||{}),function(e){(e.services||(e.services={})).addAllService=function(){function r(e,t,r,n){var a,o,i=[],s=[];if(r="addAll"+r,"string"==typeof n)for(a=n.split(" "),o=0;o<a.length;o++)s.push(a[o]);if(!function e(t){for(var n in t)n===r&&i.push(t[n]),"$parent"===n&&e(t[n])}(e),void 0!==t[r]&&"string"==typeof t[r])for(a=t[r].split(" "),o=0;o<a.length;o++)0===a[o].indexOf("class=")?s.push(a[o].substring(6,a[o].length)):i.push(a[o]);return(n=0<s.length?' class="'+s.join(" ")+'" ':" ")+(0<i.length?i.join(" ")+" ":"")}this.getAddAllGroupOptions=function(e,t,n){return r(e,t,"Group",n)},this.getAddAllFieldOptions=function(e,t,n){return r(e,t,"Field",n)},this.getAddAllLabelOptions=function(e,t,n){return r(e,t,"Label",n)},this.addAll=function(e,t,n,r){return this["getAddAll"+t+"Options"](e,r,n)||[]}}}(fng=fng||{}),function(e){(e.services||(e.services={})).cssFrameworkService=function(){var n={framework:"bs3"};return{setOptions:function(e){angular.extend(n,e)},$get:function(){return{framework:function(){return n.framework},setFrameworkForDemoWebsite:function(e){n.framework=e},span:function(e){var t;switch(n.framework){case"bs2":t="span"+Math.floor(e);break;case"bs3":t="col-xs-"+Math.floor(e)}return t},offset:function(e){var t;switch(n.framework){case"bs2":t="offset"+Math.floor(e);break;case"bs3":t="col-lg-offset-"+Math.floor(e)}return t},rowFluid:function(){var e;switch(n.framework){case"bs2":e="row-fluid";break;case"bs3":e="row"}return e}}}}}}(fng=fng||{}),function(e){function t(c){return{loadControllerAndMenu:function(e,t,n,r,a){var o,i={};t+="Ctrl",i.$scope=e.modelControllers[n]=a;var s=a.$parent;s.items=s.items||[];function l(e){angular.forEach(e,function(e){e.divider?r=!0:e[o]&&(r&&(r=!1,s.items.push({divider:!0})),s.items.push(e))})}try{c(t,i),o=s.newRecord?"creating":s.id?"editing":"listing",angular.isObject(i.$scope.contextMenu)&&(l(i.$scope.contextMenu),i.$scope.contextMenuPromise&&i.$scope.contextMenuPromise.then(function(e){return l(e)})),e.modelNameDisplayPromise&&e.modelNameDisplayPromise.then(function(e){s.modelNameDisplay=e})}catch(e){/is not a function, got undefined/.test(e.message)||/\[\$controller:ctrlreg\] The controller with the name/.test(e.message)||console.log("Unable to instantiate "+t+" - "+e.message)}}}}((e.services||(e.services={})).fngModelCtrlService=t).$inject=["$controller"]}(fng=fng||{}),function(e){var t;function n(n,t){var a,r,s={hashPrefix:"",html5Mode:!1,routing:"ngroute",prefix:""},l=["edit","view"],o=[{route:"/analyse/:model/:reportSchemaName",state:"analyse::model::report",templateUrl:"base-analysis.html"},{route:"/analyse/:model",state:"analyse::model",templateUrl:"base-analysis.html"},{route:"/:model/:id/edit",state:"model::edit",templateUrl:"base-edit.html"},{route:"/:model/:id/edit/:tab",state:"model::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:id/view",state:"model::edit",templateUrl:"base-view.html"},{route:"/:model/:id/view/:tab",state:"model::view::tab",templateUrl:"base-view.html"},{route:"/:model/new",state:"model::new",templateUrl:"base-edit.html"},{route:"/:model",state:"model::list",templateUrl:"base-list.html"},{route:"/:model/viewonly",state:"model::view",templateUrl:"base-list-view.html"},{route:"/:model/:form/:id/edit",state:"model::form::edit",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/edit/:tab",state:"model::form::edit::tab",templateUrl:"base-edit.html"},{route:"/:model/:form/:id/view",state:"model::form::view",templateUrl:"base-view.html"},{route:"/:model/:form/:id/view/:tab",state:"model::form::view::tab",templateUrl:"base-view.html"},{route:"/:model/:form/new",state:"model::form::new",templateUrl:"base-edit.html"},{route:"/:model/:form",state:"model::form::list",templateUrl:"base-list.html"},{route:"/:model/:form/viewonly",state:"model::form::list::view",templateUrl:"base-list-view.html"}],c=null,d={};function i(e){var t=e;return s.templateFolder&&(t="/"!==s.templateFolder[s.templateFolder.length-1]?s.templateFolder+"/"+t:s.templateFolder+t),t}function u(e,n,r){void 0===n&&(n=""),n=n||"",angular.forEach(e,function(e){a.when(n+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))}),s.variantsForDemoWebsite&&angular.forEach(s.variantsForDemoWebsite,function(t){angular.forEach(e,function(e){a.when(n+t+e.route,angular.extend(e.options||{templateUrl:i(e.templateUrl)},r))})})}function f(e,t,n){void 0===t&&(t=""),t=t||"",angular.forEach(e,function(e){r.state(e.state,angular.extend(e.options||{url:t+e.route,templateUrl:e.templateUrl},n))})}function p(e,t,n,r,a,o){var i,s=r?"/"+r:"",l=e+"/"+n,c=o?"/"+o:"";switch(t){case"list":i=l+s;break;case"edit":i=l+s+"/"+a+"/edit"+c;break;case"view":i=l+s+"/"+a+"/view"+c;break;case"read":i=l+s+"/"+a+"/read"+c;break;case"new":i=l+s+"/new"+c}return i}function m(e,t){switch(s.routing){case"ngroute":a=n.get("$routeProvider"),e&&u(e),u(t,s.prefix,s.add2fngRoutes);break;case"uirouter":r=n.get("$stateProvider"),e&&f(s.fixedRoutes),f(t,s.prefix,s.add2fngRoutes)}}return{start:function(e){angular.extend(s,e),s.prefix[0]&&"/"!==s.prefix[0]&&(s.prefix="/"+s.prefix),t.html5Mode(s.html5Mode),""!==s.hashPrefix?t.hashPrefix(s.hashPrefix):s.html5Mode||t.hashPrefix(""),m(s.fixedRoutes,o)},addRoutes:function(e,t){m(e,t)},registerAction:function(e){l.push(e)},$get:function(){return{router:function(){return s.routing},prefix:function(){return s.prefix},parsePathFunc:function(){return function(e){if(e!==c){c=e,d={newRecord:!1},0<s.prefix.length&&0===e.indexOf(s.prefix)&&(e=e.slice(s.prefix.length));var t=e.split("/");s.variants&&-1!==s.variants.indexOf(t[1])&&(d.variant=t[1],t.shift());var n=t.length;if("analyse"===t[1])d.analyse=!0,d.modelName=t[2],d.reportSchemaName=4<=n?t[3]:null;else{d.modelName=t[1];var r=[t[n-1],t[n-2]],a=r.indexOf("new"),o=r.indexOf("viewonly"),i=void 0;-1===a&&-1===o?-1!==(i=l.reduce(function(e,t){var n=r.indexOf(t);return-1<n?n:e},-1))&&(n-=2+i,d.id=t[n]):-1!==a?(d.newRecord=!0,n-=1+a):n-=1+o,1!==i&&1!==a||(d.tab=r[0]),2<n&&(d.formName=t[2])}}return d}},buildUrl:function(e){var t=s.html5Mode?"":"#";return t+=s.hashPrefix,(t+=s.prefix)[0]&&(t+="/"),t+="/"===e[0]?e.slice(1):e},buildOperationUrl:function(e,t,n,r,a){return p(s.prefix,e,t,n,r,a)},redirectTo:function(){return function(e,t,n,r,a){var o;n.search({}),o="onDelete"===e?s.onDelete?"new"===s.onDelete?p(s.prefix,"new",t.modelName,t.formName,r,a):s.onDelete:p(s.prefix,"list",t.modelName,t.formName,r,a):p(s.prefix,e,t.modelName,t.formName,r,a),n.path(o)}}}}}}t=e.services||(e.services={}),n.$inject=["$injector","$locationProvider"],t.routingService=n}(fng=fng||{}),function(e){function t(e,t,o,n,i){function g(e,t,n,r,a,o,i,s){function l(e,t){var n=angular.copy(e),r=_.find(i.tabs,function(e){return e.title===n});if(!r){if(0===i.tabs.length&&0<i.formSchema.length){i.tabs.push({title:"Main",content:[],active:"Main"===i.tab||!i.tab}),r=i.tabs[0];for(var a=0;a<i.formSchema.length;a++)r.content.push(i.formSchema[a])}r=i.tabs[i.tabs.push({title:n,containerType:"tab",content:[],active:n===i.tab})-1]}r.content.push(t)}for(var c in"function"==typeof i.onSchemaFetch&&i.onSchemaFetch(e,t),t)if(t.hasOwnProperty(c))if("_id"===c)r&&t._id.options&&t._id.options.list&&w(r,t._id.options.list,c);else if(t.hasOwnProperty(c)){var d=t[c],u=d.options||{},f=u.form||{};if(d.schema&&!f.hidden){if(o&&n){var p=[];g("Nested "+c,d.schema,p,null,c+".",!0,i,s);var m=y(c,f,a);m.schema=p,f.tab&&l(f.tab,m),void 0!==f.order?n.splice(f.order,0,m):n.push(m)}}else{if(n&&!f.hidden){var h=y(c,f,a);if(x(h.showIf,h.name,i)&&"options"!==c){var v=b(h,d,u,i,s);v.tab&&l(v.tab,v),void 0!==f.order?n.splice(f.order,0,v):n.push(v)}}r&&u.list&&w(r,u.list,c)}}"function"==typeof i.onSchemaProcessed&&i.onSchemaProcessed(e,"Main "===e.slice(0,5)?i.baseSchema():n),r&&0===r.length&&k(e,r,n,t)}function b(t,e,n,r,a){if(e.caster&&(t.array=!0,e=e.caster,angular.extend(n,e.options),e.options&&e.options.form&&angular.extend(t,e.options.form)),"String"===e.instance)n.enum?(t.type=t.type||"select",t.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):(t.options=i.suffixCleanId(t,"Options"),r[t.options]=n.enum)):(t.type||(t.type=-1!==t.name.toLowerCase().indexOf("password")?"password":"text"),n.match&&(t.add='pattern="'+n.match+'" '+(t.add||"")));else if("ObjectID"===e.instance)t.ref=n.ref,t.link&&(t.link.linkOnly?(t.type="link",t.linktext=t.link.text):t.link.label?t.linklabel=!0:console.log("Unsupported link setup"),t.form=t.link.form,t.linktab=t.link.linktab,delete t.link),"link"!==t.type&&(t.type="select",t.select2||n.form&&n.form.select2?console.log("support for fng-select2 has been removed in 0.8.3 - please convert to fng-ui-select"):t.directive&&(t.noLookup||t[o("camelCase")(t.directive)]&&t[o("camelCase")(t.directive)].fngAjax)||function(){if(t.options=i.suffixCleanId(t,"Options"),t.ids=i.suffixCleanId(t,"_ids"),!t.hidden)if(n.ref)i.setUpLookupOptions(n.ref,t,r,a,g);else if(n.lookupListRef)i.setUpLookupListOptions(n.lookupListRef,t,r,a),t.lookupListRef=n.lookupListRef;else if(n.internalRef)i.handleInternalLookup(r,t,n.internalRef),t.internalRef=n.internalRef;else if(!n.customLookupOptions)throw new Error("No supported select lookup type found in "+t.name)}());else if("Date"===e.instance){if(!t.type)if(t.intType="date",t.readonly)t.type="text";else if(t.directive)t.type="text";else try{t.add=t.add||"",angular.module("ui.date").requires,t.type="text",t.add+=" ui-date ui-date-format "}catch(e){t.type="date",t.add+=' fng-naked-date="x" '}}else if("boolean"===e.instance.toLowerCase())t.type=t.type||"checkbox";else{if("Number"!==e.instance)throw new Error("Field "+t.name+" is of unsupported type "+e.instance);t.type=t.type||"number",void 0!==n.min&&(t.add='min="'+n.min+'" '+(t.add||"")),void 0!==n.max&&(t.add='max="'+n.max+'" '+(t.add||"")),t.step&&(t.add='step="'+t.step+'" '+(t.add||""))}return n.required&&(t.required=!0),n.readonly&&(t.readonly=!0),void 0!==e.defaultValue?t.defaultValue=e.defaultValue:e.options&&void 0!==e.options.default&&console.log("No support for default with no value, yet"),t}function c(e,t,n){for(var r=e.split("."),a=n||t.record,o=0,i=r.length;o<i;o++)a[r[o]]||(a[r[o]]=o===i-1?[]:{}),a=a[r[o]];return a}function v(e,r){function t(e){var t=e;if("string"==typeof e&&"$"===e.slice(0,1)){var n=e.split(".");switch(n.length){case 1:t=i.getListData(r,e.slice(1));break;case 2:t=i.getListData(r,n[1]);break;default:throw new Error("Unsupported showIf format")}}return t}var n,a=t(e.lhs),o=t(e.rhs);switch(e.comp){case"eq":n=a===o;break;case"ne":n=a!==o;break;default:throw new Error("Unsupported comparator "+e.comp)}return n}var y=function(e,t,n){return t.name=n+e,t},w=function(e,t,n){"object"==typeof t?(t.name=n,e.push(t)):e.push({name:n})},k=function(e,t,n,r){if(n){for(var a=0,o=n.length;a<o;a++)if("text"===n[a].type){t.push({name:n[a].name});break}0===t.length&&0!==n.length&&t.push({name:n[0].name})}if(0===t.length){for(var i in r)if("_id"!==i&&r.hasOwnProperty(i)){t.push({name:i});break}if(0===t.length)throw new Error("Unable to generate a title for "+e)}},x=function(e,r,a){var o=0;function t(e){if("string"==typeof e&&"$"===e.slice(0,1)){var t=e.slice(1),n=a.dataDependencies[t]||[];n.push(r),a.dataDependencies[t]=n,o+=1}}var n=!0;return e&&(t(e.lhs),t(e.rhs),0!==o||v(e,void 0)||(n=!1)),n};return{generateEditUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/edit")},generateViewUrl:function(e,t){return n.buildUrl(t.modelName+"/"+(t.formName?t.formName+"/":"")+e._id+"/view")},generateNewUrl:function(e){return n.buildUrl(e.modelName+"/"+(e.formName?e.formName+"/":"")+"new")},handleFieldType:b,handleSchema:g,updateDataDependentDisplay:function(e,t,n,r){var a,o,i,s,l,c;for(var d in r.dataDependencies)if(r.dataDependencies.hasOwnProperty(d)){var u=d.split(".");if(1===u.length){if(n||!t||e[d]!==t[d])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var f=a[o];for(i=0;i<r.formSchema.length;i+=1)r.formSchema[i].name===f&&(l=angular.element(document.querySelector("#cg_"+r.formSchema[i].id)),v(r.formSchema[i].showIf,e)?l.removeClass("ng-hide"):l.addClass("ng-hide"))}}else{if(2!==u.length)throw new Error("You can only go down one level of subdocument with showIf");if(void 0===c&&(c=!0),e[u[0]])for(s=0;s<e[u[0]].length;s++)if(n||!t||!t[u[0]]||!t[u[0]][s]||e[u[0]][s][u[1]]!==t[u[0]][s][u[1]])for(a=r.dataDependencies[d],o=0;o<a.length;o+=1){var p=a[o].split(".");if(2!==p.length)throw new Error("Conditional display must control dependent fields at same level ");for(i=0;i<r.formSchema.length;i+=1)if(r.formSchema[i].name===p[0])for(var m=r.formSchema[i].schema,h=0;h<m.length;h++)m[h].name===a[o]&&(0===(l=angular.element(document.querySelector("#f_"+p[0]+"List_"+s+" #cg_f_"+a[o].replace(".","_")))).length?l=angular.element(document.querySelector("#f_elements-"+s+"-"+p[1])):c=!1,0<l.length&&(v(r.formSchema[i].schema[h].showIf,e[u[0]][s])?l.show():l.hide()))}}}return c},add:function(t,e,n,r){var a;if(e.target.offsetParent){var o=c(t,n,r),i=n.formSchema.find(function(e){return e.name===t}),s=i?i.schema:null,l=s?n.setDefaults(s,t+"."):{};"function"==typeof(null===(a=n.dataEventFunctions)||void 0===a?void 0:a.onInitialiseNewSubDoc)&&n.dataEventFunctions.onInitialiseNewSubDoc(t,s,l),o.push(l),n.setFormDirty(e)}},unshift:function(e,t,n,r){c(e,n,r).unshift({}),n.setFormDirty(t)},remove:function(t,e,n,r,a){var o,i=c(t,r,a);if("function"==typeof r.dataEventFunctions.onDeleteSubDoc){var s=r.formSchema.find(function(e){return e.name===t}),l=s?s.schema:null;o=r.dataEventFunctions.onDeleteSubDoc(t,l,i,e)}o?r.showError(o):(i.splice(e,1),r.setFormDirty(n))},hasError:function(e,t,n,r){var a=!1;if(r){var o=r[r.topLevelFormName];if("null"!==e&&(o=o[e.replace("$index",n)]),o){var i=o[t];i&&i.$invalid&&!i.$$attr.readonly&&(i.$dirty?a=!0:angular.forEach(i.$validators,function(e,t){"required"!==t&&i.$error[t]&&(a=!0)}))}}else console.log("hasError called with no scope! ",e,t,n);return a},decorateScope:function(a,o,n,e){a.record=e.record,a.phase="init",a.disableFunctions=e.disableFunctions,a.dataEventFunctions=e.dataEventFunctions,a.topLevelFormName=void 0,a.formSchema=[],a.tabs=[],a.listSchema=[],a.recordList=[],a.dataDependencies={},a.internalLookups=[],a.listLookups=[],a.conversions={},a.pageSize=60,a.pagesLoaded=0,(e.baseScope=a).generateEditUrl=function(e){return o.generateEditUrl(e,a)},a.generateViewUrl=function(e){return o.generateViewUrl(e,a)},a.generateNewUrl=function(){return o.generateNewUrl(a)},a.scrollTheList=function(){return n.scrollTheList(a)},a.getListData=function(e,t){return n.getListData(e,t,a.listSchema,a)},a.setPristine=function(e){e&&a.dismissError(),a[a.topLevelFormName]&&a[a.topLevelFormName].$setPristine()},a.skipCols=function(e){return 0<e?"col-md-offset-3":""},a.setFormDirty=function(e){e?angular.element(e.target).inheritedData("$formController").$setDirty():console.log("setFormDirty called without an event (fine in a unit test)")},a.add=function(e,t,n){return o.add(e,t,a,n)},a.hasError=function(e,t,n){return o.hasError(e,t,n,a)},a.unshift=function(e,t,n){return o.unshift(e,t,a,n)},a.remove=function(e,t,n,r){return o.remove(e,t,n,a,r)},a.baseSchema=function(){return a.tabs.length?a.tabs:a.formSchema}}}}((e.services||(e.services={})).formGenerator=t).$inject=["$location","$timeout","$filter","routingService","recordHandler"]}(fng=fng||{}),function(e){var t;function n(f,p,m,a){function d(e,t){var n=["vertical","inline"];return t||n.push("stacked"),!e||"undefined"===e||!n.includes(e)}function s(){return"bs2"===f.framework()?"icon":"glyphicon glyphicon"}return{isHorizontalStyle:d,fieldChrome:function(e,t,n){var r=t.classes||"",a="",o="",i="";if(t.showWhen=t.showWhen||t.showwhen,t.showWhen&&("string"==typeof t.showWhen?i+='ng-show="'+t.showWhen+'"':i+='ng-show="'+function(e,a){function t(e){var t=e;if("string"==typeof e)if("$"===e.slice(0,1)){t=(a||"record")+".";var n=e.slice(1).split(".");if(1<n.length){var r=n.pop();t+=n.join(".")+"[$index]."+r}else t+=e.slice(1)}else t="'"+e+"'";return t}var n=["eq","ne","gt","gte","lt","lte"].indexOf(e.comp);if(-1===n)throw new Error("Invalid comparison in showWhen");return t(e.lhs)+["===","!==",">",">=","<","<="][n]+t(e.rhs)}(t.showWhen,n.model)+'"'),t.id&&"function"==typeof t.id.replace&&(i+=' id="cg_'+t.id.replace(/\./g,"-")+'"'),"bs3"===f.framework()){var s;r+=" form-group","vertical"===n.formstyle&&"block-level"!==t.size&&(a+='<div class="row">',r+=" col-sm-"+p.sizeAsNumber(t.size),o+="</div>");var l=null,c=t.name.split(".");s=n&&void 0!==n.subkeyno?n.subschemaroot.replace(/\./g,"-")+"-subkey"+n.subkeyno+"-"+c[c.length-1]:n.subschema?(l="form_"+c.slice(0,-1).join("_")+"$index",t.name.replace(/\./g,"-")):"f_"+t.name.replace(/\./g,"_"),a+="<div"+m.addAll(e,"Group",r,n)+" ng-class=\"{'has-error': hasError('"+l+"','"+s+"', $index)}\"",o+="</div>"}else o=d(n.formstyle,!0)?(a+="<div"+m.addAll(e,"Group","control-group",n),"</div>"):(a+="<span ","</span>");return{template:a+=(i||"")+">",closeTag:o}},label:function(e,t,n,r){var a="";if("bs3"===f.framework()||!["inline","stacked"].includes(r.formstyle)&&""!==t.label||n){a="<label";var o="control-label";if(d(r.formstyle,!1)?(t.linklabel||(a+=' for="'+t.id+'"'),void 0!==t.labelDefaultClass?o+=" "+t.labelDefaultClass:"bs3"===f.framework()&&(o+=" col-sm-3")):["inline","stacked"].includes(r.formstyle)&&(a+=' for="'+t.id+'"',o+=" sr-only"),a+=m.addAll(e,"Label",null,r)+' class="'+o+'">'+t.label,n&&(a+=' <i id="add_'+t.id+'" ng-click="add(\''+t.name+'\',$event)" class="'+s()+'-plus-sign"></i>'),a+="</label>",t.linklabel){var i='<fng-link fld="'+t.name+'" ref="'+t.ref+'" text="'+escape(a)+'"';t.form&&(i+=' form="'+t.form+'"'),t.linktab&&(i+=' linktab="'+t.linktab+'"'),a=i+="></fng-link>"}}return a},glyphClass:s,allInputsVars:function(e,t,n,r,a,o){var i,s=t.placeHolder,l="",c="",d="",u="";return"bs3"===f.framework()?(l=-1===["horizontal","vertical","inline"].indexOf(n.formstyle)?" input-sm":"",c="col-sm-"+p.sizeAsNumber(t.size),u=" form-control"):d=t.size?" input-"+t.size:"",["inline","stacked"].includes(n.formstyle)&&(s=s||t.label),i='data-ng-model="'+r+'"'+(a?' id="'+a+'" name="'+a+'" ':' name="'+o+'" '),i+=s?'placeholder="'+s+'" ':"",t.popup&&(i+='title="'+t.popup+'" '),t.ariaLabel&&(i+='aria-label="'+t.ariaLabel+'" '),{common:i+=m.addAll(e,"Field",null,n),sizeClassBS3:c,sizeClassBS2:d,compactClass:l,formControl:u}},inputChrome:function(e,t,n,r){"bs3"===f.framework()&&d(n.formstyle,!0)&&"checkbox"!==t.type&&(e='<div class="bs3-input '+r.sizeClassBS3+'">'+e+"</div>");var a=(t.helpInline||"")+(t.helpinline||"");if(0<a.length){var o="bs2"===f.framework()?{el:"span",cl:"help-inline"}:{el:"div",cl:"help-block"};e+="<"+o.el+' class="'+o.cl+'">'+a+"</"+o.el+">"}return n.noid||(e+='<div ng-if="'+(n.name||"myForm")+"['"+t.id+'\'].$dirty" class="help-block"> <div ng-messages="'+(n.name||"myForm")+"['"+t.id+'\'].$error"> <div ng-messages-include="error-messages.html"> </div> </div></div>'),t.help&&(e+='<div class="help-block">'+t.help+"</div>"),e},generateSimpleInput:function(e,t,n){var r="<input "+e+'type="'+t.type+'" ';return t.label||t.ariaLabel?n.subschema&&(r+='aria-label="'+(t.label?a("titleCase")(n.subschemaroot)+" "+t.label:t.popup||t.name.replace(/\./g," "))+'" '):r+='aria-label="'+t.name.replace(/\./g," ")+'" ',"inline"!==n.formstyle||"bs2"!==f.framework()||t.size||(r+='class="input-small"'),r+=" />"},controlDivClasses:function(e){var t=[];return d(e.formstyle,!1)&&t.push("bs2"===f.framework()?"controls":"col-sm-9"),t},handleInputAndControlDiv:function(e,t){return 0<t.length&&(e='<div class="'+t.join(" ")+'">'+e+"</div>"),e},handleArrayInputAndControlDiv:function(e,t,n,r){var a="<div ";return"bs3"===f.framework()&&(a+='ng-class="skipCols($index)" '),a+='class="'+t.join(" ")+'" id="'+n.id+'List" ',a+='ng-repeat="arrayItem in '+(r.model||"record")+"."+n.name+' track by $index">',a+=e,"link"!==n.type&&(a+="<i ng-click=\"remove('"+n.name+'\',$index,$event)" id="remove_'+n.id+'_{{$index}}" class="'+s()+'-minus-sign"></i>'),a+="</div>"},addTextInputMarkup:function(e,t,n){var r="",a=e.formControl.trim()+e.compactClass+e.sizeClassBS2+(t.class?" "+t.class:"");return 0!==a.length&&(r+='class="'+a+'"'),t.add&&(r+=" "+t.add+" "),r+=n,t.readonly?r+=" "+("boolean"==typeof t.readOnly?"readonly":'ng-readonly="'+t.readonly+'"')+" ":r+=" ",r}}}t=e.services||(e.services={}),n.$inject=["cssFrameworkService","inputSizeHelper","addAllService","$filter"],t.formMarkupHelper=n}(fng=fng||{}),function(e){(e.services||(e.services={})).inputSizeHelper=function(){var t=[1,2,4,6,8,10,12],n=["mini","small","medium","large","xlarge","xxlarge","block-level"];return{sizeMapping:t,sizeDescriptions:n,defaultSizeOffset:2,sizeAsNumber:function(e){return t[e?n.indexOf(e):2]}}}}(fng=fng||{}),function(e){var t;function n(b){return{extractFromAttr:function(e,t){function n(e){var t=e.replace(/&quot;/g,'"');return"true"===t?t=!0:"false"===t?t=!1:!isNaN(parseFloat(t))&&isFinite(t)&&(t=parseFloat(t)),t}var r={},a={formStyle:e.formstyle},o={},i=t?t.length:0;for(var s in e)e.hasOwnProperty(s)&&("fngFld"===s.slice(0,6)?r[s.slice(6).toLowerCase()]=n(e[s]):"fngOpt"===s.slice(0,6)?a[s.slice(6).toLowerCase()]=n(e[s]):t&&s.slice(0,i)===t&&(o[_.kebabCase(s.slice(i))]=n(e[s])));return{info:r,options:a,directiveOptions:o}},buildInputMarkup:function(e,t,n,r,a,o,i){var s,l,c,d=b.fieldChrome(e,n,r,' id="cg_'+n.id+'"'),u=b.controlDivClasses(r),f=d.template+b.label(e,n,a,r);if(c=a?(s="arrayItem"+(o?".x":""),l=n.id+"_{{$index}}",n.name+"_{{$index}}"):(s=t+"."+n.name,l=n.id,n.name),r.subschema&&-1!==n.name.indexOf(".")){var p=t+".",m=n.name,h=r.subschemaroot,v=m.slice(h.length+1);s=p,r.index?l="f_"+(s+=h+"["+r.index+"]."+v).slice(p.length).replace(/(\.|\[|\]\.)/g,"-"):(s+=h,r.subkey?(l=s.slice(p.length).replace(/\./g,"-")+"-subkey"+r.subkeyno+"-"+v,s+="[$_arrayOffset_"+h.replace(/\./g,"_")+"_"+r.subkeyno+"]."+v):(s+="[$index]."+v,l=null,c=m.replace(/\./g,"-")))}var g=b.allInputsVars(e,n,r,s,l,c);return g.modelString=s,f+=b["handle"+(a?"Array":"")+"InputAndControlDiv"](b.inputChrome(i(g),n,r,g),u,n,r),f+=d.closeTag},findIdInSchemaAndFlagNeedX:function e(t,n){for(var r=!1,a=0;a<t.length;a++){var o=t[a];if(o.id===n){r=o.needsX=!0;break}if(o.schema&&e(o.schema,n)){r=!0;break}}return r}}}t=e.services||(e.services={}),n.$inject=["formMarkupHelper"],t.pluginHelper=n}(fng=fng||{}),function(e){var t;function n(l,o,a,d,i,s,p,e){var c=function(e){return void 0===e&&(e=function(e){return Math.floor(e).toString(16)}),e(Date.now()/1e3)+" ".repeat(16).replace(/./g,function(){return e(16*Math.random())})};function u(e){if(-1===["cancel","backdrop click","escape key press"].indexOf(e))throw e}function b(e,t){return(e.id||"f_"+e.name).replace(/\./g,"_")+t}function f(e,t,n,r){void 0===r&&(r=!1);for(var a=t.split("."),o=a.length-1,i=e,s=0;s<o;s++){if(!i)throw new Error("walkTree failed: Object = "+e+", fieldname = "+t+", i = "+s);if(i=angular.isArray(i)?_.map(i,function(e){return e[a[s]]}):(r&&!i[a[s]]&&(i[a[s]]={}),i[a[s]]),angular.isArray(i)&&void 0!==n)if(n.scope&&"function"==typeof n.scope)i=i[n.scope().$index];else{if("number"!=typeof n)throw new Error("Unsupported element type in walkTree "+t);i=i[n]}if(!i)break}return{lastObject:i,key:i?a[o]:void 0}}function y(e,t,n,r){var a=f(e,t,n,!!r);if(a.lastObject&&a.key)if(r)if(angular.isArray(a.lastObject))for(var o=0;o<a.lastObject.length;o++)a.lastObject[o][a.key]=r[o];else a.lastObject[a.key]=r;else delete a.lastObject[a.key]}function m(t,n,e,r){if(void 0===r&&(r=!1),!n.topLevelFormName||n[n.topLevelFormName]&&(r||n[n.topLevelFormName].$pristine)){x(t.name,e.master,function(e){return"object"==typeof e&&e.id?e:D(t,e,n[b(t,"Options")],n[b(t,"_ids")])});var a=w(e.master,t.name);a&&y(n.record,t.name,void 0,a)}}var w=function(e,t,n){var r,a=f(e,t,n);return a.lastObject&&a.key&&(r=angular.isArray(a.lastObject)?_.map(a.lastObject,function(e){return e[a.key]}):a.lastObject[a.key]),r};function k(e,t,n,r){void 0===n&&(n=null);var a=w(e,t)||"";if(a&&n){var o=_.find(n,function(e){return e.name===t});if(o)switch(o.params){case void 0:break;case"timestamp":var i=a.toString().substring(0,8),s=new Date(1e3*parseInt(i,16));a=s.toLocaleDateString()+" "+s.toLocaleTimeString();break;default:a=r.dataEventFunctions[o.params](e)}}return a}function x(e,t,n){var r,a,o=(r=e.split("."),a=[r[0]],1<r.length&&a.push(r.slice(1).join(".")),a);if(1<o.length)!function(e,t,n){if(void 0!==t)if(angular.isArray(t))for(var r=0;r<t.length;r++)x(e,t[r],n);else x(e,t,n)}(o[1],t[o[0]],n);else if(t[o[0]]){var i=t[o[0]];if(angular.isArray(i))for(var s=i.length-1;0<=s;s--){var l=typeof i[s];("undefined"==l||"object"==l&&0===Object.keys(i[s]).length)&&i.splice(s,1)}t[o[0]]=n(i)}}function v(e,t,n,r,a){var o="string"==typeof t?e[t]:t,i="string"==typeof n?e[n]:n;o.length=0,i.length=0,r&&0<r.length&&r.forEach(function(e){var t=e[a];t&&0<t.length&&(o.push(t),e._id||(e._id=c()),i.push(e._id))})}var $=function(e){var t=!1;return e.needsX?t=!0:e.directive||("text"===e.type?t=!0:"select"!==e.type||e.ids||(t=!0)),t};function C(e,t,n){var r=e.conversions;return n&&(r=w(r,n)||{}),r[t]}var g=function(e,t,n,r,a,o,i){o=o||t;for(var s=0;s<e.length;s++){var l=e[s],c=l.name.slice(n);c.length||(c=l.name.split(".").pop());var d=w(t,c);if("date"===l.intType&&"string"==typeof d&&y(t,c,null,new Date(d)),l.schema){if(d)for(var u=0;u<d.length;u++)d[u]=g(l.schema,d[u],1+c.length,r,c,o,u)}else{l.internalRef&&v(r,l.options,l.ids,o[l.internalRef.property],l.internalRef.value);var f=k(t,c,null,r);if(l.array&&$(l)&&f&&!(0<f.length&&f[0].x))for(var p=0;p<f.length;p++)f[p]={x:f[p]};var m=r[b(l,"_ids")],h=void 0;if(d&&m&&0<m.length){if(-1!==c.indexOf("."))throw new Error("Trying to directly assign to a nested field 332");!d.toString().match(/^[a-f0-9]{24}$/)||l.internalRef&&l.internalRef.noConvert||(t[c]=D(l,d,r[b(l,"Options")],m))}else l.select2?(console.log("fng-select2 is deprecated - use fng-ui-select instead"),l.select2):d&&(h=C(r,c,a))&&h.fngajax&&!h.noconvert&&h.fngajax(d,l,function(e,t){y(o,e.name,i,t),F(angular.element("#"+e.id),function(){y(r.record,e.name,i,t)})})}}return t};function D(e,t,n,r){if(e.array){for(var a=[],o=!e.directive||$(e),i=0;i<t.length;i++){var s=t[i];s&&s.x&&(s=s.x);var l=N(s,r,n,e.name);o&&(l={x:l}),a.push(l)}return a}return e.select2?{id:t,text:N(t,r,n,e.name)}:N(t,r,n,e.name)}function S(e,t,n,r){var a=_.isObject(e)?e.x||e.text:e;if(a&&a.match(/^[0-9a-f]{24}$/))return a;var o=t.indexOf(a);if(-1===o)throw new Error("convertListValueToId: Invalid data - value "+a+" not found in "+t+" processing "+r);return n[o]}function h(e,t,n){n.master=g(t.formSchema,e,0,t),t.phase="ready",t.cancel()}var F=function(e,t){var n=e.inheritedData("$ngModelController"),r=n&&n.$pristine;r&&(n.$pristine=!1),t(),r&&(n.$pristine=!0)},N=function(e,t,n,r){"object"==typeof e&&(e=e.id);var a=t.indexOf(e);if(-1===a&&-1===(a=n.indexOf(e)))throw new Error("convertIdToListValue: Invalid data - id "+e+" not found in "+t+" processing "+r);return n[a]};function E(t,n,r,e,a){if(a&&0<a.length&&a.length===e.length&&n[r]){var o=a.findIndex(function(e){return e[t.value]===n[r]});if(-1<o){var i=e[o][t.value];i&&(n[r]=i)}}}function L(e,u,n,t,f){var r=!u.id&&!u.newRecord;function a(o,d){u.internalLookups.forEach(function(n){var r=o[n.ref.property],a=d[n.ref.property];v(u,n.lookupOptions,n.lookupIds,r,n.ref.value),(r&&0<r.length||a&&0<a.length)&&n.handlers.forEach(function(t){if(t.possibleArray){var e=w(u.record,t.possibleArray,null);e&&0<e.length&&e.forEach(function(e){return E(n.ref,e,t.lastPart,r,a)})}else angular.isArray(u.record[t.lastPart])?u.record[t.lastPart].forEach(function(e){E(n.ref,e,"x",r,a)}):E(n.ref,u.record,t.lastPart,r,a)})}),u.listLookups.forEach(function(l){function e(e,t){var n=e[t];return n&&n.id&&(n=n.id),n}function c(e){y(u.record,e.name)}var t=l.ref.id.slice(1);if(t.includes("."))throw new Error("No support for nested list lookups yet - "+JSON.stringify(l.ref));var n=e(o,t);n!==e(d,t)&&(l.handlers.forEach(function(e){u[e.formInstructions.options].length=0,u[e.formInstructions.ids].length=0}),n?p.readRecord(l.ref.collection,n).then(function(s){l.handlers.forEach(function(e){for(var t=u[e.formInstructions.options],n=u[e.formInstructions.ids],r=s.data[l.ref.property]||[],a=0;a<r.length;a++){var o=r[a][l.ref.value],i=_.sortedIndex(t,o);t[i]===o&&(o=o+" ("+r[a]._id+")",i=_.sortedIndex(t,o)),t.splice(i,0,o),n.splice(i,0,r[a]._id)}0===Object.keys(d).length?m(e.formInstructions,u,f,!0):c(e.formInstructions)})}):l.handlers.forEach(function(e){c(e.formInstructions)}))})}function o(){u.phase="ready",u.cancel(),a(u.record,{})}if(n.handleSchema("Main "+u.modelName,e,r?null:u.formSchema,u.listSchema,"",!0,u,f),r)f.allowLocationChange=!0;else{var i=!0;if(u.newRecord||(u.dropConversionWatcher=u.$watchCollection("conversions",function(e,t){e!==t&&u.originalData&&h(u.originalData,u,f)})),u.$watch("record",function(e,t){e!==t&&(0<Object.keys(t).length&&u.dropConversionWatcher&&(u.dropConversionWatcher(),u.dropConversionWatcher=null),i=n.updateDataDependentDisplay(e,t,i,u),a(e,t))},!0),u.id)"function"==typeof u.dataEventFunctions.onBeforeRead?u.dataEventFunctions.onBeforeRead(u.id,function(e){e?u.showError(e):t.readRecord(u,f)}):t.readRecord(u,f);else{f.allowLocationChange=!1,f.master=u.setDefaults(u.formSchema);var s=u.initialiseNewRecord||l.$$search.r;if(s)try{Object.assign(f.master,JSON.parse(s)),u.newRecordsStartPristine||u.$on("fngCancel",function(){d(function(){u[u.topLevelFormName]&&u[u.topLevelFormName].$setDirty()},1e3)})}catch(e){console.log("Error parsing specified record : "+e.message)}"function"==typeof u.dataEventFunctions.onInitialiseNewRecord&&(console.log("onInitialiseNewRecord is deprecated - use the async version - onNewRecordInit(data,cb)"),u.dataEventFunctions.onInitialiseNewRecord(f.master)),"function"==typeof u.dataEventFunctions.onNewRecordInit?u.dataEventFunctions.onNewRecordInit(f.master,function(e){e?u.showError(e):o()}):o()}}}function t(r){return function(e){if(-1!==[200,400].indexOf(e.status)){var t="";for(var n in e.data.errors)if(e.data.errors.hasOwnProperty(n)){switch(t+="<li><b>"+a("titleCase")(n)+": </b> ",e.data.errors[n].type){case"enum":t+="You need to select from the list of values";break;default:t+=e.data.errors[n].message}t+="</li>"}t=0<t.length?e.data.message+"<br /><ul>"+t+"</ul>":e.data.message||e.data.err||"Error! Sorry - No further details available.",r.showError(t)}else r.showError(e.status+" "+JSON.stringify(e.data))}}function A(e,t,n){n.allowLocationChange=!1,t.phase="reading","function"==typeof t.dataEventFunctions.onAfterRead&&t.dataEventFunctions.onAfterRead(e),t.originalData=e,h(e,t,n)}function r(e,t,n,r){var a=t.name.split("."),o=r.find(function(e){return e.ref.property===n.property&&e.ref.value===n.value}),i={formInstructions:t,lastPart:a.pop(),possibleArray:a.join(".")};o||(o={ref:n,lookupOptions:[],lookupIds:[],handlers:[]},r.push(o)),o.handlers.push(i),e[t.options]=o.lookupOptions,e[t.ids]=o.lookupIds}return{readRecord:function(t,n){t.readingRecord=p.readRecord(t.modelName,t.id),t.readingRecord.then(function(e){A(angular.copy(e.data),t,n)},function(e){404===e.status?l.path("/404"):t.handleHttpError(e)})},scrollTheList:function(n){var r=n.pagesLoaded;p.getPagedAndFilteredList(n.modelName,{aggregate:l.$$search.a,find:l.$$search.f,limit:n.pageSize,skip:r*n.pageSize,order:l.$$search.o}).then(function(e){var t=e.data;angular.isArray(t)?r===n.pagesLoaded?(n.pagesLoaded++,n.recordList=n.recordList.concat(t)):console.log("DEBUG: infinite scroll component asked for a page twice - the model was "+n.modelName):n.showError(t,"Invalid query")},n.handleHttpError)},deleteRecord:function(e,t,n){p.deleteRecord(t.modelName,e).then(function(){"function"==typeof t.dataEventFunctions.onAfterDelete&&t.dataEventFunctions.onAfterDelete(n.master),i.redirectTo()("onDelete",t,l)},function(e){404===e.status?i.redirectTo()("onDelete",t,l):t.showError(e.statusText+" ("+e.status+") while deleting record<br />"+e.data,"Error deleting record")})},updateDocument:function(e,n,r,a){r.phase="updating",p.updateRecord(r.modelName,r.id,e).then(function(e){var t=e.data;!1!==t.success?("function"==typeof r.dataEventFunctions.onAfterUpdate&&r.dataEventFunctions.onAfterUpdate(t,a.master),n.redirect?(n.allowChange&&(a.allowLocationChange=!0),o.location=n.redirect):(A(t,r,a),r.setPristine(!1))):r.showError(t)},r.handleHttpError)},createNew:function(e,n,r,a){p.createRecord(r.modelName,e).then(function(e){var t=e.data;!1!==t.success?(a.allowLocationChange=!0,"function"==typeof r.dataEventFunctions.onAfterCreate&&r.dataEventFunctions.onAfterCreate(t),n.redirect?o.location=n.redirect:i.redirectTo()("edit",r,l,t._id)):r.showError(t)},r.handleHttpError)},getListData:k,suffixCleanId:b,setData:y,setUpLookupOptions:function(n,l,c,d,r){var u=c[l.options]=[],f=c[l.ids]=[];e.getSchema(n).then(function(e){var t=e.data,s=[];r("Lookup "+n,t,null,s,"",!1,c,d),(void 0!==l.filter&&l.filter?p.getPagedAndFilteredList(n,l.filter):p.getAll(n)).then(function(e){var t=angular.copy(e.data);if(t){for(var n=0;n<t.length;n++){for(var r="",a=0;a<s.length;a++){var o=t[n][s[a].name];r+=o?o+" ":""}r=r.trim();var i=_.sortedIndex(u,r);u[i]===r&&(r=r+" ("+t[n]._id+")",i=_.sortedIndex(u,r)),u.splice(i,0,r),f.splice(i,0,t[n]._id)}c.readingRecord&&c.readingRecord.then(function(){m(l,c,d)})}})})},setUpLookupListOptions:function(o,i,s,l){var c=s[i.options]=[],d=s[i.ids]=[];"$"===o.id[0]?r(s,i,o,s.listLookups):p.readRecord(o.collection,s.$eval(o.id)).then(function(e){for(var t=e.data[o.property],n=0;n<t.length;n++){var r=t[n][o.value],a=_.sortedIndex(c,r);c[a]===r&&(r=r+" ("+t[n]._id+")",a=_.sortedIndex(c,r)),c.splice(a,0,r),d.splice(a,0,t[n]._id)}m(i,s,l)})},handleInternalLookup:function(e,t,n){r(e,t,n,e.internalLookups)},preservePristine:F,convertToMongoModel:function d(u,f,p,m,h){function v(e,t){var n;return t&&t.fngajax?e&&(n=e.id||e):e&&(n=e.text||(e.x?e.x.text:e)),n}function e(){var t=u[g],e=t.name.slice(p),n=k(f,e,null,m);if(t.schema){if(n)for(var r=0;r<n.length;r++)n[r]=d(t.schema,n[r],1+e.length,m,e)}else{if(t.array&&$(t)&&n)for(var a=0;a<n.length;a++)n[a]=n[a].x;var o=m[b(t,"_ids")];if(o&&0<o.length)x(e,f,function(e){return function(e,t,n,r){if(e.array){for(var a=[],o=0;o<t.length;o++)a.push(S(t[o],n,r,e.name));return a}return S(t,n,r,e.name)}(t,e,m[b(t,"Options")],o)});else{var i=C(m,e,h);if(i){var s=w(f,e,null),l=void 0;if(t.array){if(l=[],s)for(var c=0;c<s.length;c++)l[c]=v(s[c],i)}else l=v(s,i);y(f,e,null,l)}}}}for(var g=0;g<u.length;g++)e();return f},convertIdToListValue:N,handleError:t,decorateScope:function(c,n,r,a){c.handleHttpError=t(c),c.cancel=function(){angular.copy(a.master,c.record),c.$broadcast("fngCancel",c),d(c.setPristine)},c.$on("showErrorMessage",function(e,t){e.defaultPrevented||(e.defaultPrevented=!0,c.showError(t.body,t.title))}),c.showError=function(t,e){if(c.alertTitle=e||"Error!","string"==typeof t)c.errorMessage=t;else if(t)if(t.message&&"string"==typeof t.message)c.errorMessage=t.message;else if(t.data&&t.data.message)c.errorMessage=t.data.message;else try{c.errorMessage=JSON.stringify(t)}catch(e){c.errorMessage=t}else c.errorMessage="An error occurred - that's all we got. Sorry.";c.errorHideTimer=window.setTimeout(function(){c.dismissError(),c.$digest()},3500+1e3*(c.alertTitle+c.errorMessage).length/50),c.errorVisible=!0,window.setTimeout(function(){c.$digest()})},c.clearTimeout=function(){c.errorHideTimer&&(clearTimeout(c.errorHideTimer),delete c.errorHideTimer)},c.dismissError=function(){c.clearTimeout,c.errorVisible=!1,delete c.errorMessage,delete c.alertTitle},c.stickError=function(){clearTimeout(c.errorHideTimer)},c.prepareForSave=function(t){var n=r.convertToMongoModel(c.formSchema,angular.copy(c.record),0,c);c.id?"function"==typeof c.dataEventFunctions.onBeforeUpdate?c.dataEventFunctions.onBeforeUpdate(n,a.master,function(e){e?t(e):t(null,n)}):t(null,n):"function"==typeof c.dataEventFunctions.onBeforeCreate?c.dataEventFunctions.onBeforeCreate(n,function(e){e?t(e):t(null,n)}):t(null,n)},c.save=function(n){n=n||{},c.prepareForSave(function(e,t){e?"_update_handled_"!==e&&d(function(){c.showError(e)}):c.id?r.updateDocument(t,n,c,a):r.createNew(t,n,c,a)})},c.newClick=function(){i.redirectTo()("new",c,l)},c.$on("$locationChangeStart",function(e,t){a.allowLocationChange||c.isCancelDisabled()||(e.preventDefault(),n.open({template:'<div class="modal-header">\n <h3>Record modified</h3>\n</div>\n<div class="modal-body">\n <p>Would you like to save your changes?</p>\n</div>\n<div class="modal-footer">\n <button class="btn btn-primary dlg-yes" ng-click="yes()">Yes</button>\n <button class="btn btn-warning dlg-no" ng-click="no()">No</button>\n <button class="btn dlg-cancel" ng-click="cancel()">Cancel</button>\n</div>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result.then(function(e){e?c.save({redirect:t,allowChange:!0}):(a.allowLocationChange=!0,o.location=t)}).catch(u))}),c.deleteClick=function(){if(c.record._id){var e=void 0;if(c.unconfirmedDelete)e=Promise.resolve(!0);else e=n.open({template:'<div class="modal-header">\n <h3>Delete Item</h3>\n</div>\n<div class="modal-body">\n <p>Are you sure you want to delete this record?</p>\n</div>\n<div class="modal-footer">\n <button class="btn btn-primary dlg-no" ng-click="cancel()">No</button>\n <button class="btn btn-warning dlg-yes" ng-click="yes()">Yes</button>\n</div>',controller:"SaveChangesModalCtrl",backdrop:"static"}).result;e.then(function(e){function t(){r.deleteRecord(c.id,c,a)}e&&("function"==typeof c.dataEventFunctions.onBeforeDelete?c.dataEventFunctions.onBeforeDelete(a.master,function(e){e?"_delete_handled_"!==e&&c.showError(e):t()}):t())}).catch(u)}},c.isCancelDisabled=function(){return!(!c[c.topLevelFormName]||!c[c.topLevelFormName].$pristine)||"function"==typeof c.disableFunctions.isCancelDisabled&&c.disableFunctions.isCancelDisabled(c.record,a.master,c[c.topLevelFormName])},c.isSaveDisabled=function(){c.whyDisabled=void 0;var e=!1;if(c[c.topLevelFormName]?c[c.topLevelFormName].$invalid?(c.whyDisabled="The form data is invalid:",function n(e,r){e.$$controls.forEach(function(e){if(e.$invalid)if(e.$$controls)n(e,e.$name);else if(c.whyDisabled+="<br /><strong>",r&&(c.whyDisabled+=r+" "),"bs2"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().find("label")&&e.$$element.parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().find("label").text():"bs3"===s.framework()&&e.$$element&&e.$$element.parent()&&e.$$element.parent().parent()&&e.$$element.parent().parent().parent()&&e.$$element.parent().parent().parent().find("label")&&e.$$element.parent().parent().parent().find("label").text()?c.whyDisabled+=e.$$element.parent().parent().parent().find("label").text():c.whyDisabled+=e.$name,c.whyDisabled+="</strong>: ",e.$error)for(var t in e.$error)if(e.$error.hasOwnProperty(t))switch(t){case"required":c.whyDisabled+="Field missing required value. ";break;case"pattern":c.whyDisabled+="Field does not match required pattern. ";break;default:c.whyDisabled+=t+". "}})}(c[c.topLevelFormName])):c[c.topLevelFormName].$pristine&&(e=!0):c.whyDisabled="Top level form name invalid",e||c.whyDisabled)return!0;if("function"!=typeof c.disableFunctions.isSaveDisabled)return!1;var t=c.disableFunctions.isSaveDisabled(c.record,a.master,c[c.topLevelFormName]);return c.whyDisabled="string"==typeof t?t:"An application level user-specified function is inhibiting saving the record",!!t},c.isDeleteDisabled=function(){return!c.id||"function"==typeof c.disableFunctions.isDeleteDisabled&&c.disableFunctions.isDeleteDisabled(c.record,a.master,c[c.topLevelFormName])},c.isNewDisabled=function(){return"function"==typeof c.disableFunctions.isNewDisabled&&c.disableFunctions.isNewDisabled(c.record,a.master,c[c.topLevelFormName])},c.setDefaults=function(e,t){void 0===t&&(t="");var n={};return e.forEach(function(e){void 0!==e.defaultValue&&(n[e.name.replace(t,"")]=e.defaultValue)}),n},c.getVal=function(e,t){if(-1===e.indexOf("$index")||void 0!==t)return e=e.replace(/\$index/g,t),c.$eval("record."+e)},c.sortableOptions={update:function(){c.topLevelFormName&&c[c.topLevelFormName].$setDirty()}},c.setUpCustomLookupOptions=function(e,t,n,r){for(var a=0,o=[c,r];a<o.length;a++){var i=o[a];i&&(i[e.ids]=t,i[e.options]=n)}var s=w(c.record,e.name);if(s){if(angular.isArray(s))for(var l=0;l<s.length;l++)s[l]=N(s[l],t,n,e.name);else s=N(s,t,n,e.name);y(c.record,e.name,void 0,s)}}},fillFormFromBackendCustomSchema:L,fillFormWithBackendSchema:function(t,n,r,a){e.getSchema(t.modelName,t.formName).then(function(e){L(e.data,t,n,r,a)},t.handleHttpError)}}}t=e.services||(e.services={}),n.$inject=["$location","$window","$filter","$timeout","routingService","cssFrameworkService","SubmissionsService","SchemasService"],t.recordHandler=n}(fng=fng||{}),function(e){var t;function n(n){return{getSchema:function(e,t){return n.get("/api/schema/"+e+(t?"/"+t:""),{cache:!0})}}}t=e.services||(e.services={}),n.$inject=["$http"],t.SchemasService=n}(fng=fng||{}),function(e){var t;function n(r,a){function n(e){function t(e,t){void 0!==t&&""!==t&&("object"==typeof t&&(t=JSON.stringify(t)),""===n?n="?":n+="&",n+=e+"="+t)}var n="";return t("l",e.limit),t("f",e.find),t("a",e.aggregate),t("o",e.order),t("s",e.skip),n}var o=!0;return{getListAttributes:function(e,t){return r.get("/api/"+e+"/"+t+"/list")},readRecord:function(e,t){return r.get("/api/"+e+"/"+t)},getAll:function(e,t){var n=angular.extend({cache:o},t);return r.get("/api/"+e,n)},getPagedAndFilteredList:function(e,t){return r.get("/api/"+e+n(t))},deleteRecord:function(e,t){return r.delete("/api/"+e+"/"+t)},updateRecord:function(e,t,n){return a.get("$http").remove("/api/"+e),r.post("/api/"+e+"/"+t,n)},createRecord:function(e,t){return a.get("$http").remove("/api/"+e),r.post("/api/"+e,t)},useCache:function(e){o=e},getCache:function(){return!!a.get("$http")},clearCache:function(){a.get("$http").removeAll()}}}t=e.services||(e.services={}),n.$inject=["$http","$cacheFactory"],t.SubmissionsService=n}(fng=fng||{}),function(f){var e;function t(t,n,e,r,a,o,i,s,l){t.sharedData={record:{},disableFunctions:{},dataEventFunctions:{},modelControllers:[]};var c={master:{},fngInvalidRequired:"fng-invalid-required",allowLocationChange:!0};t.errorVisible=!1,angular.extend(t,i.parsePathFunc()(e.$$path));var d=r("titleCase")(t.modelName,!0);function u(){l.fillFormWithBackendSchema(t,s,l,c);for(var e=0;e<t.sharedData.modelControllers.length;e++)t.sharedData.modelControllers[e].onBaseCtrlReady&&t.sharedData.modelControllers[e].onBaseCtrlReady(t);t.$on("$destroy",function(){t.sharedData.modelControllers.forEach(function(e){return e.$destroy()}),n.$broadcast("fngControllersUnloaded")})}o.loadControllerAndMenu(t.sharedData,d,0,!1,t.$new()),t.formName&&o.loadControllerAndMenu(t.sharedData,d+r("titleCase")(t.formName,!0),1,!1,t.$new()),n.$broadcast("fngControllersLoaded",t.sharedData,t.modelName),t.modelNameDisplay=t.sharedData.modelNameDisplay||r("titleCase")(t.modelName),n.$broadcast("fngFormLoadStart",t),s.decorateScope(t,s,l,t.sharedData),l.decorateScope(t,a,l,c),"function"==typeof f.formsAngular.beforeProcess?f.formsAngular.beforeProcess(t,function(e){e?t.showError(e.message,"Error preparing to process form"):u()}):u()}e=f.controllers||(f.controllers={}),t.$inject=["$scope","$rootScope","$location","$filter","$uibModal","fngModelCtrlService","routingService","formGenerator","recordHandler"],e.BaseCtrl=t}(fng=fng||{}),function(e){var t;function n(e,t){e.yes=function(){t.close(!0)},e.no=function(){t.close(!1)},e.cancel=function(){t.dismiss("cancel")}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$uibModalInstance"],t.SaveChangesModalCtrl=n}(fng=fng||{}),function(e){var t;function n(t,e,n,r){t.models=[],e.get("/api/models").then(function(e){t.models=e.data},function(){n.path("/404")}),t.newUrl=function(e){return r.buildUrl(e+"/new")},t.listUrl=function(e){return r.buildUrl(e)}}t=e.controllers||(e.controllers={}),n.$inject=["$scope","$http","$location","routingService"],t.ModelCtrl=n}(fng=fng||{}),function(e){var t;function n(e,i,t,r,n,a){function o(){i.items=[],i.contextMenu=void 0}e.navScope=i,o(),i.toggleCollapsed=function(){i.collapsed=!i.collapsed},i.isCollapsed=!0,i.showShortcuts=!1,i.shortcuts=[{key:"?",act:"Show shortcuts"},{key:"/",act:"Jump to search"},{key:"Ctrl+Shift+S",act:"Save the current record"},{key:"Ctrl+Shift+Esc",act:"Cancel changes on the current record"},{key:"Ctrl+Shift+Ins",act:"Create a new record"},{key:"Ctrl+Shift+X",act:"Delete the current record"}],i.markupShortcut=function(e){return'<span class="key">'+e.split("+").join('</span> + <span class="key">')+"</span>"},i.globalShortcuts=function(n){function e(e){var t=document.getElementById(e);t&&(t.disabled||setTimeout(function(){t.click()}),n.preventDefault())}if(191===n.keyCode&&(!("INPUT"==(a=(r=n).target.tagName)||"SELECT"==a||"TEXTAREA"==a||"DIV"==a&&r.target.classList.contains("ck-editor__editable"))||n.ctrlKey&&!n.altKey&&!n.metaKey))if(n.ctrlKey||!n.shiftKey){var t=document.getElementById("searchinput");t&&(t.focus(),n.preventDefault())}else i.showShortcuts=!0;else 83===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("saveButton"):27===n.keyCode&&(n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey||i.showShortcuts)?n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("cancelButton"):i.showShortcuts=!1:45===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey?e("newButton"):88===n.keyCode&&n.ctrlKey&&n.shiftKey&&!n.altKey&&!n.metaKey&&e("deleteButton");var r,a},i.css=function(e,t){return"function"==typeof a[e]?a[e](t):"error text-error"},i.$on("fngControllersLoaded",function(e,t,n){i.contextMenu=t.dropDownDisplay||t.modelNameDisplay||r("titleCase")(n,!1),t.dropDownDisplayPromise&&t.dropDownDisplayPromise.then(function(e){i.contextMenu=e})}),i.$on("fngControllersUnloaded",function(e){o()}),i.doClick=function(e,t){var n=angular.element(t.target),r=i.items[e];if(r.divider||n.parent().hasClass("disabled"))t.preventDefault();else if(r.broadcast)i.$broadcast(r.broadcast);else{var a=r.args||[],o=r.fn;if("function"==typeof o)switch(a.length){case 0:o();break;case 1:o(a[0]);break;case 2:o(a[0],a[1]);break;case 3:o(a[0],a[1],a[2]);break;case 4:o(a[0],a[1],a[2],a[3])}else if(o)throw new Error("Incorrect menu setup")}},i.isHidden=function(e){function t(e){return!!e.isHidden&&e.isHidden()}var n=!1;if(i.items[e].divider)if(0===e)n=!0;else for(var r=!1,a=e-1;0<=a&&!n&&!r;)i.items[a].divider?n=!0:t(i.items[a])?--a:r=!0;return n||t(i.items[e])},i.isDisabled=function(e){return!!i.items[e].isDisabled&&i.items[e].isDisabled()},i.buildUrl=function(e){return n.buildUrl(e)},i.dropdownClass=function(e){var t="";return i.items[e].divider?t="divider":i.isDisabled(e)&&(t="disabled"),t}}t=e.controllers||(e.controllers={}),n.$inject=["$rootScope","$scope","$location","$filter","routingService","cssFrameworkService"],t.NavCtrl=n}(fng=fng||{}),function(e){e.formsAngular=angular.module("formsAngular",["ngSanitize","ngMessages","ui.bootstrap","infinite-scroll","monospaced.elastic"]).controller("BaseCtrl",e.controllers.BaseCtrl).controller("SaveChangesModalCtrl",e.controllers.SaveChangesModalCtrl).controller("LinkCtrl",e.controllers.LinkCtrl).controller("ModelCtrl",e.controllers.ModelCtrl).controller("NavCtrl",e.controllers.NavCtrl).directive("modelControllerDropdown",e.directives.modelControllerDropdown).directive("errorDisplay",e.directives.errorDisplay).directive("fngLink",e.directives.fngLink).directive("formInput",e.directives.formInput).directive("formButtons",e.directives.formButtons).directive("globalSearch",e.directives.globalSearch).directive("fngNakedDate",e.directives.fngNakedDate).filter("camelCase",e.filters.camelCase).filter("titleCase",e.filters.titleCase).filter("extractTimestampFromMongoID",e.filters.extractTimestampFromMongoID).service("addAllService",e.services.addAllService).provider("cssFrameworkService",e.services.cssFrameworkService).provider("routingService",e.services.routingService).factory("fngModelCtrlService",e.services.fngModelCtrlService).factory("formGenerator",e.services.formGenerator).factory("formMarkupHelper",e.services.formMarkupHelper).factory("inputSizeHelper",e.services.inputSizeHelper).factory("pluginHelper",e.services.pluginHelper).factory("recordHandler",e.services.recordHandler).factory("SchemasService",e.services.SchemasService).factory("SubmissionsService",e.services.SubmissionsService)}(fng=fng||{});var formsAngular=fng.formsAngular;angular.module("formsAngular").run(["$templateCache",function(e){e.put("base-analysis.html",'<div ng-controller="AnalysisCtrl">\n <error-display></error-display>\n <div class="container-fluid page-header report-header">\n <div ng-class="css(\'rowFluid\')">\n <div class="header-lhs col-xs-7 span7">\n <h1>{{ titleWithSubstitutions }}</h1>\n </div>\n <div class="header-rhs col-xs-5 span5">\n <form-input schema="paramSchema" name="paramForm" ng-show="paramSchema" formstyle="horizontalCompact"></form-input>\n </div>\n </div>\n </div>\n <div class="container-fluid page-body report-body">\n <div class="row-fluid report-grow">\n <div class="gridStyle" style="height:100%;" ui-grid="gridOptions" ui-grid-selection ui-grid-resize-columns></div>\n </div>\n </div>\n</div>\n'),e.put("base-edit.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span id="header-data-desc">\n <span ng-show="!!editFormHeader" >{{ editFormHeader() }}</span>\n <span ng-hide="!!editFormHeader" ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </span>\n </h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <div form-buttons></div>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact"></form-input>\n </div>\n\x3c!-- <pre>--\x3e\n \x3c!--Record--\x3e\n \x3c!--{{ record | json }}--\x3e\n \x3c!--formSchema--\x3e\n \x3c!--{{ formSchema | json }}--\x3e\n\x3c!-- </pre>--\x3e\n</div>\n'),e.put("base-list-view.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateViewUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n'),e.put("base-list.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header list-header">\n <div class="header-lhs col-sm-8 span8">\n <h1>{{modelNameDisplay}}</h1>\n </div>\n <div class="header-rhs col-sm-2 span2">\n <a ng-href="{{generateNewUrl()}}"><button id="newBtn" class="btn btn-default"><i class="icon-plus"></i> New</button></a>\n </div>\n </div>\n <div class="page-body list-body">\n <div ng-class="css(\'rowFluid\')" infinite-scroll="scrollTheList()">\n <a ng-repeat="record in recordList" ng-href="{{generateEditUrl(record)}}">\n <div class="list-item">\n <div ng-class="css(\'span\',12/listSchema.length)" ng-repeat="field in listSchema">{{getListData(record, field.name)}} </div>\n </div>\n </a>\n </div>\n </div>\n</div>\n'),e.put("base-view.html",'<div ng-controller="BaseCtrl">\n <error-display></error-display>\n <div ng-class="css(\'rowFluid\')" class="page-header edit-header">\n <div class="header-lhs col-sm-8 span8">\n <h1 id="header-text">{{modelNameDisplay}} :\n <span ng-repeat="field in listSchema" ng-bind-html="getListData(record, field.name) + \' \'"></span>\n </h1>\n </div>\n </div>\n <div class="container-fluid page-body edit-body">\n <form-input name="baseForm" schema="baseSchema()" formstyle="compact" viewform="true"></form-input>\n </div>\n</div>\n'),e.put("error-display-bs2.html",'<div id="display-error" ng-show="errorVisible" class="row-fluid ng-hide">\n <div class="alert alert-error offset1 span10">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="icon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="icon-eye-open"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n'),e.put("error-display-bs3.html",'<div id="display-error" ng-show="errorVisible" class="row ng-hide">\n <div class="alert alert-error col-md-offset-1 col-md-10 alert-danger">\n <button type="button" id="err-hide" class="close" ng-click="dismissError()"><i class="glyphicon glyphicon-remove"></i></button>\n <button type="button" id="err-pin" class="close" ng-click="stickError()"><i class="glyphicon glyphicon-pushpin"></i></button>\n <h4 id="err-title">{{alertTitle}}</h4>\n <div id="err-msg" ng-bind-html="errorMessage"></div>\n </div>\n</div>\n'),e.put("error-messages.html",'<div ng-message="required">A value is required for this field</div>\n<div ng-message="minlength">Too few characters entered</div>\n<div ng-message="maxlength">Too many characters entered</div>\n<div ng-message="min">That value is too small</div>\n<div ng-message="max">That value is too large</div>\n<div ng-message="email">You need to enter a valid email address</div>\n<div ng-message="pattern">This field does not match the expected pattern</div>\n'),e.put("form-button-bs2.html",'<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-mini btn-primary form-btn" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="icon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-mini btn-warning form-btn" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="icon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-mini btn-success form-btn" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="icon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-mini btn-danger form-btn" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="icon-minus"></i> Delete</button>\n </div>\n</div>\n'),e.put("form-button-bs3.html",'<div class="form-btn-grp">\n <div class="btn-group pull-right">\n <button id="saveButton" class="btn btn-primary form-btn btn-xs" ng-click="save()" ng-disabled="isSaveDisabled()"><i class="glyphicon glyphicon-ok"></i> Save</button>\n <div id="why-disabled" ng-class="{showwhy:!!whyDisabled}" ng-bind-html="whyDisabled"></div>\n <button id="cancelButton" class="btn btn-warning form-btn btn-xs" ng-click="cancel()" ng-disabled="isCancelDisabled()"><i class="glyphicon glyphicon-remove"></i> Cancel</button>\n </div>\n <div class="btn-group pull-right">\n <button id="newButton" class="btn btn-success form-btn btn-xs" ng-click="newClick()" ng-disabled="isNewDisabled()"><i class="glyphicon glyphicon-plus"></i> New</button>\n <button id="deleteButton" class="btn btn-danger form-btn btn-xs" ng-click="deleteClick()" ng-disabled="isDeleteDisabled()"><i class="glyphicon glyphicon-minus"></i> Delete</button>\n </div>\n</div>\n'),e.put("search-bs2.html",'<form class="navbar-search pull-right">\n <div id="search-cg" class="control-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)">{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n'),e.put("search-bs3.html",'<form class="pull-right navbar-form">\n <div id="search-cg" class="form-group" ng-class="errorClass">\n <input type="text" spellcheck="false" autocomplete="off" id="searchinput" ng-model="searchTarget" ng-model-options="{debounce:250}" class="search-query form-control" placeholder="{{searchPlaceholder}}" ng-keyup="handleKey($event)">\n </div>\n</form>\n<div class="results-container" ng-show="results.length >= 1">\n <div class="search-results">\n <div ng-repeat="result in results">\n <span ng-class="resultClass($index)" ng-click="selectResult($index)" title={{result.additional}}>{{result.resourceText}} {{result.text}}</span>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n')}]);
@@ -157,6 +157,8 @@ declare module fng {
157
157
  formstyle?: formStyle; // (only valid on a sub schema) sets style of sub form.
158
158
  sortable? : boolean | string; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
159
159
  ngClass?: string; // Allows for conditional per-item styling through the addition of an ng-class expression to the class list of li elements created for each item in the array
160
+ subDocContainerType?: 'fieldset' | 'well' | 'well-large' | 'well-small' | string | ((info) => {before: '', after: ''}); // allows each element in the array to be nested in a container
161
+ subDocContainerProps?: any; // the parameters that will be passed if subDocContainerType is a function
160
162
 
161
163
  /*
162
164
  The next section relates to the display of sub documents
@@ -246,6 +246,7 @@ var FormsAngular = /** @class */ (function () {
246
246
  };
247
247
  ;
248
248
  FormsAngular.prototype.internalSearch = function (req, resourcesToSearch, includeResourceInResults, limit, callback) {
249
+ var _a, _b, _c, _d;
249
250
  if (typeof req.query === 'undefined') {
250
251
  req.query = {};
251
252
  }
@@ -278,9 +279,29 @@ var FormsAngular = /** @class */ (function () {
278
279
  if (filter) {
279
280
  filter = JSON.parse(filter);
280
281
  }
282
+ // See if we are narrowing down the resources
283
+ var collectionName;
284
+ var collectionNameLower;
285
+ var colonPos = searchFor.indexOf(':');
286
+ switch (colonPos) {
287
+ case -1:
288
+ // Original behaviour = do nothing different
289
+ break;
290
+ case 0:
291
+ // "Special search" - yet to be implemented
292
+ break;
293
+ default:
294
+ collectionName = searchFor.slice(0, colonPos);
295
+ collectionNameLower = collectionName.toLowerCase();
296
+ searchFor = searchFor.slice(colonPos + 1, 999);
297
+ if (searchFor === '') {
298
+ searchFor = '?';
299
+ }
300
+ break;
301
+ }
281
302
  for (var i = 0; i < resourceCount; i++) {
282
303
  var resource = resourcesToSearch[i];
283
- if (resourceCount === 1 || resource.options.searchImportance !== false) {
304
+ if (resourceCount === 1 || (resource.options.searchImportance !== false && (!collectionName || collectionName === resource.resourceName || ((_b = (_a = resource.options) === null || _a === void 0 ? void 0 : _a.synonyms) === null || _b === void 0 ? void 0 : _b.find(function (s) { var _a; return ((_a = s.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === collectionNameLower; }))))) {
284
305
  var schema = resource.model.schema;
285
306
  var indexedFields = [];
286
307
  for (var j = 0; j < schema._indexes.length; j++) {
@@ -302,8 +323,14 @@ var FormsAngular = /** @class */ (function () {
302
323
  if (indexedFields.length === 0) {
303
324
  console.log('ERROR: Searching on a collection with no indexes ' + resource.resourceName);
304
325
  }
326
+ var synonymObj = (_d = (_c = resource.options) === null || _c === void 0 ? void 0 : _c.synonyms) === null || _d === void 0 ? void 0 : _d.find(function (s) { return s.name.toLowerCase() === collectionNameLower; });
327
+ var synonymFilter = synonymObj === null || synonymObj === void 0 ? void 0 : synonymObj.filter;
305
328
  for (var m = 0; m < indexedFields.length; m++) {
306
- searches.push({ resource: resource, field: indexedFields[m] });
329
+ var searchObj = { resource: resource, field: indexedFields[m] };
330
+ if (synonymFilter) {
331
+ searchObj.filter = synonymFilter;
332
+ }
333
+ searches.push(searchObj);
307
334
  }
308
335
  }
309
336
  }
@@ -330,98 +357,94 @@ var FormsAngular = /** @class */ (function () {
330
357
  searchCriteria = { $regex: '^(' + modifiedSearchStr + ')', $options: 'i' };
331
358
  }
332
359
  var handleSearchResultsFromIndex = function (err, docs, item, cb) {
333
- if (!err && docs && docs.length > 0) {
334
- async.map(docs, function (aDoc, cbdoc) {
335
- return __awaiter(this, void 0, void 0, function () {
336
- function handleResultsInList() {
337
- if (multiMatchPossible) {
338
- resultObject.matched = resultObject.matched || [];
339
- // record the index of string that matched, so we don't count it against another field
340
- for (var i = 0; i < searchStrings.length; i++) {
341
- if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
342
- resultObject.matched.push(i);
343
- break;
344
- }
345
- }
360
+ function handleSingleSearchResult(aDoc, cbdoc) {
361
+ var thisId = aDoc._id.toString(), resultObject, resultPos;
362
+ function handleResultsInList() {
363
+ if (multiMatchPossible) {
364
+ resultObject.matched = resultObject.matched || [];
365
+ // record the index of string that matched, so we don't count it against another field
366
+ for (var i = 0; i < searchStrings.length; i++) {
367
+ if (aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
368
+ resultObject.matched.push(i);
369
+ break;
346
370
  }
347
- resultObject.searchImportance = item.resource.options.searchImportance || 99;
348
- if (item.resource.options.localisationData) {
349
- resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
350
- resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
351
- resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
371
+ }
372
+ }
373
+ resultObject.searchImportance = item.resource.options.searchImportance || 99;
374
+ if (item.resource.options.localisationData) {
375
+ resultObject.resource = translate(resultObject.resource, item.resource.options.localisationData, "resource");
376
+ resultObject.resourceText = translate(resultObject.resourceText, item.resource.options.localisationData, "resourceText");
377
+ resultObject.resourceTab = translate(resultObject.resourceTab, item.resource.options.localisationData, "resourceTab");
378
+ }
379
+ results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
380
+ cbdoc(null);
381
+ }
382
+ // Do we already have them in the list?
383
+ for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
384
+ if (results[resultPos].id.toString() === thisId) {
385
+ break;
386
+ }
387
+ }
388
+ if (resultPos >= 0) {
389
+ resultObject = Object.assign({}, results[resultPos]);
390
+ // If they have already matched then improve their weighting
391
+ if (multiMatchPossible) {
392
+ // record the index of string that matched, so we don't count it against another field
393
+ for (var i = 0; i < searchStrings.length; i++) {
394
+ if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
395
+ resultObject.matched.push(i);
396
+ resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
397
+ // remove it from current position
398
+ results.splice(resultPos, 1);
399
+ // and re-insert where appropriate
400
+ results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
401
+ break;
352
402
  }
353
- results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
354
- cbdoc(null);
355
403
  }
356
- var thisId, resultObject, resultPos, i, addHits_1, specialListingFormat;
357
- return __generator(this, function (_a) {
358
- switch (_a.label) {
359
- case 0:
360
- thisId = aDoc._id.toString();
361
- for (resultPos = results.length - 1; resultPos >= 0; resultPos--) {
362
- if (results[resultPos].id.toString() === thisId) {
363
- break;
364
- }
365
- }
366
- if (!(resultPos >= 0)) return [3 /*break*/, 1];
367
- resultObject = Object.assign({}, results[resultPos]);
368
- // If they have already matched then improve their weighting
369
- if (multiMatchPossible) {
370
- // record the index of string that matched, so we don't count it against another field
371
- for (i = 0; i < searchStrings.length; i++) {
372
- if (!resultObject.matched.includes(i) && aDoc[item.field].toLowerCase().indexOf(searchStrings[i]) === 0) {
373
- resultObject.matched.push(i);
374
- resultObject.addHits = Math.max((resultObject.addHits || 9) - 1, 0);
375
- // remove it from current position
376
- results.splice(resultPos, 1);
377
- // and re-insert where appropriate
378
- results.splice(_.sortedIndexBy(results, resultObject, calcResultValue), 0, resultObject);
379
- break;
380
- }
381
- }
382
- }
383
- cbdoc(null);
384
- return [3 /*break*/, 4];
385
- case 1:
386
- if (multiMatchPossible)
387
- // If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
388
- if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
389
- addHits_1 = 7;
390
- }
391
- specialListingFormat = item.resource.options.searchResultFormat;
392
- if (!specialListingFormat) return [3 /*break*/, 3];
393
- return [4 /*yield*/, specialListingFormat.apply(aDoc)];
394
- case 2:
395
- resultObject = _a.sent();
396
- resultObject.addHits = addHits_1;
397
- handleResultsInList();
398
- return [3 /*break*/, 4];
399
- case 3:
400
- that.getListFields(item.resource, aDoc, function (err, description) {
401
- if (err) {
402
- cbdoc(err);
403
- }
404
- else {
405
- resultObject = {
406
- id: aDoc._id,
407
- weighting: 9999,
408
- addHits: addHits_1,
409
- text: description
410
- };
411
- if (resourceCount > 1 || includeResourceInResults) {
412
- resultObject.resource = resultObject.resourceText = item.resource.resourceName;
413
- }
414
- handleResultsInList();
415
- }
416
- });
417
- _a.label = 4;
418
- case 4: return [2 /*return*/];
404
+ }
405
+ cbdoc(null);
406
+ }
407
+ else {
408
+ // Otherwise add them new...
409
+ var addHits_1;
410
+ if (multiMatchPossible)
411
+ // If they match the whole search phrase in one index they get smaller addHits (so they sort higher)
412
+ if (aDoc[item.field].toLowerCase().indexOf(searchFor) === 0) {
413
+ addHits_1 = 7;
414
+ }
415
+ // Use special listings format if defined
416
+ var specialListingFormat = item.resource.options.searchResultFormat;
417
+ if (specialListingFormat) {
418
+ specialListingFormat.apply(aDoc, [req])
419
+ .then(function (resultObj) {
420
+ resultObject = resultObj;
421
+ resultObject.addHits = addHits_1;
422
+ handleResultsInList();
423
+ });
424
+ }
425
+ else {
426
+ that.getListFields(item.resource, aDoc, function (err, description) {
427
+ if (err) {
428
+ cbdoc(err);
429
+ }
430
+ else {
431
+ resultObject = {
432
+ id: aDoc._id,
433
+ weighting: 9999,
434
+ addHits: addHits_1,
435
+ text: description
436
+ };
437
+ if (resourceCount > 1 || includeResourceInResults) {
438
+ resultObject.resource = resultObject.resourceText = item.resource.resourceName;
439
+ }
440
+ handleResultsInList();
419
441
  }
420
442
  });
421
- });
422
- }, function (err) {
423
- cb(err);
424
- });
443
+ }
444
+ }
445
+ }
446
+ if (!err && docs && docs.length > 0) {
447
+ async.map(docs, handleSingleSearchResult, cb);
425
448
  }
426
449
  else {
427
450
  cb(err);
@@ -429,13 +452,14 @@ var FormsAngular = /** @class */ (function () {
429
452
  };
430
453
  this.searchFunc(searches, function (item, cb) {
431
454
  var searchDoc = {};
432
- if (filter) {
433
- that.hackVariables(filter);
434
- extend(searchDoc, filter);
435
- if (filter[item.field]) {
455
+ var searchFilter = filter || item.filter;
456
+ if (searchFilter) {
457
+ that.hackVariables(searchFilter);
458
+ extend(searchDoc, searchFilter);
459
+ if (searchFilter[item.field]) {
436
460
  delete searchDoc[item.field];
437
461
  var obj1 = {}, obj2 = {};
438
- obj1[item.field] = filter[item.field];
462
+ obj1[item.field] = searchFilter[item.field];
439
463
  obj2[item.field] = searchCriteria;
440
464
  searchDoc['$and'] = [obj1, obj2];
441
465
  }
@@ -690,7 +714,7 @@ var FormsAngular = /** @class */ (function () {
690
714
  reportSchema = JSON.parse(req.query.r);
691
715
  break;
692
716
  default:
693
- return [2 /*return*/, self.renderError(new mongoose_1.Error('Invalid "r" parameter'), null, req, res, next)];
717
+ return [2 /*return*/, self.renderError(new mongoose_1.Error('Invalid "r" parameter'), null, req, res)];
694
718
  }
695
719
  }
696
720
  else {
@@ -717,7 +741,7 @@ var FormsAngular = /** @class */ (function () {
717
741
  schemaCopy.params = schemaCopy.params || [];
718
742
  self.reportInternal(req, req.resource, schemaCopy, function (err, result) {
719
743
  if (err) {
720
- self.renderError(err, null, req, res, next);
744
+ self.renderError(err, null, req, res);
721
745
  }
722
746
  else {
723
747
  res.send(result);
@@ -765,7 +789,7 @@ var FormsAngular = /** @class */ (function () {
765
789
  };
766
790
  ;
767
791
  FormsAngular.prototype.sanitisePipeline = function (aggregationParam, hiddenFields, findFuncQry) {
768
- var _a, _b;
792
+ var _a, _b, _c, _d;
769
793
  var that = this;
770
794
  var array = Array.isArray(aggregationParam) ? aggregationParam : [aggregationParam];
771
795
  var retVal = [];
@@ -783,6 +807,20 @@ var FormsAngular = /** @class */ (function () {
783
807
  case '$merge':
784
808
  case '$out':
785
809
  throw new mongoose_1.Error('Cannot use potentially destructive pipeline stages');
810
+ case '$unionWith':
811
+ /*
812
+ Sanitise the pipeline we are doing a union with, removing hidden fields from that collection
813
+ */
814
+ var unionCollectionName = stage.$unionWith.coll;
815
+ var unionResource = that.getResourceFromCollection(unionCollectionName);
816
+ var unionHiddenLookupFields = {};
817
+ if (unionResource) {
818
+ if (((_b = (_a = unionResource.options) === null || _a === void 0 ? void 0 : _a.hide) === null || _b === void 0 ? void 0 : _b.length) > 0) {
819
+ unionHiddenLookupFields = this_1.generateHiddenFields(unionResource, false);
820
+ }
821
+ }
822
+ stage.$unionWith.pipeline = that.sanitisePipeline(stage.$unionWith.pipeline, unionHiddenLookupFields, findFuncQry);
823
+ break;
786
824
  case '$match':
787
825
  this_1.hackVariables(array[pipelineSection]['$match']);
788
826
  retVal.push(array[pipelineSection]);
@@ -803,7 +841,7 @@ var FormsAngular = /** @class */ (function () {
803
841
  }
804
842
  var resource = that.getResourceFromCollection(collectionName);
805
843
  if (resource) {
806
- if (((_b = (_a = resource.options) === null || _a === void 0 ? void 0 : _a.hide) === null || _b === void 0 ? void 0 : _b.length) > 0) {
844
+ if (((_d = (_c = resource.options) === null || _c === void 0 ? void 0 : _c.hide) === null || _d === void 0 ? void 0 : _d.length) > 0) {
807
845
  var hiddenLookupFields = this_1.generateHiddenFields(resource, false);
808
846
  var hiddenFieldsObj_1 = {};
809
847
  Object.keys(hiddenLookupFields).forEach(function (hf) {
@@ -936,8 +974,8 @@ var FormsAngular = /** @class */ (function () {
936
974
  else {
937
975
  // TODO - this ref func can probably be done away with now that list fields can have ref
938
976
  var j_1 = 0;
939
- async.whilst(function () {
940
- return j_1 < findResults.length;
977
+ async.whilst(function (cbtest) {
978
+ cbtest(null, j_1 < findResults.length);
941
979
  }, function (cbres) {
942
980
  var theResult = findResults[j_1];
943
981
  translateObject.translations[j_1] = translateObject.translations[j_1] || {};
@@ -1092,7 +1130,7 @@ var FormsAngular = /** @class */ (function () {
1092
1130
  var self_1 = this;
1093
1131
  this.filteredFind(req.resource, req, aggregationParam, findParam, projectParam, orderParam, limitParam, skipParam, function (err, docs) {
1094
1132
  if (err) {
1095
- return self_1.renderError(err, null, req, res, next);
1133
+ return self_1.renderError(err, null, req, res);
1096
1134
  }
1097
1135
  else {
1098
1136
  res.send(docs);
@@ -1164,7 +1202,7 @@ var FormsAngular = /** @class */ (function () {
1164
1202
  function doAggregation(queryObj, cb) {
1165
1203
  if (aggregationParam) {
1166
1204
  aggregationParam = that.sanitisePipeline(aggregationParam, hiddenFields, queryObj);
1167
- resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
1205
+ void resource.model.aggregate(aggregationParam, function (err, aggregationResults) {
1168
1206
  if (err) {
1169
1207
  throw err;
1170
1208
  }
@@ -1282,6 +1320,7 @@ var FormsAngular = /** @class */ (function () {
1282
1320
  var hiddenFields = this.generateHiddenFields(resource, false);
1283
1321
  hiddenFields.__v = false;
1284
1322
  that.doFindFunc(req, resource, function (err, queryObj) {
1323
+ var _a;
1285
1324
  if (err) {
1286
1325
  cb(err);
1287
1326
  }
@@ -1303,7 +1342,7 @@ var FormsAngular = /** @class */ (function () {
1303
1342
  else {
1304
1343
  crit = idSel;
1305
1344
  }
1306
- cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, req.query.p)));
1345
+ cb(null, resource.model.findOne(crit).select(that.generateProjection(hiddenFields, (_a = req.query) === null || _a === void 0 ? void 0 : _a.p)));
1307
1346
  }
1308
1347
  });
1309
1348
  };
@@ -31,6 +31,8 @@ declare module fngServer {
31
31
  [pathName: string]: Path;
32
32
  }
33
33
 
34
+ export type ISearchResultFormatter = () => Promise<ISearchResult>;
35
+
34
36
  export interface ResourceOptions {
35
37
  suppressDeprecatedMessage?: boolean;
36
38
  onRemove?: (doc, req, cb) => void;
@@ -40,11 +42,12 @@ declare module fngServer {
40
42
  findFunc?: (req, cb) => void,
41
43
  getOrgCriteria?: (userOrganisation: string) => Promise<any>
42
44
  idIsList?: IIdIsList,
43
- searchResultFormat?: ISearchResult,
45
+ searchResultFormat?: ISearchResultFormatter,
44
46
  searchOrder?: any,
45
47
  listOrder?: any,
46
48
  onAccess?: (req, cb) => void,
47
49
  searchFunc?: SearchFunc;
50
+ synonyms? : {name: string, filter?: any}[], // name must be lower case
48
51
  // below here are autogenerated
49
52
  listFields?: { field: string }[]; // added after preprocess
50
53
  dependents?: { resource: Resource, keys: string[]} []; // can be added by generateDependencyList
@@ -62,12 +65,15 @@ declare module fngServer {
62
65
  callback: (err: Error, docs?: any[]) => void
63
66
  ) => void;
64
67
 
65
- interface Resource {
66
- resourceName: string;
68
+ interface ResourceExport {
67
69
  model?: Model<any>; // TODO TS Get rid of the ? here
68
70
  options?: ResourceOptions;
69
71
  }
70
72
 
73
+ interface Resource extends ResourceExport {
74
+ resourceName: string;
75
+ }
76
+
71
77
  interface ListParams {
72
78
  ref: Boolean; // The object is this a lookup?
73
79
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "Mark Chapman <support@forms-angular.org>",
4
4
  "description": "A form builder that sits on top of Angular.js, Twitter Bootstrap, jQuery UI, Angular-UI, Express and Mongoose. Opinionated or what?",
5
5
  "homepage": "http://forms-angular.org",
6
- "version": "0.12.0-beta.168",
6
+ "version": "0.12.0-beta.171",
7
7
  "engines": {
8
8
  "node": ">=8.x",
9
9
  "npm": ">=5.x"