@liedekef/ftable 1.1.5 → 1.1.7
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 +43 -160
- package/ftable.js +44 -161
- package/ftable.min.js +3 -3
- package/ftable.umd.js +44 -161
- package/package.json +1 -1
- package/themes/basic/ftable_basic.css +25 -25
- package/themes/basic/ftable_basic.min.css +1 -1
- package/themes/ftable_theme_base.less +35 -35
- package/themes/lightcolor/blue/ftable.css +33 -33
- package/themes/lightcolor/blue/ftable.min.css +1 -1
- package/themes/lightcolor/ftable_lightcolor_base.less +6 -5
- package/themes/lightcolor/gray/ftable.css +33 -33
- package/themes/lightcolor/gray/ftable.min.css +1 -1
- package/themes/lightcolor/green/ftable.css +33 -33
- package/themes/lightcolor/green/ftable.min.css +1 -1
- package/themes/lightcolor/orange/ftable.css +33 -33
- package/themes/lightcolor/orange/ftable.min.css +1 -1
- package/themes/lightcolor/red/ftable.css +33 -33
- package/themes/lightcolor/red/ftable.min.css +1 -1
- package/themes/metro/blue/ftable.css +25 -25
- package/themes/metro/blue/ftable.min.css +1 -1
- package/themes/metro/brown/ftable.css +25 -25
- package/themes/metro/brown/ftable.min.css +1 -1
- package/themes/metro/crimson/ftable.css +25 -25
- package/themes/metro/crimson/ftable.min.css +1 -1
- package/themes/metro/darkgray/ftable.css +25 -25
- package/themes/metro/darkgray/ftable.min.css +1 -1
- package/themes/metro/darkorange/ftable.css +25 -25
- package/themes/metro/darkorange/ftable.min.css +1 -1
- package/themes/metro/green/ftable.css +25 -25
- package/themes/metro/green/ftable.min.css +1 -1
- package/themes/metro/lightgray/ftable.css +25 -25
- package/themes/metro/lightgray/ftable.min.css +1 -1
- package/themes/metro/pink/ftable.css +25 -25
- package/themes/metro/pink/ftable.min.css +1 -1
- package/themes/metro/purple/ftable.css +25 -25
- package/themes/metro/purple/ftable.min.css +1 -1
- package/themes/metro/red/ftable.css +25 -25
- package/themes/metro/red/ftable.min.css +1 -1
package/ftable.esm.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
// Modern fTable - Vanilla JS Refactor
|
|
3
|
-
|
|
4
2
|
const FTABLE_DEFAULT_MESSAGES = {
|
|
5
3
|
serverCommunicationError: 'An error occurred while communicating to the server.',
|
|
6
4
|
loadingMessage: 'Loading records...',
|
|
@@ -748,7 +746,9 @@ class FTableFormBuilder {
|
|
|
748
746
|
}
|
|
749
747
|
|
|
750
748
|
try {
|
|
751
|
-
const response =
|
|
749
|
+
const response = this.options.forcePost
|
|
750
|
+
? await FTableHttpClient.post(url)
|
|
751
|
+
: await FTableHttpClient.get(url);
|
|
752
752
|
const options = response.Options || response.options || response || [];
|
|
753
753
|
|
|
754
754
|
// Only cache if noCache is false
|
|
@@ -971,10 +971,10 @@ class FTableFormBuilder {
|
|
|
971
971
|
const visibleInput = FTableDOMHelper.create('input', {
|
|
972
972
|
className: field.inputClass || 'datepicker-input',
|
|
973
973
|
attributes: {
|
|
974
|
-
id: 'ftable-toolbarsearch-' + fieldName,
|
|
975
974
|
id: 'Edit-' + fieldName,
|
|
976
975
|
type: 'text',
|
|
977
976
|
'data-date': value,
|
|
977
|
+
placeholder: field.placeholder || '',
|
|
978
978
|
readOnly: true
|
|
979
979
|
}
|
|
980
980
|
});
|
|
@@ -1354,10 +1354,14 @@ class FTable extends FTableEventEmitter {
|
|
|
1354
1354
|
this.element = typeof element === 'string' ?
|
|
1355
1355
|
document.querySelector(element) : element;
|
|
1356
1356
|
|
|
1357
|
+
if (!this.element) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1357
1361
|
// Prevent double initialization
|
|
1358
|
-
if (element.ftableInstance) {
|
|
1362
|
+
if (this.element.ftableInstance) {
|
|
1359
1363
|
//console.warn('FTable is already initialized on this element. Using that.');
|
|
1360
|
-
return element.ftableInstance;
|
|
1364
|
+
return this.element.ftableInstance;
|
|
1361
1365
|
}
|
|
1362
1366
|
|
|
1363
1367
|
this.options = this.mergeOptions(options);
|
|
@@ -1394,6 +1398,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1394
1398
|
logLevel: FTableLogger.LOG_LEVELS.WARN,
|
|
1395
1399
|
actions: {},
|
|
1396
1400
|
fields: {},
|
|
1401
|
+
forcePost: true,
|
|
1397
1402
|
animationsEnabled: true,
|
|
1398
1403
|
loadingAnimationDelay: 1000,
|
|
1399
1404
|
defaultDateLocale: '',
|
|
@@ -1949,6 +1954,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1949
1954
|
attributes: {
|
|
1950
1955
|
id: 'ftable-toolbarsearch-' + fieldName,
|
|
1951
1956
|
type: 'text',
|
|
1957
|
+
placeholder: field.placeholder || '',
|
|
1952
1958
|
readOnly: true
|
|
1953
1959
|
}
|
|
1954
1960
|
});
|
|
@@ -2519,13 +2525,15 @@ class FTable extends FTableEventEmitter {
|
|
|
2519
2525
|
// Create overlay to capture clicks outside menu
|
|
2520
2526
|
this.elements.columnSelectionOverlay = FTableDOMHelper.create('div', {
|
|
2521
2527
|
className: 'ftable-contextmenu-overlay',
|
|
2522
|
-
parent: this.elements.mainContainer
|
|
2528
|
+
//parent: this.elements.mainContainer
|
|
2529
|
+
parent: document.body
|
|
2523
2530
|
});
|
|
2524
2531
|
|
|
2525
2532
|
// Create the menu
|
|
2526
2533
|
this.elements.columnSelectionMenu = FTableDOMHelper.create('div', {
|
|
2527
2534
|
className: 'ftable-column-selection-container',
|
|
2528
|
-
parent: this.elements.columnSelectionOverlay
|
|
2535
|
+
//parent: this.elements.columnSelectionOverlay
|
|
2536
|
+
parent: document.body
|
|
2529
2537
|
});
|
|
2530
2538
|
|
|
2531
2539
|
// Populate menu with column options
|
|
@@ -2611,29 +2619,36 @@ class FTable extends FTableEventEmitter {
|
|
|
2611
2619
|
}
|
|
2612
2620
|
|
|
2613
2621
|
positionColumnSelectionMenu(e) {
|
|
2614
|
-
const
|
|
2615
|
-
const menuWidth = 200; // Approximate menu width
|
|
2616
|
-
const menuHeight = this.columnList.length * 30 + 20; // Approximate height
|
|
2622
|
+
const self = this;
|
|
2617
2623
|
|
|
2618
|
-
|
|
2619
|
-
let
|
|
2624
|
+
// Use clientX/clientY (relative to viewport)
|
|
2625
|
+
let left = e.clientX;
|
|
2626
|
+
let top = e.clientY;
|
|
2620
2627
|
|
|
2621
|
-
//
|
|
2622
|
-
|
|
2623
|
-
left = Math.max(0, containerRect.width - menuWidth);
|
|
2624
|
-
}
|
|
2628
|
+
// Define minimum width
|
|
2629
|
+
const minWidth = 100;
|
|
2625
2630
|
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
}
|
|
2631
|
+
// Position the menu
|
|
2632
|
+
self.elements.columnSelectionMenu.style.position = 'absolute';
|
|
2633
|
+
self.elements.columnSelectionMenu.style.left = `${left}px`;
|
|
2634
|
+
self.elements.columnSelectionMenu.style.top = `${top}px`;
|
|
2635
|
+
self.elements.columnSelectionMenu.style.minWidth = `${minWidth}px`;
|
|
2636
|
+
self.elements.columnSelectionMenu.style.boxSizing = 'border-box';
|
|
2637
|
+
|
|
2638
|
+
// Optional: Adjust if menu would overflow right edge
|
|
2639
|
+
const menuWidth = self.elements.columnSelectionMenu.offsetWidth;
|
|
2640
|
+
const windowWidth = window.innerWidth;
|
|
2629
2641
|
|
|
2630
|
-
|
|
2631
|
-
|
|
2642
|
+
if (left + menuWidth > windowWidth) {
|
|
2643
|
+
left = Math.max(10, windowWidth - menuWidth - 10); // 10px margin
|
|
2644
|
+
self.elements.columnSelectionMenu.style.left = `${left}px`;
|
|
2645
|
+
}
|
|
2632
2646
|
}
|
|
2633
2647
|
|
|
2634
2648
|
hideColumnSelectionMenu() {
|
|
2635
2649
|
if (this.elements.columnSelectionOverlay) {
|
|
2636
2650
|
this.elements.columnSelectionOverlay.remove();
|
|
2651
|
+
this.elements.columnSelectionMenu.remove();
|
|
2637
2652
|
this.elements.columnSelectionOverlay = null;
|
|
2638
2653
|
this.elements.columnSelectionMenu = null;
|
|
2639
2654
|
}
|
|
@@ -2876,7 +2891,9 @@ class FTable extends FTableEventEmitter {
|
|
|
2876
2891
|
if (typeof listAction === 'function') {
|
|
2877
2892
|
data = await listAction(params);
|
|
2878
2893
|
} else if (typeof listAction === 'string') {
|
|
2879
|
-
data =
|
|
2894
|
+
data = this.options.forcePost
|
|
2895
|
+
? await FTableHttpClient.post(listAction, params)
|
|
2896
|
+
: await FTableHttpClient.get(listAction, params);
|
|
2880
2897
|
} else {
|
|
2881
2898
|
throw new Error('No valid listAction provided');
|
|
2882
2899
|
}
|
|
@@ -4410,7 +4427,9 @@ class FTable extends FTableEventEmitter {
|
|
|
4410
4427
|
...params
|
|
4411
4428
|
};
|
|
4412
4429
|
|
|
4413
|
-
const response =
|
|
4430
|
+
const response = this.options.forcePost
|
|
4431
|
+
? await FTableHttpClient.post(url, fullParams)
|
|
4432
|
+
: await FTableHttpClient.get(url, fullParams);
|
|
4414
4433
|
|
|
4415
4434
|
if (!response || !response.Record) {
|
|
4416
4435
|
throw new Error('Invalid response or missing Record');
|
|
@@ -4712,140 +4731,4 @@ class FTable extends FTableEventEmitter {
|
|
|
4712
4731
|
}
|
|
4713
4732
|
}
|
|
4714
4733
|
|
|
4715
|
-
// Export for use
|
|
4716
|
-
//window.FTable = FTable;
|
|
4717
|
-
|
|
4718
|
-
// Usage example:
|
|
4719
|
-
/*
|
|
4720
|
-
const table = new FTable('#myTable', {
|
|
4721
|
-
title: 'My Data Table',
|
|
4722
|
-
paging: true,
|
|
4723
|
-
pageSize: 25,
|
|
4724
|
-
sorting: true,
|
|
4725
|
-
selecting: true,
|
|
4726
|
-
actions: {
|
|
4727
|
-
listAction: '/api/users',
|
|
4728
|
-
createAction: '/api/users',
|
|
4729
|
-
updateAction: '/api/users',
|
|
4730
|
-
deleteAction: '/api/users'
|
|
4731
|
-
},
|
|
4732
|
-
fields: {
|
|
4733
|
-
id: { key: true, list: false },
|
|
4734
|
-
name: {
|
|
4735
|
-
title: 'Name',
|
|
4736
|
-
type: 'text',
|
|
4737
|
-
inputAttributes: "maxlength=100 required"
|
|
4738
|
-
},
|
|
4739
|
-
email: {
|
|
4740
|
-
title: 'Email',
|
|
4741
|
-
type: 'email',
|
|
4742
|
-
width: '40%',
|
|
4743
|
-
inputAttributes: {
|
|
4744
|
-
pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
|
|
4745
|
-
}
|
|
4746
|
-
},
|
|
4747
|
-
created: { title: 'Created', type: 'date', width: '30%' }
|
|
4748
|
-
},
|
|
4749
|
-
toolbarsearch: true,
|
|
4750
|
-
childTable: {
|
|
4751
|
-
title: 'Child Records',
|
|
4752
|
-
actions: {
|
|
4753
|
-
listAction: '/api/users/{id}/orders', // {id} will be replaced with parent record id
|
|
4754
|
-
createAction: '/api/users/{id}/orders',
|
|
4755
|
-
updateAction: '/api/orders',
|
|
4756
|
-
deleteAction: '/api/orders'
|
|
4757
|
-
},
|
|
4758
|
-
fields: {
|
|
4759
|
-
orderId: { key: true, list: false },
|
|
4760
|
-
orderDate: { title: 'Date', type: 'date' },
|
|
4761
|
-
amount: { title: 'Amount', type: 'number' }
|
|
4762
|
-
}
|
|
4763
|
-
},
|
|
4764
|
-
childTableColumnsVisible: true,
|
|
4765
|
-
|
|
4766
|
-
});
|
|
4767
|
-
|
|
4768
|
-
// Or dynamic child table
|
|
4769
|
-
childTable: async function(parentRecord) {
|
|
4770
|
-
return {
|
|
4771
|
-
title: `Orders for ${parentRecord.name}`,
|
|
4772
|
-
actions: {
|
|
4773
|
-
listAction: `/api/users/${parentRecord.id}/orders`
|
|
4774
|
-
},
|
|
4775
|
-
fields: {
|
|
4776
|
-
// Dynamic fields based on parent
|
|
4777
|
-
}
|
|
4778
|
-
};
|
|
4779
|
-
}
|
|
4780
|
-
|
|
4781
|
-
// function for select options
|
|
4782
|
-
fields: {
|
|
4783
|
-
assignee: {
|
|
4784
|
-
title: 'Assigned To',
|
|
4785
|
-
type: 'select',
|
|
4786
|
-
options: async function(params) {
|
|
4787
|
-
// params contains dependsOnValue, dependsOnField, etc.
|
|
4788
|
-
const department = params.dependsOnValue;
|
|
4789
|
-
const response = await fetch(`/api/users?department=${department}`);
|
|
4790
|
-
return response.json();
|
|
4791
|
-
},
|
|
4792
|
-
dependsOn: 'department'
|
|
4793
|
-
}
|
|
4794
|
-
}
|
|
4795
|
-
|
|
4796
|
-
// child table:
|
|
4797
|
-
phoneNumbers: {
|
|
4798
|
-
title: 'Phones',
|
|
4799
|
-
display: (data) => {
|
|
4800
|
-
const img = document.createElement('img');
|
|
4801
|
-
img.className = 'child-opener-image';
|
|
4802
|
-
img.src = '/Content/images/Misc/phone.png';
|
|
4803
|
-
img.title = 'Edit phone numbers';
|
|
4804
|
-
img.style.cursor = 'pointer';
|
|
4805
|
-
|
|
4806
|
-
parentRow = img.closest('tr');
|
|
4807
|
-
img.addEventListener('click', () => {
|
|
4808
|
-
e.stopPropagation();
|
|
4809
|
-
if (parentRow.childRow) {
|
|
4810
|
-
myTable.closeChildTable(parentRow);
|
|
4811
|
-
} else {
|
|
4812
|
-
myTable.openChildTable( parentRow, {
|
|
4813
|
-
title: `${data.record.Name} - Phone numbers`,
|
|
4814
|
-
actions: {
|
|
4815
|
-
listAction: `/PagingPerson/PhoneList?PersonId=${data.record.PersonId}`,
|
|
4816
|
-
deleteAction: '/PagingPerson/DeletePhone',
|
|
4817
|
-
updateAction: '/PagingPerson/UpdatePhone',
|
|
4818
|
-
createAction: `/PagingPerson/CreatePhone?PersonId=${data.record.PersonId}`
|
|
4819
|
-
},
|
|
4820
|
-
fields: {
|
|
4821
|
-
PhoneId: { key: true },
|
|
4822
|
-
Number: { title: 'Number', type: 'text' },
|
|
4823
|
-
Type: { title: 'Type', options: { 0: 'Home', 1: 'Work', 2: 'Mobile' } }
|
|
4824
|
-
}
|
|
4825
|
-
}, (childTable) => {
|
|
4826
|
-
console.log('Child table created');
|
|
4827
|
-
};
|
|
4828
|
-
}
|
|
4829
|
-
});
|
|
4830
|
-
img.addEventListener('click', (e) => {
|
|
4831
|
-
e.stopPropagation();
|
|
4832
|
-
if (parentRow.childRow) {
|
|
4833
|
-
myTable.closeChildTable(parentRow);
|
|
4834
|
-
} else {
|
|
4835
|
-
myTable.openChildTable(parentRow, childOptions);
|
|
4836
|
-
}
|
|
4837
|
-
});
|
|
4838
|
-
|
|
4839
|
-
return img;
|
|
4840
|
-
}
|
|
4841
|
-
}
|
|
4842
|
-
|
|
4843
|
-
// Clear specific options cache
|
|
4844
|
-
table.clearOptionsCache('/api/countries');
|
|
4845
|
-
|
|
4846
|
-
table.load();
|
|
4847
|
-
*/
|
|
4848
|
-
|
|
4849
|
-
window.FTable = FTable;
|
|
4850
|
-
|
|
4851
4734
|
export default FTable;
|
package/ftable.js
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
5
5
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.FTable = factory());
|
|
6
6
|
}(this, (function () {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const FTABLE_DEFAULT_MESSAGES = {
|
|
7
|
+
const FTABLE_DEFAULT_MESSAGES = {
|
|
10
8
|
serverCommunicationError: 'An error occurred while communicating to the server.',
|
|
11
9
|
loadingMessage: 'Loading records...',
|
|
12
10
|
noDataAvailable: 'No data available!',
|
|
@@ -753,7 +751,9 @@ class FTableFormBuilder {
|
|
|
753
751
|
}
|
|
754
752
|
|
|
755
753
|
try {
|
|
756
|
-
const response =
|
|
754
|
+
const response = this.options.forcePost
|
|
755
|
+
? await FTableHttpClient.post(url)
|
|
756
|
+
: await FTableHttpClient.get(url);
|
|
757
757
|
const options = response.Options || response.options || response || [];
|
|
758
758
|
|
|
759
759
|
// Only cache if noCache is false
|
|
@@ -976,10 +976,10 @@ class FTableFormBuilder {
|
|
|
976
976
|
const visibleInput = FTableDOMHelper.create('input', {
|
|
977
977
|
className: field.inputClass || 'datepicker-input',
|
|
978
978
|
attributes: {
|
|
979
|
-
id: 'ftable-toolbarsearch-' + fieldName,
|
|
980
979
|
id: 'Edit-' + fieldName,
|
|
981
980
|
type: 'text',
|
|
982
981
|
'data-date': value,
|
|
982
|
+
placeholder: field.placeholder || '',
|
|
983
983
|
readOnly: true
|
|
984
984
|
}
|
|
985
985
|
});
|
|
@@ -1359,10 +1359,14 @@ class FTable extends FTableEventEmitter {
|
|
|
1359
1359
|
this.element = typeof element === 'string' ?
|
|
1360
1360
|
document.querySelector(element) : element;
|
|
1361
1361
|
|
|
1362
|
+
if (!this.element) {
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1362
1366
|
// Prevent double initialization
|
|
1363
|
-
if (element.ftableInstance) {
|
|
1367
|
+
if (this.element.ftableInstance) {
|
|
1364
1368
|
//console.warn('FTable is already initialized on this element. Using that.');
|
|
1365
|
-
return element.ftableInstance;
|
|
1369
|
+
return this.element.ftableInstance;
|
|
1366
1370
|
}
|
|
1367
1371
|
|
|
1368
1372
|
this.options = this.mergeOptions(options);
|
|
@@ -1399,6 +1403,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1399
1403
|
logLevel: FTableLogger.LOG_LEVELS.WARN,
|
|
1400
1404
|
actions: {},
|
|
1401
1405
|
fields: {},
|
|
1406
|
+
forcePost: true,
|
|
1402
1407
|
animationsEnabled: true,
|
|
1403
1408
|
loadingAnimationDelay: 1000,
|
|
1404
1409
|
defaultDateLocale: '',
|
|
@@ -1954,6 +1959,7 @@ class FTable extends FTableEventEmitter {
|
|
|
1954
1959
|
attributes: {
|
|
1955
1960
|
id: 'ftable-toolbarsearch-' + fieldName,
|
|
1956
1961
|
type: 'text',
|
|
1962
|
+
placeholder: field.placeholder || '',
|
|
1957
1963
|
readOnly: true
|
|
1958
1964
|
}
|
|
1959
1965
|
});
|
|
@@ -2524,13 +2530,15 @@ class FTable extends FTableEventEmitter {
|
|
|
2524
2530
|
// Create overlay to capture clicks outside menu
|
|
2525
2531
|
this.elements.columnSelectionOverlay = FTableDOMHelper.create('div', {
|
|
2526
2532
|
className: 'ftable-contextmenu-overlay',
|
|
2527
|
-
parent: this.elements.mainContainer
|
|
2533
|
+
//parent: this.elements.mainContainer
|
|
2534
|
+
parent: document.body
|
|
2528
2535
|
});
|
|
2529
2536
|
|
|
2530
2537
|
// Create the menu
|
|
2531
2538
|
this.elements.columnSelectionMenu = FTableDOMHelper.create('div', {
|
|
2532
2539
|
className: 'ftable-column-selection-container',
|
|
2533
|
-
parent: this.elements.columnSelectionOverlay
|
|
2540
|
+
//parent: this.elements.columnSelectionOverlay
|
|
2541
|
+
parent: document.body
|
|
2534
2542
|
});
|
|
2535
2543
|
|
|
2536
2544
|
// Populate menu with column options
|
|
@@ -2616,29 +2624,36 @@ class FTable extends FTableEventEmitter {
|
|
|
2616
2624
|
}
|
|
2617
2625
|
|
|
2618
2626
|
positionColumnSelectionMenu(e) {
|
|
2619
|
-
const
|
|
2620
|
-
const menuWidth = 200; // Approximate menu width
|
|
2621
|
-
const menuHeight = this.columnList.length * 30 + 20; // Approximate height
|
|
2627
|
+
const self = this;
|
|
2622
2628
|
|
|
2623
|
-
|
|
2624
|
-
let
|
|
2629
|
+
// Use clientX/clientY (relative to viewport)
|
|
2630
|
+
let left = e.clientX;
|
|
2631
|
+
let top = e.clientY;
|
|
2625
2632
|
|
|
2626
|
-
//
|
|
2627
|
-
|
|
2628
|
-
left = Math.max(0, containerRect.width - menuWidth);
|
|
2629
|
-
}
|
|
2633
|
+
// Define minimum width
|
|
2634
|
+
const minWidth = 100;
|
|
2630
2635
|
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
}
|
|
2636
|
+
// Position the menu
|
|
2637
|
+
self.elements.columnSelectionMenu.style.position = 'absolute';
|
|
2638
|
+
self.elements.columnSelectionMenu.style.left = `${left}px`;
|
|
2639
|
+
self.elements.columnSelectionMenu.style.top = `${top}px`;
|
|
2640
|
+
self.elements.columnSelectionMenu.style.minWidth = `${minWidth}px`;
|
|
2641
|
+
self.elements.columnSelectionMenu.style.boxSizing = 'border-box';
|
|
2642
|
+
|
|
2643
|
+
// Optional: Adjust if menu would overflow right edge
|
|
2644
|
+
const menuWidth = self.elements.columnSelectionMenu.offsetWidth;
|
|
2645
|
+
const windowWidth = window.innerWidth;
|
|
2634
2646
|
|
|
2635
|
-
|
|
2636
|
-
|
|
2647
|
+
if (left + menuWidth > windowWidth) {
|
|
2648
|
+
left = Math.max(10, windowWidth - menuWidth - 10); // 10px margin
|
|
2649
|
+
self.elements.columnSelectionMenu.style.left = `${left}px`;
|
|
2650
|
+
}
|
|
2637
2651
|
}
|
|
2638
2652
|
|
|
2639
2653
|
hideColumnSelectionMenu() {
|
|
2640
2654
|
if (this.elements.columnSelectionOverlay) {
|
|
2641
2655
|
this.elements.columnSelectionOverlay.remove();
|
|
2656
|
+
this.elements.columnSelectionMenu.remove();
|
|
2642
2657
|
this.elements.columnSelectionOverlay = null;
|
|
2643
2658
|
this.elements.columnSelectionMenu = null;
|
|
2644
2659
|
}
|
|
@@ -2881,7 +2896,9 @@ class FTable extends FTableEventEmitter {
|
|
|
2881
2896
|
if (typeof listAction === 'function') {
|
|
2882
2897
|
data = await listAction(params);
|
|
2883
2898
|
} else if (typeof listAction === 'string') {
|
|
2884
|
-
data =
|
|
2899
|
+
data = this.options.forcePost
|
|
2900
|
+
? await FTableHttpClient.post(listAction, params)
|
|
2901
|
+
: await FTableHttpClient.get(listAction, params);
|
|
2885
2902
|
} else {
|
|
2886
2903
|
throw new Error('No valid listAction provided');
|
|
2887
2904
|
}
|
|
@@ -4415,7 +4432,9 @@ class FTable extends FTableEventEmitter {
|
|
|
4415
4432
|
...params
|
|
4416
4433
|
};
|
|
4417
4434
|
|
|
4418
|
-
const response =
|
|
4435
|
+
const response = this.options.forcePost
|
|
4436
|
+
? await FTableHttpClient.post(url, fullParams)
|
|
4437
|
+
: await FTableHttpClient.get(url, fullParams);
|
|
4419
4438
|
|
|
4420
4439
|
if (!response || !response.Record) {
|
|
4421
4440
|
throw new Error('Invalid response or missing Record');
|
|
@@ -4717,141 +4736,5 @@ class FTable extends FTableEventEmitter {
|
|
|
4717
4736
|
}
|
|
4718
4737
|
}
|
|
4719
4738
|
|
|
4720
|
-
// Export for use
|
|
4721
|
-
//window.FTable = FTable;
|
|
4722
|
-
|
|
4723
|
-
// Usage example:
|
|
4724
|
-
/*
|
|
4725
|
-
const table = new FTable('#myTable', {
|
|
4726
|
-
title: 'My Data Table',
|
|
4727
|
-
paging: true,
|
|
4728
|
-
pageSize: 25,
|
|
4729
|
-
sorting: true,
|
|
4730
|
-
selecting: true,
|
|
4731
|
-
actions: {
|
|
4732
|
-
listAction: '/api/users',
|
|
4733
|
-
createAction: '/api/users',
|
|
4734
|
-
updateAction: '/api/users',
|
|
4735
|
-
deleteAction: '/api/users'
|
|
4736
|
-
},
|
|
4737
|
-
fields: {
|
|
4738
|
-
id: { key: true, list: false },
|
|
4739
|
-
name: {
|
|
4740
|
-
title: 'Name',
|
|
4741
|
-
type: 'text',
|
|
4742
|
-
inputAttributes: "maxlength=100 required"
|
|
4743
|
-
},
|
|
4744
|
-
email: {
|
|
4745
|
-
title: 'Email',
|
|
4746
|
-
type: 'email',
|
|
4747
|
-
width: '40%',
|
|
4748
|
-
inputAttributes: {
|
|
4749
|
-
pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$'
|
|
4750
|
-
}
|
|
4751
|
-
},
|
|
4752
|
-
created: { title: 'Created', type: 'date', width: '30%' }
|
|
4753
|
-
},
|
|
4754
|
-
toolbarsearch: true,
|
|
4755
|
-
childTable: {
|
|
4756
|
-
title: 'Child Records',
|
|
4757
|
-
actions: {
|
|
4758
|
-
listAction: '/api/users/{id}/orders', // {id} will be replaced with parent record id
|
|
4759
|
-
createAction: '/api/users/{id}/orders',
|
|
4760
|
-
updateAction: '/api/orders',
|
|
4761
|
-
deleteAction: '/api/orders'
|
|
4762
|
-
},
|
|
4763
|
-
fields: {
|
|
4764
|
-
orderId: { key: true, list: false },
|
|
4765
|
-
orderDate: { title: 'Date', type: 'date' },
|
|
4766
|
-
amount: { title: 'Amount', type: 'number' }
|
|
4767
|
-
}
|
|
4768
|
-
},
|
|
4769
|
-
childTableColumnsVisible: true,
|
|
4770
|
-
|
|
4771
|
-
});
|
|
4772
|
-
|
|
4773
|
-
// Or dynamic child table
|
|
4774
|
-
childTable: async function(parentRecord) {
|
|
4775
|
-
return {
|
|
4776
|
-
title: `Orders for ${parentRecord.name}`,
|
|
4777
|
-
actions: {
|
|
4778
|
-
listAction: `/api/users/${parentRecord.id}/orders`
|
|
4779
|
-
},
|
|
4780
|
-
fields: {
|
|
4781
|
-
// Dynamic fields based on parent
|
|
4782
|
-
}
|
|
4783
|
-
};
|
|
4784
|
-
}
|
|
4785
|
-
|
|
4786
|
-
// function for select options
|
|
4787
|
-
fields: {
|
|
4788
|
-
assignee: {
|
|
4789
|
-
title: 'Assigned To',
|
|
4790
|
-
type: 'select',
|
|
4791
|
-
options: async function(params) {
|
|
4792
|
-
// params contains dependsOnValue, dependsOnField, etc.
|
|
4793
|
-
const department = params.dependsOnValue;
|
|
4794
|
-
const response = await fetch(`/api/users?department=${department}`);
|
|
4795
|
-
return response.json();
|
|
4796
|
-
},
|
|
4797
|
-
dependsOn: 'department'
|
|
4798
|
-
}
|
|
4799
|
-
}
|
|
4800
|
-
|
|
4801
|
-
// child table:
|
|
4802
|
-
phoneNumbers: {
|
|
4803
|
-
title: 'Phones',
|
|
4804
|
-
display: (data) => {
|
|
4805
|
-
const img = document.createElement('img');
|
|
4806
|
-
img.className = 'child-opener-image';
|
|
4807
|
-
img.src = '/Content/images/Misc/phone.png';
|
|
4808
|
-
img.title = 'Edit phone numbers';
|
|
4809
|
-
img.style.cursor = 'pointer';
|
|
4810
|
-
|
|
4811
|
-
parentRow = img.closest('tr');
|
|
4812
|
-
img.addEventListener('click', () => {
|
|
4813
|
-
e.stopPropagation();
|
|
4814
|
-
if (parentRow.childRow) {
|
|
4815
|
-
myTable.closeChildTable(parentRow);
|
|
4816
|
-
} else {
|
|
4817
|
-
myTable.openChildTable( parentRow, {
|
|
4818
|
-
title: `${data.record.Name} - Phone numbers`,
|
|
4819
|
-
actions: {
|
|
4820
|
-
listAction: `/PagingPerson/PhoneList?PersonId=${data.record.PersonId}`,
|
|
4821
|
-
deleteAction: '/PagingPerson/DeletePhone',
|
|
4822
|
-
updateAction: '/PagingPerson/UpdatePhone',
|
|
4823
|
-
createAction: `/PagingPerson/CreatePhone?PersonId=${data.record.PersonId}`
|
|
4824
|
-
},
|
|
4825
|
-
fields: {
|
|
4826
|
-
PhoneId: { key: true },
|
|
4827
|
-
Number: { title: 'Number', type: 'text' },
|
|
4828
|
-
Type: { title: 'Type', options: { 0: 'Home', 1: 'Work', 2: 'Mobile' } }
|
|
4829
|
-
}
|
|
4830
|
-
}, (childTable) => {
|
|
4831
|
-
console.log('Child table created');
|
|
4832
|
-
};
|
|
4833
|
-
}
|
|
4834
|
-
});
|
|
4835
|
-
img.addEventListener('click', (e) => {
|
|
4836
|
-
e.stopPropagation();
|
|
4837
|
-
if (parentRow.childRow) {
|
|
4838
|
-
myTable.closeChildTable(parentRow);
|
|
4839
|
-
} else {
|
|
4840
|
-
myTable.openChildTable(parentRow, childOptions);
|
|
4841
|
-
}
|
|
4842
|
-
});
|
|
4843
|
-
|
|
4844
|
-
return img;
|
|
4845
|
-
}
|
|
4846
|
-
}
|
|
4847
|
-
|
|
4848
|
-
// Clear specific options cache
|
|
4849
|
-
table.clearOptionsCache('/api/countries');
|
|
4850
|
-
|
|
4851
|
-
table.load();
|
|
4852
|
-
*/
|
|
4853
|
-
|
|
4854
|
-
window.FTable = FTable;
|
|
4855
|
-
|
|
4856
4739
|
return FTable;
|
|
4857
4740
|
})));
|