@liedekef/ftable 1.1.43 → 1.1.45
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/ftable.esm.js +28 -23
- package/ftable.js +28 -23
- package/ftable.min.js +1 -1
- package/ftable.umd.js +28 -23
- package/package.json +1 -1
package/ftable.esm.js
CHANGED
|
@@ -199,7 +199,7 @@ class FTableDOMHelper {
|
|
|
199
199
|
|
|
200
200
|
if (options.attributes) {
|
|
201
201
|
Object.entries(options.attributes).forEach(([key, value]) => {
|
|
202
|
-
if (value !==
|
|
202
|
+
if (value !== null)
|
|
203
203
|
element.setAttribute(key, value);
|
|
204
204
|
});
|
|
205
205
|
}
|
|
@@ -1064,7 +1064,10 @@ class FTableFormBuilder {
|
|
|
1064
1064
|
|
|
1065
1065
|
let input;
|
|
1066
1066
|
|
|
1067
|
-
if (value ==
|
|
1067
|
+
if (value == undefined) {
|
|
1068
|
+
value = null;
|
|
1069
|
+
}
|
|
1070
|
+
if (value == null && field.defaultValue ) {
|
|
1068
1071
|
value = field.defaultValue;
|
|
1069
1072
|
}
|
|
1070
1073
|
// Auto-detect select type if options are provided
|
|
@@ -1126,10 +1129,16 @@ class FTableFormBuilder {
|
|
|
1126
1129
|
// Otherwise, fallback to default
|
|
1127
1130
|
else {
|
|
1128
1131
|
container.appendChild(input);
|
|
1132
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1133
|
+
container.appendChild(input.datalistElement);
|
|
1134
|
+
}
|
|
1129
1135
|
}
|
|
1130
1136
|
} else {
|
|
1131
1137
|
// No custom input function — just add the default input
|
|
1132
1138
|
container.appendChild(input);
|
|
1139
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1140
|
+
container.appendChild(input.datalistElement);
|
|
1141
|
+
}
|
|
1133
1142
|
}
|
|
1134
1143
|
|
|
1135
1144
|
// Add explanation if provided
|
|
@@ -1155,7 +1164,7 @@ class FTableFormBuilder {
|
|
|
1155
1164
|
attributes: {
|
|
1156
1165
|
id: 'real-' + fieldName,
|
|
1157
1166
|
type: 'hidden',
|
|
1158
|
-
value: value
|
|
1167
|
+
value: value,
|
|
1159
1168
|
name: fieldName
|
|
1160
1169
|
}
|
|
1161
1170
|
});
|
|
@@ -1165,7 +1174,7 @@ class FTableFormBuilder {
|
|
|
1165
1174
|
id: `Edit-${fieldName}`,
|
|
1166
1175
|
type: 'text',
|
|
1167
1176
|
'data-date': value,
|
|
1168
|
-
placeholder: field.placeholder ||
|
|
1177
|
+
placeholder: field.placeholder || null,
|
|
1169
1178
|
readOnly: true
|
|
1170
1179
|
};
|
|
1171
1180
|
// Set any additional attributes
|
|
@@ -1219,8 +1228,8 @@ class FTableFormBuilder {
|
|
|
1219
1228
|
const attributes = {
|
|
1220
1229
|
type: inputType,
|
|
1221
1230
|
id: `Edit-${fieldName}`,
|
|
1222
|
-
placeholder: field.placeholder ||
|
|
1223
|
-
value: value
|
|
1231
|
+
placeholder: field.placeholder || null,
|
|
1232
|
+
value: value
|
|
1224
1233
|
};
|
|
1225
1234
|
|
|
1226
1235
|
// extra check for name and multiple
|
|
@@ -1241,7 +1250,7 @@ class FTableFormBuilder {
|
|
|
1241
1250
|
attributes.name = name;
|
|
1242
1251
|
|
|
1243
1252
|
const input = FTableDOMHelper.create('input', {
|
|
1244
|
-
className: field.inputClass ||
|
|
1253
|
+
className: field.inputClass || null,
|
|
1245
1254
|
attributes: attributes
|
|
1246
1255
|
});
|
|
1247
1256
|
|
|
@@ -1263,8 +1272,8 @@ class FTableFormBuilder {
|
|
|
1263
1272
|
type: 'text',
|
|
1264
1273
|
name: fieldName,
|
|
1265
1274
|
id: `Edit-${fieldName}`,
|
|
1266
|
-
placeholder: field.placeholder ||
|
|
1267
|
-
value: value
|
|
1275
|
+
placeholder: field.placeholder || null,
|
|
1276
|
+
value: value,
|
|
1268
1277
|
list: `${fieldName}-datalist`
|
|
1269
1278
|
};
|
|
1270
1279
|
|
|
@@ -1275,7 +1284,7 @@ class FTableFormBuilder {
|
|
|
1275
1284
|
}
|
|
1276
1285
|
|
|
1277
1286
|
const input = FTableDOMHelper.create('input', {
|
|
1278
|
-
className: field.inputClass ||
|
|
1287
|
+
className: field.inputClass || null,
|
|
1279
1288
|
attributes: attributes
|
|
1280
1289
|
});
|
|
1281
1290
|
|
|
@@ -1291,10 +1300,7 @@ class FTableFormBuilder {
|
|
|
1291
1300
|
this.populateDatalistOptions(datalist, field.options);
|
|
1292
1301
|
}
|
|
1293
1302
|
|
|
1294
|
-
//
|
|
1295
|
-
document.body.appendChild(datalist);
|
|
1296
|
-
|
|
1297
|
-
// Store reference for cleanup
|
|
1303
|
+
// Store reference
|
|
1298
1304
|
input.datalistElement = datalist;
|
|
1299
1305
|
|
|
1300
1306
|
return input;
|
|
@@ -1329,7 +1335,7 @@ class FTableFormBuilder {
|
|
|
1329
1335
|
type: 'hidden',
|
|
1330
1336
|
name: fieldName,
|
|
1331
1337
|
id: `Edit-${fieldName}`,
|
|
1332
|
-
value: value
|
|
1338
|
+
value: value
|
|
1333
1339
|
};
|
|
1334
1340
|
|
|
1335
1341
|
// Apply inputAttributes
|
|
@@ -1345,7 +1351,7 @@ class FTableFormBuilder {
|
|
|
1345
1351
|
const attributes = {
|
|
1346
1352
|
name: fieldName,
|
|
1347
1353
|
id: `Edit-${fieldName}`,
|
|
1348
|
-
placeholder: field.placeholder ||
|
|
1354
|
+
placeholder: field.placeholder || null
|
|
1349
1355
|
};
|
|
1350
1356
|
|
|
1351
1357
|
// Apply inputAttributes
|
|
@@ -1355,9 +1361,9 @@ class FTableFormBuilder {
|
|
|
1355
1361
|
}
|
|
1356
1362
|
|
|
1357
1363
|
const textarea = FTableDOMHelper.create('textarea', {
|
|
1358
|
-
className: field.inputClass ||
|
|
1364
|
+
className: field.inputClass || null,
|
|
1359
1365
|
attributes: attributes,
|
|
1360
|
-
value: value
|
|
1366
|
+
value: value
|
|
1361
1367
|
});
|
|
1362
1368
|
return textarea;
|
|
1363
1369
|
}
|
|
@@ -1386,7 +1392,7 @@ class FTableFormBuilder {
|
|
|
1386
1392
|
attributes.name = name;
|
|
1387
1393
|
|
|
1388
1394
|
const select = FTableDOMHelper.create('select', {
|
|
1389
|
-
className: field.inputClass ||
|
|
1395
|
+
className: field.inputClass || null,
|
|
1390
1396
|
attributes: attributes
|
|
1391
1397
|
});
|
|
1392
1398
|
|
|
@@ -1431,7 +1437,7 @@ class FTableFormBuilder {
|
|
|
1431
1437
|
|
|
1432
1438
|
const radio = FTableDOMHelper.create('input', {
|
|
1433
1439
|
attributes: radioAttributes,
|
|
1434
|
-
className: field.inputClass ||
|
|
1440
|
+
className: field.inputClass || null,
|
|
1435
1441
|
parent: radioWrapper
|
|
1436
1442
|
});
|
|
1437
1443
|
|
|
@@ -1565,11 +1571,10 @@ class FTableFormBuilder {
|
|
|
1565
1571
|
}
|
|
1566
1572
|
attributes.name = name;
|
|
1567
1573
|
|
|
1568
|
-
|
|
1569
|
-
className: field.inputClass ||
|
|
1574
|
+
return FTableDOMHelper.create('input', {
|
|
1575
|
+
className: field.inputClass || null,
|
|
1570
1576
|
attributes: attributes
|
|
1571
1577
|
});
|
|
1572
|
-
return input;
|
|
1573
1578
|
}
|
|
1574
1579
|
}
|
|
1575
1580
|
|
package/ftable.js
CHANGED
|
@@ -200,7 +200,7 @@ class FTableDOMHelper {
|
|
|
200
200
|
|
|
201
201
|
if (options.attributes) {
|
|
202
202
|
Object.entries(options.attributes).forEach(([key, value]) => {
|
|
203
|
-
if (value !==
|
|
203
|
+
if (value !== null)
|
|
204
204
|
element.setAttribute(key, value);
|
|
205
205
|
});
|
|
206
206
|
}
|
|
@@ -1065,7 +1065,10 @@ class FTableFormBuilder {
|
|
|
1065
1065
|
|
|
1066
1066
|
let input;
|
|
1067
1067
|
|
|
1068
|
-
if (value ==
|
|
1068
|
+
if (value == undefined) {
|
|
1069
|
+
value = null;
|
|
1070
|
+
}
|
|
1071
|
+
if (value == null && field.defaultValue ) {
|
|
1069
1072
|
value = field.defaultValue;
|
|
1070
1073
|
}
|
|
1071
1074
|
// Auto-detect select type if options are provided
|
|
@@ -1127,10 +1130,16 @@ class FTableFormBuilder {
|
|
|
1127
1130
|
// Otherwise, fallback to default
|
|
1128
1131
|
else {
|
|
1129
1132
|
container.appendChild(input);
|
|
1133
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1134
|
+
container.appendChild(input.datalistElement);
|
|
1135
|
+
}
|
|
1130
1136
|
}
|
|
1131
1137
|
} else {
|
|
1132
1138
|
// No custom input function — just add the default input
|
|
1133
1139
|
container.appendChild(input);
|
|
1140
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1141
|
+
container.appendChild(input.datalistElement);
|
|
1142
|
+
}
|
|
1134
1143
|
}
|
|
1135
1144
|
|
|
1136
1145
|
// Add explanation if provided
|
|
@@ -1156,7 +1165,7 @@ class FTableFormBuilder {
|
|
|
1156
1165
|
attributes: {
|
|
1157
1166
|
id: 'real-' + fieldName,
|
|
1158
1167
|
type: 'hidden',
|
|
1159
|
-
value: value
|
|
1168
|
+
value: value,
|
|
1160
1169
|
name: fieldName
|
|
1161
1170
|
}
|
|
1162
1171
|
});
|
|
@@ -1166,7 +1175,7 @@ class FTableFormBuilder {
|
|
|
1166
1175
|
id: `Edit-${fieldName}`,
|
|
1167
1176
|
type: 'text',
|
|
1168
1177
|
'data-date': value,
|
|
1169
|
-
placeholder: field.placeholder ||
|
|
1178
|
+
placeholder: field.placeholder || null,
|
|
1170
1179
|
readOnly: true
|
|
1171
1180
|
};
|
|
1172
1181
|
// Set any additional attributes
|
|
@@ -1220,8 +1229,8 @@ class FTableFormBuilder {
|
|
|
1220
1229
|
const attributes = {
|
|
1221
1230
|
type: inputType,
|
|
1222
1231
|
id: `Edit-${fieldName}`,
|
|
1223
|
-
placeholder: field.placeholder ||
|
|
1224
|
-
value: value
|
|
1232
|
+
placeholder: field.placeholder || null,
|
|
1233
|
+
value: value
|
|
1225
1234
|
};
|
|
1226
1235
|
|
|
1227
1236
|
// extra check for name and multiple
|
|
@@ -1242,7 +1251,7 @@ class FTableFormBuilder {
|
|
|
1242
1251
|
attributes.name = name;
|
|
1243
1252
|
|
|
1244
1253
|
const input = FTableDOMHelper.create('input', {
|
|
1245
|
-
className: field.inputClass ||
|
|
1254
|
+
className: field.inputClass || null,
|
|
1246
1255
|
attributes: attributes
|
|
1247
1256
|
});
|
|
1248
1257
|
|
|
@@ -1264,8 +1273,8 @@ class FTableFormBuilder {
|
|
|
1264
1273
|
type: 'text',
|
|
1265
1274
|
name: fieldName,
|
|
1266
1275
|
id: `Edit-${fieldName}`,
|
|
1267
|
-
placeholder: field.placeholder ||
|
|
1268
|
-
value: value
|
|
1276
|
+
placeholder: field.placeholder || null,
|
|
1277
|
+
value: value,
|
|
1269
1278
|
list: `${fieldName}-datalist`
|
|
1270
1279
|
};
|
|
1271
1280
|
|
|
@@ -1276,7 +1285,7 @@ class FTableFormBuilder {
|
|
|
1276
1285
|
}
|
|
1277
1286
|
|
|
1278
1287
|
const input = FTableDOMHelper.create('input', {
|
|
1279
|
-
className: field.inputClass ||
|
|
1288
|
+
className: field.inputClass || null,
|
|
1280
1289
|
attributes: attributes
|
|
1281
1290
|
});
|
|
1282
1291
|
|
|
@@ -1292,10 +1301,7 @@ class FTableFormBuilder {
|
|
|
1292
1301
|
this.populateDatalistOptions(datalist, field.options);
|
|
1293
1302
|
}
|
|
1294
1303
|
|
|
1295
|
-
//
|
|
1296
|
-
document.body.appendChild(datalist);
|
|
1297
|
-
|
|
1298
|
-
// Store reference for cleanup
|
|
1304
|
+
// Store reference
|
|
1299
1305
|
input.datalistElement = datalist;
|
|
1300
1306
|
|
|
1301
1307
|
return input;
|
|
@@ -1330,7 +1336,7 @@ class FTableFormBuilder {
|
|
|
1330
1336
|
type: 'hidden',
|
|
1331
1337
|
name: fieldName,
|
|
1332
1338
|
id: `Edit-${fieldName}`,
|
|
1333
|
-
value: value
|
|
1339
|
+
value: value
|
|
1334
1340
|
};
|
|
1335
1341
|
|
|
1336
1342
|
// Apply inputAttributes
|
|
@@ -1346,7 +1352,7 @@ class FTableFormBuilder {
|
|
|
1346
1352
|
const attributes = {
|
|
1347
1353
|
name: fieldName,
|
|
1348
1354
|
id: `Edit-${fieldName}`,
|
|
1349
|
-
placeholder: field.placeholder ||
|
|
1355
|
+
placeholder: field.placeholder || null
|
|
1350
1356
|
};
|
|
1351
1357
|
|
|
1352
1358
|
// Apply inputAttributes
|
|
@@ -1356,9 +1362,9 @@ class FTableFormBuilder {
|
|
|
1356
1362
|
}
|
|
1357
1363
|
|
|
1358
1364
|
const textarea = FTableDOMHelper.create('textarea', {
|
|
1359
|
-
className: field.inputClass ||
|
|
1365
|
+
className: field.inputClass || null,
|
|
1360
1366
|
attributes: attributes,
|
|
1361
|
-
value: value
|
|
1367
|
+
value: value
|
|
1362
1368
|
});
|
|
1363
1369
|
return textarea;
|
|
1364
1370
|
}
|
|
@@ -1387,7 +1393,7 @@ class FTableFormBuilder {
|
|
|
1387
1393
|
attributes.name = name;
|
|
1388
1394
|
|
|
1389
1395
|
const select = FTableDOMHelper.create('select', {
|
|
1390
|
-
className: field.inputClass ||
|
|
1396
|
+
className: field.inputClass || null,
|
|
1391
1397
|
attributes: attributes
|
|
1392
1398
|
});
|
|
1393
1399
|
|
|
@@ -1432,7 +1438,7 @@ class FTableFormBuilder {
|
|
|
1432
1438
|
|
|
1433
1439
|
const radio = FTableDOMHelper.create('input', {
|
|
1434
1440
|
attributes: radioAttributes,
|
|
1435
|
-
className: field.inputClass ||
|
|
1441
|
+
className: field.inputClass || null,
|
|
1436
1442
|
parent: radioWrapper
|
|
1437
1443
|
});
|
|
1438
1444
|
|
|
@@ -1566,11 +1572,10 @@ class FTableFormBuilder {
|
|
|
1566
1572
|
}
|
|
1567
1573
|
attributes.name = name;
|
|
1568
1574
|
|
|
1569
|
-
|
|
1570
|
-
className: field.inputClass ||
|
|
1575
|
+
return FTableDOMHelper.create('input', {
|
|
1576
|
+
className: field.inputClass || null,
|
|
1571
1577
|
attributes: attributes
|
|
1572
1578
|
});
|
|
1573
|
-
return input;
|
|
1574
1579
|
}
|
|
1575
1580
|
}
|
|
1576
1581
|
|
package/ftable.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(e=>{let s={serverCommunicationError:"An error occurred while communicating to the server.",loadingMessage:"Loading records...",noDataAvailable:"No data available!",addNewRecord:"Add new record",editRecord:"Edit record",areYouSure:"Are you sure?",deleteConfirmation:"This record will be deleted. Are you sure?",yes:"Yes",no:"No",save:"Save",saving:"Saving",cancel:"Cancel",deleteText:"Delete",deleting:"Deleting",error:"An error has occured",close:"Close",cannotLoadOptionsFor:"Cannot load options for field {0}!",pagingInfo:"Showing {0}-{1} of {2}",canNotDeletedRecords:"Can not delete {0} of {1} records!",deleteProgress:"Deleting {0} of {1} records, processing...",pageSizeChangeLabel:"Row count",gotoPageLabel:"Go to page",sortingInfoPrefix:"Sorting applied: ",sortingInfoSuffix:"",ascending:"Ascending",descending:"Descending",sortingInfoNone:"No sorting applied",resetSorting:"Reset sorting",csvExport:"CSV",printTable:"🖨️ Print",cloneRecord:"Clone Record",resetTable:"Reset table",resetTableConfirm:"This will reset all columns, pagesize, sorting to their defaults. Do you want to continue?",resetSearch:"Reset"};class t{constructor(){this.cache=new Map,this.pendingRequests=new Map}generateKey(e,t){return e+"?"+Object.keys(t||{}).sort().map(e=>e+"="+t[e]).join("&")}get(e,t){e=this.generateKey(e,t);return this.cache.get(e)}set(e,t,s){e=this.generateKey(e,t);this.cache.set(e,s)}clear(e=null,t=null){if(e)if(t){t=this.generateKey(e,t);this.cache.delete(t)}else{var s,a=e.split("?")[0];for([s]of this.cache)s.startsWith(a)&&this.cache.delete(s)}else this.cache.clear()}async getOrCreate(e,t,s){let a=this.generateKey(e,t);e=this.cache.get(a);return e||(this.pendingRequests.has(a)?this.pendingRequests.get(a):(t=(async()=>{try{var e=await s();return this.cache.set(a,e),e}finally{this.pendingRequests.delete(a)}})(),this.pendingRequests.set(a,t),t))}size(){return this.cache.size}}class a{static LOG_LEVELS={DEBUG:0,INFO:1,WARN:2,ERROR:3,NONE:4};constructor(e=a.LOG_LEVELS.WARN){this.level=e}log(t,e){var s;!window.console||t<this.level||(s=Object.keys(a.LOG_LEVELS).find(e=>a.LOG_LEVELS[e]===t),console.log(`fTable ${s}: `+e))}debug(e){this.log(a.LOG_LEVELS.DEBUG,e)}info(e){this.log(a.LOG_LEVELS.INFO,e)}warn(e){this.log(a.LOG_LEVELS.WARN,e)}error(e){this.log(a.LOG_LEVELS.ERROR,e)}}class u{static create(e,t={}){let s=document.createElement(e);return t.className&&(s.className=t.className),t.style&&(s.style.cssText=t.style),t.attributes&&Object.entries(t.attributes).forEach(([e,t])=>{""!==t&&s.setAttribute(e,t)}),t.text&&(s.textContent=t.text),t.html&&(s.innerHTML=t.html),t.parent&&t.parent.appendChild(s),s}static find(e,t=document){return t.querySelector(e)}static findAll(e,t=document){return Array.from(t.querySelectorAll(e))}static addClass(e,t){e.classList.add(...t.split(" "))}static removeClass(e,t){e.classList.remove(...t.split(" "))}static toggleClass(e,t){e.classList.toggle(t)}static show(e){e.style.display=""}static hide(e){e.style.display="none"}static escapeHtml(e){if(!e)return e;let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>t[e])}}class l{static async request(e,t={}){var s={method:"GET",headers:{}},a={...s,...t};t.headers&&(a.headers={...s.headers,...t.headers});try{var i=await fetch(e,a);if(401===i.status)throw new Error("Unauthorized");if(!i.ok)throw new Error("HTTP error! status: "+i.status);var o=i.headers.get("content-type");if(o&&o.includes("application/json"))return await i.json();var r=await i.text();try{return JSON.parse(r)}catch{return{Result:"OK",Message:r}}}catch(e){throw e}}static async get(e,t={}){let a=new URL(e,window.location.href);return Object.entries(t).forEach(([e,s])=>{if(null!=s)if(Array.isArray(s)){let t=e.replace(/\[\]$/,"")+"[]";s.forEach(e=>{null!=e&&a.searchParams.append(t,e)})}else a.searchParams.append(e,s)}),this.request(a.toString(),{method:"GET",headers:{"Content-Type":"application/x-www-form-urlencoded"}})}static async post(e,t={}){e=new URL(e,window.location.href);let a=new FormData;return Object.entries(t).forEach(([e,s])=>{if(null!=s)if(Array.isArray(s)){let t=e.replace(/\[\]$/,"")+"[]";s.forEach(e=>{null!=e&&a.append(t,e)})}else a.append(e,s)}),this.request(e.toString(),{method:"POST",body:a})}}class i{constructor(e,t="localStorage"){this.prefix=e,this.method=t}set(e,t){var s,e=""+this.prefix+e;"localStorage"===this.method?localStorage.setItem(e,t):((s=new Date).setDate(s.getDate()+30),document.cookie=e+`=${t}; expires=${s.toUTCString()}; path=/`)}get(e){e=""+this.prefix+e;if("localStorage"===this.method)return localStorage.getItem(e);var t,s=e+"=";for(t of decodeURIComponent(document.cookie).split(";")){for(;" "===t.charAt(0);)t=t.substring(1);if(0===t.indexOf(s))return t.substring(s.length,t.length)}return null}remove(e){e=""+this.prefix+e;"localStorage"===this.method?localStorage.removeItem(e):document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"}generatePrefix(e,t){e=e?e+"#":"";return"ftable#"+(t=>{let s=0;if(0!==t.length)for(let e=0;e<t.length;e++){var a=t.charCodeAt(e);s=(s<<5)-s+a,s&=s}return s})(e+=t.join("$")+"#c"+t.length)}}class o{constructor(e={}){this.options={title:"Modal",content:"",buttons:[],className:"ftable-modal",parent:document.body,...e},this.overlay=null,this.modal=null,this.isOpen=!1}create(){this.overlay=u.create("div",{className:"ftable-modal-overlay",parent:this.options.parent}),this.modal=u.create("div",{className:"ftable-modal "+this.options.className,parent:this.overlay});u.create("h2",{className:"ftable-modal-header",text:this.options.title,parent:this.modal});u.create("span",{className:"ftable-modal-close",html:"×",parent:this.modal}).addEventListener("click",()=>this.close());var e=u.create("div",{className:"ftable-modal-body",parent:this.modal});if("string"==typeof this.options.content?e.innerHTML=this.options.content:e.appendChild(this.options.content),0<this.options.buttons.length){let s=u.create("div",{className:"ftable-modal-footer",parent:this.modal});this.options.buttons.forEach(e=>{var t=u.create("button",{className:"ftable-dialog-button "+(e.className||""),html:`<span>${e.text}</span>`,parent:s});e.onClick&&(t._originalOnClick=e.onClick,t.addEventListener("click",this._createWrappedClickHandler(t)))})}return this.options.closeOnOverlayClick&&this.overlay.addEventListener("click",e=>{e.target===this.overlay&&this.close()}),this.hide(),this}show(){return this.modal||this.create(),this.overlay.style.display="flex",this.isOpen=!0,this.modal.querySelectorAll(".ftable-dialog-button").forEach(e=>{e.disabled=!1}),this}hide(){return this.overlay&&(this.overlay.style.display="none"),this.isOpen=!1,this}close(){return this.hide(),this.options.onClose&&this.options.onClose(),this}destroy(){return this.overlay&&this.overlay.remove(),this.isOpen=!1,this}setContent(e){this.options.content=e;var t=this.modal.querySelector(".ftable-modal-body");t&&(t.innerHTML="","string"==typeof e?t.innerHTML=e:t.appendChild(e))}_createWrappedClickHandler(a){return async e=>{a.disabled=!0;try{var t,s=a._originalOnClick;"function"==typeof s&&(t=s.call(a,e))instanceof Promise&&await t}catch(e){console.error("Modal button action failed:",e)}finally{a.disabled=!1}}}}class r{constructor(e){this.options=e,this.dependencies=new Map,this.optionsCache=new t,this.originalFieldOptions=new Map,this.resolvedFieldOptions=new Map,Object.keys(this.options.fields||{}).forEach(e=>{this.resolvedFieldOptions.set(e,{})}),Object.entries(this.options.fields).forEach(([e,t])=>{this.originalFieldOptions.set(e,t.options)})}async getFieldOptions(t,s="table",e={}){var a=this.options.fields[t],i=this.originalFieldOptions.get(t);if(!i)return null;var o=this.shouldForceRefreshForContext(a,s,e),r=this.generateOptionsCacheKey(s,e);if(!o&&!e.forceRefresh){var n=this.resolvedFieldOptions.get(t)[r];if(n)return n}try{var l={...a,options:i},c=await this.resolveOptions(l,{...e},s,o);return this.resolvedFieldOptions.get(t)[r]=c}catch(e){return console.error(`Failed to resolve options for ${t} (${s}):`,e),i}}clearResolvedOptions(e=null,s=null){e?this.resolvedFieldOptions.has(e)&&(s?this.resolvedFieldOptions.get(e)[s]=null:this.resolvedFieldOptions.set(e,{table:null,create:null,edit:null})):s?this.resolvedFieldOptions.forEach((e,t)=>{this.resolvedFieldOptions.get(t)[s]=null}):this.resolvedFieldOptions.forEach((e,t)=>{this.resolvedFieldOptions.set(t,{table:null,create:null,edit:null})})}shouldForceRefreshForContext(e,t,s){return!!e.noCache&&("boolean"==typeof e.noCache?e.noCache:"function"==typeof e.noCache?e.noCache({context:t,...s}):"object"==typeof e.noCache&&!0===e.noCache[t])}generateOptionsCacheKey(e,t){let s=[e];return t.dependedValues&&Object.keys(t.dependedValues).sort().forEach(e=>{s.push(e+"="+t.dependedValues[e])}),s.join("|")}shouldIncludeField(e,t){return"create"===t?!1!==e.create&&!(!0===e.key&&!0!==e.create):"edit"!==t||!1!==e.edit}createFieldContainer(e,t,s,a){var i=u.create("div",{className:"hidden"!=t.type?"ftable-input-field-container":"",attributes:{id:"ftable-input-field-container-div-"+e}}),t=("hidden"!=t.type&&u.create("div",{className:"ftable-input-label",text:t.inputTitle||t.title,parent:i}),this.createInput(e,t,s[e],a));return i.appendChild(t),i}async createForm(e="create",t={}){this.currentFormRecord=t;var s,a,i,o,r=u.create("form",{className:`ftable-dialog-form ftable-${e}-form`});this.buildDependencyMap();for([s,a]of Object.entries(this.options.fields))this.shouldIncludeField(a,e)&&(i={...a},a.dependsOn?i.options=a.options:(o=await this.getFieldOptions(s,e,{record:t,source:e}),i.options=o),o=this.createFieldContainer(s,i,t,e),r.appendChild(o));return this.setupDependencyListeners(r),r}shouldResolveOptions(e){return e&&("function"==typeof e||"string"==typeof e)&&!Array.isArray(e)&&!("object"==typeof e&&!Array.isArray(e)&&0<Object.keys(e).length)}buildDependencyMap(){this.dependencies.clear(),Object.entries(this.options.fields).forEach(([t,s])=>{if(s.dependsOn){let e;"string"==typeof s.dependsOn&&(e=s.dependsOn.split(",").map(e=>e.trim()).filter(e=>e)).forEach(e=>{this.dependencies.has(e)||this.dependencies.set(e,[]),this.dependencies.get(e).push(t)})}})}setupDependencyListeners(s){Array.from(this.dependencies.keys()).forEach(e=>{var t=s.querySelector(`[name="${e}"]`);t&&t.addEventListener("change",()=>{this.handleDependencyChange(s,e)})}),this.handleDependencyChange(s)}async resolveOptions(e,t={},s="",a=!1){if(!e.options)return[];if(Array.isArray(e.options)||"object"==typeof e.options)return e.options;let i;t={...t,source:s,clearCache:()=>{a=!0,this.updateFieldCacheSetting(e,s,!0)}};if("function"==typeof e.options)i=await e.options(t);else{if("string"!=typeof e.options)return[];i=e.options}t=i&&"object"==typeof i&&i.url;let o=t?i.url:i;if(a=t&&void 0!==i.noCache?i.noCache:a,"string"!=typeof o)return[];if(!a)return this.optionsCache.getOrCreate(o,{},async()=>{try{var e=this.options.forcePost?await l.post(o):await l.get(o);return e.Options||e.options||e||[]}catch(e){return console.error(`Failed to load options from ${o}:`,e),[]}});try{var r=this.options.forcePost?await l.post(o):await l.get(o);return r.Options||r.options||r||[]}catch(e){return console.error(`Failed to load options from ${o}:`,e),[]}}updateFieldCacheSetting(e,t,s){e.noCache?"boolean"==typeof e.noCache?e.noCache={table:e.noCache,create:e.noCache,edit:e.noCache,[t]:s}:"object"==typeof e.noCache&&(e.noCache[t]=s):e.noCache={[t]:s}}clearOptionsCache(e=null,t=null){this.optionsCache.clear(e,t)}getFormValues(e){var t={},s=e.elements;for(let e=0;e<s.length;e++){var a=s[e],i=a.name;if(i&&!a.disabled)switch(a.type){case"checkbox":t[i]=a.checked?a.value||"1":"0";break;case"radio":a.checked&&(t[i]=a.value);break;case"select-multiple":t[i]=Array.from(a.selectedOptions).map(e=>e.value);break;default:t[i]=a.value}}return t}async handleDependencyChange(e,s=""){var a,i,o=this.getFormValues(e),r=e.classList.contains("ftable-create-form")?"create":"edit",n=this.currentFormRecord||{},l={record:n,source:r,form:e,dependedValues:o};for([a,i]of Object.entries(this.options.fields))if(i.dependsOn){if(""!==s)if(!i.dependsOn.split(",").map(e=>e.trim()).filter(e=>e).includes(s))continue;let t=e.querySelector(`[name="${a}"]`);if(t&&this.shouldIncludeField(i,r))try{"SELECT"===t.tagName?t.innerHTML='<option value="">Loading...</option>':"INPUT"===t.tagName&&t.list&&(c=document.getElementById(t.list.id))&&(c.innerHTML="");var c,d=t.value||n[a]||"",h={...l,dependsOnField:i.dependsOn,dependsOnValue:o[i.dependsOn]},p=await this.getFieldOptions(a,r,h);"SELECT"===t.tagName?this.populateSelectOptions(t,p,d):"INPUT"===t.tagName&&t.list&&(this.populateDatalistOptions(t.list,p),d)&&(t.value=d),setTimeout(()=>{t.dispatchEvent(new Event("change",{bubbles:!0}))},0)}catch(e){console.error(`Error loading options for ${a}:`,e),"SELECT"===t.tagName&&(t.innerHTML='<option value="">Error</option>')}}}parseInputAttributes(e){if("string"!=typeof e)return e||{};for(var t={},s=/(\w+)(?:=("[^"]*"|'[^']*'|\S+))?/g;null!==(i=s.exec(e));){var a=i[1],i=i[2]?i[2].replace(/^["']|["']$/g,""):"";t[a]=""===i?"true":i}return t}createInput(e,t,s,a){var i=u.create("div",{className:`ftable-input ftable-${t.type||"text"}-input`});let o;switch(null==s&&(s=t.defaultValue),!t.type&&t.options&&(t.type="select"),t.type){case"hidden":o=this.createHiddenInput(e,t,s);break;case"textarea":o=this.createTextarea(e,t,s);break;case"select":o=this.createSelect(e,t,s);break;case"checkbox":o=this.createCheckbox(e,t,s);break;case"radio":o=this.createRadioGroup(e,t,s);break;case"datalist":o=this.createDatalistInput(e,t,s);break;case"file":o=this.createFileInput(e,t,s);break;case"date":case"datetime":case"datetime-local":o=this.createDateInput(e,t,s);break;default:o=this.createTypedInput(e,t,s)}return"function"==typeof t.input?(a={field:t,record:this.currentFormRecord,inputField:o,formType:a},"string"==typeof(a=t.input(a))?i.innerHTML=a:a instanceof Node?i.appendChild(a):i.appendChild(o)):i.appendChild(o),t.explain&&u.create("div",{className:"ftable-field-explain",html:`<small>${t.explain}</small>`,parent:i}),i}createDateInput(s,a,i){if("undefined"==typeof FDatepicker)return createTypedInput(s,a,i);{let e=a.dateFormat||this.options.defaultDateFormat;var o,r=document.createElement("div"),n=u.create("input",{attributes:{id:"real-"+s,type:"hidden",value:i||"",name:s}}),i={id:"Edit-"+s,type:"text","data-date":i,placeholder:a.placeholder||"",readOnly:!0};a.inputAttributes&&(o=this.parseInputAttributes(a.inputAttributes),Object.assign(i,o));let t=u.create("input",{className:a.inputClass||"datepicker-input",attributes:i});switch(r.appendChild(n),r.appendChild(t),a.type){case"date":setTimeout(()=>{new FDatepicker(t,{format:e,altField:"real-"+s,altFormat:"Y-m-d"})},0);break;case"datetime":case"datetime-local":setTimeout(()=>{new FDatepicker(t,{format:e,timepicker:!0,altField:"real-"+s,altFormat:"Y-m-d H:i:00"})},0)}return r}}createTypedInput(e,t,s){var a,s={type:t.type||"text",id:"Edit-"+e,placeholder:t.placeholder||"",value:s||""};let i=e,o=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(s,a),void 0!==a.multiple&&!1!==a.multiple)&&(i=e+"[]"),s.name=i,u.create("input",{className:t.inputClass||"",attributes:s}));return o.addEventListener("keypress",e=>{if(13===(e.keyCode||e.which))return e.preventDefault(),o.dispatchEvent(new Event("change",{bubbles:!0})),!1}),o}createDatalistInput(e,t,s){var s={type:"text",name:e,id:"Edit-"+e,placeholder:t.placeholder||"",value:s||"",list:e+"-datalist"},a=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(s,a)),u.create("input",{className:t.inputClass||"",attributes:s})),s=u.create("datalist",{attributes:{id:e+"-datalist"}});return t.options&&this.populateDatalistOptions(s,t.options),document.body.appendChild(s),a.datalistElement=s,a}populateDatalistOptions(s,e){s.innerHTML="",Array.isArray(e)?e.forEach(e=>{u.create("option",{attributes:{value:e.Value||e.value||e},text:e.DisplayText||e.text||e,parent:s})}):"object"==typeof e&&Object.entries(e).forEach(([e,t])=>{u.create("option",{attributes:{value:e},text:t,parent:s})})}createHiddenInput(e,t,s){e={type:"hidden",name:e,id:"Edit-"+e,value:s||""};return t.inputAttributes&&(s=this.parseInputAttributes(t.inputAttributes),Object.assign(e,s)),u.create("input",{attributes:e})}createTextarea(e,t,s){var e={name:e,id:"Edit-"+e,placeholder:t.placeholder||""},a=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(e,a)),u.create("textarea",{className:t.inputClass||"",attributes:e,value:s||""}));return a}createSelect(e,t,s){var a={name:e,id:"Edit-"+e};let i=e;t.inputAttributes&&(o=this.parseInputAttributes(t.inputAttributes),Object.assign(a,o),void 0!==o.multiple&&!1!==o.multiple)&&(i=e+"[]"),a.name=i;var o=u.create("select",{className:t.inputClass||"",attributes:a});return t.options&&this.populateSelectOptions(o,t.options,s),o}createRadioGroup(o,r,n){let l=u.create("div",{className:"ftable-radio-group"});return r.options&&(Array.isArray(r.options)?r.options:"object"==typeof r.options?Object.entries(r.options).map(([e,t])=>({Value:e,DisplayText:t})):[]).forEach((e,t)=>{var s=u.create("div",{className:"ftable-radio-wrapper",parent:l}),a=o+"_"+t,i={type:"radio",name:o,id:a,value:e.Value||e.value||e},t=(r.required&&0===t&&(i.required="required"),r.disabled&&(i.disabled="disabled"),r.inputAttributes&&(t=this.parseInputAttributes(r.inputAttributes),Object.assign(i,t)),u.create("input",{attributes:i,className:r.inputClass||"",parent:s}));i.value===n&&(t.checked=!0),u.create("label",{attributes:{for:a},text:e.DisplayText||e.text||e,parent:s})}),l}createCheckbox(e,t,s){var a=u.create("div",{className:"ftable-yesno-check-wrapper"}),s=[1,"1",!0,"true"].includes(s);let i=this.options.messages.no,o=this.options.messages.yes;return t.values&&"object"==typeof t.values&&(void 0!==t.values[0]&&(i=t.values[0]),void 0!==t.values[1])&&(o=t.values[1]),u.create("input",{className:["ftable-yesno-check-input",t.inputClass||""].filter(Boolean).join(" "),attributes:{type:"checkbox",name:e,id:"Edit-"+e,value:"1"},parent:a}).checked=s,t.label?u.create("label",{className:"ftable-yesno-check-fixedlabel",attributes:{for:"Edit-"+e},text:t.label,parent:a}):u.create("label",{className:"ftable-yesno-check-text",attributes:{for:"Edit-"+e,"data-yes":o,"data-no":i},parent:a}),a}populateSelectOptions(a,e,i){a.innerHTML="",Array.isArray(e)?e.forEach(e=>{var t=void 0!==e.Value?e.Value:void 0!==e.value?e.value:e;let s=u.create("option",{attributes:{value:t},text:e.DisplayText||e.text||e,parent:a});e.Data&&"object"==typeof e.Data&&Object.entries(e.Data).forEach(([e,t])=>{s.setAttribute("data-"+e,t)}),s.value==i&&(s.selected=!0)}):"object"==typeof e&&Object.entries(e).forEach(([e,t])=>{t=u.create("option",{attributes:{value:e},text:t,parent:a});e==i&&(t.selected=!0)})}createFileInput(e,t,s){var a,i={type:"file",id:"Edit-"+e};let o=e;return t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(i,a),void 0!==a.multiple&&!1!==a.multiple)&&(o=e+"[]"),i.name=o,u.create("input",{className:t.inputClass||"",attributes:i})}}class n extends class{constructor(){this.events={}}on(e,t){return this.events[e]||(this.events[e]=[]),this.events[e].push(t),this}once(t,s){let a=(...e)=>{this.off(t,a),s.apply(this,e)};return a.fn=s,this.on(t,a),this}emit(e,t={}){return this.events[e]&&this.events[e].forEach(e=>e(t)),this}off(e,t){return this.events[e]&&(this.events[e]=this.events[e].filter(e=>e!==t)),this}}{constructor(e,t={}){if(super(),this.element="string"==typeof e?document.querySelector(e):e,this.element){if(this.element.ftableInstance)return this.element.ftableInstance;this.options=this.mergeOptions(t),this.verifyOptions(),this.logger=new a(this.options.logLevel),this.userPrefs=new i("",this.options.saveUserPreferencesMethod),this.formBuilder=new r(this.options,this),this.state={records:[],totalRecordCount:0,currentPage:1,isLoading:!1,selectedRecords:new Set,sorting:[],searchQueries:{}},this.elements={},this.modals={},this.searchTimeout=null,this.lastSortEvent=null,this._recalculatedOnce=!1,this.shiftKeyDown=!1,this.lastSelectedRow=null,(this.element.ftableInstance=this).init()}}mergeOptions(e){var t={tableId:void 0,logLevel:a.LOG_LEVELS.WARN,actions:{},fields:{},forcePost:!0,closeOnOverlayClick:!0,animationsEnabled:!0,loadingAnimationDelay:1e3,defaultDateLocale:"",defaultDateFormat:"Y-m-d",saveUserPreferences:!0,saveUserPreferencesMethod:"localStorage",defaultSorting:"",tableReset:!1,paging:!1,pageList:"normal",pageSize:10,pageSizes:[10,25,50,100,250,500],gotoPageArea:"combobox",sorting:!1,multiSorting:!1,multiSortingCtrlKey:!0,selecting:!1,multiselect:!1,openChildAsAccordion:!1,toolbarsearch:!1,toolbarreset:!0,searchDebounceMs:300,listCache:3e4,messages:{...s}};return this.deepMerge(t,e)}deepMerge(e,t){var s,a={...e};for(s in t)t[s]&&"object"==typeof t[s]&&!Array.isArray(t[s])?a[s]=this.deepMerge(a[s]||{},t[s]):a[s]=t[s];return a}verifyOptions(){this.options.pageSize&&!this.options.pageSizes.includes(this.options.pageSize)&&(this.options.pageSize=this.options.pageSizes[0])}static setMessages(e){Object.assign(s,e)}init(){this.processFieldDefinitions(),this.createMainStructure(),this.setupFTableUserPreferences(),this.createTable(),this.createModals(),this.options.paging&&this.createPagingUI(),this.resolveAsyncFieldOptions().then(()=>{setTimeout(()=>{this.refreshDisplayValues()},0)}).catch(console.error),this.bindEvents(),this.updateSortingHeaders(),this.renderSortingInfo(),this.initColumnWidths()}initColumnWidths(){var e=this.columnList.filter(e=>{e=this.options.fields[e];return"hidden"!==e.visibility&&"separator"!==e.visibility});let t=e.length;e.forEach(e=>{e=this.options.fields[e];e.width=e.width||100/t+"%"})}normalizeColumnWidths(){var e=this.elements.mainContainer,t=this.columnList.map(e=>({th:this.elements.table.querySelector(`[data-field-name="${e}"]`),field:this.options.fields[e]})).filter(e=>e.th&&"hidden"!==e.field.visibility&&"separator"!==e.field.visibility);if(0!==t.length){let s=e.offsetWidth,a=0;t.forEach(e=>{var t=e.th.offsetWidth/s*100;e.field.width=t+"%",e.th.style.width=e.field.width,a+=t})}}parseDefaultSorting(e){let o=[];return e&&"string"==typeof e&&e.split(",").forEach(s=>{s=s.trim();if(s){var a=s.toUpperCase().indexOf(" DESC"),i=s.toUpperCase().indexOf(" ASC");let e="ASC",t=s;e=0<a?(t=s.slice(0,a).trim(),"DESC"):(t=(0<i?s.slice(0,i):s).trim(),"ASC");a=this.options.fields[t];a&&!1!==a.sorting&&o.push({fieldName:t,direction:e})}}),o}addEssentialCSS(){var e;document.querySelector("#ftable-essential-css")||((e=document.createElement("style")).id="ftable-essential-css",e.textContent=`
|
|
1
|
+
(e=>{let s={serverCommunicationError:"An error occurred while communicating to the server.",loadingMessage:"Loading records...",noDataAvailable:"No data available!",addNewRecord:"Add new record",editRecord:"Edit record",areYouSure:"Are you sure?",deleteConfirmation:"This record will be deleted. Are you sure?",yes:"Yes",no:"No",save:"Save",saving:"Saving",cancel:"Cancel",deleteText:"Delete",deleting:"Deleting",error:"An error has occured",close:"Close",cannotLoadOptionsFor:"Cannot load options for field {0}!",pagingInfo:"Showing {0}-{1} of {2}",canNotDeletedRecords:"Can not delete {0} of {1} records!",deleteProgress:"Deleting {0} of {1} records, processing...",pageSizeChangeLabel:"Row count",gotoPageLabel:"Go to page",sortingInfoPrefix:"Sorting applied: ",sortingInfoSuffix:"",ascending:"Ascending",descending:"Descending",sortingInfoNone:"No sorting applied",resetSorting:"Reset sorting",csvExport:"CSV",printTable:"🖨️ Print",cloneRecord:"Clone Record",resetTable:"Reset table",resetTableConfirm:"This will reset all columns, pagesize, sorting to their defaults. Do you want to continue?",resetSearch:"Reset"};class t{constructor(){this.cache=new Map,this.pendingRequests=new Map}generateKey(e,t){return e+"?"+Object.keys(t||{}).sort().map(e=>e+"="+t[e]).join("&")}get(e,t){e=this.generateKey(e,t);return this.cache.get(e)}set(e,t,s){e=this.generateKey(e,t);this.cache.set(e,s)}clear(e=null,t=null){if(e)if(t){t=this.generateKey(e,t);this.cache.delete(t)}else{var s,a=e.split("?")[0];for([s]of this.cache)s.startsWith(a)&&this.cache.delete(s)}else this.cache.clear()}async getOrCreate(e,t,s){let a=this.generateKey(e,t);e=this.cache.get(a);return e||(this.pendingRequests.has(a)?this.pendingRequests.get(a):(t=(async()=>{try{var e=await s();return this.cache.set(a,e),e}finally{this.pendingRequests.delete(a)}})(),this.pendingRequests.set(a,t),t))}size(){return this.cache.size}}class a{static LOG_LEVELS={DEBUG:0,INFO:1,WARN:2,ERROR:3,NONE:4};constructor(e=a.LOG_LEVELS.WARN){this.level=e}log(t,e){var s;!window.console||t<this.level||(s=Object.keys(a.LOG_LEVELS).find(e=>a.LOG_LEVELS[e]===t),console.log(`fTable ${s}: `+e))}debug(e){this.log(a.LOG_LEVELS.DEBUG,e)}info(e){this.log(a.LOG_LEVELS.INFO,e)}warn(e){this.log(a.LOG_LEVELS.WARN,e)}error(e){this.log(a.LOG_LEVELS.ERROR,e)}}class u{static create(e,t={}){let s=document.createElement(e);return t.className&&(s.className=t.className),t.style&&(s.style.cssText=t.style),t.attributes&&Object.entries(t.attributes).forEach(([e,t])=>{null!==t&&s.setAttribute(e,t)}),t.text&&(s.textContent=t.text),t.html&&(s.innerHTML=t.html),t.parent&&t.parent.appendChild(s),s}static find(e,t=document){return t.querySelector(e)}static findAll(e,t=document){return Array.from(t.querySelectorAll(e))}static addClass(e,t){e.classList.add(...t.split(" "))}static removeClass(e,t){e.classList.remove(...t.split(" "))}static toggleClass(e,t){e.classList.toggle(t)}static show(e){e.style.display=""}static hide(e){e.style.display="none"}static escapeHtml(e){if(!e)return e;let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,e=>t[e])}}class l{static async request(e,t={}){var s={method:"GET",headers:{}},a={...s,...t};t.headers&&(a.headers={...s.headers,...t.headers});try{var i=await fetch(e,a);if(401===i.status)throw new Error("Unauthorized");if(!i.ok)throw new Error("HTTP error! status: "+i.status);var o=i.headers.get("content-type");if(o&&o.includes("application/json"))return await i.json();var r=await i.text();try{return JSON.parse(r)}catch{return{Result:"OK",Message:r}}}catch(e){throw e}}static async get(e,t={}){let a=new URL(e,window.location.href);return Object.entries(t).forEach(([e,s])=>{if(null!=s)if(Array.isArray(s)){let t=e.replace(/\[\]$/,"")+"[]";s.forEach(e=>{null!=e&&a.searchParams.append(t,e)})}else a.searchParams.append(e,s)}),this.request(a.toString(),{method:"GET",headers:{"Content-Type":"application/x-www-form-urlencoded"}})}static async post(e,t={}){e=new URL(e,window.location.href);let a=new FormData;return Object.entries(t).forEach(([e,s])=>{if(null!=s)if(Array.isArray(s)){let t=e.replace(/\[\]$/,"")+"[]";s.forEach(e=>{null!=e&&a.append(t,e)})}else a.append(e,s)}),this.request(e.toString(),{method:"POST",body:a})}}class i{constructor(e,t="localStorage"){this.prefix=e,this.method=t}set(e,t){var s,e=""+this.prefix+e;"localStorage"===this.method?localStorage.setItem(e,t):((s=new Date).setDate(s.getDate()+30),document.cookie=e+`=${t}; expires=${s.toUTCString()}; path=/`)}get(e){e=""+this.prefix+e;if("localStorage"===this.method)return localStorage.getItem(e);var t,s=e+"=";for(t of decodeURIComponent(document.cookie).split(";")){for(;" "===t.charAt(0);)t=t.substring(1);if(0===t.indexOf(s))return t.substring(s.length,t.length)}return null}remove(e){e=""+this.prefix+e;"localStorage"===this.method?localStorage.removeItem(e):document.cookie=e+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"}generatePrefix(e,t){e=e?e+"#":"";return"ftable#"+(t=>{let s=0;if(0!==t.length)for(let e=0;e<t.length;e++){var a=t.charCodeAt(e);s=(s<<5)-s+a,s&=s}return s})(e+=t.join("$")+"#c"+t.length)}}class o{constructor(e={}){this.options={title:"Modal",content:"",buttons:[],className:"ftable-modal",parent:document.body,...e},this.overlay=null,this.modal=null,this.isOpen=!1}create(){this.overlay=u.create("div",{className:"ftable-modal-overlay",parent:this.options.parent}),this.modal=u.create("div",{className:"ftable-modal "+this.options.className,parent:this.overlay});u.create("h2",{className:"ftable-modal-header",text:this.options.title,parent:this.modal});u.create("span",{className:"ftable-modal-close",html:"×",parent:this.modal}).addEventListener("click",()=>this.close());var e=u.create("div",{className:"ftable-modal-body",parent:this.modal});if("string"==typeof this.options.content?e.innerHTML=this.options.content:e.appendChild(this.options.content),0<this.options.buttons.length){let s=u.create("div",{className:"ftable-modal-footer",parent:this.modal});this.options.buttons.forEach(e=>{var t=u.create("button",{className:"ftable-dialog-button "+(e.className||""),html:`<span>${e.text}</span>`,parent:s});e.onClick&&(t._originalOnClick=e.onClick,t.addEventListener("click",this._createWrappedClickHandler(t)))})}return this.options.closeOnOverlayClick&&this.overlay.addEventListener("click",e=>{e.target===this.overlay&&this.close()}),this.hide(),this}show(){return this.modal||this.create(),this.overlay.style.display="flex",this.isOpen=!0,this.modal.querySelectorAll(".ftable-dialog-button").forEach(e=>{e.disabled=!1}),this}hide(){return this.overlay&&(this.overlay.style.display="none"),this.isOpen=!1,this}close(){return this.hide(),this.options.onClose&&this.options.onClose(),this}destroy(){return this.overlay&&this.overlay.remove(),this.isOpen=!1,this}setContent(e){this.options.content=e;var t=this.modal.querySelector(".ftable-modal-body");t&&(t.innerHTML="","string"==typeof e?t.innerHTML=e:t.appendChild(e))}_createWrappedClickHandler(a){return async e=>{a.disabled=!0;try{var t,s=a._originalOnClick;"function"==typeof s&&(t=s.call(a,e))instanceof Promise&&await t}catch(e){console.error("Modal button action failed:",e)}finally{a.disabled=!1}}}}class r{constructor(e){this.options=e,this.dependencies=new Map,this.optionsCache=new t,this.originalFieldOptions=new Map,this.resolvedFieldOptions=new Map,Object.keys(this.options.fields||{}).forEach(e=>{this.resolvedFieldOptions.set(e,{})}),Object.entries(this.options.fields).forEach(([e,t])=>{this.originalFieldOptions.set(e,t.options)})}async getFieldOptions(t,s="table",e={}){var a=this.options.fields[t],i=this.originalFieldOptions.get(t);if(!i)return null;var o=this.shouldForceRefreshForContext(a,s,e),r=this.generateOptionsCacheKey(s,e);if(!o&&!e.forceRefresh){var n=this.resolvedFieldOptions.get(t)[r];if(n)return n}try{var l={...a,options:i},c=await this.resolveOptions(l,{...e},s,o);return this.resolvedFieldOptions.get(t)[r]=c}catch(e){return console.error(`Failed to resolve options for ${t} (${s}):`,e),i}}clearResolvedOptions(e=null,s=null){e?this.resolvedFieldOptions.has(e)&&(s?this.resolvedFieldOptions.get(e)[s]=null:this.resolvedFieldOptions.set(e,{table:null,create:null,edit:null})):s?this.resolvedFieldOptions.forEach((e,t)=>{this.resolvedFieldOptions.get(t)[s]=null}):this.resolvedFieldOptions.forEach((e,t)=>{this.resolvedFieldOptions.set(t,{table:null,create:null,edit:null})})}shouldForceRefreshForContext(e,t,s){return!!e.noCache&&("boolean"==typeof e.noCache?e.noCache:"function"==typeof e.noCache?e.noCache({context:t,...s}):"object"==typeof e.noCache&&!0===e.noCache[t])}generateOptionsCacheKey(e,t){let s=[e];return t.dependedValues&&Object.keys(t.dependedValues).sort().forEach(e=>{s.push(e+"="+t.dependedValues[e])}),s.join("|")}shouldIncludeField(e,t){return"create"===t?!1!==e.create&&!(!0===e.key&&!0!==e.create):"edit"!==t||!1!==e.edit}createFieldContainer(e,t,s,a){var i=u.create("div",{className:"hidden"!=t.type?"ftable-input-field-container":"",attributes:{id:"ftable-input-field-container-div-"+e}}),t=("hidden"!=t.type&&u.create("div",{className:"ftable-input-label",text:t.inputTitle||t.title,parent:i}),this.createInput(e,t,s[e],a));return i.appendChild(t),i}async createForm(e="create",t={}){this.currentFormRecord=t;var s,a,i,o,r=u.create("form",{className:`ftable-dialog-form ftable-${e}-form`});this.buildDependencyMap();for([s,a]of Object.entries(this.options.fields))this.shouldIncludeField(a,e)&&(i={...a},a.dependsOn?i.options=a.options:(o=await this.getFieldOptions(s,e,{record:t,source:e}),i.options=o),o=this.createFieldContainer(s,i,t,e),r.appendChild(o));return this.setupDependencyListeners(r),r}shouldResolveOptions(e){return e&&("function"==typeof e||"string"==typeof e)&&!Array.isArray(e)&&!("object"==typeof e&&!Array.isArray(e)&&0<Object.keys(e).length)}buildDependencyMap(){this.dependencies.clear(),Object.entries(this.options.fields).forEach(([t,s])=>{if(s.dependsOn){let e;"string"==typeof s.dependsOn&&(e=s.dependsOn.split(",").map(e=>e.trim()).filter(e=>e)).forEach(e=>{this.dependencies.has(e)||this.dependencies.set(e,[]),this.dependencies.get(e).push(t)})}})}setupDependencyListeners(s){Array.from(this.dependencies.keys()).forEach(e=>{var t=s.querySelector(`[name="${e}"]`);t&&t.addEventListener("change",()=>{this.handleDependencyChange(s,e)})}),this.handleDependencyChange(s)}async resolveOptions(e,t={},s="",a=!1){if(!e.options)return[];if(Array.isArray(e.options)||"object"==typeof e.options)return e.options;let i;t={...t,source:s,clearCache:()=>{a=!0,this.updateFieldCacheSetting(e,s,!0)}};if("function"==typeof e.options)i=await e.options(t);else{if("string"!=typeof e.options)return[];i=e.options}t=i&&"object"==typeof i&&i.url;let o=t?i.url:i;if(a=t&&void 0!==i.noCache?i.noCache:a,"string"!=typeof o)return[];if(!a)return this.optionsCache.getOrCreate(o,{},async()=>{try{var e=this.options.forcePost?await l.post(o):await l.get(o);return e.Options||e.options||e||[]}catch(e){return console.error(`Failed to load options from ${o}:`,e),[]}});try{var r=this.options.forcePost?await l.post(o):await l.get(o);return r.Options||r.options||r||[]}catch(e){return console.error(`Failed to load options from ${o}:`,e),[]}}updateFieldCacheSetting(e,t,s){e.noCache?"boolean"==typeof e.noCache?e.noCache={table:e.noCache,create:e.noCache,edit:e.noCache,[t]:s}:"object"==typeof e.noCache&&(e.noCache[t]=s):e.noCache={[t]:s}}clearOptionsCache(e=null,t=null){this.optionsCache.clear(e,t)}getFormValues(e){var t={},s=e.elements;for(let e=0;e<s.length;e++){var a=s[e],i=a.name;if(i&&!a.disabled)switch(a.type){case"checkbox":t[i]=a.checked?a.value||"1":"0";break;case"radio":a.checked&&(t[i]=a.value);break;case"select-multiple":t[i]=Array.from(a.selectedOptions).map(e=>e.value);break;default:t[i]=a.value}}return t}async handleDependencyChange(e,s=""){var a,i,o=this.getFormValues(e),r=e.classList.contains("ftable-create-form")?"create":"edit",n=this.currentFormRecord||{},l={record:n,source:r,form:e,dependedValues:o};for([a,i]of Object.entries(this.options.fields))if(i.dependsOn){if(""!==s)if(!i.dependsOn.split(",").map(e=>e.trim()).filter(e=>e).includes(s))continue;let t=e.querySelector(`[name="${a}"]`);if(t&&this.shouldIncludeField(i,r))try{"SELECT"===t.tagName?t.innerHTML='<option value="">Loading...</option>':"INPUT"===t.tagName&&t.list&&(c=document.getElementById(t.list.id))&&(c.innerHTML="");var c,d=t.value||n[a]||"",h={...l,dependsOnField:i.dependsOn,dependsOnValue:o[i.dependsOn]},p=await this.getFieldOptions(a,r,h);"SELECT"===t.tagName?this.populateSelectOptions(t,p,d):"INPUT"===t.tagName&&t.list&&(this.populateDatalistOptions(t.list,p),d)&&(t.value=d),setTimeout(()=>{t.dispatchEvent(new Event("change",{bubbles:!0}))},0)}catch(e){console.error(`Error loading options for ${a}:`,e),"SELECT"===t.tagName&&(t.innerHTML='<option value="">Error</option>')}}}parseInputAttributes(e){if("string"!=typeof e)return e||{};for(var t={},s=/(\w+)(?:=("[^"]*"|'[^']*'|\S+))?/g;null!==(i=s.exec(e));){var a=i[1],i=i[2]?i[2].replace(/^["']|["']$/g,""):"";t[a]=""===i?"true":i}return t}createInput(e,t,s,a){var i=u.create("div",{className:`ftable-input ftable-${t.type||"text"}-input`});let o;switch(null==(s=null==s?null:s)&&t.defaultValue&&(s=t.defaultValue),!t.type&&t.options&&(t.type="select"),t.type){case"hidden":o=this.createHiddenInput(e,t,s);break;case"textarea":o=this.createTextarea(e,t,s);break;case"select":o=this.createSelect(e,t,s);break;case"checkbox":o=this.createCheckbox(e,t,s);break;case"radio":o=this.createRadioGroup(e,t,s);break;case"datalist":o=this.createDatalistInput(e,t,s);break;case"file":o=this.createFileInput(e,t,s);break;case"date":case"datetime":case"datetime-local":o=this.createDateInput(e,t,s);break;default:o=this.createTypedInput(e,t,s)}return"function"==typeof t.input?(a={field:t,record:this.currentFormRecord,inputField:o,formType:a},"string"==typeof(a=t.input(a))?i.innerHTML=a:a instanceof Node?i.appendChild(a):(i.appendChild(o),o.datalistElement&&o.datalistElement instanceof Node&&i.appendChild(o.datalistElement))):(i.appendChild(o),o.datalistElement&&o.datalistElement instanceof Node&&i.appendChild(o.datalistElement)),t.explain&&u.create("div",{className:"ftable-field-explain",html:`<small>${t.explain}</small>`,parent:i}),i}createDateInput(s,a,i){if("undefined"==typeof FDatepicker)return createTypedInput(s,a,i);{let e=a.dateFormat||this.options.defaultDateFormat;var o,r=document.createElement("div"),n=u.create("input",{attributes:{id:"real-"+s,type:"hidden",value:i,name:s}}),i={id:"Edit-"+s,type:"text","data-date":i,placeholder:a.placeholder||null,readOnly:!0};a.inputAttributes&&(o=this.parseInputAttributes(a.inputAttributes),Object.assign(i,o));let t=u.create("input",{className:a.inputClass||"datepicker-input",attributes:i});switch(r.appendChild(n),r.appendChild(t),a.type){case"date":setTimeout(()=>{new FDatepicker(t,{format:e,altField:"real-"+s,altFormat:"Y-m-d"})},0);break;case"datetime":case"datetime-local":setTimeout(()=>{new FDatepicker(t,{format:e,timepicker:!0,altField:"real-"+s,altFormat:"Y-m-d H:i:00"})},0)}return r}}createTypedInput(e,t,s){var a,s={type:t.type||"text",id:"Edit-"+e,placeholder:t.placeholder||null,value:s};let i=e,o=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(s,a),void 0!==a.multiple&&!1!==a.multiple)&&(i=e+"[]"),s.name=i,u.create("input",{className:t.inputClass||null,attributes:s}));return o.addEventListener("keypress",e=>{if(13===(e.keyCode||e.which))return e.preventDefault(),o.dispatchEvent(new Event("change",{bubbles:!0})),!1}),o}createDatalistInput(e,t,s){var s={type:"text",name:e,id:"Edit-"+e,placeholder:t.placeholder||null,value:s,list:e+"-datalist"},a=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(s,a)),u.create("input",{className:t.inputClass||null,attributes:s})),s=u.create("datalist",{attributes:{id:e+"-datalist"}});return t.options&&this.populateDatalistOptions(s,t.options),a.datalistElement=s,a}populateDatalistOptions(s,e){s.innerHTML="",Array.isArray(e)?e.forEach(e=>{u.create("option",{attributes:{value:e.Value||e.value||e},text:e.DisplayText||e.text||e,parent:s})}):"object"==typeof e&&Object.entries(e).forEach(([e,t])=>{u.create("option",{attributes:{value:e},text:t,parent:s})})}createHiddenInput(e,t,s){e={type:"hidden",name:e,id:"Edit-"+e,value:s};return t.inputAttributes&&(s=this.parseInputAttributes(t.inputAttributes),Object.assign(e,s)),u.create("input",{attributes:e})}createTextarea(e,t,s){var e={name:e,id:"Edit-"+e,placeholder:t.placeholder||null},a=(t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(e,a)),u.create("textarea",{className:t.inputClass||null,attributes:e,value:s}));return a}createSelect(e,t,s){var a={name:e,id:"Edit-"+e};let i=e;t.inputAttributes&&(o=this.parseInputAttributes(t.inputAttributes),Object.assign(a,o),void 0!==o.multiple&&!1!==o.multiple)&&(i=e+"[]"),a.name=i;var o=u.create("select",{className:t.inputClass||null,attributes:a});return t.options&&this.populateSelectOptions(o,t.options,s),o}createRadioGroup(o,r,n){let l=u.create("div",{className:"ftable-radio-group"});return r.options&&(Array.isArray(r.options)?r.options:"object"==typeof r.options?Object.entries(r.options).map(([e,t])=>({Value:e,DisplayText:t})):[]).forEach((e,t)=>{var s=u.create("div",{className:"ftable-radio-wrapper",parent:l}),a=o+"_"+t,i={type:"radio",name:o,id:a,value:e.Value||e.value||e},t=(r.required&&0===t&&(i.required="required"),r.disabled&&(i.disabled="disabled"),r.inputAttributes&&(t=this.parseInputAttributes(r.inputAttributes),Object.assign(i,t)),u.create("input",{attributes:i,className:r.inputClass||null,parent:s}));i.value===n&&(t.checked=!0),u.create("label",{attributes:{for:a},text:e.DisplayText||e.text||e,parent:s})}),l}createCheckbox(e,t,s){var a=u.create("div",{className:"ftable-yesno-check-wrapper"}),s=[1,"1",!0,"true"].includes(s);let i=this.options.messages.no,o=this.options.messages.yes;return t.values&&"object"==typeof t.values&&(void 0!==t.values[0]&&(i=t.values[0]),void 0!==t.values[1])&&(o=t.values[1]),u.create("input",{className:["ftable-yesno-check-input",t.inputClass||""].filter(Boolean).join(" "),attributes:{type:"checkbox",name:e,id:"Edit-"+e,value:"1"},parent:a}).checked=s,t.label?u.create("label",{className:"ftable-yesno-check-fixedlabel",attributes:{for:"Edit-"+e},text:t.label,parent:a}):u.create("label",{className:"ftable-yesno-check-text",attributes:{for:"Edit-"+e,"data-yes":o,"data-no":i},parent:a}),a}populateSelectOptions(a,e,i){a.innerHTML="",Array.isArray(e)?e.forEach(e=>{var t=void 0!==e.Value?e.Value:void 0!==e.value?e.value:e;let s=u.create("option",{attributes:{value:t},text:e.DisplayText||e.text||e,parent:a});e.Data&&"object"==typeof e.Data&&Object.entries(e.Data).forEach(([e,t])=>{s.setAttribute("data-"+e,t)}),s.value==i&&(s.selected=!0)}):"object"==typeof e&&Object.entries(e).forEach(([e,t])=>{t=u.create("option",{attributes:{value:e},text:t,parent:a});e==i&&(t.selected=!0)})}createFileInput(e,t,s){var a,i={type:"file",id:"Edit-"+e};let o=e;return t.inputAttributes&&(a=this.parseInputAttributes(t.inputAttributes),Object.assign(i,a),void 0!==a.multiple&&!1!==a.multiple)&&(o=e+"[]"),i.name=o,u.create("input",{className:t.inputClass||null,attributes:i})}}class n extends class{constructor(){this.events={}}on(e,t){return this.events[e]||(this.events[e]=[]),this.events[e].push(t),this}once(t,s){let a=(...e)=>{this.off(t,a),s.apply(this,e)};return a.fn=s,this.on(t,a),this}emit(e,t={}){return this.events[e]&&this.events[e].forEach(e=>e(t)),this}off(e,t){return this.events[e]&&(this.events[e]=this.events[e].filter(e=>e!==t)),this}}{constructor(e,t={}){if(super(),this.element="string"==typeof e?document.querySelector(e):e,this.element){if(this.element.ftableInstance)return this.element.ftableInstance;this.options=this.mergeOptions(t),this.verifyOptions(),this.logger=new a(this.options.logLevel),this.userPrefs=new i("",this.options.saveUserPreferencesMethod),this.formBuilder=new r(this.options,this),this.state={records:[],totalRecordCount:0,currentPage:1,isLoading:!1,selectedRecords:new Set,sorting:[],searchQueries:{}},this.elements={},this.modals={},this.searchTimeout=null,this.lastSortEvent=null,this._recalculatedOnce=!1,this.shiftKeyDown=!1,this.lastSelectedRow=null,(this.element.ftableInstance=this).init()}}mergeOptions(e){var t={tableId:void 0,logLevel:a.LOG_LEVELS.WARN,actions:{},fields:{},forcePost:!0,closeOnOverlayClick:!0,animationsEnabled:!0,loadingAnimationDelay:1e3,defaultDateLocale:"",defaultDateFormat:"Y-m-d",saveUserPreferences:!0,saveUserPreferencesMethod:"localStorage",defaultSorting:"",tableReset:!1,paging:!1,pageList:"normal",pageSize:10,pageSizes:[10,25,50,100,250,500],gotoPageArea:"combobox",sorting:!1,multiSorting:!1,multiSortingCtrlKey:!0,selecting:!1,multiselect:!1,openChildAsAccordion:!1,toolbarsearch:!1,toolbarreset:!0,searchDebounceMs:300,listCache:3e4,messages:{...s}};return this.deepMerge(t,e)}deepMerge(e,t){var s,a={...e};for(s in t)t[s]&&"object"==typeof t[s]&&!Array.isArray(t[s])?a[s]=this.deepMerge(a[s]||{},t[s]):a[s]=t[s];return a}verifyOptions(){this.options.pageSize&&!this.options.pageSizes.includes(this.options.pageSize)&&(this.options.pageSize=this.options.pageSizes[0])}static setMessages(e){Object.assign(s,e)}init(){this.processFieldDefinitions(),this.createMainStructure(),this.setupFTableUserPreferences(),this.createTable(),this.createModals(),this.options.paging&&this.createPagingUI(),this.resolveAsyncFieldOptions().then(()=>{setTimeout(()=>{this.refreshDisplayValues()},0)}).catch(console.error),this.bindEvents(),this.updateSortingHeaders(),this.renderSortingInfo(),this.initColumnWidths()}initColumnWidths(){var e=this.columnList.filter(e=>{e=this.options.fields[e];return"hidden"!==e.visibility&&"separator"!==e.visibility});let t=e.length;e.forEach(e=>{e=this.options.fields[e];e.width=e.width||100/t+"%"})}normalizeColumnWidths(){var e=this.elements.mainContainer,t=this.columnList.map(e=>({th:this.elements.table.querySelector(`[data-field-name="${e}"]`),field:this.options.fields[e]})).filter(e=>e.th&&"hidden"!==e.field.visibility&&"separator"!==e.field.visibility);if(0!==t.length){let s=e.offsetWidth,a=0;t.forEach(e=>{var t=e.th.offsetWidth/s*100;e.field.width=t+"%",e.th.style.width=e.field.width,a+=t})}}parseDefaultSorting(e){let o=[];return e&&"string"==typeof e&&e.split(",").forEach(s=>{s=s.trim();if(s){var a=s.toUpperCase().indexOf(" DESC"),i=s.toUpperCase().indexOf(" ASC");let e="ASC",t=s;e=0<a?(t=s.slice(0,a).trim(),"DESC"):(t=(0<i?s.slice(0,i):s).trim(),"ASC");a=this.options.fields[t];a&&!1!==a.sorting&&o.push({fieldName:t,direction:e})}}),o}addEssentialCSS(){var e;document.querySelector("#ftable-essential-css")||((e=document.createElement("style")).id="ftable-essential-css",e.textContent=`
|
|
2
2
|
.ftable-row-animation {
|
|
3
3
|
transition: background-color 0.3s ease;
|
|
4
4
|
}
|
package/ftable.umd.js
CHANGED
|
@@ -200,7 +200,7 @@ class FTableDOMHelper {
|
|
|
200
200
|
|
|
201
201
|
if (options.attributes) {
|
|
202
202
|
Object.entries(options.attributes).forEach(([key, value]) => {
|
|
203
|
-
if (value !==
|
|
203
|
+
if (value !== null)
|
|
204
204
|
element.setAttribute(key, value);
|
|
205
205
|
});
|
|
206
206
|
}
|
|
@@ -1065,7 +1065,10 @@ class FTableFormBuilder {
|
|
|
1065
1065
|
|
|
1066
1066
|
let input;
|
|
1067
1067
|
|
|
1068
|
-
if (value ==
|
|
1068
|
+
if (value == undefined) {
|
|
1069
|
+
value = null;
|
|
1070
|
+
}
|
|
1071
|
+
if (value == null && field.defaultValue ) {
|
|
1069
1072
|
value = field.defaultValue;
|
|
1070
1073
|
}
|
|
1071
1074
|
// Auto-detect select type if options are provided
|
|
@@ -1127,10 +1130,16 @@ class FTableFormBuilder {
|
|
|
1127
1130
|
// Otherwise, fallback to default
|
|
1128
1131
|
else {
|
|
1129
1132
|
container.appendChild(input);
|
|
1133
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1134
|
+
container.appendChild(input.datalistElement);
|
|
1135
|
+
}
|
|
1130
1136
|
}
|
|
1131
1137
|
} else {
|
|
1132
1138
|
// No custom input function — just add the default input
|
|
1133
1139
|
container.appendChild(input);
|
|
1140
|
+
if (input.datalistElement && input.datalistElement instanceof Node) {
|
|
1141
|
+
container.appendChild(input.datalistElement);
|
|
1142
|
+
}
|
|
1134
1143
|
}
|
|
1135
1144
|
|
|
1136
1145
|
// Add explanation if provided
|
|
@@ -1156,7 +1165,7 @@ class FTableFormBuilder {
|
|
|
1156
1165
|
attributes: {
|
|
1157
1166
|
id: 'real-' + fieldName,
|
|
1158
1167
|
type: 'hidden',
|
|
1159
|
-
value: value
|
|
1168
|
+
value: value,
|
|
1160
1169
|
name: fieldName
|
|
1161
1170
|
}
|
|
1162
1171
|
});
|
|
@@ -1166,7 +1175,7 @@ class FTableFormBuilder {
|
|
|
1166
1175
|
id: `Edit-${fieldName}`,
|
|
1167
1176
|
type: 'text',
|
|
1168
1177
|
'data-date': value,
|
|
1169
|
-
placeholder: field.placeholder ||
|
|
1178
|
+
placeholder: field.placeholder || null,
|
|
1170
1179
|
readOnly: true
|
|
1171
1180
|
};
|
|
1172
1181
|
// Set any additional attributes
|
|
@@ -1220,8 +1229,8 @@ class FTableFormBuilder {
|
|
|
1220
1229
|
const attributes = {
|
|
1221
1230
|
type: inputType,
|
|
1222
1231
|
id: `Edit-${fieldName}`,
|
|
1223
|
-
placeholder: field.placeholder ||
|
|
1224
|
-
value: value
|
|
1232
|
+
placeholder: field.placeholder || null,
|
|
1233
|
+
value: value
|
|
1225
1234
|
};
|
|
1226
1235
|
|
|
1227
1236
|
// extra check for name and multiple
|
|
@@ -1242,7 +1251,7 @@ class FTableFormBuilder {
|
|
|
1242
1251
|
attributes.name = name;
|
|
1243
1252
|
|
|
1244
1253
|
const input = FTableDOMHelper.create('input', {
|
|
1245
|
-
className: field.inputClass ||
|
|
1254
|
+
className: field.inputClass || null,
|
|
1246
1255
|
attributes: attributes
|
|
1247
1256
|
});
|
|
1248
1257
|
|
|
@@ -1264,8 +1273,8 @@ class FTableFormBuilder {
|
|
|
1264
1273
|
type: 'text',
|
|
1265
1274
|
name: fieldName,
|
|
1266
1275
|
id: `Edit-${fieldName}`,
|
|
1267
|
-
placeholder: field.placeholder ||
|
|
1268
|
-
value: value
|
|
1276
|
+
placeholder: field.placeholder || null,
|
|
1277
|
+
value: value,
|
|
1269
1278
|
list: `${fieldName}-datalist`
|
|
1270
1279
|
};
|
|
1271
1280
|
|
|
@@ -1276,7 +1285,7 @@ class FTableFormBuilder {
|
|
|
1276
1285
|
}
|
|
1277
1286
|
|
|
1278
1287
|
const input = FTableDOMHelper.create('input', {
|
|
1279
|
-
className: field.inputClass ||
|
|
1288
|
+
className: field.inputClass || null,
|
|
1280
1289
|
attributes: attributes
|
|
1281
1290
|
});
|
|
1282
1291
|
|
|
@@ -1292,10 +1301,7 @@ class FTableFormBuilder {
|
|
|
1292
1301
|
this.populateDatalistOptions(datalist, field.options);
|
|
1293
1302
|
}
|
|
1294
1303
|
|
|
1295
|
-
//
|
|
1296
|
-
document.body.appendChild(datalist);
|
|
1297
|
-
|
|
1298
|
-
// Store reference for cleanup
|
|
1304
|
+
// Store reference
|
|
1299
1305
|
input.datalistElement = datalist;
|
|
1300
1306
|
|
|
1301
1307
|
return input;
|
|
@@ -1330,7 +1336,7 @@ class FTableFormBuilder {
|
|
|
1330
1336
|
type: 'hidden',
|
|
1331
1337
|
name: fieldName,
|
|
1332
1338
|
id: `Edit-${fieldName}`,
|
|
1333
|
-
value: value
|
|
1339
|
+
value: value
|
|
1334
1340
|
};
|
|
1335
1341
|
|
|
1336
1342
|
// Apply inputAttributes
|
|
@@ -1346,7 +1352,7 @@ class FTableFormBuilder {
|
|
|
1346
1352
|
const attributes = {
|
|
1347
1353
|
name: fieldName,
|
|
1348
1354
|
id: `Edit-${fieldName}`,
|
|
1349
|
-
placeholder: field.placeholder ||
|
|
1355
|
+
placeholder: field.placeholder || null
|
|
1350
1356
|
};
|
|
1351
1357
|
|
|
1352
1358
|
// Apply inputAttributes
|
|
@@ -1356,9 +1362,9 @@ class FTableFormBuilder {
|
|
|
1356
1362
|
}
|
|
1357
1363
|
|
|
1358
1364
|
const textarea = FTableDOMHelper.create('textarea', {
|
|
1359
|
-
className: field.inputClass ||
|
|
1365
|
+
className: field.inputClass || null,
|
|
1360
1366
|
attributes: attributes,
|
|
1361
|
-
value: value
|
|
1367
|
+
value: value
|
|
1362
1368
|
});
|
|
1363
1369
|
return textarea;
|
|
1364
1370
|
}
|
|
@@ -1387,7 +1393,7 @@ class FTableFormBuilder {
|
|
|
1387
1393
|
attributes.name = name;
|
|
1388
1394
|
|
|
1389
1395
|
const select = FTableDOMHelper.create('select', {
|
|
1390
|
-
className: field.inputClass ||
|
|
1396
|
+
className: field.inputClass || null,
|
|
1391
1397
|
attributes: attributes
|
|
1392
1398
|
});
|
|
1393
1399
|
|
|
@@ -1432,7 +1438,7 @@ class FTableFormBuilder {
|
|
|
1432
1438
|
|
|
1433
1439
|
const radio = FTableDOMHelper.create('input', {
|
|
1434
1440
|
attributes: radioAttributes,
|
|
1435
|
-
className: field.inputClass ||
|
|
1441
|
+
className: field.inputClass || null,
|
|
1436
1442
|
parent: radioWrapper
|
|
1437
1443
|
});
|
|
1438
1444
|
|
|
@@ -1566,11 +1572,10 @@ class FTableFormBuilder {
|
|
|
1566
1572
|
}
|
|
1567
1573
|
attributes.name = name;
|
|
1568
1574
|
|
|
1569
|
-
|
|
1570
|
-
className: field.inputClass ||
|
|
1575
|
+
return FTableDOMHelper.create('input', {
|
|
1576
|
+
className: field.inputClass || null,
|
|
1571
1577
|
attributes: attributes
|
|
1572
1578
|
});
|
|
1573
|
-
return input;
|
|
1574
1579
|
}
|
|
1575
1580
|
}
|
|
1576
1581
|
|