forms-angular 0.12.0-beta.264 → 0.12.0-beta.265
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.
- package/dist/client/forms-angular.js +357 -207
- package/dist/client/forms-angular.min.js +1 -1
- package/dist/client/index.d.ts +24 -13
- package/dist/server/data_form.js +35 -24
- package/dist/server/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -12,8 +12,60 @@ var fng;
|
|
|
12
12
|
(function (fng) {
|
|
13
13
|
var directives;
|
|
14
14
|
(function (directives) {
|
|
15
|
-
/*@ngInject*/
|
|
16
15
|
modelControllerDropdown.$inject = ["SecurityService"];
|
|
16
|
+
function dropDownItem($compile) {
|
|
17
|
+
return {
|
|
18
|
+
restrict: "AE",
|
|
19
|
+
replace: true,
|
|
20
|
+
link: function (scope, element) {
|
|
21
|
+
var template = ' <a ng-show="choice.text || choice.textFunc" class="dropdown-option" ng-href="{{choice.url || choice.urlFunc()}}" ng-click="doClick($index, $event, choice)">' +
|
|
22
|
+
" {{ choice.text || choice.textFunc() }}" +
|
|
23
|
+
" </a>";
|
|
24
|
+
element.replaceWith($compile(template)(scope));
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
directives.dropDownItem = dropDownItem;
|
|
29
|
+
function dropDownSubMenu($compile) {
|
|
30
|
+
return {
|
|
31
|
+
restrict: "AE",
|
|
32
|
+
replace: true,
|
|
33
|
+
link: function (scope, element) {
|
|
34
|
+
var parent = element[0].parentElement;
|
|
35
|
+
var template = ' <a ng-show="choice.text || choice.textFunc" class="dropdown-option open-sub-menu" data-ng-mouseenter="mouseenter()">' +
|
|
36
|
+
" {{ choice.text || choice.textFunc() }}" +
|
|
37
|
+
" </a>" +
|
|
38
|
+
// for now, the remainder of this template does not honour RBAC - come back to this if anyone ever reports it
|
|
39
|
+
' <ul class="uib-dropdown-menu dropdown-menu sub-menu">' +
|
|
40
|
+
" <li ng-repeat=\"choice in choice.items\" ng-attr-id=\"{{choice.id}}\">" + // ${itemVisibilityStr} ${itemDisabledStr}
|
|
41
|
+
' <drop-down-item data-ng-if="::!choice.items"></drop-down-item>' +
|
|
42
|
+
' <drop-down-sub-menu data-ng-if="::choice.items"></drop-down-sub-menu>' +
|
|
43
|
+
" </li>" +
|
|
44
|
+
" </ul>";
|
|
45
|
+
var us = $compile(template)(scope);
|
|
46
|
+
element.replaceWith(us);
|
|
47
|
+
scope.mouseenter = function () {
|
|
48
|
+
// generally-speaking, we want the bottom of the sub-menu to line-up with the bottom of its parent menu
|
|
49
|
+
// item. we could achieve that using css alone, but the problem comes when the sub menu is too tall, and bottom-
|
|
50
|
+
// aligning it like that causes the top of the menu to overflow the navbar (or even higher).
|
|
51
|
+
// so we need to detect that case, and cap the top of the sub-menu at the top of the parent menu.
|
|
52
|
+
// this is harder than it sounds, as the top of the sub menu needs to be expressed (as a negative number)
|
|
53
|
+
// relative to the top of the parent menu item (because that is the closest relative-positioned parent
|
|
54
|
+
// to the submenu, and therefore what it - as an absolutely-positioned element - is expressed in relation to)
|
|
55
|
+
var parentRect = parent.getBoundingClientRect();
|
|
56
|
+
var ourHeight = us[2].getBoundingClientRect().height;
|
|
57
|
+
var offset = ourHeight - 5; // this is the top padding
|
|
58
|
+
if (offset > parentRect.top) {
|
|
59
|
+
offset -= offset - parentRect.top + parentRect.height;
|
|
60
|
+
}
|
|
61
|
+
offset -= parentRect.height;
|
|
62
|
+
us[2].style.top = "-".concat(offset, "px");
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
directives.dropDownSubMenu = dropDownSubMenu;
|
|
68
|
+
/*@ngInject*/
|
|
17
69
|
function modelControllerDropdown(SecurityService) {
|
|
18
70
|
var menuVisibilityStr;
|
|
19
71
|
var menuDisabledStr;
|
|
@@ -24,7 +76,7 @@ var fng;
|
|
|
24
76
|
var oneTimeBinding = fng.formsAngular.elemSecurityFuncBinding !== "normal";
|
|
25
77
|
var bindingStr = oneTimeBinding ? "::" : "";
|
|
26
78
|
if (SecurityService.canDoSecurity("hidden")) {
|
|
27
|
-
menuVisibilityStr = "ng-if=\"contextMenuId && !contextMenuHidden\" ".concat(SecurityService.getHideableAttrs(
|
|
79
|
+
menuVisibilityStr = "ng-if=\"contextMenuId && !contextMenuHidden\" ".concat(SecurityService.getHideableAttrs("{{ ::contextMenuId }}"));
|
|
28
80
|
if (oneTimeBinding) {
|
|
29
81
|
// because the isHidden(...) logic is highly likely to be model dependent, that cannot be one-time bound. to
|
|
30
82
|
// be able to combine one-time and regular binding, we'll use ng-if for the one-time bound stuff and ng-hide for the rest
|
|
@@ -33,20 +85,20 @@ var fng;
|
|
|
33
85
|
else if (fng.formsAngular.elemSecurityFuncBinding === "normal") {
|
|
34
86
|
itemVisibilityStr = "ng-hide=\"".concat(itemVisibilityStr, " || (!choice.divider && isSecurelyHidden(choice.id))\"");
|
|
35
87
|
}
|
|
36
|
-
itemVisibilityStr += " ".concat(SecurityService.getHideableAttrs(
|
|
88
|
+
itemVisibilityStr += " ".concat(SecurityService.getHideableAttrs("{{ ::choice.id }}"));
|
|
37
89
|
}
|
|
38
90
|
else {
|
|
39
91
|
menuVisibilityStr = "";
|
|
40
92
|
itemVisibilityStr = "ng-hide=\"".concat(itemVisibilityStr, "\"");
|
|
41
93
|
}
|
|
42
94
|
if (SecurityService.canDoSecurity("disabled")) {
|
|
43
|
-
menuDisabledStr = "disableable-link ng-disabled=\"contextMenuDisabled\" ".concat(SecurityService.getDisableableAttrs(
|
|
95
|
+
menuDisabledStr = "disableable-link ng-disabled=\"contextMenuDisabled\" ".concat(SecurityService.getDisableableAttrs("{{ ::contextMenuId }}"));
|
|
44
96
|
// as ng-class is already being used, we'll add the .disabled class if the menu item is securely disabled using
|
|
45
97
|
// class="{{ }}". note that we "prevent" a disabled menu item from being clicked by checking for the DISABLED
|
|
46
98
|
// attribute in the doClick(...) function, and aborting if this is found.
|
|
47
99
|
// note that the 'normal' class introduced here might not actually do anything, but for one-time binding to work
|
|
48
100
|
// properly, we need a truthy value
|
|
49
|
-
itemDisabledStr += " class=\"{{ ".concat(bindingStr, "(!choice.divider && isSecurelyDisabled(choice.id)) ? 'disabled' : 'normal' }}\" ").concat(SecurityService.getDisableableAttrs(
|
|
101
|
+
itemDisabledStr += " class=\"{{ ".concat(bindingStr, "(!choice.divider && isSecurelyDisabled(choice.id)) ? 'disabled' : 'normal' }}\" ").concat(SecurityService.getDisableableAttrs("{{ ::choice.id }}"));
|
|
50
102
|
}
|
|
51
103
|
else {
|
|
52
104
|
menuDisabledStr = "";
|
|
@@ -60,9 +112,8 @@ var fng;
|
|
|
60
112
|
" </a>" +
|
|
61
113
|
' <ul class="uib-dropdown-menu dropdown-menu">' +
|
|
62
114
|
" <li ng-repeat=\"choice in items\" ng-attr-id=\"{{choice.id}}\" ".concat(itemVisibilityStr, " ").concat(itemDisabledStr, ">") +
|
|
63
|
-
' <
|
|
64
|
-
"
|
|
65
|
-
" </a>" +
|
|
115
|
+
' <drop-down-item data-ng-if="!choice.items"></drop-down-item>' +
|
|
116
|
+
' <drop-down-sub-menu data-ng-if="choice.items"></drop-down-sub-menu>' +
|
|
66
117
|
" </li>" +
|
|
67
118
|
" </ul>" +
|
|
68
119
|
"</li>",
|
|
@@ -914,8 +965,13 @@ var fng;
|
|
|
914
965
|
}
|
|
915
966
|
}
|
|
916
967
|
else {
|
|
968
|
+
// NB: Any changes to what properties we support @@-wrapped pseudonyms for here should be repeated in
|
|
969
|
+
// PluginHelperService.extractFromAttr
|
|
970
|
+
info.help = FormMarkupHelperService.handlePseudos(scope, info.help);
|
|
971
|
+
info.label = FormMarkupHelperService.handlePseudos(scope, info.label);
|
|
972
|
+
info.popup = FormMarkupHelperService.handlePseudos(scope, info.popup);
|
|
917
973
|
// Handle arrays here
|
|
918
|
-
var controlDivClasses = FormMarkupHelperService.controlDivClasses(options);
|
|
974
|
+
var controlDivClasses = FormMarkupHelperService.controlDivClasses(options, info);
|
|
919
975
|
if (info.array) {
|
|
920
976
|
controlDivClasses.push('fng-array');
|
|
921
977
|
if (options.formstyle === 'inline' || options.formstyle === 'stacked') {
|
|
@@ -1116,179 +1172,201 @@ var fng;
|
|
|
1116
1172
|
}
|
|
1117
1173
|
return result;
|
|
1118
1174
|
};
|
|
1175
|
+
scope.$on("regenerateFormMarkup", function (event, formId) {
|
|
1176
|
+
if (!attrs.formid || attrs.formid !== formId) {
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
generateForm(scope[attrs.schema]);
|
|
1180
|
+
});
|
|
1119
1181
|
var unwatch = scope.$watch(attrs.schema, function (newValue) {
|
|
1120
1182
|
if (newValue) {
|
|
1121
1183
|
var newArrayValue = angular.isArray(newValue) ? newValue : [newValue]; // otherwise some old tests stop working for no real reason
|
|
1122
1184
|
if (newArrayValue.length > 0 && typeof unwatch === "function") {
|
|
1123
1185
|
unwatch();
|
|
1124
1186
|
unwatch = null;
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
}
|
|
1143
|
-
hiddenTabReintroductionMethod = tab.hiddenTabReintroductionMethod;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
// now we have established that we don't have more than one value for hiddenTabArrayProp, apply a default if no
|
|
1147
|
-
// value has been provided at all...
|
|
1148
|
-
if (!hiddenTabArrayProp) {
|
|
1149
|
-
hiddenTabArrayProp = "record.hiddenTabs";
|
|
1150
|
-
}
|
|
1151
|
-
// ...and then replace all blanks with this value so the processInstructions() call made below can deal with
|
|
1152
|
-
// each tab independently of the others
|
|
1153
|
-
for (var _a = 0, hideableTabs_2 = hideableTabs; _a < hideableTabs_2.length; _a++) {
|
|
1154
|
-
var tab = hideableTabs_2[_a];
|
|
1155
|
-
tab.hiddenTabArrayProp = hiddenTabArrayProp;
|
|
1187
|
+
generateForm(newArrayValue);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}, true);
|
|
1191
|
+
var formElement;
|
|
1192
|
+
var generateForm = function (schema) {
|
|
1193
|
+
var elementHtml = '';
|
|
1194
|
+
var recordAttribute = attrs.model || 'record'; // By default data comes from scope.record
|
|
1195
|
+
var theRecord = scope[recordAttribute];
|
|
1196
|
+
var hideableTabs = schema.filter(function (s) { return s && s.containerType === "tab" && s.hideable; });
|
|
1197
|
+
var hiddenTabArrayProp;
|
|
1198
|
+
var hiddenTabReintroductionMethod;
|
|
1199
|
+
for (var _i = 0, hideableTabs_1 = hideableTabs; _i < hideableTabs_1.length; _i++) {
|
|
1200
|
+
var tab = hideableTabs_1[_i];
|
|
1201
|
+
if (tab.hiddenTabArrayProp) {
|
|
1202
|
+
if (hiddenTabArrayProp && tab.hiddenTabArrayProp !== hiddenTabArrayProp) {
|
|
1203
|
+
throw new Error("Currently, tab sets with more than one value for hiddenTabArrayProp are not supported");
|
|
1156
1204
|
}
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
});
|
|
1205
|
+
hiddenTabArrayProp = tab.hiddenTabArrayProp;
|
|
1206
|
+
}
|
|
1207
|
+
if (tab.hiddenTabReintroductionMethod) {
|
|
1208
|
+
if (hiddenTabReintroductionMethod && tab.hiddenTabReintroductionMethod !== hiddenTabReintroductionMethod) {
|
|
1209
|
+
throw new Error("Currently, tab sets with more than one value for hiddenTabReintroductionMethod are not supported");
|
|
1163
1210
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1211
|
+
hiddenTabReintroductionMethod = tab.hiddenTabReintroductionMethod;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
// now we have established that we don't have more than one value for hiddenTabArrayProp, apply a default if no
|
|
1215
|
+
// value has been provided at all...
|
|
1216
|
+
if (!hiddenTabArrayProp) {
|
|
1217
|
+
hiddenTabArrayProp = "record.hiddenTabs";
|
|
1218
|
+
}
|
|
1219
|
+
// ...and then replace all blanks with this value so the processInstructions() call made below can deal with
|
|
1220
|
+
// each tab independently of the others
|
|
1221
|
+
for (var _a = 0, hideableTabs_2 = hideableTabs; _a < hideableTabs_2.length; _a++) {
|
|
1222
|
+
var tab = hideableTabs_2[_a];
|
|
1223
|
+
tab.hiddenTabArrayProp = hiddenTabArrayProp;
|
|
1224
|
+
}
|
|
1225
|
+
if (hiddenTabReintroductionMethod === "tab") {
|
|
1226
|
+
schema.push({
|
|
1227
|
+
containerType: "+tab",
|
|
1228
|
+
hiddenTabArrayProp: hiddenTabArrayProp,
|
|
1229
|
+
content: []
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
theRecord = theRecord || {};
|
|
1233
|
+
if ((attrs.subschema || attrs.model) && !attrs.forceform) {
|
|
1234
|
+
elementHtml = '';
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
scope.topLevelFormName = attrs.name || 'myForm'; // Form name defaults to myForm
|
|
1238
|
+
// Copy attrs we don't process into form
|
|
1239
|
+
var customAttrs = '';
|
|
1240
|
+
for (var thisAttr in attrs) {
|
|
1241
|
+
if (attrs.hasOwnProperty(thisAttr)) {
|
|
1242
|
+
if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model', 'viewform'].indexOf(thisAttr) === -1) {
|
|
1243
|
+
customAttrs += ' ' + attrs.$attr[thisAttr] + '="' + attrs[thisAttr] + '"';
|
|
1244
|
+
}
|
|
1167
1245
|
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1246
|
+
}
|
|
1247
|
+
var tag = attrs.forceform ? 'ng-form' : 'form';
|
|
1248
|
+
elementHtml = "<".concat(tag, " name=\"").concat(scope.topLevelFormName, "\" class=\"").concat(convertFormStyleToClass(attrs.formstyle), "\" novalidate ").concat(customAttrs, ">");
|
|
1249
|
+
}
|
|
1250
|
+
if (theRecord === scope.topLevelFormName) {
|
|
1251
|
+
throw new Error('Model and Name must be distinct - they are both ' + theRecord);
|
|
1252
|
+
}
|
|
1253
|
+
elementHtml += processInstructions(schema, true, attrs);
|
|
1254
|
+
if (tabsSetup === tabsSetupState.Forced) {
|
|
1255
|
+
elementHtml += '</uib-tabset>';
|
|
1256
|
+
}
|
|
1257
|
+
elementHtml += attrs.subschema ? '' : '</form>';
|
|
1258
|
+
var compiledFormElement = $compile(elementHtml)(scope);
|
|
1259
|
+
if (formElement) {
|
|
1260
|
+
var topLevelForm = scope[scope.topLevelFormName];
|
|
1261
|
+
formElement.replaceWith(compiledFormElement);
|
|
1262
|
+
// the replaceWith will cause the scope[scope.topLevelFormName] to be cleared, so we need to...:
|
|
1263
|
+
scope[scope.topLevelFormName] = topLevelForm;
|
|
1264
|
+
}
|
|
1265
|
+
else {
|
|
1266
|
+
element.replaceWith(compiledFormElement);
|
|
1267
|
+
}
|
|
1268
|
+
// remember the element that we're now represented by (which is no longer the value
|
|
1269
|
+
// of element passed to our link function). This will enable us to replace the
|
|
1270
|
+
// correct element upon receipt of a regenerateFormMarkup request.
|
|
1271
|
+
formElement = compiledFormElement;
|
|
1272
|
+
// If there are subkeys we need to fix up ng-model references when record is read
|
|
1273
|
+
// If we have modelControllers we need to let them know when we have form + data
|
|
1274
|
+
var sharedData = scope[attrs.shared || 'sharedData'];
|
|
1275
|
+
var modelControllers = sharedData ? sharedData.modelControllers : [];
|
|
1276
|
+
if ((subkeys.length > 0 || modelControllers.length > 0) && !scope.phaseWatcher) {
|
|
1277
|
+
var unwatch2 = scope.$watch('phase', function (newValue) {
|
|
1278
|
+
scope.phaseWatcher = true;
|
|
1279
|
+
if (newValue === 'ready' && typeof unwatch2 === "function") {
|
|
1280
|
+
unwatch2();
|
|
1281
|
+
unwatch2 = null;
|
|
1282
|
+
// Tell the 'model controllers' that the form and data are there
|
|
1283
|
+
for (var i = 0; i < modelControllers.length; i++) {
|
|
1284
|
+
if (modelControllers[i].onAllReady) {
|
|
1285
|
+
modelControllers[i].onAllReady(scope);
|
|
1177
1286
|
}
|
|
1178
1287
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
var unwatch2 = scope.$watch('phase', function (newValue) {
|
|
1198
|
-
scope.phaseWatcher = true;
|
|
1199
|
-
if (newValue === 'ready' && typeof unwatch2 === "function") {
|
|
1200
|
-
unwatch2();
|
|
1201
|
-
unwatch2 = null;
|
|
1202
|
-
// Tell the 'model controllers' that the form and data are there
|
|
1203
|
-
for (var i = 0; i < modelControllers_1.length; i++) {
|
|
1204
|
-
if (modelControllers_1[i].onAllReady) {
|
|
1205
|
-
modelControllers_1[i].onAllReady(scope);
|
|
1288
|
+
// For each one of the subkeys sets in the form we need to fix up ng-model references
|
|
1289
|
+
for (var subkeyCtr = 0; subkeyCtr < subkeys.length; subkeyCtr++) {
|
|
1290
|
+
var info = subkeys[subkeyCtr];
|
|
1291
|
+
var arrayOffset;
|
|
1292
|
+
var matching;
|
|
1293
|
+
var arrayToProcess = angular.isArray(info.subkey) ? info.subkey : [info.subkey];
|
|
1294
|
+
var parts = info.name.split('.');
|
|
1295
|
+
var dataVal = theRecord;
|
|
1296
|
+
while (parts.length > 1) {
|
|
1297
|
+
dataVal = dataVal[parts.shift()] || {};
|
|
1298
|
+
}
|
|
1299
|
+
dataVal = dataVal[parts[0]] = dataVal[parts[0]] || [];
|
|
1300
|
+
// For each of the required subkeys of this type
|
|
1301
|
+
for (var thisOffset = 0; thisOffset < arrayToProcess.length; thisOffset++) {
|
|
1302
|
+
if (arrayToProcess[thisOffset].selectFunc) {
|
|
1303
|
+
// Get the array offset from a function
|
|
1304
|
+
if (!scope[arrayToProcess[thisOffset].selectFunc] || typeof scope[arrayToProcess[thisOffset].selectFunc] !== 'function') {
|
|
1305
|
+
throw new Error('Subkey function ' + arrayToProcess[thisOffset].selectFunc + ' is not properly set up');
|
|
1206
1306
|
}
|
|
1307
|
+
arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
|
|
1207
1308
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
var
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
dataVal = dataVal[parts[0]] = dataVal[parts[0]] || [];
|
|
1220
|
-
// For each of the required subkeys of this type
|
|
1221
|
-
for (var thisOffset = 0; thisOffset < arrayToProcess.length; thisOffset++) {
|
|
1222
|
-
if (arrayToProcess[thisOffset].selectFunc) {
|
|
1223
|
-
// Get the array offset from a function
|
|
1224
|
-
if (!scope[arrayToProcess[thisOffset].selectFunc] || typeof scope[arrayToProcess[thisOffset].selectFunc] !== 'function') {
|
|
1225
|
-
throw new Error('Subkey function ' + arrayToProcess[thisOffset].selectFunc + ' is not properly set up');
|
|
1226
|
-
}
|
|
1227
|
-
arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
|
|
1228
|
-
}
|
|
1229
|
-
else if (arrayToProcess[thisOffset].keyList) {
|
|
1230
|
-
// We are choosing the array element by matching one or more keys
|
|
1231
|
-
var thisSubkeyList = arrayToProcess[thisOffset].keyList;
|
|
1232
|
-
for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
|
|
1233
|
-
matching = true;
|
|
1234
|
-
for (var keyField in thisSubkeyList) {
|
|
1235
|
-
if (thisSubkeyList.hasOwnProperty(keyField)) {
|
|
1236
|
-
// Not (currently) concerned with objects here - just simple types and lookups
|
|
1237
|
-
if (dataVal[arrayOffset][keyField] !== thisSubkeyList[keyField] &&
|
|
1238
|
-
(typeof dataVal[arrayOffset][keyField] === 'undefined' || !dataVal[arrayOffset][keyField].text || dataVal[arrayOffset][keyField].text !== thisSubkeyList[keyField])) {
|
|
1239
|
-
matching = false;
|
|
1240
|
-
break;
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
if (matching) {
|
|
1309
|
+
else if (arrayToProcess[thisOffset].keyList) {
|
|
1310
|
+
// We are choosing the array element by matching one or more keys
|
|
1311
|
+
var thisSubkeyList = arrayToProcess[thisOffset].keyList;
|
|
1312
|
+
for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
|
|
1313
|
+
matching = true;
|
|
1314
|
+
for (var keyField in thisSubkeyList) {
|
|
1315
|
+
if (thisSubkeyList.hasOwnProperty(keyField)) {
|
|
1316
|
+
// Not (currently) concerned with objects here - just simple types and lookups
|
|
1317
|
+
if (dataVal[arrayOffset][keyField] !== thisSubkeyList[keyField] &&
|
|
1318
|
+
(typeof dataVal[arrayOffset][keyField] === 'undefined' || !dataVal[arrayOffset][keyField].text || dataVal[arrayOffset][keyField].text !== thisSubkeyList[keyField])) {
|
|
1319
|
+
matching = false;
|
|
1245
1320
|
break;
|
|
1246
1321
|
}
|
|
1247
1322
|
}
|
|
1248
|
-
if (!matching) {
|
|
1249
|
-
// There is no matching array element
|
|
1250
|
-
switch (arrayToProcess[thisOffset].onNotFound) {
|
|
1251
|
-
case 'error':
|
|
1252
|
-
var errorMessage = 'Cannot find matching ' + (arrayToProcess[thisOffset].title || arrayToProcess[thisOffset].path);
|
|
1253
|
-
//Have to do this async as setPristine clears it
|
|
1254
|
-
$timeout(function () {
|
|
1255
|
-
scope.showError(errorMessage, 'Unable to set up form correctly');
|
|
1256
|
-
});
|
|
1257
|
-
arrayOffset = -1;
|
|
1258
|
-
//throw new Error(scope.errorMessage);
|
|
1259
|
-
break;
|
|
1260
|
-
case 'create':
|
|
1261
|
-
default:
|
|
1262
|
-
var nameElements = info.name.split('.');
|
|
1263
|
-
var lastPart = nameElements.pop();
|
|
1264
|
-
var possibleArray = nameElements.join('.');
|
|
1265
|
-
var obj = theRecord;
|
|
1266
|
-
// Should loop here when / if we re-introduce nesting
|
|
1267
|
-
if (possibleArray) {
|
|
1268
|
-
obj = obj[possibleArray];
|
|
1269
|
-
}
|
|
1270
|
-
arrayOffset = obj[lastPart].push(thisSubkeyList) - 1;
|
|
1271
|
-
break;
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
1323
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1324
|
+
if (matching) {
|
|
1325
|
+
break;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (!matching) {
|
|
1329
|
+
// There is no matching array element
|
|
1330
|
+
switch (arrayToProcess[thisOffset].onNotFound) {
|
|
1331
|
+
case 'error':
|
|
1332
|
+
var errorMessage = 'Cannot find matching ' + (arrayToProcess[thisOffset].title || arrayToProcess[thisOffset].path);
|
|
1333
|
+
//Have to do this async as setPristine clears it
|
|
1334
|
+
$timeout(function () {
|
|
1335
|
+
scope.showError(errorMessage, 'Unable to set up form correctly');
|
|
1336
|
+
});
|
|
1337
|
+
arrayOffset = -1;
|
|
1338
|
+
//throw new Error(scope.errorMessage);
|
|
1339
|
+
break;
|
|
1340
|
+
case 'create':
|
|
1341
|
+
default:
|
|
1342
|
+
var nameElements = info.name.split('.');
|
|
1343
|
+
var lastPart = nameElements.pop();
|
|
1344
|
+
var possibleArray = nameElements.join('.');
|
|
1345
|
+
var obj = theRecord;
|
|
1346
|
+
// Should loop here when / if we re-introduce nesting
|
|
1347
|
+
if (possibleArray) {
|
|
1348
|
+
obj = obj[possibleArray];
|
|
1349
|
+
}
|
|
1350
|
+
arrayOffset = obj[lastPart].push(thisSubkeyList) - 1;
|
|
1351
|
+
break;
|
|
1277
1352
|
}
|
|
1278
|
-
scope['$_arrayOffset_' + info.name.replace(/\./g, '_') + '_' + thisOffset] = arrayOffset;
|
|
1279
1353
|
}
|
|
1280
1354
|
}
|
|
1355
|
+
else {
|
|
1356
|
+
throw new Error('Invalid subkey setup for ' + info.name);
|
|
1357
|
+
}
|
|
1358
|
+
scope['$_arrayOffset_' + info.name.replace(/\./g, '_') + '_' + thisOffset] = arrayOffset;
|
|
1281
1359
|
}
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
$rootScope.$broadcast('formInputDone', attrs.name);
|
|
1285
|
-
if (FormGeneratorService.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
|
|
1286
|
-
// If this is not a test force the data dependent updates to the DOM
|
|
1287
|
-
FormGeneratorService.updateDataDependentDisplay(theRecord, null, true, scope);
|
|
1360
|
+
}
|
|
1288
1361
|
}
|
|
1289
|
-
}
|
|
1362
|
+
});
|
|
1290
1363
|
}
|
|
1291
|
-
|
|
1364
|
+
$rootScope.$broadcast('formInputDone', attrs.name);
|
|
1365
|
+
if (FormGeneratorService.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
|
|
1366
|
+
// If this is not a test force the data dependent updates to the DOM
|
|
1367
|
+
FormGeneratorService.updateDataDependentDisplay(theRecord, null, true, scope);
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1292
1370
|
}
|
|
1293
1371
|
};
|
|
1294
1372
|
}
|
|
@@ -2851,9 +2929,78 @@ var fng;
|
|
|
2851
2929
|
function isArrayElement(scope, info, options) {
|
|
2852
2930
|
return scope["$index"] !== undefined || !!options.subschema;
|
|
2853
2931
|
}
|
|
2932
|
+
function performPseudoReplacements(scope, str, substitutionSrc) {
|
|
2933
|
+
while (str.includes("@@")) {
|
|
2934
|
+
var firstCharPos = str.indexOf("@@") + 2;
|
|
2935
|
+
var lastCharPos = str.indexOf("@@", firstCharPos) - 1;
|
|
2936
|
+
var token = str.substring(firstCharPos, lastCharPos + 1);
|
|
2937
|
+
var plural = token.endsWith("s");
|
|
2938
|
+
if (plural) {
|
|
2939
|
+
token = token.slice(0, -1);
|
|
2940
|
+
}
|
|
2941
|
+
var upperStr = token[0].toUpperCase() === token[0] ? "true" : "false";
|
|
2942
|
+
token = token.toLocaleLowerCase();
|
|
2943
|
+
var replacement = void 0;
|
|
2944
|
+
if (substitutionSrc === "global") {
|
|
2945
|
+
replacement = fng.formsAngular.pseudo(token, upperStr === "true");
|
|
2946
|
+
}
|
|
2947
|
+
else if (substitutionSrc === "scopeStatic") {
|
|
2948
|
+
replacement = scope.sharedData.pseudo(token, upperStr === "true");
|
|
2949
|
+
}
|
|
2950
|
+
else if (substitutionSrc === "scopeDynamic") {
|
|
2951
|
+
replacement = "{{ sharedData.pseudo('".concat(token, "', ").concat(upperStr, ") }}");
|
|
2952
|
+
}
|
|
2953
|
+
else {
|
|
2954
|
+
replacement = "";
|
|
2955
|
+
}
|
|
2956
|
+
str =
|
|
2957
|
+
str.substring(0, firstCharPos - 2) +
|
|
2958
|
+
replacement +
|
|
2959
|
+
(plural ? "s" : "") +
|
|
2960
|
+
str.substring(lastCharPos + 3);
|
|
2961
|
+
}
|
|
2962
|
+
return str;
|
|
2963
|
+
}
|
|
2964
|
+
// Text surrounded by @@ @@ is assumed to be something that can have a pseudonym:
|
|
2965
|
+
// - If the sharedData object has been assigned a pseudo() function:
|
|
2966
|
+
// - then if dynamicFuncName has a value, we will set up a function on scope that will call that function to perform
|
|
2967
|
+
// the necessary substitutions. This would be useful for directives that use a template where labels, hints etc. already use {{ }}
|
|
2968
|
+
// notation (which would prevent any additional {{ }} that we nested in our result from working as intended).
|
|
2969
|
+
// - otherwise, we will set up the necessary dynamic calls to that sharedData.pseudo function using {{ }} notation
|
|
2970
|
+
// - Otherwise, if a pseudo callback has been provided in the IFng options, we will use that to perform a one-off (static) replacement.
|
|
2971
|
+
// - Otherwise (though not expected to happen), we will just remove the @@ tags, leaving the token(s) unchanged.
|
|
2972
|
+
// If the first character of the pseudonym token is upper case, then its replacement will use
|
|
2973
|
+
// titlecase, otherwise its replacement will be in lowercase.
|
|
2974
|
+
// If the last character of the pseudonym token is "s", then its replacement will be pluralised.
|
|
2975
|
+
function handlePseudos(scope, str, dynamicFuncName) {
|
|
2976
|
+
var _a;
|
|
2977
|
+
if (!(str === null || str === void 0 ? void 0 : str.includes("@@"))) {
|
|
2978
|
+
return str;
|
|
2979
|
+
}
|
|
2980
|
+
var substitutionSrc;
|
|
2981
|
+
if (typeof ((_a = scope === null || scope === void 0 ? void 0 : scope.sharedData) === null || _a === void 0 ? void 0 : _a.pseudo) === "function") {
|
|
2982
|
+
if (dynamicFuncName) {
|
|
2983
|
+
scope[dynamicFuncName] = function () {
|
|
2984
|
+
return performPseudoReplacements(scope, str, "scopeStatic");
|
|
2985
|
+
};
|
|
2986
|
+
substitutionSrc = "none"; // now the dynamic function has been set up, remove the @@ @@ tags (probably not essential, but might avoid confusion)
|
|
2987
|
+
}
|
|
2988
|
+
else {
|
|
2989
|
+
substitutionSrc = "scopeDynamic";
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
else if (typeof fng.formsAngular.pseudo === "function") {
|
|
2993
|
+
substitutionSrc = "global";
|
|
2994
|
+
}
|
|
2995
|
+
else {
|
|
2996
|
+
substitutionSrc = "none";
|
|
2997
|
+
}
|
|
2998
|
+
return performPseudoReplacements(scope, str, substitutionSrc);
|
|
2999
|
+
}
|
|
2854
3000
|
return {
|
|
2855
3001
|
isHorizontalStyle: isHorizontalStyle,
|
|
2856
3002
|
isArrayElement: isArrayElement,
|
|
3003
|
+
handlePseudos: handlePseudos,
|
|
2857
3004
|
fieldChrome: function fieldChrome(scope, info, options) {
|
|
2858
3005
|
var insert = '';
|
|
2859
3006
|
if (info.id && typeof info.id.replace === "function") {
|
|
@@ -2909,7 +3056,7 @@ var fng;
|
|
|
2909
3056
|
classes += ' form-group';
|
|
2910
3057
|
if (options.formstyle === 'vertical' && info.size !== 'block-level') {
|
|
2911
3058
|
template += '<div class="row">';
|
|
2912
|
-
classes += ' col-sm-' + InputSizeHelperService.sizeAsNumber(info
|
|
3059
|
+
classes += ' col-sm-' + InputSizeHelperService.sizeAsNumber(info);
|
|
2913
3060
|
closeTag += '</div>';
|
|
2914
3061
|
}
|
|
2915
3062
|
var modelControllerName;
|
|
@@ -2955,7 +3102,12 @@ var fng;
|
|
|
2955
3102
|
classes += ' ' + fieldInfo.labelDefaultClass;
|
|
2956
3103
|
}
|
|
2957
3104
|
else if (CssFrameworkService.framework() === 'bs3') {
|
|
2958
|
-
|
|
3105
|
+
if (fieldInfo.coloffset) {
|
|
3106
|
+
classes += ' col-sm-' + (3 - fieldInfo.coloffset).toString();
|
|
3107
|
+
}
|
|
3108
|
+
else {
|
|
3109
|
+
classes += ' col-sm-3';
|
|
3110
|
+
}
|
|
2959
3111
|
}
|
|
2960
3112
|
}
|
|
2961
3113
|
else if (['inline', 'stacked'].includes(options.formstyle)) {
|
|
@@ -2992,7 +3144,7 @@ var fng;
|
|
|
2992
3144
|
var formControl = '';
|
|
2993
3145
|
if (CssFrameworkService.framework() === 'bs3') {
|
|
2994
3146
|
compactClass = (['horizontal', 'vertical', 'inline'].indexOf(options.formstyle) === -1) ? ' input-sm' : '';
|
|
2995
|
-
sizeClassBS3 = 'col-sm-' + InputSizeHelperService.sizeAsNumber(fieldInfo
|
|
3147
|
+
sizeClassBS3 = 'col-sm-' + InputSizeHelperService.sizeAsNumber(fieldInfo);
|
|
2996
3148
|
formControl = ' form-control';
|
|
2997
3149
|
}
|
|
2998
3150
|
else {
|
|
@@ -3069,10 +3221,18 @@ var fng;
|
|
|
3069
3221
|
result += ' />';
|
|
3070
3222
|
return result;
|
|
3071
3223
|
},
|
|
3072
|
-
controlDivClasses: function controlDivClasses(options) {
|
|
3224
|
+
controlDivClasses: function controlDivClasses(options, fieldInfo) {
|
|
3073
3225
|
var result = [];
|
|
3074
3226
|
if (isHorizontalStyle(options.formstyle, false)) {
|
|
3075
|
-
|
|
3227
|
+
if (CssFrameworkService.framework() === 'bs2') {
|
|
3228
|
+
result.push('controls');
|
|
3229
|
+
}
|
|
3230
|
+
else if (fieldInfo.coloffset) {
|
|
3231
|
+
result.push('col-sm-' + (9 + fieldInfo.coloffset).toString());
|
|
3232
|
+
}
|
|
3233
|
+
else {
|
|
3234
|
+
result.push('col-sm-9');
|
|
3235
|
+
}
|
|
3076
3236
|
}
|
|
3077
3237
|
return result;
|
|
3078
3238
|
},
|
|
@@ -3134,8 +3294,12 @@ var fng;
|
|
|
3134
3294
|
sizeMapping: sizeMapping,
|
|
3135
3295
|
sizeDescriptions: sizeDescriptions,
|
|
3136
3296
|
defaultSizeOffset: defaultSizeOffset,
|
|
3137
|
-
sizeAsNumber: function (
|
|
3138
|
-
|
|
3297
|
+
sizeAsNumber: function (info) {
|
|
3298
|
+
var result = sizeMapping[info.size ? sizeDescriptions.indexOf(info.size) : defaultSizeOffset];
|
|
3299
|
+
if (info.coloffset) {
|
|
3300
|
+
result += info.coloffset;
|
|
3301
|
+
}
|
|
3302
|
+
return result;
|
|
3139
3303
|
}
|
|
3140
3304
|
};
|
|
3141
3305
|
}
|
|
@@ -3198,33 +3362,8 @@ var fng;
|
|
|
3198
3362
|
function internalGenDisabledStr(scope, id, processedAttrs, idSuffix, params) {
|
|
3199
3363
|
return internalGenDisabledAttrs(scope, id, processedAttrs, idSuffix, params).join(" ");
|
|
3200
3364
|
}
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
// If the first character of the pseudonym token is upper case, then its replacement will use
|
|
3204
|
-
// titlecase, otherwise its replacement will be in lowercase.
|
|
3205
|
-
// If the last character of the pseudonym token is "s", then its replacement will be pluralised.
|
|
3206
|
-
function handlePseudos(str) {
|
|
3207
|
-
if (!str) {
|
|
3208
|
-
return str;
|
|
3209
|
-
}
|
|
3210
|
-
var result = str;
|
|
3211
|
-
while (result.includes("@@")) {
|
|
3212
|
-
var firstCharPos = result.indexOf("@@") + 2;
|
|
3213
|
-
var lastCharPos = result.indexOf("@@", firstCharPos) - 1;
|
|
3214
|
-
var token = result.substring(firstCharPos, lastCharPos + 1);
|
|
3215
|
-
var plural = token.endsWith("s");
|
|
3216
|
-
if (plural) {
|
|
3217
|
-
token = token.slice(0, -1);
|
|
3218
|
-
}
|
|
3219
|
-
var upperStr = token[0].toUpperCase() === token[0] ? "true" : "false";
|
|
3220
|
-
token = token.toLocaleLowerCase();
|
|
3221
|
-
result =
|
|
3222
|
-
result.substring(0, firstCharPos - 2) +
|
|
3223
|
-
"{{ baseScope.pseudo('".concat(token, "', ").concat(upperStr, ") }}") +
|
|
3224
|
-
(plural ? "s" : "") +
|
|
3225
|
-
result.substring(lastCharPos + 3);
|
|
3226
|
-
}
|
|
3227
|
-
return result;
|
|
3365
|
+
function handlePseudos(scope, str, dynamicFuncName) {
|
|
3366
|
+
return FormMarkupHelperService.handlePseudos(scope, str, dynamicFuncName);
|
|
3228
3367
|
}
|
|
3229
3368
|
function makeIdStringUniqueForArrayElements(scope, processedAttrs, idString) {
|
|
3230
3369
|
if (FormMarkupHelperService.isArrayElement(scope, processedAttrs.info, processedAttrs.options)) {
|
|
@@ -3287,7 +3426,7 @@ var fng;
|
|
|
3287
3426
|
// of whether or not the datetime picker is actually disabled) to indicate that it potentially could be
|
|
3288
3427
|
return disabledStr + " " + rawDisabledAttrs[1];
|
|
3289
3428
|
}
|
|
3290
|
-
function extractFromAttr(attr, directiveName) {
|
|
3429
|
+
function extractFromAttr(attr, directiveName, scope, opts) {
|
|
3291
3430
|
function deserialize(str) {
|
|
3292
3431
|
var retVal = str.replace(/"/g, '"');
|
|
3293
3432
|
if (retVal === "true") {
|
|
@@ -3326,12 +3465,9 @@ var fng;
|
|
|
3326
3465
|
}
|
|
3327
3466
|
}
|
|
3328
3467
|
var result = { info: info, options: options, directiveOptions: directiveOptions };
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
// TODO - do this better when fng is re-written!
|
|
3333
|
-
result.info.help = handlePseudos(result.info.help);
|
|
3334
|
-
result.info.label = handlePseudos(result.info.label);
|
|
3468
|
+
result.info.help = handlePseudos(scope, result.info.help, (opts === null || opts === void 0 ? void 0 : opts.setUpDynamicHelpFunc) ? "help" : undefined);
|
|
3469
|
+
result.info.label = handlePseudos(scope, result.info.label, (opts === null || opts === void 0 ? void 0 : opts.setUpDynamicLabelFunc) ? "label" : undefined);
|
|
3470
|
+
result.info.popup = handlePseudos(scope, result.info.popup);
|
|
3335
3471
|
return result;
|
|
3336
3472
|
}
|
|
3337
3473
|
function genIdAndDisabledStr(scope, processedAttrs, idSuffix, params) {
|
|
@@ -3342,7 +3478,7 @@ var fng;
|
|
|
3342
3478
|
return {
|
|
3343
3479
|
extractFromAttr: extractFromAttr,
|
|
3344
3480
|
buildInputMarkup: function buildInputMarkup(scope, attrs, params, generateInputControl) {
|
|
3345
|
-
var processedAttrs = params.processedAttrs || extractFromAttr(attrs, "");
|
|
3481
|
+
var processedAttrs = params.processedAttrs || extractFromAttr(attrs, "", scope);
|
|
3346
3482
|
var info = {};
|
|
3347
3483
|
if (!params.ignoreFieldInfoFromAttrs) {
|
|
3348
3484
|
Object.assign(info, processedAttrs.info);
|
|
@@ -3355,7 +3491,7 @@ var fng;
|
|
|
3355
3491
|
if (fieldChrome.omit) {
|
|
3356
3492
|
return "";
|
|
3357
3493
|
}
|
|
3358
|
-
var controlDivClasses = FormMarkupHelperService.controlDivClasses(options);
|
|
3494
|
+
var controlDivClasses = FormMarkupHelperService.controlDivClasses(options, info);
|
|
3359
3495
|
var elementHtml = fieldChrome.template + FormMarkupHelperService.label(scope, info, params.addButtons, options);
|
|
3360
3496
|
var idString = info.id;
|
|
3361
3497
|
if (info.array || options.subschema) {
|
|
@@ -3972,8 +4108,20 @@ var fng;
|
|
|
3972
4108
|
$scope.$watch("record", function (newValue, oldValue) {
|
|
3973
4109
|
if (newValue !== oldValue) {
|
|
3974
4110
|
if (Object.keys(oldValue).length > 0 && $scope.dropConversionWatcher) {
|
|
3975
|
-
|
|
4111
|
+
// We don't want to convert changed data, so we need to stop watching the conversions
|
|
4112
|
+
// after the record has finished its initialisation and this watch has begun detecting actual changes.
|
|
4113
|
+
// In some rare cases, it is possible that a "change" to the record can be made programatically
|
|
4114
|
+
// before all of the directives that might need to add conversions have finished doing so.
|
|
4115
|
+
// This can happen in situations where promise resolutions interrupt the compilation process.
|
|
4116
|
+
// If we're not careful, we can end up with <select> inputs that are blank even when the underlying
|
|
4117
|
+
// field does have a value.
|
|
4118
|
+
// To avoid this, we'll use a $timeout to give for the digest queue to fully clear out - this should
|
|
4119
|
+
// ensure that all directives have been compiled before the conversion watcher is actually dropped.
|
|
4120
|
+
var dropWatcherFunc_1 = $scope.dropConversionWatcher;
|
|
3976
4121
|
$scope.dropConversionWatcher = null;
|
|
4122
|
+
$timeout(function () {
|
|
4123
|
+
dropWatcherFunc_1();
|
|
4124
|
+
});
|
|
3977
4125
|
}
|
|
3978
4126
|
force = formGeneratorInstance.updateDataDependentDisplay(newValue, oldValue, force, $scope);
|
|
3979
4127
|
processLookupHandlers(newValue, oldValue);
|
|
@@ -5492,9 +5640,9 @@ var fng;
|
|
|
5492
5640
|
$scope.$on('fngControllersUnloaded', function (evt) {
|
|
5493
5641
|
clearContextMenu();
|
|
5494
5642
|
});
|
|
5495
|
-
$scope.doClick = function (index, event) {
|
|
5643
|
+
$scope.doClick = function (index, event, item) {
|
|
5496
5644
|
var option = angular.element(event.target);
|
|
5497
|
-
|
|
5645
|
+
item = item || $scope.items[index];
|
|
5498
5646
|
if (item.divider || option.parent().hasClass('disabled')) {
|
|
5499
5647
|
event.preventDefault();
|
|
5500
5648
|
}
|
|
@@ -5602,6 +5750,8 @@ var fng;
|
|
|
5602
5750
|
.controller('ModelCtrl', fng.controllers.ModelCtrl)
|
|
5603
5751
|
.controller('NavCtrl', fng.controllers.NavCtrl)
|
|
5604
5752
|
.directive('modelControllerDropdown', fng.directives.modelControllerDropdown)
|
|
5753
|
+
.directive('dropDownItem', fng.directives.dropDownItem)
|
|
5754
|
+
.directive('dropDownSubMenu', fng.directives.dropDownSubMenu)
|
|
5605
5755
|
.directive('errorDisplay', fng.directives.errorDisplay)
|
|
5606
5756
|
.directive('fngLink', fng.directives.fngLink)
|
|
5607
5757
|
.directive('formInput', fng.directives.formInput)
|
|
@@ -5637,5 +5787,5 @@ $templateCache.put('error-display-bs3.html','<div id="display-error" ng-show="er
|
|
|
5637
5787
|
$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');
|
|
5638
5788
|
$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');
|
|
5639
5789
|
$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');
|
|
5640
|
-
$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:
|
|
5641
|
-
$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:
|
|
5790
|
+
$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 <a href="{{result.href}}" ng-class="resultClass($index)" title="{{result.additional}}">{{result.resourceText}} {{result.text}}</a>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');
|
|
5791
|
+
$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 <a href="{{result.href}}" ng-class="resultClass($index)" title="{{result.additional}}">{{result.resourceText}} {{result.text}}</a>\n </div>\n <div ng-show="moreCount > 0">(plus more - continue typing to narrow down search...)\n </div>\n </div>\n</div>\n');}]);
|