From 9d5255c7c0db2350e090ac3a66df6354f9383997 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Mon, 22 Sep 2025 09:00:17 +0200
Subject: [PATCH 1/7] [Advanced Logbook] Enabled csv button + tweak datatable
---
assets/js/sections/logbookadvanced.js | 204 +++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 1 deletion(-)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index a70279d88..549d647c1 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -174,6 +174,205 @@ function updateRow(qso) {
function loadQSOTable(rows) {
const $table = $('#qsoList');
+ if (!$table.length) return;
+
+ // Safety destroy if an old instance exists
+ if ($.fn.dataTable && $.fn.dataTable.isDataTable($table)) {
+ try {
+ const old = $table.DataTable();
+ if (typeof old.scroller === 'function') {
+ try { old.scroller().destroy(); } catch (e) {}
+ }
+ try { old.off(); old.clear(); old.destroy(); } catch (e) {}
+ } catch (e) {}
+ $table.find('tbody').empty();
+ $table.removeClass('dataTable'); // remove leftover class
+ }
+
+ const langUrl = getDataTablesLanguageUrl();
+
+ const initTable = function(language) {
+ // make sure moment plugin (if used) is set
+ if ($.fn.dataTable && $.fn.dataTable.moment) {
+ $.fn.dataTable.moment(custom_date_format + ' HH:mm');
+ }
+
+ // Build the full data array (array-of-arrays). Keep metadata properties on the array.
+ const allData = [];
+ for (let i = 0; i < rows.length; i++) {
+ const qso = rows[i];
+ const data = [];
+
+ data.push('
');
+
+ if ((user_options.datetime.show ?? 'true') == "true") {
+ data.push(qso.datetime === '' ? 'Missing date' : qso.qsoDateTime);
+ }
+ if ((user_options.de.show ?? 'true') == "true") {
+ data.push(qso.de.replaceAll('0', 'Ø'));
+ }
+ if ((user_options.dx.show ?? 'true') == "true") {
+ if (qso.dx === '') {
+ data.push('Missing callsign');
+ } else {
+ let dxHtml = '' + qso.dx.replaceAll('0', 'Ø') + '';
+ if (qso.callsign != '') {
+ dxHtml += ' L';
+ }
+ dxHtml += '
' +
+ '
' +
+ '
' +
+ '';
+ data.push(dxHtml);
+ }
+ }
+
+ // The rest of the user_options fields (kept exactly like your original)
+ if ((user_options.mode.show ?? 'true') == "true") data.push(qso.mode === '' ? 'Missing mode' : qso.mode);
+ if ((user_options.rsts.show ?? 'true') == "true") data.push(qso.rstS);
+ if ((user_options.rstr.show ?? 'true') == "true") data.push(qso.rstR);
+ if ((user_options.band.show ?? 'true') == "true") data.push(qso.band === '' ? 'Missing band' : qso.band);
+ if ((user_options.frequency.show ?? 'true') == "true") data.push(qso.frequency);
+ if ((user_options.gridsquare.show ?? 'true') == "true") data.push(qso.gridsquare);
+ if ((user_options.name.show ?? 'true') == "true") data.push(qso.name);
+ if ((user_options.qth.show ?? 'true') == "true") data.push(qso.qth);
+ if ((user_options.qslvia.show ?? 'true') == "true") data.push(qso.qslVia);
+ if ((user_options.clublog.show ?? 'true') == "true") data.push(qso.clublog);
+ if ((user_options.qsl.show ?? 'true') == "true") data.push(qso.qsl);
+ if ($(".eqslconfirmation")[0] && (user_options.eqsl.show ?? 'true') == "true") data.push(qso.eqsl);
+ if ($(".lotwconfirmation")[0] && (user_options.lotw.show ?? 'true') == "true") data.push(qso.lotw);
+ if ((user_options.qrz.show ?? 'true') == "true") data.push(qso.qrz);
+ if ((user_options.dcl.show ?? 'true') == "true") data.push(qso.dcl);
+ if ((user_options.qslmsgs.show ?? 'true') == "true") data.push(qso.qslMessage);
+ if ((user_options.qslmsgr.show ?? 'true') == "true") data.push(qso.qslMessageR);
+ if ((user_options.dxcc.show ?? 'true') == "true") data.push(qso.dxcc + qso.flag + (qso.end == null ? '' : ' Deleted DXCC'));
+ if ((user_options.state.show ?? 'true') == "true") data.push(qso.state);
+ if ((user_options.county.show ?? 'true') == "true") data.push(qso.county);
+ if ((user_options.cqzone.show ?? 'true') == "true") data.push(qso.cqzone);
+ if ((user_options.ituzone.show ?? 'true') == "true") data.push(qso.ituzone);
+ if ((user_options.iota.show ?? 'true') == "true") data.push(qso.iota);
+ if ((user_options.pota.show ?? 'true') == "true") data.push(qso.pota);
+ if ((user_options.sota.show ?? 'true') == "true") data.push(qso.sota);
+ if ((user_options.dok.show ?? 'true') == "true") data.push(qso.dok);
+ if ((user_options.wwff.show ?? 'true') == "true") data.push(qso.wwff);
+ if ((user_options.sig.show ?? 'true') == "true") data.push(qso.sig);
+ if ((user_options.region.show ?? 'true') == "true") data.push(qso.region);
+ if ((user_options.operator.show ?? 'true') == "true") data.push(qso.operator);
+ if ((user_options.comment.show ?? 'true') == "true") data.push(qso.comment);
+ if ((user_options.propagation.show ?? 'true') == "true") data.push(qso.propagation);
+ if ((user_options.contest.show ?? 'true') == "true") data.push(qso.contest);
+ if ((user_options.myrefs.show ?? 'true') == "true") data.push(qso.deRefs);
+ if ((user_options.continent.show ?? 'true') == "true") data.push(qso.continent);
+ if ((user_options.distance.show ?? 'true') == "true") data.push(qso.distance);
+ if ((user_options.antennaazimuth.show ?? 'true') == "true") data.push(qso.antennaazimuth);
+ if ((user_options.antennaelevation.show ?? 'true') == "true") data.push(qso.antennaelevation);
+ if ((user_options.profilename.show ?? 'true') == "true") data.push(qso.profilename);
+ if ((user_options.stationpower.show ?? 'true') == "true") data.push(qso.stationpower);
+
+ // metadata accessible inside createdRow
+ data.id = 'qsoID-' + qso.qsoID;
+ data._qsoID = qso.qsoID;
+
+ allData.push(data);
+ }
+
+ // cache header index lookups (avoid repeated DOM queries)
+ const distanceIdx = $(".distance-column-sort").index();
+ const azIdx = $(".antennaazimuth-column-sort").index();
+ const elIdx = $(".antennaelevation-column-sort").index();
+ const powerIdx = $(".stationpower-column-sort").index();
+
+ // DataTables init (data provided up-front)
+ const table = $table.DataTable({
+ data: allData,
+ deferRender: true,
+ scrollY: window.innerHeight - $('#searchForm').innerHeight() - 250,
+ scrollCollapse: true,
+ paging: true, // required for Scroller
+ scroller: true,
+ displayStart: 0,
+ language: language,
+ ordering: true,
+ orderClasses: false,
+ responsive: false,
+ createdRow: function(row, data) {
+ if (data && data.id) $(row).attr('id', data.id);
+ if (data && data._qsoID) $(row).data('qsoID', data._qsoID);
+ },
+ // robust info text so "259 to 250" can't appear
+ infoCallback: function(settings) {
+ const api = new $.fn.dataTable.Api(settings);
+ const info = api.page.info();
+ if (info.recordsDisplay === 0) return 'Showing 0 to 0 of 0 entries';
+ const dispStart = info.start + 1;
+ const dispEnd = Math.min(info.recordsDisplay, info.start + info.length);
+ return 'Showing ' + dispStart + ' to ' + dispEnd + ' of ' + info.recordsDisplay + ' entries';
+ },
+ columnDefs: [
+ { orderable: false, targets: 0 },
+ { targets: distanceIdx, type: "numbersort" },
+ { targets: azIdx, type: "numbersort" },
+ { targets: elIdx, type: "numbersort" },
+ { targets: powerIdx, type: "numbersort" },
+ ],
+ dom: 'Bfrtip',
+ buttons: [
+ {
+ extend: 'csv',
+ className: 'mb-1 btn btn-sm btn-primary', // Bootstrap classes
+ init: function(api, node, config) {
+ $(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
+ },
+ }
+ ]
+ });
+
+ // Ensure scroller measured and page reset
+ try { if (table.scroller) table.scroller().measure(); } catch (e) {}
+ try { table.page('first').draw(false); } catch (e) { table.draw(false); }
+
+ // Delegate tooltip creation (create on demand)
+ $table.off('mouseenter', '[data-bs-toggle="tooltip"]').on('mouseenter', '[data-bs-toggle="tooltip"]', function () {
+ if (!$(this).data('bs.tooltip')) {
+ $(this).tooltip();
+ }
+ });
+
+ // Delegate checkbox handling (shift-click selection) — no per-row listeners
+ let lastChecked = null;
+ $table.off('click', '.row-check').on('click', '.row-check', function (e) {
+ const checkboxes = $table.find('.row-check').toArray();
+ if (e.shiftKey && lastChecked) {
+ let start = checkboxes.indexOf(this);
+ let end = checkboxes.indexOf(lastChecked);
+ [start, end] = [Math.min(start, end), Math.max(start, end)];
+ for (let i = start; i <= end; i++) {
+ checkboxes[i].checked = lastChecked.checked;
+ $(checkboxes[i]).closest('tr').toggleClass('activeRow', lastChecked.checked);
+ }
+ } else {
+ $(this).closest('tr').toggleClass('activeRow', this.checked);
+ }
+ lastChecked = this;
+ });
+
+ // rebind other UI bits after table init (if function exists)
+ if (typeof rebind_checkbox_trigger === 'function') rebind_checkbox_trigger();
+ };
+
+ // load language then init
+ if (langUrl) {
+ $.getJSON(langUrl)
+ .done(function(language) { initTable(language); })
+ .fail(function() { console.error("Failed to load DataTables language file at " + langUrl); initTable({}); });
+ } else {
+ initTable({});
+ }
+}
+
+
+function loadQSOTable2(rows) {
+ const $table = $('#qsoList');
// Prevent initializing if already a DataTable
if ($.fn.DataTable.isDataTable($table)) {
@@ -191,8 +390,11 @@ function loadQSOTable(rows) {
ordering: true,
scrollY: window.innerHeight - $('#searchForm').innerHeight() - 250,
scrollCollapse: true,
- paging: false,
language: language,
+ deferRender: true, // delay DOM creation until needed
+ ordering: true,
+ paging: true,
+ scroller: true,
createdRow: function (row, data, dataIndex) {
$(row).attr('id', data.id);
},
From 3e9ef5d684032c506c323fba25cdf41d7e557635 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Mon, 22 Sep 2025 12:37:30 +0200
Subject: [PATCH 2/7] Replace slashed zero, remove LoTW L and trim whitespace
in callsign
---
assets/js/sections/logbookadvanced.js | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 549d647c1..3225c0173 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -323,6 +323,26 @@ function loadQSOTable(rows) {
init: function(api, node, config) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
+ exportOptions: {
+ columns: ':visible',
+ format: {
+ body: function (data, row, column, node) {
+ // strip HTML tags first (like DataTables does by default)
+ if (typeof data === 'string') {
+ data = data.replace(/<[^>]*>/g, '');
+ }
+ // then replace Ø with 0 in specific columns
+ if (column === 1 || column === 2 || column === 3) {
+ // remove a trailing "L" and trim whitespaces
+ data = data.replace(/\s*L\s*$/, '').trim();
+ if (typeof data === 'string' && data.includes('Ø')) {
+ data = data.replace(/Ø/g, '0');
+ }
+ }
+ return data;
+ }
+ }
+ }
}
]
});
From 2c839bb621ef8ca22ca9f9df02dfdb90d5f8a59c Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Mon, 22 Sep 2025 12:42:14 +0200
Subject: [PATCH 3/7] Remove checkbox in csv export
---
assets/js/sections/logbookadvanced.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 3225c0173..30c5ebdb3 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -324,7 +324,7 @@ function loadQSOTable(rows) {
$(node).removeClass('dt-button').addClass('btn btn-primary'); // Ensure Bootstrap class applies
},
exportOptions: {
- columns: ':visible',
+ columns: ':visible:not(:eq(0))', // export all visible except column 4
format: {
body: function (data, row, column, node) {
// strip HTML tags first (like DataTables does by default)
From 5c9a58d6171fe8cff0e8b6c0977270730a901ba5 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Mon, 22 Sep 2025 12:50:18 +0200
Subject: [PATCH 4/7] Replace arrows
---
assets/js/sections/logbookadvanced.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 30c5ebdb3..0149f03fc 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -339,6 +339,12 @@ function loadQSOTable(rows) {
data = data.replace(/Ø/g, '0');
}
}
+ if (typeof data === 'string' && data.includes('▲')) {
+ data = data.replace(/▲/g, '');
+ }
+ if (typeof data === 'string' && data.includes('▼')) {
+ data = data.replace(/▼/g, '');
+ }
return data;
}
}
From 83616c3722df6e9d2bd74a5870938a7fdf0980f2 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Mon, 22 Sep 2025 13:08:19 +0200
Subject: [PATCH 5/7] Get rid of tooltip
---
assets/js/sections/logbookadvanced.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 0149f03fc..25397e8ec 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -340,11 +340,13 @@ function loadQSOTable(rows) {
}
}
if (typeof data === 'string' && data.includes('▲')) {
- data = data.replace(/▲/g, '');
+ data = data.replace(/▲/g, '');
}
if (typeof data === 'string' && data.includes('▼')) {
- data = data.replace(/▼/g, '');
+ data = data.replace(/▼/g, '');
}
+
+ data = data.replace(/ data-bs-toggle="tooltip" data-bs-html="true" class="[^"]*">/g, '');
return data;
}
}
From af86ffc58a3408c1f89e90dcc65d3d3dd0d9192a Mon Sep 17 00:00:00 2001
From: phl0
Date: Mon, 22 Sep 2025 15:20:15 +0200
Subject: [PATCH 6/7] Remove extra br inside HTML
---
assets/js/sections/logbookadvanced.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 25397e8ec..7df8f2eaf 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -328,6 +328,9 @@ function loadQSOTable(rows) {
format: {
body: function (data, row, column, node) {
// strip HTML tags first (like DataTables does by default)
+ if (typeof data === 'string' && data.includes('
')) {
+ data = data.replace(/
/g, '');
+ }
if (typeof data === 'string') {
data = data.replace(/<[^>]*>/g, '');
}
From aca174394691ae4433f88584efe22b8e759c8602 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Tue, 23 Sep 2025 10:40:31 +0200
Subject: [PATCH 7/7] Removed tweaking, not happy with it
---
assets/js/sections/logbookadvanced.js | 219 ++------------------------
1 file changed, 14 insertions(+), 205 deletions(-)
diff --git a/assets/js/sections/logbookadvanced.js b/assets/js/sections/logbookadvanced.js
index 7df8f2eaf..d9c81742e 100644
--- a/assets/js/sections/logbookadvanced.js
+++ b/assets/js/sections/logbookadvanced.js
@@ -174,146 +174,35 @@ function updateRow(qso) {
function loadQSOTable(rows) {
const $table = $('#qsoList');
- if (!$table.length) return;
- // Safety destroy if an old instance exists
- if ($.fn.dataTable && $.fn.dataTable.isDataTable($table)) {
- try {
- const old = $table.DataTable();
- if (typeof old.scroller === 'function') {
- try { old.scroller().destroy(); } catch (e) {}
- }
- try { old.off(); old.clear(); old.destroy(); } catch (e) {}
- } catch (e) {}
- $table.find('tbody').empty();
- $table.removeClass('dataTable'); // remove leftover class
+ // Prevent initializing if already a DataTable
+ if ($.fn.DataTable.isDataTable($table)) {
+ $table.DataTable().clear().destroy();
}
const langUrl = getDataTablesLanguageUrl();
const initTable = function(language) {
- // make sure moment plugin (if used) is set
- if ($.fn.dataTable && $.fn.dataTable.moment) {
- $.fn.dataTable.moment(custom_date_format + ' HH:mm');
- }
+ $.fn.dataTable.moment(custom_date_format + ' HH:mm');
- // Build the full data array (array-of-arrays). Keep metadata properties on the array.
- const allData = [];
- for (let i = 0; i < rows.length; i++) {
- const qso = rows[i];
- const data = [];
-
- data.push('');
-
- if ((user_options.datetime.show ?? 'true') == "true") {
- data.push(qso.datetime === '' ? 'Missing date' : qso.qsoDateTime);
- }
- if ((user_options.de.show ?? 'true') == "true") {
- data.push(qso.de.replaceAll('0', 'Ø'));
- }
- if ((user_options.dx.show ?? 'true') == "true") {
- if (qso.dx === '') {
- data.push('Missing callsign');
- } else {
- let dxHtml = '' + qso.dx.replaceAll('0', 'Ø') + '';
- if (qso.callsign != '') {
- dxHtml += ' L';
- }
- dxHtml += '
' +
- '
' +
- '
' +
- '';
- data.push(dxHtml);
- }
- }
-
- // The rest of the user_options fields (kept exactly like your original)
- if ((user_options.mode.show ?? 'true') == "true") data.push(qso.mode === '' ? 'Missing mode' : qso.mode);
- if ((user_options.rsts.show ?? 'true') == "true") data.push(qso.rstS);
- if ((user_options.rstr.show ?? 'true') == "true") data.push(qso.rstR);
- if ((user_options.band.show ?? 'true') == "true") data.push(qso.band === '' ? 'Missing band' : qso.band);
- if ((user_options.frequency.show ?? 'true') == "true") data.push(qso.frequency);
- if ((user_options.gridsquare.show ?? 'true') == "true") data.push(qso.gridsquare);
- if ((user_options.name.show ?? 'true') == "true") data.push(qso.name);
- if ((user_options.qth.show ?? 'true') == "true") data.push(qso.qth);
- if ((user_options.qslvia.show ?? 'true') == "true") data.push(qso.qslVia);
- if ((user_options.clublog.show ?? 'true') == "true") data.push(qso.clublog);
- if ((user_options.qsl.show ?? 'true') == "true") data.push(qso.qsl);
- if ($(".eqslconfirmation")[0] && (user_options.eqsl.show ?? 'true') == "true") data.push(qso.eqsl);
- if ($(".lotwconfirmation")[0] && (user_options.lotw.show ?? 'true') == "true") data.push(qso.lotw);
- if ((user_options.qrz.show ?? 'true') == "true") data.push(qso.qrz);
- if ((user_options.dcl.show ?? 'true') == "true") data.push(qso.dcl);
- if ((user_options.qslmsgs.show ?? 'true') == "true") data.push(qso.qslMessage);
- if ((user_options.qslmsgr.show ?? 'true') == "true") data.push(qso.qslMessageR);
- if ((user_options.dxcc.show ?? 'true') == "true") data.push(qso.dxcc + qso.flag + (qso.end == null ? '' : ' Deleted DXCC'));
- if ((user_options.state.show ?? 'true') == "true") data.push(qso.state);
- if ((user_options.county.show ?? 'true') == "true") data.push(qso.county);
- if ((user_options.cqzone.show ?? 'true') == "true") data.push(qso.cqzone);
- if ((user_options.ituzone.show ?? 'true') == "true") data.push(qso.ituzone);
- if ((user_options.iota.show ?? 'true') == "true") data.push(qso.iota);
- if ((user_options.pota.show ?? 'true') == "true") data.push(qso.pota);
- if ((user_options.sota.show ?? 'true') == "true") data.push(qso.sota);
- if ((user_options.dok.show ?? 'true') == "true") data.push(qso.dok);
- if ((user_options.wwff.show ?? 'true') == "true") data.push(qso.wwff);
- if ((user_options.sig.show ?? 'true') == "true") data.push(qso.sig);
- if ((user_options.region.show ?? 'true') == "true") data.push(qso.region);
- if ((user_options.operator.show ?? 'true') == "true") data.push(qso.operator);
- if ((user_options.comment.show ?? 'true') == "true") data.push(qso.comment);
- if ((user_options.propagation.show ?? 'true') == "true") data.push(qso.propagation);
- if ((user_options.contest.show ?? 'true') == "true") data.push(qso.contest);
- if ((user_options.myrefs.show ?? 'true') == "true") data.push(qso.deRefs);
- if ((user_options.continent.show ?? 'true') == "true") data.push(qso.continent);
- if ((user_options.distance.show ?? 'true') == "true") data.push(qso.distance);
- if ((user_options.antennaazimuth.show ?? 'true') == "true") data.push(qso.antennaazimuth);
- if ((user_options.antennaelevation.show ?? 'true') == "true") data.push(qso.antennaelevation);
- if ((user_options.profilename.show ?? 'true') == "true") data.push(qso.profilename);
- if ((user_options.stationpower.show ?? 'true') == "true") data.push(qso.stationpower);
-
- // metadata accessible inside createdRow
- data.id = 'qsoID-' + qso.qsoID;
- data._qsoID = qso.qsoID;
-
- allData.push(data);
- }
-
- // cache header index lookups (avoid repeated DOM queries)
- const distanceIdx = $(".distance-column-sort").index();
- const azIdx = $(".antennaazimuth-column-sort").index();
- const elIdx = $(".antennaelevation-column-sort").index();
- const powerIdx = $(".stationpower-column-sort").index();
-
- // DataTables init (data provided up-front)
const table = $table.DataTable({
- data: allData,
- deferRender: true,
+ searching: true,
+ responsive: false,
+ ordering: true,
scrollY: window.innerHeight - $('#searchForm').innerHeight() - 250,
scrollCollapse: true,
- paging: true, // required for Scroller
- scroller: true,
- displayStart: 0,
language: language,
ordering: true,
- orderClasses: false,
- responsive: false,
- createdRow: function(row, data) {
- if (data && data.id) $(row).attr('id', data.id);
- if (data && data._qsoID) $(row).data('qsoID', data._qsoID);
- },
- // robust info text so "259 to 250" can't appear
- infoCallback: function(settings) {
- const api = new $.fn.dataTable.Api(settings);
- const info = api.page.info();
- if (info.recordsDisplay === 0) return 'Showing 0 to 0 of 0 entries';
- const dispStart = info.start + 1;
- const dispEnd = Math.min(info.recordsDisplay, info.start + info.length);
- return 'Showing ' + dispStart + ' to ' + dispEnd + ' of ' + info.recordsDisplay + ' entries';
+ paging: false,
+ createdRow: function (row, data, dataIndex) {
+ $(row).attr('id', data.id);
},
columnDefs: [
{ orderable: false, targets: 0 },
- { targets: distanceIdx, type: "numbersort" },
- { targets: azIdx, type: "numbersort" },
- { targets: elIdx, type: "numbersort" },
- { targets: powerIdx, type: "numbersort" },
+ { targets: $(".distance-column-sort").index(), type: "numbersort" },
+ { targets: $(".antennaazimuth-column-sort").index(), type: "numbersort" },
+ { targets: $(".antennaelevation-column-sort").index(), type: "numbersort" },
+ { targets: $(".stationpower-column-sort").index(), type: "numbersort" },
],
dom: 'Bfrtip',
buttons: [
@@ -358,86 +247,6 @@ function loadQSOTable(rows) {
]
});
- // Ensure scroller measured and page reset
- try { if (table.scroller) table.scroller().measure(); } catch (e) {}
- try { table.page('first').draw(false); } catch (e) { table.draw(false); }
-
- // Delegate tooltip creation (create on demand)
- $table.off('mouseenter', '[data-bs-toggle="tooltip"]').on('mouseenter', '[data-bs-toggle="tooltip"]', function () {
- if (!$(this).data('bs.tooltip')) {
- $(this).tooltip();
- }
- });
-
- // Delegate checkbox handling (shift-click selection) — no per-row listeners
- let lastChecked = null;
- $table.off('click', '.row-check').on('click', '.row-check', function (e) {
- const checkboxes = $table.find('.row-check').toArray();
- if (e.shiftKey && lastChecked) {
- let start = checkboxes.indexOf(this);
- let end = checkboxes.indexOf(lastChecked);
- [start, end] = [Math.min(start, end), Math.max(start, end)];
- for (let i = start; i <= end; i++) {
- checkboxes[i].checked = lastChecked.checked;
- $(checkboxes[i]).closest('tr').toggleClass('activeRow', lastChecked.checked);
- }
- } else {
- $(this).closest('tr').toggleClass('activeRow', this.checked);
- }
- lastChecked = this;
- });
-
- // rebind other UI bits after table init (if function exists)
- if (typeof rebind_checkbox_trigger === 'function') rebind_checkbox_trigger();
- };
-
- // load language then init
- if (langUrl) {
- $.getJSON(langUrl)
- .done(function(language) { initTable(language); })
- .fail(function() { console.error("Failed to load DataTables language file at " + langUrl); initTable({}); });
- } else {
- initTable({});
- }
-}
-
-
-function loadQSOTable2(rows) {
- const $table = $('#qsoList');
-
- // Prevent initializing if already a DataTable
- if ($.fn.DataTable.isDataTable($table)) {
- $table.DataTable().clear().destroy();
- }
-
- const langUrl = getDataTablesLanguageUrl();
-
- const initTable = function(language) {
- $.fn.dataTable.moment(custom_date_format + ' HH:mm');
-
- const table = $table.DataTable({
- searching: false,
- responsive: false,
- ordering: true,
- scrollY: window.innerHeight - $('#searchForm').innerHeight() - 250,
- scrollCollapse: true,
- language: language,
- deferRender: true, // delay DOM creation until needed
- ordering: true,
- paging: true,
- scroller: true,
- createdRow: function (row, data, dataIndex) {
- $(row).attr('id', data.id);
- },
- columnDefs: [
- { orderable: false, targets: 0 },
- { targets: $(".distance-column-sort").index(), type: "numbersort" },
- { targets: $(".antennaazimuth-column-sort").index(), type: "numbersort" },
- { targets: $(".antennaelevation-column-sort").index(), type: "numbersort" },
- { targets: $(".stationpower-column-sort").index(), type: "numbersort" },
- ]
- });
-
for (i = 0; i < rows.length; i++) {
let qso = rows[i];