@liedekef/ftable 1.1.7 → 1.1.9

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.
Files changed (38) hide show
  1. package/ftable.esm.js +41 -42
  2. package/ftable.js +41 -42
  3. package/ftable.min.js +2 -2
  4. package/ftable.umd.js +41 -42
  5. package/package.json +1 -1
  6. package/themes/basic/ftable_basic.css +10 -0
  7. package/themes/basic/ftable_basic.min.css +1 -1
  8. package/themes/ftable_theme_base.less +14 -0
  9. package/themes/lightcolor/blue/ftable.css +10 -0
  10. package/themes/lightcolor/blue/ftable.min.css +1 -1
  11. package/themes/lightcolor/gray/ftable.css +10 -0
  12. package/themes/lightcolor/gray/ftable.min.css +1 -1
  13. package/themes/lightcolor/green/ftable.css +10 -0
  14. package/themes/lightcolor/green/ftable.min.css +1 -1
  15. package/themes/lightcolor/orange/ftable.css +10 -0
  16. package/themes/lightcolor/orange/ftable.min.css +1 -1
  17. package/themes/lightcolor/red/ftable.css +10 -0
  18. package/themes/lightcolor/red/ftable.min.css +1 -1
  19. package/themes/metro/blue/ftable.css +10 -0
  20. package/themes/metro/blue/ftable.min.css +1 -1
  21. package/themes/metro/brown/ftable.css +10 -0
  22. package/themes/metro/brown/ftable.min.css +1 -1
  23. package/themes/metro/crimson/ftable.css +10 -0
  24. package/themes/metro/crimson/ftable.min.css +1 -1
  25. package/themes/metro/darkgray/ftable.css +10 -0
  26. package/themes/metro/darkgray/ftable.min.css +1 -1
  27. package/themes/metro/darkorange/ftable.css +10 -0
  28. package/themes/metro/darkorange/ftable.min.css +1 -1
  29. package/themes/metro/green/ftable.css +10 -0
  30. package/themes/metro/green/ftable.min.css +1 -1
  31. package/themes/metro/lightgray/ftable.css +10 -0
  32. package/themes/metro/lightgray/ftable.min.css +1 -1
  33. package/themes/metro/pink/ftable.css +10 -0
  34. package/themes/metro/pink/ftable.min.css +1 -1
  35. package/themes/metro/purple/ftable.css +10 -0
  36. package/themes/metro/purple/ftable.min.css +1 -1
  37. package/themes/metro/red/ftable.css +10 -0
  38. package/themes/metro/red/ftable.min.css +1 -1
package/ftable.esm.js CHANGED
@@ -272,11 +272,15 @@ class FTableHttpClient {
272
272
  }
273
273
 
