mirror of
https://github.com/magicbug/Cloudlog
synced 2026-08-13 17:49:35 -04:00
Adds a `qso_show_profile_image` JS flag from the user session and updates callbook panel rendering to honor it. The panel now omits the image column when profile images are disabled, keeps the empty-image message only when images are enabled, and applies a single-column layout class for no-image states.
1968 lines
63 KiB
JavaScript
1968 lines
63 KiB
JavaScript
var lastCallsignUpdated=""
|
|
var callsignLookupRequestId = 0;
|
|
var callsignDxccQuickRequestId = 0;
|
|
var callsignDxccQuickTimer = null;
|
|
var isSubmitting = false;
|
|
var lastResetCatSyncNoticeAt = 0;
|
|
var suppressNextResetHandler = false;
|
|
var previousContactsLookupMode = false;
|
|
var htmxAutoRefreshTimer = null;
|
|
|
|
function hasFieldValue(value) {
|
|
return value !== null && value !== undefined && String(value).trim() !== "";
|
|
}
|
|
|
|
function normalizeFieldValue(value) {
|
|
return String(value ?? "").trim();
|
|
}
|
|
|
|
function escapeNoticeValue(value) {
|
|
return String(value || '').replace(/[&<>"']/g, function(char) {
|
|
var escapes = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
"'": '''
|
|
};
|
|
return escapes[char] || char;
|
|
});
|
|
}
|
|
|
|
function showQsoNotice(message, alertType) {
|
|
var safeType = alertType || 'info';
|
|
var $container = $('#notice-alerts-container');
|
|
if ($container.length === 0) {
|
|
$container = $('<div id="notice-alerts-container"></div>');
|
|
var $rightColumn = $('.col-sm-7').first();
|
|
var $mapCard = $rightColumn.find('.qso-map').first();
|
|
if ($mapCard.length > 0) {
|
|
$container.insertBefore($mapCard);
|
|
} else if ($rightColumn.length > 0) {
|
|
$rightColumn.prepend($container);
|
|
}
|
|
}
|
|
|
|
$container.html('<div id="notice-alerts" class="alert alert-' + safeType + '" role="alert">' + message + '</div>');
|
|
|
|
setTimeout(function() {
|
|
$('#notice-alerts').fadeOut(300, function() {
|
|
$(this).remove();
|
|
});
|
|
}, 5000);
|
|
}
|
|
|
|
function shouldReplaceLookupField($field, incomingValue, fieldKey, approval) {
|
|
if (!hasFieldValue(incomingValue)) {
|
|
return false;
|
|
}
|
|
|
|
var currentValue = normalizeFieldValue($field.val());
|
|
var nextValue = normalizeFieldValue(incomingValue);
|
|
|
|
if (!hasFieldValue(currentValue) || currentValue === nextValue) {
|
|
return true;
|
|
}
|
|
|
|
if (!approval) {
|
|
return false;
|
|
}
|
|
|
|
if (approval.replaceAll) {
|
|
return true;
|
|
}
|
|
|
|
return approval.replaceSelected.has(fieldKey);
|
|
}
|
|
|
|
function getLookupOverwriteConflicts(result) {
|
|
var conflicts = [];
|
|
|
|
var fieldMappings = [
|
|
{ key: 'name', label: 'Name', selector: '#name', value: result.callsign_name },
|
|
{ key: 'qth', label: 'QTH', selector: '#qth', value: result.callsign_qth },
|
|
{ key: 'locator', label: 'Grid', selector: '#locator', value: result.callsign_qra },
|
|
{ key: 'qsl_via', label: 'QSL Via', selector: '#qsl_via', value: result.qsl_manager }
|
|
];
|
|
|
|
fieldMappings.forEach(function(field) {
|
|
var incomingValue = normalizeFieldValue(field.value);
|
|
if (!hasFieldValue(incomingValue)) {
|
|
return;
|
|
}
|
|
|
|
var currentValue = normalizeFieldValue($(field.selector).val());
|
|
if (hasFieldValue(currentValue) && currentValue !== incomingValue) {
|
|
conflicts.push({
|
|
key: field.key,
|
|
label: field.label,
|
|
currentValue: currentValue,
|
|
nextValue: incomingValue
|
|
});
|
|
}
|
|
});
|
|
|
|
return conflicts;
|
|
}
|
|
|
|
function showLookupOverwriteModal(conflicts) {
|
|
return new Promise(function(resolve) {
|
|
if (!conflicts || conflicts.length === 0) {
|
|
resolve({ replaceAll: false, replaceSelected: new Set() });
|
|
return;
|
|
}
|
|
|
|
var modalElement = document.getElementById('callsignOverwriteModal');
|
|
var conflictList = document.getElementById('callsignOverwriteConflicts');
|
|
var keepExistingBtn = document.getElementById('callsignOverwriteKeepExisting');
|
|
var replaceSelectedBtn = document.getElementById('callsignOverwriteReplaceSelected');
|
|
var replaceAllBtn = document.getElementById('callsignOverwriteReplaceAll');
|
|
|
|
if (!modalElement || !conflictList || typeof bootstrap === 'undefined') {
|
|
resolve({ replaceAll: false, replaceSelected: new Set() });
|
|
return;
|
|
}
|
|
|
|
conflictList.innerHTML = '';
|
|
conflicts.forEach(function(conflict) {
|
|
var escapedCurrent = $('<div/>').text(conflict.currentValue).html();
|
|
var escapedNext = $('<div/>').text(conflict.nextValue).html();
|
|
var itemHtml = '' +
|
|
'<div class="form-check mb-2">' +
|
|
'<input class="form-check-input callsign-overwrite-choice" type="checkbox" id="overwrite_' + conflict.key + '" data-field-key="' + conflict.key + '" checked>' +
|
|
'<label class="form-check-label" for="overwrite_' + conflict.key + '">' +
|
|
'<strong>' + conflict.label + '</strong><br>' +
|
|
'<small class="text-muted">Current: ' + escapedCurrent + '</small><br>' +
|
|
'<small>Suggested: ' + escapedNext + '</small>' +
|
|
'</label>' +
|
|
'</div>';
|
|
conflictList.insertAdjacentHTML('beforeend', itemHtml);
|
|
});
|
|
|
|
var modalInstance = bootstrap.Modal.getOrCreateInstance(modalElement);
|
|
var resolved = false;
|
|
|
|
function finalizeDecision(decision) {
|
|
if (resolved) {
|
|
return;
|
|
}
|
|
resolved = true;
|
|
resolve(decision);
|
|
modalInstance.hide();
|
|
}
|
|
|
|
keepExistingBtn.onclick = function() {
|
|
finalizeDecision({ replaceAll: false, replaceSelected: new Set() });
|
|
};
|
|
|
|
replaceSelectedBtn.onclick = function() {
|
|
var selected = new Set();
|
|
document.querySelectorAll('.callsign-overwrite-choice:checked').forEach(function(input) {
|
|
selected.add(input.getAttribute('data-field-key'));
|
|
});
|
|
finalizeDecision({ replaceAll: false, replaceSelected: selected });
|
|
};
|
|
|
|
replaceAllBtn.onclick = function() {
|
|
var selected = new Set();
|
|
conflicts.forEach(function(conflict) {
|
|
selected.add(conflict.key);
|
|
});
|
|
finalizeDecision({ replaceAll: true, replaceSelected: selected });
|
|
};
|
|
|
|
modalElement.addEventListener('hidden.bs.modal', function hiddenHandler() {
|
|
modalElement.removeEventListener('hidden.bs.modal', hiddenHandler);
|
|
if (!resolved) {
|
|
resolve({ replaceAll: false, replaceSelected: new Set() });
|
|
}
|
|
}, { once: true });
|
|
|
|
modalInstance.show();
|
|
});
|
|
}
|
|
|
|
function applyLookupLocator(result, approval) {
|
|
if (!shouldReplaceLookupField($('#locator'), result.callsign_qra, 'locator', approval)) {
|
|
return;
|
|
}
|
|
|
|
$('#locator').val(result.callsign_qra);
|
|
$('#locator_info').html(result.bearing);
|
|
|
|
if (result.callsign_distance != "" && result.callsign_distance != 0) {
|
|
document.getElementById("distance").value = result.callsign_distance;
|
|
}
|
|
|
|
if (result.callsign_qra != "") {
|
|
if (result.confirmed) {
|
|
$('#locator').addClass("confirmedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked and confirmed in the past');
|
|
} else if (result.workedBefore) {
|
|
$('#locator').addClass("workedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked in the past');
|
|
} else {
|
|
$('#locator').addClass("newGrid");
|
|
$('#locator').attr('title', 'New grid!');
|
|
}
|
|
} else {
|
|
$('#locator').removeClass("workedGrid");
|
|
$('#locator').removeClass("confirmedGrid");
|
|
$('#locator').removeClass("newGrid");
|
|
$('#locator').attr('title', '');
|
|
}
|
|
}
|
|
|
|
$( document ).ready(function() {
|
|
setTimeout(function() {
|
|
var callsignValue = localStorage.getItem("quicklogCallsign");
|
|
if (callsignValue !== null && callsignValue !== undefined) {
|
|
$("#callsign").val(callsignValue);
|
|
$("#mode").focus();
|
|
localStorage.removeItem("quicklogCallsign");
|
|
}
|
|
}, 100);
|
|
$('#reset_time').click(function() {
|
|
var now = new Date();
|
|
var localTime = now.getTime();
|
|
var utc = localTime + (now.getTimezoneOffset() * 60000);
|
|
$('#start_time').val(("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2)+':'+("0" + now.getUTCSeconds()).slice(-2));
|
|
$("[id='start_time']").each(function() {
|
|
$(this).attr("value", ("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2)+':'+("0" + now.getUTCSeconds()).slice(-2));
|
|
});
|
|
});
|
|
$('#reset_start_time').click(function() {
|
|
var now = new Date();
|
|
var localTime = now.getTime();
|
|
var utc = localTime + (now.getTimezoneOffset() * 60000);
|
|
$('#start_time').val(("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2));
|
|
$("[id='start_time']").each(function() {
|
|
$(this).attr("value", ("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2)+':'+("0" + now.getUTCSeconds()).slice(-2));
|
|
});
|
|
$('#end_time').val(("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2));
|
|
$("[id='end_time']").each(function() {
|
|
$(this).attr("value", ("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2)+':'+("0" + now.getUTCSeconds()).slice(-2));
|
|
});
|
|
});
|
|
$('#reset_end_time').click(function() {
|
|
var now = new Date();
|
|
var localTime = now.getTime();
|
|
var utc = localTime + (now.getTimezoneOffset() * 60000);
|
|
$('#end_time').val(("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2));
|
|
$("[id='end_time']").each(function() {
|
|
$(this).attr("value", ("0" + now.getUTCHours()).slice(-2)+':'+("0" + now.getUTCMinutes()).slice(-2)+':'+("0" + now.getUTCSeconds()).slice(-2));
|
|
});
|
|
});
|
|
var favs={};
|
|
get_fav();
|
|
|
|
$('#fav_add').click(function (event) {
|
|
save_fav();
|
|
});
|
|
|
|
$(document).on("click", "#fav_del", function (event) {
|
|
del_fav($(this).attr('name'));
|
|
});
|
|
|
|
$(document).on("click", "#fav_recall", function (event) {
|
|
$('#sat_name').val(favs[this.innerText].sat_name);
|
|
$('#sat_mode').val(favs[this.innerText].sat_mode);
|
|
$('#band_rx').val(favs[this.innerText].band_rx);
|
|
$('#band').val(favs[this.innerText].band);
|
|
$('#frequency_rx').val(favs[this.innerText].frequency_rx);
|
|
$('#frequency').val(favs[this.innerText].frequency);
|
|
$('#selectPropagation').val(favs[this.innerText].prop_mode);
|
|
$('#mode').val(favs[this.innerText].mode);
|
|
});
|
|
|
|
|
|
function del_fav(name) {
|
|
if (confirm("Are you sure to delete Fav?")) {
|
|
$.ajax({
|
|
url: base_url+'index.php/user_options/del_fav',
|
|
method: 'POST',
|
|
dataType: 'json',
|
|
contentType: "application/json; charset=utf-8",
|
|
data: JSON.stringify({ "option_name": name }),
|
|
success: function(result) {
|
|
get_fav();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function get_fav() {
|
|
$.ajax({
|
|
url: base_url+'index.php/user_options/get_fav',
|
|
method: 'GET',
|
|
dataType: 'json',
|
|
contentType: "application/json; charset=utf-8",
|
|
success: function(result) {
|
|
$("#fav_menu").empty();
|
|
for (const key in result) {
|
|
$("#fav_menu").append('<label class="dropdown-item" style="display: flex; justify-content: space-between;"><span id="fav_recall">' + key + '</span><span class="badge bg-danger" id="fav_del" name="' + key + '"><i class="fas fa-trash-alt"></i></span></label>');
|
|
}
|
|
favs=result;
|
|
}
|
|
});
|
|
}
|
|
|
|
function save_fav() {
|
|
var payload={};
|
|
payload.sat_name=$('#sat_name').val();
|
|
payload.sat_mode=$('#sat_mode').val();
|
|
payload.band_rx=$('#band_rx').val();
|
|
payload.band=$('#band').val();
|
|
payload.frequency_rx=$('#frequency_rx').val();
|
|
payload.frequency=$('#frequency').val();
|
|
payload.prop_mode=$('#selectPropagation').val();
|
|
payload.mode=$('#mode').val();
|
|
$.ajax({
|
|
url: base_url+'index.php/user_options/add_edit_fav',
|
|
method: 'POST',
|
|
dataType: 'json',
|
|
contentType: "application/json; charset=utf-8",
|
|
data: JSON.stringify(payload),
|
|
success: function(result) {
|
|
get_fav();
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
var bc_bandmap = new BroadcastChannel('qso_window');
|
|
bc_bandmap.onmessage = function (ev) {
|
|
if (ev.data == 'ping') {
|
|
bc_bandmap.postMessage('pong');
|
|
}
|
|
}
|
|
|
|
var bc = new BroadcastChannel('qso_wish');
|
|
bc.onmessage = function (ev) {
|
|
if (ev.data.ping) {
|
|
let message={};
|
|
message.pong=true;
|
|
bc.postMessage(message);
|
|
} else {
|
|
$('#frequency').val(ev.data.frequency);
|
|
$("#band").val(frequencyToBand(ev.data.frequency));
|
|
if (ev.data.frequency_rx != "") {
|
|
$('#frequency_rx').val(ev.data.frequency_rx);
|
|
$("#band_rx").val(frequencyToBand(ev.data.frequency_rx));
|
|
}
|
|
$("#callsign").val(ev.data.call);
|
|
$("#callsign").focusout();
|
|
$("#callsign").blur();
|
|
}
|
|
} /* receive */
|
|
|
|
$("#locator")
|
|
.popover({ placement: 'top', title: 'Gridsquare Formatting', content: "Enter multiple (4-digit) grids separated with commas. For example: IO77,IO78" })
|
|
.focus(function () {
|
|
$('#locator').popover('show');
|
|
})
|
|
.blur(function () {
|
|
$('#locator').popover('hide');
|
|
});
|
|
|
|
$("#sat_name").change(function(){
|
|
var sat = $("#sat_name").val();
|
|
if (sat == "") {
|
|
$("#sat_mode").val("");
|
|
$("#selectPropagation").val("");
|
|
}
|
|
});
|
|
|
|
$('#input_usa_state').change(function(){
|
|
var state = $("#input_usa_state option:selected").text();
|
|
if (state != "") {
|
|
$("#stationCntyInput").prop('disabled', false);
|
|
|
|
$('#stationCntyInput').selectize({
|
|
maxItems: 1,
|
|
closeAfterSelect: true,
|
|
loadThrottle: 250,
|
|
valueField: 'name',
|
|
labelField: 'name',
|
|
searchField: 'name',
|
|
options: [],
|
|
create: false,
|
|
load: function(query, callback) {
|
|
var state = $("#input_usa_state option:selected").text();
|
|
|
|
if (!query || state == "") return callback();
|
|
$.ajax({
|
|
url: base_url+'index.php/qso/get_county',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {
|
|
query: query,
|
|
state: state,
|
|
},
|
|
error: function() {
|
|
callback();
|
|
},
|
|
success: function(res) {
|
|
callback(res);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
} else {
|
|
$("#stationCntyInput").prop('disabled', true);
|
|
//$('#stationCntyInput')[0].selectize.destroy();
|
|
$("#stationCntyInput").val("");
|
|
}
|
|
});
|
|
|
|
$('#sota_ref').selectize({
|
|
maxItems: 1,
|
|
closeAfterSelect: true,
|
|
createOnBlur: true,
|
|
selectOnTab: true,
|
|
loadThrottle: 250,
|
|
valueField: 'name',
|
|
labelField: 'name',
|
|
searchField: 'name',
|
|
options: [],
|
|
create: true,
|
|
load: function(query, callback) {
|
|
if (!query || query.length < 3) return callback(); // Only trigger if 3 or more characters are entered
|
|
$.ajax({
|
|
url: base_url+'index.php/qso/get_sota',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {
|
|
query: query,
|
|
},
|
|
error: function() {
|
|
callback();
|
|
},
|
|
success: function(res) {
|
|
callback(res);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
$('#sota_ref').change(function(){
|
|
$('#sota_info').html('<a target="_blank" href="https://summits.sota.org.uk/summit/'+$('#sota_ref').val()+'"><img width="32" height="32" src="'+base_url+'images/icons/sota.org.uk.png"></a>');
|
|
$('#sota_info').attr('title', 'Lookup '+$('#sota_ref').val()+' summit info on sota.org.uk');
|
|
});
|
|
|
|
$('#wwff_ref').selectize({
|
|
maxItems: 1,
|
|
closeAfterSelect: true,
|
|
createOnBlur: true,
|
|
selectOnTab: true,
|
|
loadThrottle: 250,
|
|
valueField: 'name',
|
|
labelField: 'name',
|
|
searchField: 'name',
|
|
options: [],
|
|
create: true,
|
|
load: function(query, callback) {
|
|
if (!query || query.length < 3) return callback(); // Only trigger if 3 or more characters are entered
|
|
$.ajax({
|
|
url: base_url+'index.php/qso/get_wwff',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {
|
|
query: query,
|
|
},
|
|
error: function() {
|
|
callback();
|
|
},
|
|
success: function(res) {
|
|
callback(res);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
$('#wwff_ref').change(function(){
|
|
$('#wwff_info').html('<a target="_blank" href="https://www.cqgma.org/zinfo.php?ref='+$('#wwff_ref').val()+'"><img width="32" height="32" src="'+base_url+'images/icons/wwff.co.png"></a>');
|
|
$('#wwff_info').attr('title', 'Lookup '+$('#wwff_ref').val()+' reference info on cqgma.org');
|
|
});
|
|
|
|
$('#pota_ref').selectize({
|
|
maxItems: null,
|
|
closeAfterSelect: true,
|
|
createOnBlur: true,
|
|
selectOnTab: true,
|
|
loadThrottle: 250,
|
|
valueField: 'name',
|
|
labelField: 'name',
|
|
searchField: 'name',
|
|
options: [],
|
|
create: true,
|
|
load: function(query, callback) {
|
|
if (!query || query.length < 3) return callback(); // Only trigger if 3 or more characters are entered
|
|
$.ajax({
|
|
url: base_url+'index.php/qso/get_pota',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {
|
|
query: query,
|
|
},
|
|
error: function() {
|
|
callback();
|
|
},
|
|
success: function(res) {
|
|
callback(res);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
$('#pota_ref').change(function(){
|
|
var raw = $('#pota_ref').val() || '';
|
|
var refs = raw.split(',').map(function(ref) {
|
|
return ref.trim();
|
|
}).filter(function(ref) {
|
|
return ref.length > 0;
|
|
});
|
|
|
|
if (refs.length === 0) {
|
|
$('#pota_info').html('');
|
|
$('#pota_info').attr('title', '');
|
|
return;
|
|
}
|
|
|
|
var links = refs.map(function(ref) {
|
|
return '<a target="_blank" href="https://pota.app/#/park/' + ref + '"><img width="32" height="32" src="' + base_url + 'images/icons/pota.app.png"></a>';
|
|
}).join(' ');
|
|
|
|
$('#pota_info').html(links);
|
|
$('#pota_info').attr('title', 'Lookup ' + refs.join(', ') + ' reference info on pota.app');
|
|
});
|
|
|
|
$('#darc_dok').selectize({
|
|
maxItems: 1,
|
|
closeAfterSelect: true,
|
|
loadThrottle: 250,
|
|
valueField: 'name',
|
|
labelField: 'name',
|
|
searchField: 'name',
|
|
options: [],
|
|
create: true,
|
|
load: function(query, callback) {
|
|
if (!query) return callback(); // Only trigger if at least 1 character is entered
|
|
$.ajax({
|
|
url: base_url+'index.php/qso/get_dok',
|
|
type: 'GET',
|
|
dataType: 'json',
|
|
data: {
|
|
query: query,
|
|
},
|
|
error: function() {
|
|
callback();
|
|
},
|
|
success: function(res) {
|
|
callback(res);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
/*
|
|
Populate the Satellite Names Field on the QSO Panel
|
|
*/
|
|
$.getJSON(base_url+"assets/json/satellite_data.json", function( data ) {
|
|
|
|
// Build the options array
|
|
var items = [];
|
|
$.each( data, function( key, val ) {
|
|
items.push(
|
|
'<option value="' + key + '">' + key + '</option>'
|
|
);
|
|
});
|
|
|
|
// Add to the datalist
|
|
$('.satellite_names_list').append(items.join( "" ));
|
|
});
|
|
|
|
// Test Consistency value on submit form //
|
|
$("#qso_input").off('submit').on('submit', function(e){
|
|
e.preventDefault();
|
|
|
|
// Prevent double submission
|
|
if (isSubmitting) {
|
|
return false;
|
|
}
|
|
|
|
var _submit = true;
|
|
if ((typeof qso_manual !== "undefined")&&(qso_manual == "1")) {
|
|
if ($('#qso_input input[name="end_time"]').length == 1) { _submit = testTimeOffConsistency(); }
|
|
}
|
|
|
|
if (_submit) {
|
|
// Mark as submitting and disable the submit button
|
|
isSubmitting = true;
|
|
$('#qso_input .warningOnSubmit').hide();
|
|
$('#qso_input .warningOnSubmit_txt').empty();
|
|
|
|
var $form = $(this);
|
|
var submitBtn = $(this).find('button[type="submit"]');
|
|
var originalText = submitBtn.data('original-text');
|
|
if (!originalText) {
|
|
// Store original text first time
|
|
originalText = submitBtn.html();
|
|
submitBtn.data('original-text', originalText);
|
|
}
|
|
submitBtn.prop('disabled', true);
|
|
submitBtn.html('<i class="fas fa-spinner fa-spin"></i> Saving...');
|
|
|
|
var ajaxSaveUrl = $form.data('ajax-save-url') || (base_url + 'index.php/qso/ajax_saveqso');
|
|
|
|
$.ajax({
|
|
url: ajaxSaveUrl,
|
|
type: 'POST',
|
|
data: $form.serialize(),
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
if (response && response.status === 'ok') {
|
|
var savedCallsign = normalizeFieldValue($('#callsign').val()).toUpperCase();
|
|
var savedStartDate = normalizeFieldValue($('#qso_input [name="start_date"]').first().val());
|
|
var savedBand = normalizeFieldValue($('#band').val());
|
|
var savedMode = normalizeFieldValue($('#mode').val());
|
|
var savedSatName = normalizeFieldValue($('#sat_name').val());
|
|
var savedSatMode = normalizeFieldValue($('#sat_mode').val());
|
|
var savedRadio = normalizeFieldValue($('#qso_input select[name="radio"]').val());
|
|
var postSaveDefaults = {
|
|
start_date: savedStartDate,
|
|
band: savedBand,
|
|
mode: savedMode,
|
|
sat_name: savedSatName,
|
|
sat_mode: savedSatMode,
|
|
radio: savedRadio
|
|
};
|
|
var saveMessage = (response && response.message) ? response.message : 'QSO Added';
|
|
if (savedCallsign && savedBand) {
|
|
saveMessage += ': <strong>' + escapeNoticeValue(savedCallsign) + ' on ' + escapeNoticeValue(savedBand) + '</strong>';
|
|
} else if (savedCallsign) {
|
|
saveMessage += ': <strong>' + escapeNoticeValue(savedCallsign) + '</strong>';
|
|
} else if (savedBand) {
|
|
saveMessage += ': <strong>on ' + escapeNoticeValue(savedBand) + '</strong>';
|
|
}
|
|
|
|
var qsoFormElement = document.getElementById('qso_input');
|
|
if (qsoFormElement) {
|
|
suppressNextResetHandler = true;
|
|
qsoFormElement.reset();
|
|
}
|
|
|
|
reset_fields();
|
|
if (document.getElementById('qsp-tab')) {
|
|
new bootstrap.Tab(document.getElementById('qsp-tab')).show();
|
|
}
|
|
reapplyPostSaveDefaults(postSaveDefaults);
|
|
syncFromSelectedRadioAfterReset();
|
|
setTimeout(function() {
|
|
syncFromSelectedRadioAfterReset();
|
|
}, 250);
|
|
showQsoNotice(saveMessage, 'info');
|
|
|
|
if (typeof htmx !== 'undefined' && document.getElementById('qso-last-table')) {
|
|
htmx.ajax('GET', base_url + 'index.php/qso/component_past_contacts', {
|
|
target: '#qso-last-table',
|
|
swap: 'innerHTML'
|
|
});
|
|
}
|
|
|
|
$('#callsign').focus();
|
|
$('#qso_input').data('initialForm', $('#qso_input').serialize());
|
|
} else {
|
|
var warningMessage = (response && response.message) ? response.message : 'Unable to save QSO. Please try again.';
|
|
|
|
if (response && response.validation_errors) {
|
|
var validationMessages = [];
|
|
$.each(response.validation_errors, function(_, msg) {
|
|
if (msg) {
|
|
validationMessages.push(msg);
|
|
}
|
|
});
|
|
if (validationMessages.length > 0) {
|
|
warningMessage = validationMessages.join('<br>');
|
|
}
|
|
}
|
|
|
|
$('#qso_input .warningOnSubmit_txt').html(warningMessage);
|
|
$('#qso_input .warningOnSubmit').show();
|
|
}
|
|
},
|
|
error: function() {
|
|
$('#qso_input .warningOnSubmit_txt').html('Unable to save QSO due to a network or server error.');
|
|
$('#qso_input .warningOnSubmit').show();
|
|
},
|
|
complete: function() {
|
|
resetSubmissionState();
|
|
}
|
|
});
|
|
}
|
|
|
|
return false;
|
|
})
|
|
|
|
// Prevent Enter key from causing double submissions
|
|
$("#qso_input").on('keydown', function(e) {
|
|
if (e.key === 'Enter' && e.target.type !== 'textarea') {
|
|
if (isSubmitting) {
|
|
e.preventDefault();
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
|
|
// Reset submission state when page becomes visible again (handles cases where submission gets stuck)
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (!document.hidden && typeof isSubmitting !== 'undefined' && isSubmitting) {
|
|
setTimeout(function() {
|
|
resetSubmissionState();
|
|
}, 1000); // Wait 1 second before resetting to avoid interfering with legitimate submissions
|
|
}
|
|
});
|
|
});
|
|
|
|
var selected_sat;
|
|
var selected_sat_mode;
|
|
|
|
$(document).on('change', 'input', function(){
|
|
var optionslist = $('.satellite_modes_list')[0].options;
|
|
var value = $(this).val();
|
|
for (var x=0;x<optionslist.length;x++){
|
|
if (optionslist[x].value === value) {
|
|
|
|
// Store selected sat mode
|
|
selected_sat_mode = value;
|
|
|
|
// get Json file
|
|
$.getJSON(base_url + "assets/json/satellite_data.json", function( data ) {
|
|
|
|
// Build the options array
|
|
var sat_modes = [];
|
|
$.each( data, function( key, val ) {
|
|
if (key == selected_sat) {
|
|
$.each( val.Modes, function( key1, val2 ) {
|
|
if(key1 == selected_sat_mode) {
|
|
|
|
if ( (val2[0].Downlink_Mode == "LSB" && val2[0].Uplink_Mode == "USB") || (val2[0].Downlink_Mode == "USB" && val2[0].Uplink_Mode == "LSB") ) { // inverting Transponder? set to SSB
|
|
$("#mode").val("SSB");
|
|
} else {
|
|
$("#mode").val(val2[0].Uplink_Mode);
|
|
}
|
|
$("#band").val(frequencyToBand(val2[0].Uplink_Freq));
|
|
$("#band_rx").val(frequencyToBand(val2[0].Downlink_Freq));
|
|
$("#frequency").val(val2[0].Uplink_Freq);
|
|
$("#frequency_rx").val(val2[0].Downlink_Freq);
|
|
$("#selectPropagation").val('SAT');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
$(document).on('change', 'input', function(){
|
|
var optionslist = $('.satellite_names_list')[0].options;
|
|
var value = $(this).val();
|
|
for (var x=0;x<optionslist.length;x++){
|
|
if (optionslist[x].value === value) {
|
|
$("#sat_mode").val("");
|
|
$('.satellite_modes_list').find('option').remove().end();
|
|
selected_sat = value;
|
|
// get Json file
|
|
$.getJSON( base_url+"assets/json/satellite_data.json", function( data ) {
|
|
|
|
// Build the options array
|
|
var sat_modes = [];
|
|
$.each( data, function( key, val ) {
|
|
if (key == value) {
|
|
$.each( val.Modes, function( key1, val2 ) {
|
|
//console.log (key1);
|
|
sat_modes.push('<option value="' + key1 + '">' + key1 + '</option>');
|
|
});
|
|
}
|
|
});
|
|
|
|
// Add to the datalist
|
|
$('.satellite_modes_list').append(sat_modes.join( "" ));
|
|
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
function changebadge(entityname) {
|
|
if (isSatelliteLookupContext()) {
|
|
$.getJSON(base_url + 'index.php/logbook/jsonlookupdxcc/' + convert_case(entityname) + '/SAT/0/0', function(result)
|
|
{
|
|
|
|
$('#callsign_info').removeClass("lotw_info_orange");
|
|
$('#callsign_info').removeClass("text-bg-secondary");
|
|
$('#callsign_info').removeClass("text-bg-success");
|
|
$('#callsign_info').removeClass("text-bg-danger");
|
|
$('#callsign_info').attr('title', '');
|
|
|
|
if (result.confirmed) {
|
|
$('#callsign_info').addClass("text-bg-success");
|
|
$('#callsign_info').attr('title', 'DXCC was already worked and confirmed in the past on this band and mode!');
|
|
} else if (result.workedBefore) {
|
|
$('#callsign_info').addClass("text-bg-success");
|
|
$('#callsign_info').addClass("lotw_info_orange");
|
|
$('#callsign_info').attr('title', 'DXCC was already worked in the past on this band and mode!');
|
|
} else {
|
|
$('#callsign_info').addClass("text-bg-danger");
|
|
$('#callsign_info').attr('title', 'New DXCC, not worked on this band and mode!');
|
|
}
|
|
})
|
|
} else {
|
|
$.getJSON(base_url + 'index.php/logbook/jsonlookupdxcc/' + convert_case(entityname) + '/0/' + $("#band").val() +'/' + $("#mode").val(), function(result)
|
|
{
|
|
// Reset CSS values before updating
|
|
$('#callsign_info').removeClass("lotw_info_orange");
|
|
$('#callsign_info').removeClass("text-bg-secondary");
|
|
$('#callsign_info').removeClass("text-bg-success");
|
|
$('#callsign_info').removeClass("text-bg-danger");
|
|
$('#callsign_info').attr('title', '');
|
|
|
|
if (result.confirmed) {
|
|
$('#callsign_info').addClass("text-bg-success");
|
|
$('#callsign_info').attr('title', 'DXCC was already worked and confirmed in the past on this band and mode!');
|
|
} else if (result.workedBefore) {
|
|
$('#callsign_info').addClass("text-bg-success");
|
|
$('#callsign_info').addClass("lotw_info_orange");
|
|
$('#callsign_info').attr('title', 'DXCC was already worked in the past on this band and mode!');
|
|
} else {
|
|
$('#callsign_info').addClass("text-bg-danger");
|
|
$('#callsign_info').attr('title', 'New DXCC, not worked on this band and mode!');
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/* Function: resetSubmissionState resets the form submission state */
|
|
function resetSubmissionState() {
|
|
if (typeof isSubmitting !== 'undefined') {
|
|
isSubmitting = false;
|
|
}
|
|
var submitBtn = $('#qso_input button[type="submit"]');
|
|
if (submitBtn.length > 0) {
|
|
submitBtn.prop('disabled', false);
|
|
// Get the original text from the button or use a fallback
|
|
var originalText = submitBtn.data('original-text');
|
|
if (!originalText) {
|
|
// Store original text first time
|
|
originalText = submitBtn.html();
|
|
submitBtn.data('original-text', originalText);
|
|
}
|
|
submitBtn.html(originalText);
|
|
}
|
|
}
|
|
|
|
function resetCallsignLookupState() {
|
|
lastCallsignUpdated = '';
|
|
// Invalidate in-flight responses from older callsign lookups.
|
|
callsignLookupRequestId++;
|
|
callsignDxccQuickRequestId++;
|
|
if (callsignDxccQuickTimer) {
|
|
clearTimeout(callsignDxccQuickTimer);
|
|
callsignDxccQuickTimer = null;
|
|
}
|
|
}
|
|
|
|
function isLookupStillCurrent(requestId, find_callsign) {
|
|
if (requestId !== callsignLookupRequestId) {
|
|
return false;
|
|
}
|
|
|
|
var currentCallsign = $('#callsign').val().toUpperCase().replace(/\//g, "-").replace('Ø', '0');
|
|
return currentCallsign === find_callsign;
|
|
}
|
|
|
|
function escapeCallbookHtml(value) {
|
|
return $('<div>').text(value == null ? '' : String(value)).html();
|
|
}
|
|
|
|
function resetCallbookPanel() {
|
|
if ($('#qso-callbook-content').length === 0) {
|
|
return;
|
|
}
|
|
|
|
$('#qso-callbook-content').html('<div class="callbook-empty">Enter a callsign to load callbook details.</div>').attr('class', 'pt-2');
|
|
}
|
|
|
|
function renderCallbookPanel(callsign, result) {
|
|
if ($('#qso-callbook-content').length === 0) {
|
|
return;
|
|
}
|
|
|
|
var showProfileImage = (typeof qso_show_profile_image === 'undefined') ? true : !!qso_show_profile_image;
|
|
var safeCallsign = escapeCallbookHtml(callsign || '');
|
|
var safeName = escapeCallbookHtml(result.callsign_name || '');
|
|
var safeQth = escapeCallbookHtml(result.callsign_qth || '');
|
|
var safeLocator = escapeCallbookHtml(result.callsign_qra || '');
|
|
var safeIota = escapeCallbookHtml(result.callsign_iota || '');
|
|
var hasImage = showProfileImage && result.image && result.image !== 'n/a';
|
|
var imageColumnHtml = '';
|
|
if (hasImage) {
|
|
imageColumnHtml = ' <div><img class="callbook-photo" src="' + escapeCallbookHtml(result.image) + '" alt="Callbook profile image"></div>';
|
|
} else if (showProfileImage) {
|
|
imageColumnHtml = ' <div><div class="callbook-empty">No profile image returned by callbook provider.</div></div>';
|
|
}
|
|
var layoutClass = imageColumnHtml ? 'callbook-layout' : 'callbook-layout callbook-layout-no-image';
|
|
|
|
var html = ''
|
|
+ '<div class="' + layoutClass + '">'
|
|
+ imageColumnHtml
|
|
+ ' <div>'
|
|
+ ' <div class="callbook-heading">' + safeCallsign + '</div>'
|
|
+ ' <div class="callbook-links">'
|
|
+ ' <a target="_blank" href="https://www.qrz.com/db/' + safeCallsign + '"><i class="fas fa-up-right-from-square"></i> QRZ profile</a>'
|
|
+ ' <a target="_blank" href="https://www.hamqth.com/' + safeCallsign + '"><i class="fas fa-up-right-from-square"></i> HamQTH profile</a>'
|
|
+ ' </div>'
|
|
+ ' <div class="callbook-meta">'
|
|
+ ' <strong>Name</strong><span>' + (safeName || '-') + '</span>'
|
|
+ ' <strong>QTH</strong><span>' + (safeQth || '-') + '</span>'
|
|
+ ' <strong>Locator</strong><span>' + (safeLocator || '-') + '</span>'
|
|
+ ' <strong>IOTA</strong><span>' + (safeIota || '-') + '</span>'
|
|
+ ' </div>'
|
|
+ ' </div>'
|
|
+ '</div>';
|
|
|
|
$('#qso-callbook-content').html(html).attr('class', 'pt-2');
|
|
}
|
|
|
|
function clearSatelliteFields() {
|
|
$('#sat_name').val('');
|
|
$('#sat_mode').val('');
|
|
$('.satellite_modes_list').find('option').remove().end();
|
|
selected_sat = '';
|
|
selected_sat_mode = '';
|
|
|
|
if ($('#selectPropagation').val() === 'SAT') {
|
|
$('#selectPropagation').val('');
|
|
}
|
|
}
|
|
|
|
function isSatelliteLookupContext() {
|
|
var propagationMode = normalizeFieldValue($('#selectPropagation').val()).toUpperCase();
|
|
var propagationModeCat = normalizeFieldValue($('#selectPropagation').data('catValue')).toUpperCase();
|
|
var satName = normalizeFieldValue($('#sat_name').val());
|
|
var satMode = normalizeFieldValue($('#sat_mode').val());
|
|
var satNameCat = normalizeFieldValue($('#sat_name').data('catValue'));
|
|
var satModeCat = normalizeFieldValue($('#sat_mode').data('catValue'));
|
|
|
|
if (propagationMode === 'SAT' || propagationModeCat === 'SAT' || satName !== '' || satMode !== '' || satNameCat !== '' || satModeCat !== '') {
|
|
return true;
|
|
}
|
|
|
|
var selectedRadioID = normalizeFieldValue($('select.radios').first().val());
|
|
var lastCatRadioID = normalizeFieldValue(window.cloudlogLastCatRadioId);
|
|
var lastCatData = window.cloudlogLastCatData;
|
|
if (selectedRadioID === '' || selectedRadioID === '0' || selectedRadioID !== lastCatRadioID || !lastCatData) {
|
|
return false;
|
|
}
|
|
|
|
var catPropMode = normalizeFieldValue(lastCatData.prop_mode).toUpperCase();
|
|
var catSatName = normalizeFieldValue(lastCatData.satname);
|
|
var catSatMode = normalizeFieldValue(lastCatData.satmode);
|
|
return catPropMode === 'SAT' || catSatName !== '' || catSatMode !== '';
|
|
}
|
|
|
|
function clearCatTrackedFieldState() {
|
|
$('#frequency, #frequency_rx, #sat_name, #sat_mode, #transmit_power, #selectPropagation, #mode').removeData('catValue');
|
|
}
|
|
|
|
/* Function: reset_fields is used to reset the fields on the QSO page */
|
|
function reset_fields() {
|
|
// Reset submission state
|
|
resetSubmissionState();
|
|
resetCallsignLookupState();
|
|
|
|
$('#locator_info').text("");
|
|
$('#country').val("");
|
|
$('#continent').val("");
|
|
$('#lotw_info').text("");
|
|
$('#lotw_info').removeClass("lotw_info_red");
|
|
$('#lotw_info').removeClass("lotw_info_yellow");
|
|
$('#lotw_info').removeClass("lotw_info_orange");
|
|
$('#qrz_info').text("");
|
|
$('#hamqth_info').text("");
|
|
$('#sota_info').text("");
|
|
$('#wwff_info').html('').attr('title', '');
|
|
$('#pota_info').html('').attr('title', '');
|
|
$('#dxcc_id').val("").trigger('change');
|
|
$('#cqz').val("");
|
|
$('#name').val("");
|
|
$('#qth').val("");
|
|
$('#locator').val("");
|
|
$('#iota_ref').val("");
|
|
$select = $('#sota_ref').selectize();
|
|
selectize = $select[0] ? $select[0].selectize : null;
|
|
if (selectize) selectize.clear();
|
|
$("#locator").removeClass("confirmedGrid");
|
|
$("#locator").removeClass("workedGrid");
|
|
$("#locator").removeClass("newGrid");
|
|
$("#callsign").removeClass("confirmedGrid");
|
|
$("#callsign").removeClass("workedGrid");
|
|
$("#callsign").removeClass("newGrid");
|
|
$('#callsign_info').removeClass("text-bg-secondary");
|
|
$('#callsign_info').removeClass("text-bg-success");
|
|
$('#callsign_info').removeClass("text-bg-danger");
|
|
resetCallbookPanel();
|
|
$('#qsl_via').val("");
|
|
$('#callsign_info').text("");
|
|
$('#input_usa_state').val("");
|
|
$('#qso-last-table').show();
|
|
$('#partial_view').html('');
|
|
$('#partial_view').hide();
|
|
previousContactsLookupMode = false;
|
|
resumeAutoRefresh();
|
|
var $select = $('#wwff_ref').selectize();
|
|
var selectize = $select[0] ? $select[0].selectize : null;
|
|
if (selectize) selectize.clear();
|
|
$select = $('#pota_ref').selectize();
|
|
selectize = $select[0] ? $select[0].selectize : null;
|
|
if (selectize) selectize.clear();
|
|
$select = $('#darc_dok').selectize();
|
|
selectize = $select[0] ? $select[0].selectize : null;
|
|
if (selectize) selectize.clear();
|
|
$select = $('#stationCntyInput').selectize();
|
|
selectize = $select[0] ? $select[0].selectize : null;
|
|
if (selectize) selectize.clear();
|
|
|
|
clearSatelliteFields();
|
|
clearCatTrackedFieldState();
|
|
|
|
mymap.setView(pos, 12);
|
|
mymap.removeLayer(markers);
|
|
$('.callsign-suggest').hide();
|
|
$('.dxccsummary').remove();
|
|
$('#timesWorked').html(lang_qso_title_previous_contacts);
|
|
renderQsoCallhistoryPanel([], 'Type a callsign to see membership details from your uploaded call history files.');
|
|
|
|
// Reapply default RST values for the current mode (e.g., CW => 599).
|
|
if (typeof setRst === 'function') {
|
|
setRst($('.mode').val());
|
|
}
|
|
}
|
|
|
|
function reapplyPostSaveDefaults(defaults) {
|
|
if (!defaults) {
|
|
return;
|
|
}
|
|
|
|
var selectedRadioForReset = normalizeFieldValue(defaults.radio || $('select.radios').first().val());
|
|
var hasSelectedRadioForReset = selectedRadioForReset !== '' && selectedRadioForReset !== '0';
|
|
|
|
if (typeof defaults.start_date !== 'undefined') {
|
|
$('#qso_input [name="start_date"]').val(defaults.start_date);
|
|
}
|
|
|
|
if (typeof defaults.band !== 'undefined') {
|
|
$('#band').val(defaults.band);
|
|
}
|
|
|
|
if (typeof defaults.mode !== 'undefined') {
|
|
$('#mode').val(defaults.mode);
|
|
}
|
|
|
|
if (!hasSelectedRadioForReset && typeof defaults.sat_name !== 'undefined') {
|
|
$('#sat_name').val(defaults.sat_name);
|
|
}
|
|
|
|
if (!hasSelectedRadioForReset && typeof defaults.sat_mode !== 'undefined') {
|
|
$('#sat_mode').val(defaults.sat_mode);
|
|
}
|
|
|
|
if (typeof defaults.radio !== 'undefined' && defaults.radio !== '') {
|
|
var radioValue = String(defaults.radio);
|
|
$('#qso_input select[name="radio"]').val(radioValue);
|
|
$('select.radios').val(radioValue);
|
|
if (typeof localStorage !== 'undefined') {
|
|
localStorage.setItem('selectedRadio', radioValue);
|
|
}
|
|
}
|
|
|
|
if (hasSelectedRadioForReset) {
|
|
// Prefer selected radio CAT values after save; avoid restoring stale sat fields.
|
|
$('#sat_name').val('').removeData('catValue');
|
|
$('#sat_mode').val('').removeData('catValue');
|
|
$('#selectPropagation').val('').removeData('catValue');
|
|
} else if ((defaults.sat_name && defaults.sat_name !== '') || (defaults.sat_mode && defaults.sat_mode !== '')) {
|
|
$('#sat_name').trigger('input');
|
|
}
|
|
|
|
if (typeof setRst === 'function') {
|
|
setRst($('#mode').val());
|
|
}
|
|
}
|
|
|
|
function resetTimers(manual) {
|
|
if (typeof manual !== 'undefined' && manual != 1) {
|
|
handleStart = setInterval(function() { getUTCTimeStamp($('.input_start_time')); }, 500);
|
|
handleEnd = setInterval(function() { getUTCTimeStamp($('.input_end_time')); }, 500);
|
|
handleDate = setInterval(function() { getUTCDateStamp($('.input_date')); }, 1000);
|
|
}
|
|
}
|
|
|
|
$("#callsign").focusout(function() {
|
|
// Temp store the callsign
|
|
var temp_callsign = $(this).val();
|
|
if (temp_callsign == lastCallsignUpdated) {
|
|
return;
|
|
}
|
|
lastCallsignUpdated = temp_callsign;
|
|
|
|
if ($(this).val().length >= 3) {
|
|
|
|
/* Find and populate DXCC */
|
|
$('.callsign-suggest').hide();
|
|
|
|
if (isSatelliteLookupContext()) {
|
|
var sat_type = "SAT";
|
|
var json_band = "0";
|
|
var json_mode = "0";
|
|
} else {
|
|
var sat_type = "0";
|
|
var json_band = $("#band").val();
|
|
var json_mode = $("#mode").val();
|
|
}
|
|
|
|
var find_callsign = $(this).val().toUpperCase();
|
|
var callsign = find_callsign;
|
|
var requestId = ++callsignLookupRequestId;
|
|
|
|
find_callsign=find_callsign.replace(/\//g, "-");
|
|
find_callsign=find_callsign.replace('Ø', '0');
|
|
|
|
// Replace / in a callsign with - to stop urls breaking
|
|
$.getJSON(base_url + 'index.php/logbook/json/' + find_callsign + '/' + sat_type + '/' + json_band + '/' + json_mode + '/' + $('#stationProfile').val(), function(result)
|
|
{
|
|
if (!isLookupStillCurrent(requestId, find_callsign)) {
|
|
return;
|
|
}
|
|
|
|
// Make sure the typed callsign and json result match
|
|
var currentCallsign = $('#callsign').val().toUpperCase().replace(/\//g, "-").replace('Ø', '0');
|
|
if(currentCallsign === find_callsign) {
|
|
|
|
// Enter lookup mode - pause auto-refresh of logbook pagination
|
|
previousContactsLookupMode = true;
|
|
pauseAutoRefresh();
|
|
|
|
// Reset QSO fields but keep current DXCC badge/country to avoid flicker.
|
|
resetDefaultQSOFields(true);
|
|
|
|
if(result.dxcc.entity != undefined) {
|
|
$('#country').val(convert_case(result.dxcc.entity));
|
|
$('#callsign_info').text(convert_case(result.dxcc.entity));
|
|
|
|
// Reset CSS values before updating
|
|
$('#callsign').removeClass("confirmedGrid");
|
|
$('#callsign').removeClass("workedGrid");
|
|
$('#callsign').removeClass("newGrid");
|
|
$('#callsign').attr('title', '');
|
|
|
|
if (result.callsignConfirmed || result.confirmed) {
|
|
$('#callsign').addClass("confirmedGrid");
|
|
$('#callsign').attr('title', 'Callsign was already worked and confirmed in the past on this band and mode!');
|
|
} else if (result.callsignWorkedBefore) {
|
|
$('#callsign').addClass("workedGrid");
|
|
$('#callsign').attr('title', 'Callsign was already worked in the past on this band and mode!');
|
|
} else {
|
|
$('#callsign').addClass("newGrid");
|
|
$('#callsign').attr('title', 'New Callsign!');
|
|
}
|
|
|
|
changebadge(result.dxcc.entity);
|
|
}
|
|
|
|
if(result.lotw_member == "active") {
|
|
$('#lotw_info').text("LoTW");
|
|
if (result.lotw_days > 365) {
|
|
$('#lotw_info').addClass('lotw_info_red');
|
|
} else if (result.lotw_days > 30) {
|
|
$('#lotw_info').addClass('lotw_info_orange');
|
|
$lotw_hint = ' lotw_info_orange';
|
|
} else if (result.lotw_days > 7) {
|
|
$('#lotw_info').addClass('lotw_info_yellow');
|
|
}
|
|
$('#lotw_link').attr('href',"https://lotw.arrl.org/lotwuser/act?act="+callsign);
|
|
$('#lotw_link').attr('target',"_blank");
|
|
$('#lotw_info').attr('data-bs-toggle',"tooltip");
|
|
$('#lotw_info').attr('title',"LoTW User. Last upload was "+result.lotw_days+" days ago");
|
|
$('[data-bs-toggle="tooltip"]').tooltip();
|
|
}
|
|
$('#qrz_info').html('<a target="_blank" href="https://www.qrz.com/db/'+callsign+'"><img width="32" height="32" src="'+base_url+'images/icons/qrz.com.png"></a>');
|
|
$('#qrz_info').attr('title', 'Lookup '+callsign+' info on qrz.com');
|
|
$('#hamqth_info').html('<a target="_blank" href="https://www.hamqth.com/'+callsign+'"><img width="32" height="32" src="'+base_url+'images/icons/hamqth.com.png"></a>');
|
|
$('#hamqth_info').attr('title', 'Lookup '+callsign+' info on hamqth.com');
|
|
renderCallbookPanel(callsign, result);
|
|
|
|
var $dok_select = $('#darc_dok').selectize();
|
|
var dok_selectize = $dok_select[0] ? $dok_select[0].selectize : null;
|
|
if (result.dxcc.adif == '230') {
|
|
$.get(base_url + 'index.php/lookup/dok/' + $('#callsign').val().toUpperCase(), function(result) {
|
|
if (!isLookupStillCurrent(requestId, find_callsign)) {
|
|
return;
|
|
}
|
|
if (result && dok_selectize) {
|
|
dok_selectize.addOption({name: result});
|
|
dok_selectize.setValue(result, false);
|
|
}
|
|
});
|
|
} else {
|
|
if (dok_selectize) dok_selectize.clear();
|
|
}
|
|
|
|
$('#dxcc_id').val(result.dxcc.adif);
|
|
$('#cqz').val(result.dxcc.cqz);
|
|
$('#ituz').val(result.dxcc.ituz);
|
|
|
|
var redIcon = L.icon({
|
|
iconUrl: icon_dot_url,
|
|
iconSize: [18, 18], // size of the icon
|
|
});
|
|
|
|
// Set Map to Lat/Long
|
|
markers.clearLayers();
|
|
mymap.setZoom(8);
|
|
if (typeof result.latlng !== "undefined" && result.latlng !== false) {
|
|
var marker = L.marker([result.latlng[0], result.latlng[1]], {icon: redIcon});
|
|
mymap.panTo([result.latlng[0], result.latlng[1]]);
|
|
mymap.setView([result.latlng[0], result.latlng[1]], 8);
|
|
} else {
|
|
var marker = L.marker([result.dxcc.lat, result.dxcc.long], {icon: redIcon});
|
|
mymap.panTo([result.dxcc.lat, result.dxcc.long]);
|
|
mymap.setView([result.dxcc.lat, result.dxcc.long], 8);
|
|
}
|
|
|
|
markers.addLayer(marker).addTo(mymap);
|
|
|
|
|
|
var overwriteConflicts = getLookupOverwriteConflicts(result);
|
|
showLookupOverwriteModal(overwriteConflicts).then(function(approval) {
|
|
if (!isLookupStillCurrent(requestId, find_callsign)) {
|
|
return;
|
|
}
|
|
|
|
if (shouldReplaceLookupField($('#qsl_via'), result.qsl_manager, 'qsl_via', approval)) {
|
|
$('#qsl_via').val(result.qsl_manager);
|
|
}
|
|
|
|
if (shouldReplaceLookupField($('#name'), result.callsign_name, 'name', approval)) {
|
|
$('#name').val(result.callsign_name);
|
|
}
|
|
|
|
if (shouldReplaceLookupField($('#qth'), result.callsign_qth, 'qth', approval)) {
|
|
$('#qth').val(result.callsign_qth);
|
|
}
|
|
|
|
applyLookupLocator(result, approval);
|
|
});
|
|
|
|
if($('#continent').val() == "") {
|
|
$('#continent').val(result.dxcc.cont);
|
|
}
|
|
|
|
/*
|
|
* Update state with returned value
|
|
*/
|
|
if($("#input_usa_state").val() == "") {
|
|
$("#input_usa_state").val(result.callsign_state).trigger('change');
|
|
}
|
|
|
|
/*
|
|
* Update county with returned value
|
|
*/
|
|
var $county_elem = $('#stationCntyInput');
|
|
if( $county_elem.length && $county_elem.has('option').length == 0 && result.callsign_us_county != "") {
|
|
var $county_select = $county_elem.selectize();
|
|
var county_selectize = $county_select[0] ? $county_select[0].selectize : null;
|
|
if (county_selectize) {
|
|
county_selectize.addOption({name: result.callsign_us_county});
|
|
county_selectize.setValue(result.callsign_us_county, false);
|
|
}
|
|
}
|
|
|
|
if(result.timesWorked != "") {
|
|
$('#timesWorked').html(result.timesWorked + ' ' + lang_qso_title_times_worked_before);
|
|
} else {
|
|
$('#timesWorked').html(lang_qso_title_previous_contacts);
|
|
}
|
|
if($('#iota_ref').val() == "") {
|
|
$('#iota_ref').val(result.callsign_iota);
|
|
}
|
|
/* display past QSOs */
|
|
var partialHtml = (typeof result.partial === 'string') ? result.partial : '';
|
|
|
|
if (partialHtml.trim() !== '') {
|
|
// State 2: Callsign found in log with past QSOs
|
|
$('#partial_view').html(partialHtml);
|
|
setPreviousContactsPanelState(true);
|
|
} else {
|
|
// State 3: Callsign found but NO past QSOs in database
|
|
var noQsoMsg = '<div class="alert alert-info small mb-2">'
|
|
+ '<i class="fa fa-info-circle me-2"></i>'
|
|
+ 'No past QSOs with <strong>' + escapeNoticeValue(find_callsign) + '</strong>—see callbook details above.'
|
|
+ '</div>';
|
|
$('#partial_view').html(noQsoMsg);
|
|
setPreviousContactsPanelState(true);
|
|
}
|
|
// Get DXX Summary
|
|
getDxccResult(result.dxcc.adif, convert_case(result.dxcc.entity));
|
|
}
|
|
});
|
|
} else {
|
|
// Reset QSO fields
|
|
resetDefaultQSOFields();
|
|
// Reset tabs - go back to Previous Contacts when callsign is cleared
|
|
resetToPreviousContactsTab();
|
|
}
|
|
})
|
|
|
|
function pauseAutoRefresh() {
|
|
if (typeof htmx !== 'undefined' && document.getElementById('qso-last-table-content')) {
|
|
var elem = document.getElementById('qso-last-table-content');
|
|
if (elem) {
|
|
elem.removeAttribute('hx-trigger');
|
|
}
|
|
}
|
|
}
|
|
|
|
function resumeAutoRefresh() {
|
|
if (typeof htmx !== 'undefined' && document.getElementById('qso-last-table-content')) {
|
|
var elem = document.getElementById('qso-last-table-content');
|
|
if (elem) {
|
|
elem.setAttribute('hx-trigger', 'every 5s');
|
|
htmx.process(elem);
|
|
}
|
|
}
|
|
}
|
|
|
|
function setPreviousContactsPanelState(showLookupDetails) {
|
|
if (showLookupDetails) {
|
|
// Show callsign-specific results (either QSOs found or "not found" message)
|
|
$('#qso-last-table').hide();
|
|
$('#qso-last-table').next('small').hide();
|
|
$('#partial_view').show();
|
|
previousContactsLookupMode = true;
|
|
return;
|
|
}
|
|
|
|
// Show paginated logbook (no callsign lookup active)
|
|
$('#qso-last-table').show();
|
|
$('#qso-last-table').next('small').show();
|
|
$('#partial_view').html('');
|
|
$('#partial_view').hide();
|
|
previousContactsLookupMode = false;
|
|
}
|
|
|
|
// Function to reset back to Previous Contacts tab
|
|
function resetToPreviousContactsTab() {
|
|
// Clear DXCC Summary tab content
|
|
$('#dxcc-summary-content').html('');
|
|
// Switch back to Previous Contacts tab
|
|
if (document.getElementById('previous-contacts-tab')) {
|
|
var previousContactsTab = new bootstrap.Tab(document.getElementById('previous-contacts-tab'));
|
|
previousContactsTab.show();
|
|
}
|
|
// Show the default previous contacts table and hide lookup details.
|
|
setPreviousContactsPanelState(false);
|
|
}
|
|
|
|
// Re-apply visibility state after HTMX updates the previous contacts markup.
|
|
if (typeof htmx !== 'undefined' && document.body) {
|
|
document.body.addEventListener('htmx:afterSwap', function(evt) {
|
|
var detail = evt && evt.detail ? evt.detail : null;
|
|
var target = detail && detail.target ? detail.target : null;
|
|
if (!target) {
|
|
return;
|
|
}
|
|
|
|
if (target.id !== 'qso-last-table' && target.id !== 'qso-last-table-content') {
|
|
return;
|
|
}
|
|
|
|
// If we're in lookup mode, keep showing the partial_view (callsign-specific results)
|
|
// If we're not in lookup mode, show the main pagination table
|
|
if (previousContactsLookupMode) {
|
|
setPreviousContactsPanelState(true);
|
|
} else if ($('#partial_view').html().trim() !== '') {
|
|
setPreviousContactsPanelState(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
// If a radio is selected, prefer current CAT values over stale form defaults.
|
|
function syncFromSelectedRadioAfterReset() {
|
|
var $radios = $('select.radios');
|
|
var selectedRadioID = String($radios.first().val() || '0');
|
|
if (selectedRadioID === '0') {
|
|
return false;
|
|
}
|
|
|
|
// Use the radio change path so CAT lock state is reset before applying values.
|
|
if ($radios.length > 0) {
|
|
$radios.first().trigger('change');
|
|
return true;
|
|
}
|
|
|
|
if (typeof updateFromCAT === 'function') {
|
|
var now = Date.now();
|
|
if (now - lastResetCatSyncNoticeAt > 1000) {
|
|
showQsoNotice('Form reset. Syncing live data from selected radio.', 'info');
|
|
lastResetCatSyncNoticeAt = now;
|
|
}
|
|
updateFromCAT(selectedRadioID);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Reset to Previous Contacts tab when form is reset
|
|
$('#qso_input').on('reset', function() {
|
|
resetCallsignLookupState();
|
|
|
|
if (suppressNextResetHandler) {
|
|
suppressNextResetHandler = false;
|
|
return;
|
|
}
|
|
|
|
setTimeout(function() {
|
|
reset_fields();
|
|
resetToPreviousContactsTab();
|
|
syncFromSelectedRadioAfterReset();
|
|
}, 100);
|
|
});
|
|
|
|
function resetQsoEntryOnEscape() {
|
|
var qsoForm = document.getElementById('qso_input');
|
|
if (!qsoForm) {
|
|
return;
|
|
}
|
|
var selectedRadioID = String($('select.radios').first().val() || '0');
|
|
var hasSelectedRadio = selectedRadioID !== '0';
|
|
|
|
// Capture the operating context the user currently has selected BEFORE native
|
|
// form reset clobbers it with server-session defaults (last logged QSO values).
|
|
var preBand = $('#band').val();
|
|
var preMode = $('#mode').val();
|
|
var preSatName = $('#sat_name').val();
|
|
var preSatMode = $('#sat_mode').val();
|
|
var prePropMode = $('#selectPropagation').val();
|
|
|
|
qsoForm.reset();
|
|
resetCallsignLookupState();
|
|
resetDefaultQSOFields();
|
|
resetToPreviousContactsTab();
|
|
$('#callsign').trigger('focus');
|
|
|
|
// The on('reset') handler runs reset_fields() + clearSatelliteFields() in 100ms.
|
|
// Re-apply the captured context afterwards so the user stays on the band/mode/
|
|
// satellite they had selected, not the one from the previous QSO session.
|
|
setTimeout(function() {
|
|
$('#band').val(preBand);
|
|
$('#mode').val(preMode);
|
|
if (!hasSelectedRadio && (preSatName || preSatMode || String(prePropMode || '').toUpperCase() === 'SAT')) {
|
|
$('#sat_name').val(preSatName);
|
|
$('#sat_mode').val(preSatMode);
|
|
$('#selectPropagation').val(prePropMode || 'SAT');
|
|
} else if (hasSelectedRadio) {
|
|
// Keep satellite fields clear until fresh CAT data is applied.
|
|
$('#sat_name').val('').removeData('catValue');
|
|
$('#sat_mode').val('').removeData('catValue');
|
|
$('#selectPropagation').val('').removeData('catValue');
|
|
}
|
|
if (typeof setRst === 'function') {
|
|
setRst($('#mode').val());
|
|
}
|
|
syncFromSelectedRadioAfterReset();
|
|
}, 150);
|
|
}
|
|
|
|
// Global ESC handling on the QSO page: reset form, return to Previous Contacts, and focus callsign.
|
|
$(document).off('keydown.qsoEscapeReset').on('keydown.qsoEscapeReset', function(e) {
|
|
if (e.key !== 'Escape' && e.keyCode !== 27) {
|
|
return;
|
|
}
|
|
|
|
if (!document.getElementById('qso_input')) {
|
|
return;
|
|
}
|
|
|
|
if ($(e.target).closest('.modal.show').length) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
window.cloudlogQsoEscHandledAt = Date.now();
|
|
resetQsoEntryOnEscape();
|
|
});
|
|
|
|
// Also handle when callsign is cleared (empty value entered)
|
|
$('#callsign').on('input keyup', function() {
|
|
if ($(this).val() === '' && lastCallsignUpdated !== '') {
|
|
resetCallsignLookupState();
|
|
resetDefaultQSOFields();
|
|
resetToPreviousContactsTab();
|
|
}
|
|
});
|
|
|
|
// Only set the frequency when not set by userdata/PHP.
|
|
if ($('#frequency').val() == "")
|
|
{
|
|
$.get(base_url + 'index.php/qso/band_to_freq/' + $('#band').val() + '/' + $('.mode').val(), function(result) {
|
|
$('#frequency').val(result);
|
|
$('#frequency_rx').val("");
|
|
});
|
|
}
|
|
|
|
/* time input shortcut */
|
|
$('#start_time').change(function() {
|
|
var raw_time = $(this).val();
|
|
if(raw_time.match(/^\d\[0-6]d$/)) {
|
|
raw_time = "0"+raw_time;
|
|
}
|
|
if(raw_time.match(/^[012]\d[0-5]\d$/)) {
|
|
raw_time = raw_time.substring(0,2)+":"+raw_time.substring(2,4);
|
|
$('#start_time').val(raw_time);
|
|
}
|
|
});
|
|
$('#end_time').change(function() {
|
|
var raw_time = $(this).val();
|
|
if(raw_time.match(/^\d\[0-6]d$/)) {
|
|
raw_time = "0"+raw_time;
|
|
}
|
|
if(raw_time.match(/^[012]\d[0-5]\d$/)) {
|
|
raw_time = raw_time.substring(0,2)+":"+raw_time.substring(2,4);
|
|
$('#end_time').val(raw_time);
|
|
}
|
|
});
|
|
|
|
/* date input shortcut */
|
|
$('#start_date').change(function() {
|
|
raw_date = $(this).val();
|
|
if(raw_date.match(/^[12]\d{3}[01]\d[0123]\d$/)) {
|
|
raw_date = raw_date.substring(0,4)+"-"+raw_date.substring(4,6)+"-"+raw_date.substring(6,8);
|
|
$('#start_date').val(raw_date);
|
|
}
|
|
});
|
|
|
|
/* on mode change */
|
|
$('.mode').change(function() {
|
|
$.get(base_url + 'index.php/qso/band_to_freq/' + $('#band').val() + '/' + $('.mode').val(), function(result) {
|
|
$('#frequency').val(result);
|
|
$('#frequency_rx').val("");
|
|
});
|
|
});
|
|
|
|
/* Calculate Frequency */
|
|
/* on band change */
|
|
$('#band').change(function() {
|
|
$.get(base_url + 'index.php/qso/band_to_freq/' + $(this).val() + '/' + $('.mode').val(), function(result) {
|
|
$('#frequency').val(result);
|
|
$('#frequency_rx').val("");
|
|
});
|
|
});
|
|
|
|
/* On Key up Calculate Bearing and Distance */
|
|
var locatorDebounceTimer = null;
|
|
$("#locator").keyup(function(){
|
|
clearTimeout(locatorDebounceTimer);
|
|
var $locator = $(this);
|
|
locatorDebounceTimer = setTimeout(function(){
|
|
if ($locator.val()) {
|
|
var qra_input = $locator.val();
|
|
|
|
var qra_lookup = qra_input.substring(0, 4);
|
|
|
|
if(qra_lookup.length >= 4) {
|
|
|
|
// Check Log if satname is provided
|
|
if (isSatelliteLookupContext()) {
|
|
|
|
//logbook/jsonlookupgrid/io77/SAT/0/0
|
|
|
|
$.getJSON(base_url + 'index.php/logbook/jsonlookupgrid/' + qra_lookup.toUpperCase() + '/SAT/0/0', function(result)
|
|
{
|
|
// Reset CSS values before updating
|
|
$('#locator').removeClass("confirmedGrid");
|
|
$('#locator').removeClass("workedGrid");
|
|
$('#locator').removeClass("newGrid");
|
|
$('#locator').attr('title', '');
|
|
|
|
if (result.confirmed) {
|
|
$('#locator').addClass("confirmedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked and confirmed in the past');
|
|
} else if (result.workedBefore) {
|
|
$('#locator').addClass("workedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked in the past');
|
|
} else {
|
|
$('#locator').addClass("newGrid");
|
|
$('#locator').attr('title', 'New grid!');
|
|
}
|
|
})
|
|
} else {
|
|
$.getJSON(base_url + 'index.php/logbook/jsonlookupgrid/' + qra_lookup.toUpperCase() + '/0/' + $("#band").val() +'/' + $("#mode").val(), function(result)
|
|
{
|
|
// Reset CSS values before updating
|
|
$('#locator').removeClass("confirmedGrid");
|
|
$('#locator').removeClass("workedGrid");
|
|
$('#locator').removeClass("newGrid");
|
|
$('#locator').attr('title', '');
|
|
|
|
if (result.confirmed) {
|
|
$('#locator').addClass("confirmedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked and confimred in the past');
|
|
} else if (result.workedBefore) {
|
|
$('#locator').addClass("workedGrid");
|
|
$('#locator').attr('title', 'Grid was already worked in the past');
|
|
} else {
|
|
$('#locator').addClass("newGrid");
|
|
$('#locator').attr('title', 'New grid!');
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
if(qra_input.length >= 4 && $locator.val().length > 0) {
|
|
// Map pin — grid → lat/lng (pure frontend math, no server round-trip)
|
|
var latlng = QraUtils.qra2latlong(qra_input);
|
|
markers.clearLayers();
|
|
if (latlng && typeof latlng[0] !== "undefined" && typeof latlng[1] !== "undefined") {
|
|
var redIcon = L.icon({
|
|
iconUrl: icon_dot_url,
|
|
iconSize: [18, 18],
|
|
});
|
|
var marker = L.marker([latlng[0], latlng[1]], {icon: redIcon});
|
|
mymap.setZoom(8);
|
|
mymap.panTo([latlng[0], latlng[1]]);
|
|
mymap.setView([latlng[0], latlng[1]], 8);
|
|
markers.addLayer(marker).addTo(mymap);
|
|
}
|
|
|
|
// Bearing and distance — pure frontend math using injected station gridsquares
|
|
var myGrid = station_gridsquares[$('#stationProfile').val()];
|
|
if (myGrid) {
|
|
var bearingStr = QraUtils.bearingString(myGrid, qra_input, qso_measurement_base);
|
|
if (bearingStr) {
|
|
$('#locator_info').html(bearingStr).fadeIn("slow");
|
|
}
|
|
|
|
var dist = QraUtils.distanceKm(myGrid, qra_input);
|
|
document.getElementById("distance").value = dist !== null ? dist : '';
|
|
}
|
|
}
|
|
}
|
|
}, 300);
|
|
});
|
|
|
|
// Change report based on mode
|
|
$('.mode').change(function(){
|
|
setRst($('.mode') .val());
|
|
});
|
|
|
|
function convert_case(str) {
|
|
var lower = str.toLowerCase();
|
|
return lower.replace(/(^| )(\w)/g, function(x) {
|
|
return x.toUpperCase();
|
|
});
|
|
}
|
|
|
|
var qsoCallhistoryLookupTimer = null;
|
|
|
|
function qsoCallhistoryEscapeHtml(unsafeText) {
|
|
return String(unsafeText || '').replace(/[&<>\"]/g, function(tag) {
|
|
var replacements = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"'
|
|
};
|
|
return replacements[tag] || tag;
|
|
});
|
|
}
|
|
|
|
function qsoCallhistoryNormalizeText(value) {
|
|
return String(value || '').trim().toLowerCase();
|
|
}
|
|
|
|
function renderQsoCallhistoryPanel(matches, defaultText) {
|
|
var $card = $('#qso-callhistory-inline');
|
|
var $panel = $('#qso-callhistory-results');
|
|
if ($panel.length === 0 || $card.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (!matches || matches.length === 0) {
|
|
$panel.html('');
|
|
$card.hide();
|
|
return;
|
|
}
|
|
|
|
var html = '<ul class="list-group list-group-flush">';
|
|
|
|
$.each(matches, function(_, match) {
|
|
var organizationLabel = String(match.organization_label || 'Member');
|
|
var membershipNumber = String(match.exch1 || '');
|
|
var memberName = String(match.name || '');
|
|
var normalizedMembershipNumber = qsoCallhistoryNormalizeText(membershipNumber);
|
|
var normalizedMemberName = qsoCallhistoryNormalizeText(memberName);
|
|
|
|
var line = '<strong>' + qsoCallhistoryEscapeHtml(match.organization_label || 'Member') + '</strong>';
|
|
if (membershipNumber && qsoCallhistoryNormalizeText(organizationLabel).indexOf(normalizedMembershipNumber) === -1) {
|
|
line += ' #' + qsoCallhistoryEscapeHtml(membershipNumber);
|
|
}
|
|
if (memberName && normalizedMemberName !== normalizedMembershipNumber) {
|
|
line += ' - ' + qsoCallhistoryEscapeHtml(memberName);
|
|
}
|
|
|
|
var sigValue = qsoCallhistoryEscapeHtml(match.organization_label || '');
|
|
var sigInfoValue = qsoCallhistoryEscapeHtml(match.exch1 || '');
|
|
if (sigValue !== '' || sigInfoValue !== '') {
|
|
line += ' <button type="button" class="btn btn-sm btn-outline-secondary qso-copy-sig-btn ms-2 py-0 px-2" data-sig="' + sigValue + '" data-siginfo="' + sigInfoValue + '"><i class="fas fa-copy me-1"></i>Copy to SIG</button>';
|
|
}
|
|
|
|
html += '<li class="list-group-item px-0 py-2">' + line + '</li>';
|
|
});
|
|
|
|
html += '</ul>';
|
|
$panel.html(html);
|
|
$card.show();
|
|
}
|
|
|
|
$(document).on('click', '.qso-copy-sig-btn', function() {
|
|
var sig = $(this).data('sig') || '';
|
|
var sigInfo = $(this).data('siginfo') || '';
|
|
|
|
$('#sig').val(sig);
|
|
$('#sig_info').val(sigInfo);
|
|
});
|
|
|
|
function lookupQsoCallhistory(callsign) {
|
|
if (qsoCallhistoryLookupTimer !== null) {
|
|
clearTimeout(qsoCallhistoryLookupTimer);
|
|
}
|
|
|
|
qsoCallhistoryLookupTimer = setTimeout(function() {
|
|
$.ajax({
|
|
url: base_url + 'index.php/callhistory/lookup',
|
|
type: 'post',
|
|
data: { callsign: callsign },
|
|
success: function(response) {
|
|
if (!response || response.status !== 'ok') {
|
|
renderQsoCallhistoryPanel([], 'No call history match for this callsign.');
|
|
return;
|
|
}
|
|
renderQsoCallhistoryPanel(response.matches || [], 'No call history match for this callsign.');
|
|
},
|
|
error: function() {
|
|
renderQsoCallhistoryPanel([], 'Call history lookup failed.');
|
|
}
|
|
});
|
|
}, 250);
|
|
}
|
|
|
|
$('#dxcc_id').on('change', function() {
|
|
if (typeof toggleDokField === 'function') toggleDokField();
|
|
if (typeof toggleUsaFields === 'function') toggleUsaFields();
|
|
$.getJSON(base_url + 'index.php/logbook/jsonentity/' + $(this).val(), function (result) {
|
|
if (result.dxcc.name != undefined) {
|
|
|
|
$('#country').val(convert_case(result.dxcc.name));
|
|
$('#cqz').val(convert_case(result.dxcc.cqz));
|
|
|
|
$('#callsign_info').removeClass("text-bg-secondary");
|
|
$('#callsign_info').removeClass("text-bg-success");
|
|
$('#callsign_info').removeClass("text-bg-danger");
|
|
$('#callsign_info').attr('title', '');
|
|
$('#callsign_info').text(convert_case(result.dxcc.name));
|
|
|
|
changebadge(result.dxcc.name);
|
|
|
|
// Set Map to Lat/Long it locator is not empty
|
|
if($('#locator').val() == "") {
|
|
var redIcon = L.icon({
|
|
iconUrl: icon_dot_url,
|
|
iconSize: [18, 18], // size of the icon
|
|
});
|
|
|
|
markers.clearLayers();
|
|
var marker = L.marker([result.dxcc.lat, result.dxcc.long], {icon: redIcon});
|
|
mymap.setZoom(8);
|
|
mymap.panTo([result.dxcc.lat, result.dxcc.long]);
|
|
markers.addLayer(marker).addTo(mymap);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
//Spacebar moves to the name field when you're entering a callsign
|
|
//Similar to contesting ux, good for pileups.
|
|
$("#callsign").on("keypress", function(e) {
|
|
if (e.which == 32){
|
|
$("#name").focus();
|
|
return false; //Eliminate space char
|
|
}
|
|
});
|
|
|
|
function quickLookupDxcc(callsign) {
|
|
if (!callsign || callsign.length < 3) {
|
|
return;
|
|
}
|
|
|
|
var requestId = ++callsignDxccQuickRequestId;
|
|
var find_callsign = callsign.toUpperCase().replace(/\//g, "-").replace('Ø', '0');
|
|
|
|
$.getJSON(base_url + 'index.php/logbook/jsondxcc/' + find_callsign, function(result) {
|
|
if (requestId !== callsignDxccQuickRequestId) {
|
|
return;
|
|
}
|
|
|
|
var currentCallsign = $('#callsign').val().toUpperCase().replace(/\//g, "-").replace('Ø', '0');
|
|
if (currentCallsign !== find_callsign) {
|
|
return;
|
|
}
|
|
|
|
if (result.dxcc && result.dxcc.entity !== undefined) {
|
|
$('#country').val(convert_case(result.dxcc.entity));
|
|
$('#callsign_info').text(convert_case(result.dxcc.entity));
|
|
changebadge(result.dxcc.entity);
|
|
$('#dxcc_id').val(result.dxcc.adif);
|
|
$('#cqz').val(result.dxcc.cqz);
|
|
$('#ituz').val(result.dxcc.ituz);
|
|
}
|
|
});
|
|
}
|
|
|
|
// On Key up check and suggest callsigns
|
|
$("#callsign").keyup(function() {
|
|
if (callsignDxccQuickTimer) {
|
|
clearTimeout(callsignDxccQuickTimer);
|
|
}
|
|
|
|
var currentCall = $(this).val();
|
|
if (currentCall.length >= 3) {
|
|
callsignDxccQuickTimer = setTimeout(function() {
|
|
quickLookupDxcc(currentCall);
|
|
}, 200);
|
|
}
|
|
|
|
if ($(this).val().length >= 3) {
|
|
$('.callsign-suggest').show();
|
|
$callsign = $(this).val().replace('Ø', '0');
|
|
lookupQsoCallhistory($callsign.toUpperCase());
|
|
$.ajax({
|
|
url: 'lookup/scp',
|
|
method: 'POST',
|
|
data: {
|
|
callsign: $callsign.toUpperCase()
|
|
},
|
|
success: function(result) {
|
|
$('.callsign-suggestions').text(result);
|
|
}
|
|
});
|
|
} else {
|
|
renderQsoCallhistoryPanel([], 'Type a callsign to see membership details from your uploaded call history files.');
|
|
}
|
|
});
|
|
|
|
//Reset QSO form Fields function
|
|
function resetDefaultQSOFields(preserveDxccState) {
|
|
var keepDxcc = preserveDxccState === true;
|
|
var preservedCountry = '';
|
|
var preservedCallsignInfoText = '';
|
|
var preservedCallsignInfoTitle = '';
|
|
var preservedCallsignInfoClass = '';
|
|
var preservedDxccId = '';
|
|
var preservedCqz = '';
|
|
var preservedItuz = '';
|
|
|
|
if (keepDxcc) {
|
|
preservedCountry = $('#country').val();
|
|
preservedCallsignInfoText = $('#callsign_info').text();
|
|
preservedCallsignInfoTitle = $('#callsign_info').attr('title') || '';
|
|
preservedCallsignInfoClass = $('#callsign_info').attr('class') || '';
|
|
preservedDxccId = $('#dxcc_id').val();
|
|
preservedCqz = $('#cqz').val();
|
|
preservedItuz = $('#ituz').val();
|
|
}
|
|
|
|
$('#callsign_info').text("");
|
|
$('#locator_info').text("");
|
|
$('#country').val("");
|
|
$('#continent').val("");
|
|
$('#lotw_info').text("");
|
|
$('#lotw_info').removeClass("lotw_info_red");
|
|
$('#lotw_info').removeClass("lotw_info_yellow");
|
|
$('#lotw_info').removeClass("lotw_info_orange");
|
|
$('#qrz_info').text("");
|
|
$('#hamqth_info').text("");
|
|
$('#dxcc_id').val("").trigger('change');
|
|
$('#cqz').val("");
|
|
$('#ituz').val("");
|
|
$("#locator").removeClass("workedGrid");
|
|
$("#locator").removeClass("confirmedGrid");
|
|
$("#locator").removeClass("newGrid");
|
|
$("#callsign").removeClass("workedGrid");
|
|
$("#callsign").removeClass("confirmedGrid");
|
|
$("#callsign").removeClass("newGrid");
|
|
$('#callsign_info').removeClass("text-bg-secondary");
|
|
$('#callsign_info').removeClass("text-bg-success");
|
|
$('#callsign_info').removeClass("text-bg-danger");
|
|
resetCallbookPanel();
|
|
$('.dxccsummary').remove();
|
|
$('#timesWorked').html(lang_qso_title_previous_contacts);
|
|
|
|
if (keepDxcc) {
|
|
$('#country').val(preservedCountry);
|
|
$('#callsign_info').text(preservedCallsignInfoText);
|
|
$('#callsign_info').attr('title', preservedCallsignInfoTitle);
|
|
$('#callsign_info').attr('class', preservedCallsignInfoClass);
|
|
$('#dxcc_id').val(preservedDxccId);
|
|
$('#cqz').val(preservedCqz);
|
|
$('#ituz').val(preservedItuz);
|
|
}
|
|
}
|
|
|
|
function closeModal() {
|
|
var container = document.getElementById("modals-here")
|
|
var backdrop = document.getElementById("modal-backdrop")
|
|
var modal = document.getElementById("modal")
|
|
|
|
modal.classList.remove("show")
|
|
backdrop.classList.remove("show")
|
|
|
|
setTimeout(function() {
|
|
container.removeChild(backdrop)
|
|
container.removeChild(modal)
|
|
}, 200)
|
|
}
|
|
|
|
// [TimeOff] test Consistency timeOff value (concidering start and end are between 23:00 and 00:59) //
|
|
function testTimeOffConsistency() {
|
|
var _start_time = $('#qso_input input[name="start_time"]').val();
|
|
var _end_time = $('#qso_input input[name="end_time"]').val();
|
|
$('#qso_input input[name="end_time"]').removeClass('inputError');
|
|
$('#qso_input .warningOnSubmit').hide();
|
|
$('#qso_input .warningOnSubmit_txt').empty();
|
|
if ( !( (parseInt(_start_time.replaceAll(':','')) <= parseInt(_end_time.replaceAll(':','')))
|
|
|| ((_start_time.substring(0,2)=="23")&&(_end_time.substring(0,2)=="00")) ) ) {
|
|
$('#qso_input input[name="end_time"]').addClass('inputError');
|
|
$('#qso_input .warningOnSubmit_txt').html(text_error_timeoff_less_timeon);
|
|
$('#qso_input .warningOnSubmit').show();
|
|
$('#qso_input input[name="end_time"]').off('change').on('change',function(){ testTimeOffConsistency(); });
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|