274
274
  if (Array.isArray(value)) {
275
+ // Clean key: remove trailing [] if present
276
+ const cleanKey = key.replace(/\[\]$/, '');
277
+ const paramKey = cleanKey + '[]'; // Always use [] suffix once
278
+
275
279
  // Append each item in the array with the same key
276
280
  // This generates query strings like `key=val1&key=val2&key=val3`
277
281
  value.forEach(item => {
278
282
  if (item !== null && item !== undefined) { // Ensure array items are also not null/undefined
279
- fullUrl.searchParams.append(key, item);
283
+ fullUrl.searchParams.append(paramKey, item);
280
284
  }
281
285
  });
282
286
  } else {
@@ -302,11 +306,15 @@ class FTableHttpClient {
302
306
  return; // Skip null or undefined values
303
307
  }
304
308
  if (Array.isArray(value)) {
309
+ // Clean key: remove trailing [] if present
310
+ const cleanKey = key.replace(/\[\]$/, '');
311
+ const paramKey = cleanKey + '[]'; // Always use [] suffix once
312
+
305
313
  // Append each item in the array with the same key
306
314
  // This generates query strings like `key=val1&key=val2&key=val3`
307
315
  value.forEach(item => {
308
316
  if (item !== null && item !== undefined) { // Ensure array items are also not null/undefined
309
- formData.append(`${key}[]`, item);
317
+ formData.append(paramKey, item);
310
318
  }
311
319
  });
312
320
  } else {
@@ -1218,64 +1226,55 @@ class FTableFormBuilder {
1218
1226
  }
1219
1227
 
1220
1228
  createCheckbox(fieldName, field, value) {
1221
- function getCheckboxText(field, value) {
1222
- if (value == undefined ) {
1223
- value = 0;
1224
- }
1225
- if (field.values && field.values[value] !== undefined) {
1226
- return field.values[value];
1227
- }
1228
- return value ? 'Yes' : 'No';
1229
- }
1230
1229
  const wrapper = FTableDOMHelper.create('div', {
1231
- className: 'ftable-checkbox-wrapper'
1230
+ className: 'ftable-yesno-check-wrapper'
1232
1231
  });
1233
1232
 
1234
1233
  const isChecked = [1, '1', true, 'true'].includes(value);
1235
1234
 
1236
- const displayValue = getCheckboxText(field, value); // Uses field.values if defined
1235
+ // Determine "Yes" and "No" labels
1236
+ let dataNo = 'No';
1237
+ let dataYes = 'Yes';
1237
1238
 
1239
+ if (field.values && typeof field.values === 'object') {
1240
+ if (field.values['0'] !== undefined) dataNo = field.values['0'];
1241
+ if (field.values['1'] !== undefined) dataYes = field.values['1'];
1242
+ }
1243
+
1244
+ // Create the checkbox
1238
1245
  const checkbox = FTableDOMHelper.create('input', {
1246
+ className: ['ftable-yesno-check-input', field.inputClass || ''].filter(Boolean).join(' '),
1239
1247
  attributes: {
1240
1248
  type: 'checkbox',
1241
1249
  name: fieldName,
1242
1250
  id: `Edit-${fieldName}`,
1243
- class: field.inputClass || '',
1244
1251
  value: '1'
1245
1252
  },
1253
+ properties: {
1254
+ checked: isChecked
1255
+ },
1246
1256
  parent: wrapper
1247
1257
  });
1248
- checkbox.checked = isChecked;
1249
1258
 
1259
+ // Create the label with data attributes
1250
1260
  const label = FTableDOMHelper.create('label', {
1251
- attributes: { for: `Edit-${fieldName}` },
1261
+ className: 'ftable-yesno-check-text',
1262
+ attributes: {
1263
+ for: `Edit-${fieldName}`,
1264
+ 'data-yes': dataYes,
1265
+ 'data-no': dataNo
1266
+ },
1252
1267
  parent: wrapper
1253
1268
  });
1254
1269
 
1255
- // Add the static formText (e.g., "Is Active?")
1270
+ // Optional: Add a static form label (e.g., "Is Active?")
1256
1271
  if (field.formText) {
1257
- FTableDOMHelper.create('span', {
1272
+ const formSpan = FTableDOMHelper.create('span', {
1258
1273
  text: field.formText,
1259
- parent: label
1260
- });
1261
- }
1262
-
1263
- // Only add dynamic value span if field.values is defined
1264
- if (field.values) {
1265
- const valueSpan = FTableDOMHelper.create('span', {
1266
- className: 'ftable-checkbox-dynamic-value',
1267
- text: ` ${displayValue}`,
1268
- parent: label
1269
- });
1270
-
1271
- // Update on change
1272
- checkbox.addEventListener('change', () => {
1273
- const newValue = checkbox.checked ? '1' : '0';
1274
- const newText = getCheckboxText(field, newValue);
1275
- valueSpan.textContent = ` ${newText}`;
1274
+ parent: wrapper
1276
1275
  });
1276
+ formSpan.style.marginLeft = '8px';
1277
1277
  }
1278
-
1279
1278
  return wrapper;
1280
1279
  }
1281
1280
 
@@ -1681,7 +1680,7 @@ class FTable extends FTableEventEmitter {
1681
1680
  // Build column list (visible, listable, non-hidden) fields
1682
1681
  this.columnList = this.fieldList.filter(name => {
1683
1682
  const field = this.options.fields[name];
1684
- return field.list !== false && field.type !== 'hidden';
1683
+ return field.list !== false;
1685
1684
  });
1686
1685
 
1687
1686
  // Find key field
@@ -2621,9 +2620,9 @@ class FTable extends FTableEventEmitter {
2621
2620
  positionColumnSelectionMenu(e) {
2622
2621
  const self = this;
2623
2622
 
2624
- // Use clientX/clientY (relative to viewport)
2625
- let left = e.clientX;
2626
- let top = e.clientY;
2623
+ // menu is bounded to the body for absolute positioning above other content, so safest is to use pageX/Y
2624
+ let left = e.pageX;
2625
+ let top = e.pageY;
2627
2626
 
2628
2627
  // Define minimum width
2629
2628
  const minWidth = 100;
@@ -2855,8 +2854,8 @@ class FTable extends FTableEventEmitter {
2855
2854
  });
2856
2855
 
2857
2856
  if (queries.length > 0) {
2858
- params['q[]'] = queries;
2859
- params['opt[]'] = searchFields;
2857
+ params['q'] = queries;
2858
+ params['opt'] = searchFields;
2860
2859
  }
2861
2860
  }
2862
2861
 
package/ftable.js CHANGED
@@ -277,11 +277,15 @@ class FTableHttpClient {
277
277
  }
278
278
 
279
279
  if (Array.isArray(value)) {
280
+ // Clean key: remove trailing [] if present
281
+ const cleanKey = key.replace(/\[\]$/, '');
282
+ const paramKey = cleanKey + '[]'; // Always use [] suffix once
283
+
280
284
  // Append each item in the array with the same key
281
285
  // This generates query strings like `key=val1&key=val2&key=val3`
282
286
  value.forEach(item => {
283
287
  if (item !== null && item !== undefined) { // Ensure array items are also not null/undefined
284
- fullUrl.searchParams.append(key, item);
288
+ fullUrl.searchParams.append(paramKey, item);
285
289
  }
286
290
  });
287
291
  } else {
@@ -307,11 +311,15 @@ class FTableHttpClient {
307
311
  return; // Skip null or undefined values
308
312
  }
309
313
  if (Array.isArray(value)) {
314
+ // Clean key: remove trailing [] if present
315
+ const cleanKey = key.replace(/\[\]$/, '');
316
+ const paramKey = cleanKey + '[]'; // Always use [] suffix once
317
+
310
318
  // Append each item in the array with the same key
311
319
  // This generates query strings like `key=val1&key=val2&key=val3`
312
320
  value.forEach(item => {
313
321
  if (item !== null && item !== undefined) { // Ensure array items are also not null/undefined
314
- formData.append(`${key}[]`, item);
322
+ formData.append(paramKey, item);
315
323
  }
316
324
  });
317
325
  } else {
@@ -1223,64 +1231,55 @@ class FTableFormBuilder {
1223
1231
  }
1224
1232
 
1225
1233
  createCheckbox(fieldName, field, value) {
1226
- function getCheckboxText(field, value) {
1227
- if (value == undefined ) {
1228
- value = 0;
1229
- }
1230
- if (field.values && field.values[value] !== undefined) {
1231
- return field.values[value];
1232
- }
1233
- return value ? 'Yes' : 'No';
1234
- }
1235
1234
  const wrapper = FTableDOMHelper.create('div', {
1236
- className: 'ftable-checkbox-wrapper'
1235
+ className: 'ftable-yesno-check-wrapper'
1237
1236
  });
1238
1237
 
1239
1238
  const isChecked = [1, '1', true, 'true'].includes(value);
1240
1239
 
1241
- const displayValue = getCheckboxText(field, value); // Uses field.values if defined
1240
+ // Determine "Yes" and "No" labels
1241
+ let dataNo = 'No';
1242
+ let dataYes = 'Yes';
1242
1243
 
1244
+ if (field.values && typeof field.values === 'object') {
1245
+ if (field.values['0'] !== undefined) dataNo = field.values['0'];
1246
+ if (field.values['1'] !== undefined) dataYes = field.values['1'];
1247
+ }
1248
+
1249
+ // Create the checkbox
1243
1250
  const checkbox = FTableDOMHelper.create('input', {
1251
+ className: ['ftable-yesno-check-input', field.inputClass || ''].filter(Boolean).join(' '),
1244
1252
  attributes: {
1245
1253
  type: 'checkbox',
1246
1254
  name: fieldName,
1247
1255
  id: `Edit-${fieldName}`,
1248
- class: field.inputClass || '',
1249
1256
  value: '1'
1250
1257
  },
1258
+ properties: {
1259
+ checked: isChecked
1260
+ },
1251
1261
  parent: wrapper
1252
1262
  });
1253
- checkbox.checked = isChecked;
1254
1263
 
1264
+ // Create the label with data attributes
1255
1265
  const label = FTableDOMHelper.create('label', {
1256
- attributes: { for: `Edit-${fieldName}` },
1266
+ className: 'ftable-yesno-check-text',
1267
+ attributes: {
1268
+ for: `Edit-${fieldName}`,
1269
+ 'data-yes': dataYes,
1270
+ 'data-no': dataNo
1271
+ },
1257
1272
  parent: wrapper
1258
1273
  });
1259
1274
 
1260
- // Add the static formText (e.g., "Is Active?")
1275
+ // Optional: Add a static form label (e.g., "Is Active?")
1261
1276
  if (field.formText) {
1262
- FTableDOMHelper.create('span', {
1277
+ const formSpan = FTableDOMHelper.create('span', {
1263
1278
  text: field.formText,
1264
- parent: label
1265
- });
1266
- }
1267
-
1268
- // Only add dynamic value span if field.values is defined
1269
- if (field.values) {
1270
- const valueSpan = FTableDOMHelper.create('span', {
1271
- className: 'ftable-checkbox-dynamic-value',
1272
- text: ` ${displayValue}`,
1273
- parent: label
1274
- });
1275
-
1276
- // Update on change
1277
- checkbox.addEventListener('change', () => {
1278
- const newValue = checkbox.checked ? '1' : '0';
1279
- const newText = getCheckboxText(field, newValue);
1280
- valueSpan.textContent = ` ${newText}`;
1279
+ parent: wrapper
1281
1280
  });
1281
+ formSpan.style.marginLeft = '8px';
1282
1282
  }
1283
-
1284
1283
  return wrapper;
1285
1284
  }
1286
1285
 
@@ -1686,7 +1685,7 @@ class FTable extends FTableEventEmitter {
1686
1685
  // Build column list (visible, listable, non-hidden) fields
1687
1686
  this.columnList = this.fieldList.filter(name => {
1688
1687
  const field = this.options.fields[name];
1689
- return field.list !== false && field.type !== 'hidden';
1688
+ return field.list !== false;
1690
1689
  });
1691
1690
 
1692
1691
  // Find key field
@@ -2626,9 +2625,9 @@ class FTable extends FTableEventEmitter {
2626
2625
  positionColumnSelectionMenu(e) {
2627
2626
  const self = this;
2628
2627
 
2629
- // Use clientX/clientY (relative to viewport)
2630
- let left = e.clientX;
2631
- let top = e.clientY;
2628
+ // menu is bounded to the body for absolute positioning above other content, so safest is to use pageX/Y
2629
+ let left = e.pageX;
2630
+ let top = e.pageY;
2632
2631
 
2633
2632
  // Define minimum width
2634
2633
  const minWidth = 100;
@@ -2860,8 +2859,8 @@ class FTable extends FTableEventEmitter {
2860
2859
  });
2861
2860
 
2862
2861
  if (queries.length > 0) {
2863
- params['q[]'] = queries;
2864
- params['opt[]'] = searchFields;
2862
+ params['q'] = queries;
2863
+ params['opt'] = searchFields;
2865
2864
  }
2866
2865
  }
2867
2866