some changes

This commit is contained in:
2026-02-24 15:03:56 +01:00
parent 648ef00bed
commit 5d524eba56
15 changed files with 316 additions and 378 deletions
+5 -14
View File
@@ -27,11 +27,8 @@ function destroyStream() {
function OnConnectivityCallback(isConnected) {
console.log("Connectivity changed:", isConnected);
if (Stream) {
Stream.Volume = $('#volumeSlider').val();
} else {
console.warn("Stream is not initialized.");
}
if (Stream) Stream.Volume = $('#volumeSlider').val();
else console.warn("Stream is not initialized.");
}
@@ -44,18 +41,14 @@ function OnPlayButtonClick(_ev) {
shouldReconnect = false;
destroyStream();
$playbutton.find('.fa-solid').toggleClass('fa-stop fa-play');
if (isAppleiOS && 'audioSession' in navigator) {
navigator.audioSession.type = "none";
}
if (isAppleiOS && 'audioSession' in navigator) navigator.audioSession.type = "none";
} else {
console.log("Starting stream...");
shouldReconnect = true;
createStream();
Stream.Start();
$playbutton.find('.fa-solid').toggleClass('fa-play fa-stop');
if (isAppleiOS && 'audioSession' in navigator) {
navigator.audioSession.type = "playback";
}
if (isAppleiOS && 'audioSession' in navigator) navigator.audioSession.type = "playback";
}
$playbutton.addClass('bg-gray').prop('disabled', true);
@@ -70,9 +63,7 @@ function updateVolume() {
newVolumeGlobal = newVolume;
console.log("Volume updated to:", newVolume);
Stream.Volume = newVolume;
} else {
console.warn("Stream is not initialized.");
}
} else console.warn("Stream is not initialized.");
}
$(document).ready(Init);
+12 -22
View File
@@ -3,18 +3,13 @@ function tuneUp() {
if (socket.readyState === WebSocket.OPEN) {
getCurrentFreq();
let addVal = 0;
if (currentFreq < 0.52) {
addVal = 9 - (Math.round(currentFreq*1000) % 9);
} else if (currentFreq < 1.71) {
if (currentFreq < 0.52) addVal = 9 - (Math.round(currentFreq*1000) % 9);
else if (currentFreq < 1.71) {
// TODO: Rework to replace 9 with 9 or 10 based on regionalisation setting
addVal = 9 - (Math.round(currentFreq*1000) % 9);
} else if (currentFreq < 29.6) {
addVal = 5 - (Math.round(currentFreq*1000) % 5);
} else if (currentFreq >= 65.9 && currentFreq < 74) {
addVal = 30 - ((Math.round(currentFreq*1000) - 65900) % 30);
} else {
addVal = 100 - (Math.round(currentFreq*1000) % 100);
}
} else if (currentFreq < 29.6) addVal = 5 - (Math.round(currentFreq*1000) % 5);
else if (currentFreq >= 65.9 && currentFreq < 74) addVal = 30 - ((Math.round(currentFreq*1000) - 65900) % 30);
else addVal = 100 - (Math.round(currentFreq*1000) % 100);
socket.send("T" + (Math.round(currentFreq*1000) + addVal));
}
}
@@ -23,18 +18,13 @@ function tuneDown() {
if (socket.readyState === WebSocket.OPEN) {
getCurrentFreq();
let subVal = 0;
if (currentFreq < 0.52) {
if (currentFreq < 0.52) subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
else if (currentFreq < 1.71) {
// TODO: Rework to replace 9 with 9 or 10 based on regionalisation setting (Americans use 10, because of dumbfuckinstan)
subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
} else if (currentFreq < 1.71) {
// TODO: Rework to replace 9 with 9 or 10 based on regionalisation setting
subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
} else if (currentFreq < 29.6) {
subVal = (Math.round(currentFreq*1000) % 5 == 0) ? 5 : (Math.round(currentFreq*1000) % 5);
} else if (currentFreq > 65.9 && currentFreq <= 74) {
subVal = ((Math.round(currentFreq*1000) - 65900) % 30 == 0) ? 30 : ((Math.round(currentFreq*1000) - 65900) % 30);
} else {
subVal = (Math.round(currentFreq*1000) % 100 == 0) ? 100 : (Math.round(currentFreq*1000) % 100);
}
} else if (currentFreq < 29.6) subVal = (Math.round(currentFreq*1000) % 5 == 0) ? 5 : (Math.round(currentFreq*1000) % 5);
else if (currentFreq > 65.9 && currentFreq <= 74) subVal = ((Math.round(currentFreq*1000) - 65900) % 30 == 0) ? 30 : ((Math.round(currentFreq*1000) - 65900) % 30);
else subVal = (Math.round(currentFreq*1000) % 100 == 0) ? 100 : (Math.round(currentFreq*1000) % 100);
socket.send("T" + (Math.round(currentFreq*1000) - subVal));
}
}
@@ -52,6 +42,6 @@ function getCurrentFreq() {
currentFreq = $('#data-frequency').text();
currentFreq = parseFloat(currentFreq).toFixed(3);
currentFreq = parseFloat(currentFreq);
return currentFreq;
}
+16 -20
View File
@@ -9,42 +9,40 @@ $(document).ready(function() {
const chatIdentityNickname = $('#chat-identity-nickname');
const chatNicknameInput = $('#chat-nickname');
const chatNicknameSave = $('#chat-nickname-save');
$(".chatbutton").on("click", function () {
togglePopup("#popup-panel-chat");
chatMessages.scrollTop(chatMessages[0].scrollHeight);
});
// Function to generate a random string
function generateRandomString(length) {
const characters = 'ABCDEFGHJKMNOPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
for (let i = 0; i < length; i++) result += characters.charAt(Math.floor(Math.random() * characters.length));
return result;
}
// Load nickname from localStorage on page load
let savedNickname = localStorage.getItem('nickname') || `User ${generateRandomString(5)}`;
chatNicknameInput.val(savedNickname);
chatIdentityNickname.text(savedNickname);
chatSocket.onmessage = function(event) {
const messageData = JSON.parse(event.data);
const isAdmin = messageData.admin ? '<span style="color: #bada55">[ADMIN]</span>' : '';
if (messageData.type === 'clientIp') {
chatIdentityNickname.html(isAdmin).append(document.createTextNode(" " + savedNickname));
chatIdentityNickname.attr('title', messageData.ip);
} else {
const chatMessage = `
<span class="color-2">[${messageData.time}]</span>
${isAdmin} <strong class="color-5" title="${typeof messageData.ip !== "undefined" ? 'IP Address: ' + messageData.ip : ''}">${messageData.nickname}</strong>:
${isAdmin} <strong class="color-5" title="${typeof messageData.ip !== "undefined" ? 'IP Address: ' + messageData.ip : ''}">${messageData.nickname}</strong>:
<span style="color: var(--color-text-2);">${$('<div/>').text(messageData.message).html()}</span><br>
`;
chatMessages.append(chatMessage);
if (chatMessages.is(':visible')) {
setTimeout(function() {
chatMessages.scrollTop(chatMessages[0].scrollHeight);
@@ -59,7 +57,7 @@ $(document).ready(function() {
}
}
};
$('.chat-send-message-btn').click(sendMessage);
chatNicknameSave.click(function() {
const currentNickname = chatNicknameInput.val().trim() || `Anonymous User ${generateRandomString(5)}`;
@@ -68,34 +66,32 @@ $(document).ready(function() {
chatIdentityNickname.text(savedNickname);
chatNicknameInput.blur();
});
chatButton.click(function() {
chatMessageCount = 0;
chatMessagesCount.text(chatMessageCount);
chatButton.removeClass('blink').addClass('bg-color-1');
chatSendInput.focus();
setTimeout(function() {
chatMessages.scrollTop(chatMessages[0].scrollHeight);
}, 100);
});
chatNicknameInput.keypress(function(event) {
if (event.which === 13) {
chatNicknameSave.trigger('click');
}
});
chatSendInput.keypress(function(event) {
if (event.which === 13) {
sendMessage();
}
if (event.which === 13) sendMessage();
});
function sendMessage() {
const nickname = savedNickname || `Anonymous User ${generateRandomString(5)}`;
const message = chatSendInput.val().trim();
if (message) {
const messageData = { nickname, message };
chatSocket.send(JSON.stringify(messageData));
+11 -27
View File
@@ -28,7 +28,7 @@ function submitConfig() {
function fetchConfig() {
$.getJSON("./getData")
.done(data => {
configData = data;
configData = data;
populateFields(configData);
initVolumeSlider();
initConnectionToggle();
@@ -38,9 +38,7 @@ function fetchConfig() {
function populateFields(data, prefix = "") {
$.each(data, (key, value) => {
if (value === null) {
value = ""; // Convert null to an empty string
}
if (value === null) value = ""; // Convert null to an empty string
let id = `${prefix}${prefix ? "-" : ""}${key}`;
const $element = $(`#${id}`);
@@ -50,16 +48,13 @@ function populateFields(data, prefix = "") {
$element.find('option').each(function() {
const $option = $(this);
const dataName = $option.data('name');
if (value.includes(dataName)) {
$option.prop('selected', true);
} else {
$option.prop('selected', false);
}
if (value.includes(dataName)) $option.prop('selected', true);
else $option.prop('selected', false);
});
$element.trigger('change');
}
return;
return;
}
if (typeof value === "object" && value !== null) {
@@ -68,11 +63,8 @@ function populateFields(data, prefix = "") {
const arrayId = `${id}-${index + 1}`;
const $arrayElement = $(`#${arrayId}`);
if ($arrayElement.length) {
$arrayElement.val(item);
} else {
console.log(`Element with id ${arrayId} not found`);
}
if ($arrayElement.length) $arrayElement.val(item);
else console.log(`Element with id ${arrayId} not found`);
});
return;
} else {
@@ -92,9 +84,7 @@ function populateFields(data, prefix = "") {
const $dropdownOption = $element.siblings('ul.options').find(`li[data-value="${value}"]`);
$element.val($dropdownOption.length ? $dropdownOption.text() : value);
$element.attr('data-value', value);
} else {
$element.val(value);
}
} else $element.val(value);
});
}
@@ -111,9 +101,7 @@ function updateConfigData(data, prefix = "") {
if ($presetElement.length) {
data[key].push($presetElement.val() || null); // Allow null if necessary
index++;
} else {
break;
}
} else break;
}
return;
}
@@ -123,16 +111,12 @@ function updateConfigData(data, prefix = "") {
const $selectedOptions = $element.find('option:selected');
$selectedOptions.each(function() {
const dataName = $(this).attr('data-name');
if (dataName) {
data[key].push(dataName);
}
if (dataName) data[key].push(dataName);
});
return;
}
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
return updateConfigData(value, id);
}
if (typeof value === "object" && value !== null && !Array.isArray(value)) return updateConfigData(value, id);
if ($element.length) {
const newValue = $element.attr("data-value") ?? $element.val() ?? null;
+42 -44
View File
@@ -23,38 +23,38 @@ $(document).ready(function() {
switch($currentDropdown.attr('id')) {
case 'data-ant':
socket.send("Z" + $(event.currentTarget).attr('data-value'));
resetRDS(getCurrentFreq()); // Reset RDS when change antenna input
break;
socket.send("Z" + $(event.currentTarget).attr('data-value'));
resetRDS(getCurrentFreq()); // Reset RDS when change antenna input
break;
case 'data-ant-phone':
socket.send("Z" + $(event.currentTarget).attr('data-value'));
resetRDS(getCurrentFreq()); // Reset RDS when change antenna input
break;
socket.send("Z" + $(event.currentTarget).attr('data-value'));
resetRDS(getCurrentFreq()); // Reset RDS when change antenna input
break;
case 'data-bw':
legacyBwValue = $(event.currentTarget).attr('data-value2') || "";
socket.send("F" + legacyBwValue);
socket.send("W" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
legacyBwValue = $(event.currentTarget).attr('data-value2') || "";
socket.send("F" + legacyBwValue);
socket.send("W" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
case 'data-bw-phone':
legacyBwValue = $(event.currentTarget).attr('data-value2') || "";
socket.send("F" + legacyBwValue);
socket.send("W" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
legacyBwValue = $(event.currentTarget).attr('data-value2') || "";
socket.send("F" + legacyBwValue);
socket.send("W" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
case 'data-agc':
socket.send("A" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
socket.send("A" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
case 'data-agc-phone':
socket.send("A" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
socket.send("A" + $(event.currentTarget).attr('data-value'));
$currentDropdown.find('input').val($(event.currentTarget).text());
break;
default:
$currentDropdown.find('input')
.val($(event.currentTarget).text())
.attr('data-value', $(event.currentTarget).data('value'));
break;
$currentDropdown.find('input')
.val($(event.currentTarget).text())
.attr('data-value', $(event.currentTarget).data('value'));
break;
}
// Use setTimeout to delay class removal
@@ -80,24 +80,24 @@ $(document).ready(function() {
const $options = currentDropdown.find('.option');
switch (event.key) {
case 'ArrowDown':
event.preventDefault();
currentIndex = (currentIndex + 1) % $options.length;
$options.eq(currentIndex).focus();
break;
event.preventDefault();
currentIndex = (currentIndex + 1) % $options.length;
$options.eq(currentIndex).focus();
break;
case 'ArrowUp':
event.preventDefault();
currentIndex = (currentIndex - 1 + $options.length) % $options.length;
$options.eq(currentIndex).focus();
break;
event.preventDefault();
currentIndex = (currentIndex - 1 + $options.length) % $options.length;
$options.eq(currentIndex).focus();
break;
case 'Enter':
event.preventDefault();
$options.eq(currentIndex).click();
break;
event.preventDefault();
$options.eq(currentIndex).click();
break;
case 'Escape':
currentDropdown.removeClass('opened');
currentDropdown = null;
currentIndex = -1;
break;
currentDropdown.removeClass('opened');
currentDropdown = null;
currentIndex = -1;
break;
}
};
@@ -106,9 +106,7 @@ $(document).ready(function() {
$listOfOptions.on('click', selectOption);
$dropdowns.on('click', 'input', toggleDropdown);
$dropdowns.on('keydown', 'input', function(event) {
if (event.key === 'Enter') {
toggleDropdown(event);
}
if (event.key === 'Enter') toggleDropdown(event);
});
$dropdowns.on('keydown', '.option', navigateOptions);
+152 -159
View File
@@ -25,23 +25,23 @@ const europe_programmes = [
const usa_programmes = [
"No PTY", "News", "Information", "Sports", "Talk", "Rock", "Classic Rock",
"Adults Hits", "Soft Rock", "Top 40", "Country", "Oldies", "Soft Music",
"Nostalgia", "Jazz", "Classical", "Rhythm and Blues", "Soft Rhythm and Blues",
"Nostalgia", "Jazz", "Classical", "Rhythm and Blues", "Soft Rhythm and Blues",
"Language", "Religious Music", "Religious Talk", "Personality", "Public", "College",
"Spanish Talk", "Spanish Music", "Hip Hop", "", "", "Weather", "Emergency Test", "Emergency"
"Spanish Talk", "Spanish Music", "Hip Hop", "", "", "Weather", "Emergency Test", "Emergency"
];
const rdsMode = localStorage.getItem('rdsMode');
$(document).ready(function () {
const signalToggle = $("#signal-units-toggle");
var $panel = $('.admin-quick-dashboard');
var panelWidth = $panel.outerWidth();
$(document).mousemove(function(e) {
var mouseX = e.pageX;
var panelLeft = parseInt($panel.css('left'));
if (mouseX <= 10 || (panelLeft === 4 && mouseX <= 100)) {
$panel.css('left', '4px');
} else {
@@ -50,10 +50,10 @@ $(document).ready(function () {
});
fillPresets();
signalToggle.on("change", function () {
const signalText = localStorage.getItem('signalUnit');
if (signalText == 'dbuv') {
signalText.text('dBµV');
} else if (signalText == 'dbf') {
@@ -62,7 +62,7 @@ $(document).ready(function () {
signalText.text('dBm');
}
});
// Check if device is an iPhone to prevent zoom on button press
if (/iPhone|iPod|iPad/.test(navigator.userAgent) && !window.MSStream) {
// Handle touchstart for buttons to prevent zoom
@@ -89,9 +89,9 @@ $(document).ready(function () {
$viewportMeta.attr('content', content);
}
}
const textInput = $('#commandinput');
textInput.on('change blur', function (event) {
const inputValue = Number(textInput.val());
// Check if the user agent contains 'iPhone'
@@ -101,18 +101,18 @@ $(document).ready(function () {
textInput.val('');
}
});
textInput.on('keyup', function (event) {
if (event.key !== 'Backspace' && localStorage.getItem('extendedFreqRange') != "true") {
let inputValue = textInput.val();
inputValue = inputValue.replace(/[^0-9.]/g, '');
if (inputValue.includes("..")) {
inputValue = inputValue.slice(0, inputValue.lastIndexOf('.')) + inputValue.slice(inputValue.lastIndexOf('.') + 1);
textInput.val(inputValue);
}
if (!inputValue.includes(".")) {
if (inputValue.startsWith('10') && inputValue.length > 2) {
inputValue = inputValue.slice(0, 3) + '.' + inputValue.slice(3);
@@ -130,31 +130,31 @@ $(document).ready(function () {
textInput.val('');
}
});
document.onkeydown = function(event) {
if (!event.repeat) {
checkKey(event);
}
};
let lastExecutionTime = 0;
const throttleDelay = 100; // Time in ms
$('#freq-container').on('wheel keypress', function (e) {
e.preventDefault();
const now = Date.now();
if (now - lastExecutionTime < throttleDelay) {
// Ignore this event as it's within the throttle delay
return;
}
lastExecutionTime = now; // Update the last execution time
getCurrentFreq();
var delta = e.originalEvent.deltaY;
var adjustment = 0;
if (e.shiftKey) {
adjustment = e.altKey ? 1 : 0.01;
} else if (e.ctrlKey) {
@@ -167,21 +167,21 @@ $(document).ready(function () {
}
return false;
}
var newFreq = currentFreq + (delta > 0 ? -adjustment : adjustment);
socket.send("T" + (Math.round(newFreq * 1000)));
return false;
});
setInterval(getServerTime, 10000);
getServerTime();
setInterval(sendPingRequest, 5000);
sendPingRequest();
$("#tuner-name").click(function() {
showTunerDescription();
});
var freqUpButton = $('#freq-up')[0];
var freqDownButton = $('#freq-down')[0];
var psContainer = $('#ps-container')[0];
@@ -189,19 +189,19 @@ $(document).ready(function () {
var piCodeContainer = $('#pi-code-container')[0];
var freqContainer = $('#freq-container')[0];
var txContainer = $('#data-station-container')[0];
$(".data-eq").click(function () {
toggleButtonState("eq");
});
$(".data-ims").click(function () {
toggleButtonState("ims");
});
$("#volumeSlider").on('mouseup', function() {
$('#volumeSlider').blur();
})
$(freqUpButton).on("click", tuneUp);
$(freqDownButton).on("click", tuneDown);
$(psContainer).on("click", copyPs);
@@ -212,37 +212,37 @@ $(document).ready(function () {
$(freqContainer).on("click", function () {
textInput.focus();
});
//FMLIST logging
$('.popup-content').on('click', function(event) {
event.stopPropagation();
$('.popup-content').removeClass('show');
});
$('.log-fmlist').on('click', function() {
const logKey = 'fmlistLogChoice';
const logTimestampKey = 'fmlistLogTimestamp';
const expirationTime = 10 * 60 * 1000;
const logKey = 'fmlistLogChoice';
const logTimestampKey = 'fmlistLogTimestamp';
const expirationTime = 10 * 60 * 1000;
const now = Date.now();
const storedChoice = localStorage.getItem(logKey);
const storedTimestamp = localStorage.getItem(logTimestampKey);
if (storedChoice && storedTimestamp && (now - storedTimestamp < expirationTime)) {
sendLog(storedChoice);
sendLog(storedChoice);
return;
}
if (parsedData.txInfo.dist > 700) {
$('.log-fmlist .mini-popup-content').addClass('show'); // Show popup if no valid choice
$('.log-fmlist-sporadice').off('click').on('click', function () {
localStorage.setItem(logKey, './log_fmlist?type=sporadice');
localStorage.setItem(logTimestampKey, now);
if(parsedData.txInfo.dist > 700) sendLog('./log_fmlist?type=sporadice');
$('.log-fmlist .mini-popup-content').removeClass('show');
});
$('.log-fmlist-tropo').off('click').on('click', function () {
localStorage.setItem(logKey, './log_fmlist?type=tropo');
localStorage.setItem(logTimestampKey, now);
@@ -250,9 +250,9 @@ $(document).ready(function () {
$('.log-fmlist .mini-popup-content').removeClass('show');
});
} else {
sendLog('./log_fmlist');
sendLog('./log_fmlist');
}
function sendLog(endpoint) {
$.ajax({
url: endpoint,
@@ -262,7 +262,7 @@ $(document).ready(function () {
},
error: function(xhr) {
let errorMessage;
switch (xhr.status) {
case 429:
errorMessage = xhr.responseText;
@@ -273,7 +273,7 @@ $(document).ready(function () {
default:
errorMessage = xhr.statusText || 'An error occurred';
}
sendToast('error', 'Log failed', errorMessage, false, true);
}
});
@@ -290,7 +290,7 @@ function getServerTime() {
dataType: "json",
success: function(data) {
const serverTimeUtc = data.serverTime;
const options = {
year: 'numeric',
month: 'short',
@@ -299,32 +299,32 @@ function getServerTime() {
minute: '2-digit',
hour12: false
};
const serverOptions = {
...options,
timeZone: 'Etc/UTC'
};
const formattedServerTime = new Date(serverTimeUtc).toLocaleString(navigator.language ? navigator.language : 'en-US', serverOptions);
$("#server-time").text(formattedServerTime);
$("#server-time").text(formattedServerTime);
},
error: function(jqXHR, textStatus, errorThrown) {
console.error("Error fetching server time:", errorThrown);
}
});
}
}
function sendPingRequest() {
const timeoutDuration = 5000;
const startTime = new Date().getTime();
const fetchWithTimeout = (url, options, timeout = timeoutDuration) => {
return new Promise((resolve, reject) => {
const timerTimeout = setTimeout(() => {
reject(new Error('Request timed out'));
}, timeout);
fetch(url, options)
.then(response => {
clearTimeout(timerTimeout);
@@ -336,7 +336,7 @@ function sendPingRequest() {
});
});
};
fetchWithTimeout('./ping', { cache: 'no-store' }, timeoutDuration)
.then(response => {
const endTime = new Date().getTime();
@@ -354,7 +354,7 @@ function sendPingRequest() {
pingTimeLimit = true;
}
});
function handleMessage(message) {
messageData = JSON.parse(message.data.length);
socket.removeEventListener('message', handleMessage);
@@ -362,7 +362,7 @@ function sendPingRequest() {
socket.addEventListener('message', handleMessage);
messageLength = messageData;
messageData = 0;
// Force reconnection if no WebSocket data after several queries
if (messageLength === 0) {
messageCounter++;
@@ -375,7 +375,7 @@ function sendPingRequest() {
} else {
messageCounter = 0;
}
// Automatic reconnection on WebSocket close with cooldown
const now = Date.now();
if (
@@ -421,12 +421,12 @@ function handleWebSocketMessage(event) {
}, 500);
return;
}
parsedData = JSON.parse(event.data);
resetDataTimeout();
updatePanels(parsedData);
const sum = signalData.reduce((acc, strNum) => acc + parseFloat(strNum), 0);
const averageSignal = sum / signalData.length;
data.push(averageSignal);
@@ -500,11 +500,11 @@ function initCanvas() {
beginAtZero: false,
grace: 0.25,
border: { display: false },
ticks: {
maxTicksLimit: 3,
ticks: {
maxTicksLimit: 3,
display: false // Hide default labels
},
grid: {
grid: {
display: false, // Hide default grid lines
},
},
@@ -513,11 +513,11 @@ function initCanvas() {
beginAtZero: false,
grace: 0.25,
border: { display: false },
ticks: {
maxTicksLimit: 3,
ticks: {
maxTicksLimit: 3,
display: false // Hide default labels for the right axis
},
grid: {
grid: {
display: false, // No grid for right axis
}
}
@@ -558,21 +558,21 @@ function initCanvas() {
case "dbm": adjustedTickValue = tick.value - 120; break;
default: adjustedTickValue = tick.value; break;
}
if (isMiddleTick) { adjustedY += 3; }
ctx.textAlign = 'right';
ctx.fillText(adjustedTickValue.toFixed(1), leftX + 25, adjustedY);
ctx.fillText(adjustedTickValue.toFixed(1), leftX + 25, adjustedY);
ctx.textAlign = 'left';
ctx.fillText(adjustedTickValue.toFixed(1), rightX - 25, adjustedY); // Right side
});
const gridLineWidth = 0.5; // Make the lines thinner to avoid overlapping text
const adjustedGridTop = chartArea.top + offset;
const adjustedGridBottom = chartArea.bottom - offset;
const middleY = chartArea.top + chartArea.height / 2;
const padding = 45; // 30px inward on both sides
// Helper function to draw a horizontal line
function drawGridLine(y) {
ctx.beginPath();
@@ -582,12 +582,12 @@ function initCanvas() {
ctx.lineWidth = gridLineWidth;
ctx.stroke();
}
// Draw the three horizontal grid lines
drawGridLine(adjustedGridTop);
drawGridLine(adjustedGridBottom);
drawGridLine(middleY);
ctx.restore();
}
}]
@@ -634,12 +634,12 @@ socket.onmessage = (event) => {
}, 500);
return;
}
parsedData = JSON.parse(event.data);
resetDataTimeout();
updatePanels(parsedData);
const sum = signalData.reduce((acc, strNum) => acc + parseFloat(strNum), 0);
const averageSignal = sum / signalData.length;
data.push(averageSignal);
@@ -661,7 +661,7 @@ function processString(string, errors) {
const alpha_range = 50;
const max_error = 10;
errors = errors?.split(',');
for (let i = 0; i < string.length; i++) {
alpha = parseInt(errors[i]) * (alpha_range / (max_error + 1));
if (alpha) {
@@ -670,27 +670,27 @@ function processString(string, errors) {
output += escapeHTML(string[i]);
}
}
return output;
}
function checkKey(e) {
e = e || window.event;
if (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) {
return;
}
if ($('#password:focus').length > 0
|| $('#chat-send-message:focus').length > 0
|| $('#volumeSlider:focus').length > 0
|| $('#chat-nickname:focus').length > 0
|| $('.option:focus').length > 0) {
return;
return;
}
getCurrentFreq();
if (socket.readyState === WebSocket.OPEN) {
switch (e.keyCode) {
case 66: // Back to previous frequency
@@ -717,9 +717,9 @@ function checkKey(e) {
let $dropdown = $(".data-ant");
let $input = $dropdown.find("input");
let $options = $dropdown.find("ul.options .option");
if ($options.length === 0) return; // No antennas available
// Find the currently selected antenna
let currentText = $input.val().trim();
let currentIndex = $options.index($options.filter(function () {
@@ -727,15 +727,15 @@ function checkKey(e) {
}));
console.log(currentIndex, currentText);
// Cycle to the next option
let nextIndex = (currentIndex + 1) % $options.length;
let $nextOption = $options.eq(nextIndex);
// Update UI
$input.attr("placeholder", $nextOption.text());
$input.data("value", $nextOption.data("value"));
let socketMessage = "Z" + $nextOption.data("value");
socket.send(socketMessage);
break;
@@ -769,7 +769,7 @@ async function copyPs() {
var signal = $('#data-signal').text();
var signalDecimal = $('#data-signal-decimal').text();
var signalUnit = $('.signal-units').eq(0).text();
try {
await copyToClipboard(frequency + " - " + pi + " | " + ps + " [" + signal + signalDecimal + " " + signalUnit + "]");
} catch (error) {
@@ -785,7 +785,7 @@ async function copyTx() {
const stationItu = $('#data-station-itu').text();
const stationDistance = $('#data-station-distance').text();
const stationErp = $('#data-station-erp').text();
try {
await copyToClipboard(frequency + " - " + pi + " | " + stationName + " [" + stationCity + ", " + stationItu + "] - " + stationDistance + " | " + stationErp + " kW");
} catch (error) {
@@ -796,7 +796,7 @@ async function copyTx() {
async function copyRt() {
var rt0 = $('#data-rt0 span').text();
var rt1 = $('#data-rt1 span').text();
try {
await copyToClipboard("[0] RT: " + rt0 + "\n[1] RT: " + rt1);
} catch (error) {
@@ -818,10 +818,10 @@ function copyToClipboard(textToCopy) {
'position': 'absolute',
'left': '-999999px'
});
$('body').prepend(textArea);
textArea.select();
try {
document.execCommand('copy');
} catch (error) {
@@ -837,9 +837,9 @@ function findOnMaps() {
var pi = $('#data-pi').text();
var latitude = localStorage.getItem('qthLongitude');
var longitude = localStorage.getItem('qthLatitude');
frequency > 74 ? frequency = frequency.toFixed(1) : null;
var url = `https://maps.fmdx.org/#qth=${longitude},${latitude}&freq=${frequency}&findPi=${pi}`;
window.open(url, "_blank");
}
@@ -849,33 +849,33 @@ function updateSignalUnits(parsedData, averageSignal) {
const signalUnit = localStorage.getItem('signalUnit');
let currentSignal;
let highestSignal = parsedData.sigTop;
currentSignal = averageSignal
let signalText = $('.signal-units');
let signalValue;
switch (signalUnit) {
case 'dbuv':
signalValue = currentSignal - 11.25;
highestSignal = highestSignal - 11.25;
signalText.text('dBµV');
break;
case 'dbm':
signalValue = currentSignal - 120;
highestSignal = highestSignal - 120;
signalText.text('dBm');
break;
default:
signalValue = currentSignal;
signalText.text('dBf');
break;
}
const formatted = (Math.round(signalValue * 10) / 10).toFixed(1);
const [integerPart, decimalPart] = formatted.split('.');
$('#data-signal-highest').text(Number(highestSignal).toFixed(1));
$('#data-signal').text(integerPart);
$('#data-signal-decimal').text('.' + decimalPart);
@@ -902,17 +902,17 @@ const $dataPty = $('.data-pty');
// Throttling function to limit the frequency of updates
function throttle(fn, wait) {
let isThrottled = false, savedArgs, savedThis;
function wrapper() {
if (isThrottled) {
savedArgs = arguments;
savedThis = this;
return;
}
fn.apply(this, arguments);
isThrottled = true;
setTimeout(function() {
isThrottled = false;
if (savedArgs) {
@@ -921,7 +921,7 @@ function throttle(fn, wait) {
}
}, wait);
}
return wrapper;
}
@@ -968,18 +968,18 @@ const updateDataElements = throttle(function(parsedData) {
updateTextIfChanged($dataFrequency, parsedData.freq);
$commandInput.attr("aria-label", "Current frequency: " + parsedData.freq);
updateHtmlIfChanged($dataPi, parsedData.pi === '?' ? "<span class='opacity-half'>?</span>" : parsedData.pi);
if ($('#ps-underscores').is(':checked')) {
parsedData.ps = parsedData.ps.replace(/\s/g, '_');
}
updateHtmlIfChanged($dataPs, parsedData.ps === '?' ? "<span class='opacity-half'>?</span>" : processString(parsedData.ps, parsedData.ps_errors));
if(parsedData.st) {
$dataSt.parent().removeClass('opacity-half');
} else {
$dataSt.parent().addClass('opacity-half');
}
if(parsedData.stForced) {
if (!parsedData.st) {
stereoColor = 'gray';
@@ -992,28 +992,28 @@ const updateDataElements = throttle(function(parsedData) {
$('.data-st.circle1').css('left', '0px');
$('.data-st.circle2').css('display', 'block');
}
updateHtmlIfChanged($dataRt0, processString(parsedData.rt0, parsedData.rt0_errors));
updateHtmlIfChanged($dataRt1, processString(parsedData.rt1, parsedData.rt1_errors));
updateTextIfChanged($dataPty, rdsMode == 'true' ? usa_programmes[parsedData.pty] : europe_programmes[parsedData.pty]);
if (parsedData.rds === true) {
$flagDesktopCointainer.css('background-color', 'var(--color-2-transparent)');
} else {
$flagDesktopCointainer.css('background-color', 'var(--color-1-transparent)');
}
$('.data-flag').html(`<i title="${parsedData.country_name}" class="flag-sm flag-sm-${parsedData.country_iso}"></i>`);
$('.data-flag-big').html(`<i title="${parsedData.country_name}" class="flag-md flag-md-${parsedData.country_iso}"></i>`);
$dataAntInput.val($('.data-ant li[data-value="' + parsedData.ant + '"]').first().text());
if (typeof parsedData.agc !== 'undefined') $dataAgcInput.val($('.data-agc li[data-value="' + parsedData.agc + '"]').first().text());
if (parsedData.bw < 500) $dataBwInput.val($('.data-bw li[data-value2="' + parsedData.bw + '"]').first().text());
else $dataBwInput.val($('.data-bw li[data-value="' + parsedData.bw + '"]').first().text());
if (parsedData.txInfo.tx.length > 1) {
updateTextIfChanged($('#data-station-name'), parsedData.txInfo.tx.replace(/%/g, '%25'));
updateTextIfChanged($('#data-station-erp'), parsedData.txInfo.erp);
@@ -1028,17 +1028,12 @@ const updateDataElements = throttle(function(parsedData) {
updateHtmlIfChanged($('#alternative-txes'), altTxInfo);
updateTextIfChanged($('#data-station-distance'), txDistance);
$dataStationContainer.css('display', 'block');
} else {
$dataStationContainer.removeAttr('style');
}
if(parsedData.txInfo.tx.length > 1 && parsedData.txInfo.dist > 150 && parsedData.txInfo.dist < 4000) {
$('.log-fmlist').removeAttr('disabled').removeClass('btn-disabled cursor-disabled');
} else {
$('.log-fmlist').attr('disabled', 'true').addClass('btn-disabled cursor-disabled');
}
} else $dataStationContainer.removeAttr('style');
if(parsedData.txInfo.tx.length > 1 && parsedData.txInfo.dist > 150 && parsedData.txInfo.dist < 4000) $('.log-fmlist').removeAttr('disabled').removeClass('btn-disabled cursor-disabled');
else $('.log-fmlist').attr('disabled', 'true').addClass('btn-disabled cursor-disabled');
updateHtmlIfChanged($('#data-regular-pi'), parsedData.txInfo.reg === true ? parsedData.txInfo.pi : '&nbsp;');
if (updateCounter % 8 === 0) {
$dataTp.html(parsedData.tp === 0 ? "<span class='opacity-half'>TP</span>" : "TP");
$dataTa.html(parsedData.ta === 0 ? "<span class='opacity-half'>TA</span>" : "TA");
@@ -1050,7 +1045,7 @@ const updateDataElements = throttle(function(parsedData) {
)
);
}
if (updateCounter % 30 === 0) {
$dataPs.attr('aria-label', parsedData.ps);
$dataRt0.attr('aria-label', parsedData.rt0);
@@ -1063,36 +1058,35 @@ let isEventListenerAdded = false;
function updatePanels(parsedData) {
updateCounter = (updateCounter % 10000) + 1; // Count to 10000 then reset back to 1
signalData.push(parsedData.sig);
if (signalData.length > 8) {
signalData.shift(); // Remove the oldest element
}
const sum = signalData.reduce((acc, strNum) => acc + parseFloat(strNum), 0);
const averageSignal = sum / signalData.length;
const sortedAf = parsedData.af.sort(compareNumbers);
const scaledArray = sortedAf.map(element => element / 1000);
const listContainer = $('#af-list');
const scrollTop = listContainer.scrollTop();
let ul = listContainer.find('ul');
if (!ul.length) {
ul = $('<ul></ul>');
listContainer.append(ul);
}
if (updateCounter % 3 === 0) {
updateButtonState("data-eq", parsedData.eq);
updateButtonState("data-ims", parsedData.ims);
// Only update #af-list on every 3rd call
ul.html('');
const listItems = scaledArray.map(createListItem);
ul.append(listItems);
// Add the event listener only once
if (!isEventListenerAdded) {
ul.on('click', 'a', function () {
@@ -1101,10 +1095,10 @@ function updatePanels(parsedData) {
});
isEventListenerAdded = true;
}
listContainer.scrollTop(scrollTop);
}
updateDataElements(parsedData);
updateSignalUnits(parsedData, averageSignal);
$('.users-online').text(parsedData.users);
@@ -1116,11 +1110,11 @@ function createListItem(element) {
function updateButtonState(buttonId, value) {
var button = $("#" + buttonId);
if (button.length === 0) {
button = $("." + buttonId);
}
if (button.length > 0) {
if (value == 0) {
button.hasClass("btn-disabled") ? null : button.addClass("btn-disabled");
@@ -1152,7 +1146,7 @@ function toggleForcedStereo() {
function toggleLock(buttonSelector, activeMessage, inactiveMessage, activeLabel, inactiveLabel) {
let $lockButton = $(buttonSelector);
if ($lockButton.hasClass('active')) {
socket.send(inactiveMessage);
$lockButton.attr('aria-label', inactiveLabel);
@@ -1166,17 +1160,17 @@ function toggleLock(buttonSelector, activeMessage, inactiveMessage, activeLabel,
function showTunerDescription() {
let parentDiv = $("#tuner-name").parent();
if (!$("#dashboard-panel-description").is(":visible")) {
parentDiv.css("border-radius", "15px 15px 0 0");
}
$("#dashboard-panel-description").slideToggle(300, function() {
if (!$(this).is(":visible")) {
parentDiv.css("border-radius", "");
}
});
$("#tuner-name i").toggleClass("rotated");
if ($(window).width() < 768) {
@@ -1187,29 +1181,29 @@ function showTunerDescription() {
function initTooltips(target = null) {
// Define scope: all tooltips or specific one if target is provided
const tooltips = target ? $(target) : $('.tooltip');
// Unbind existing event handlers before rebinding to avoid duplication
tooltips.off('mouseenter mouseleave');
tooltips.hover(function () {
if ($(this).closest('.popup-content').length) {
return;
}
var tooltipText = $(this).data('tooltip');
var placement = $(this).data('tooltip-placement') || 'top'; // Default to 'top'
// Clear existing timeouts
$(this).data('timeout', setTimeout(() => {
$('.tooltip-wrapper').remove();
var tooltip = $(`
<div class="tooltip-wrapper">
<div class="tooltiptext">${tooltipText}</div>
</div>
`);
$('body').append(tooltip);
var tooltipEl = $('.tooltiptext');
var tooltipWidth = tooltipEl.outerWidth();
var tooltipHeight = tooltipEl.outerHeight();
@@ -1217,7 +1211,7 @@ function initTooltips(target = null) {
var targetOffset = targetEl.offset();
var targetWidth = targetEl.outerWidth();
var targetHeight = targetEl.outerHeight();
// Compute position
var posX, posY;
switch (placement) {
@@ -1239,7 +1233,7 @@ function initTooltips(target = null) {
posY = targetOffset.top - tooltipHeight - 10;
break;
}
// Apply positioning
tooltipEl.css({ top: posY, left: posX, opacity: 1 });
@@ -1247,32 +1241,32 @@ function initTooltips(target = null) {
if ((/Mobi|Android|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) && ('ontouchstart' in window || navigator.maxTouchPoints)) {
setTimeout(() => { $('.tooltiptext').remove(); }, 5000);
}
}, 300));
}, function () {
clearTimeout($(this).data('timeout'));
setTimeout(() => {
$('.tooltip-wrapper').fadeOut(300, function () {
$(this).remove();
$(this).remove();
});
}, 100);
}, 100);
});
$('.popup-content').off('mouseenter').on('mouseenter', function () {
clearTimeout($('.tooltip').data('timeout'));
$('.tooltip-wrapper').fadeOut(300, function () {
$(this).remove();
$(this).remove();
});
});
}
function fillPresets() {
let hasAnyPreset = false;
for (let i = 1; i <= 4; i++) {
let presetText = localStorage.getItem(`preset${i}`);
if (presetText != "null") {
hasAnyPreset = true;
$(`#preset${i}-text`).text(presetText);
@@ -1283,9 +1277,8 @@ function initTooltips(target = null) {
$(`#preset${i}`).hide();
}
}
if (!hasAnyPreset) {
$('#preset1').parent().hide();
}
}
+14 -19
View File
@@ -3,15 +3,15 @@ $(document).ready(function() {
var modalPanel = $(".modal-panel");
var openBtn = $(".settings");
var closeBtn = $(".closeModal, .closeModalButton");
initPopups();
openBtn.on("click", function() {
openModal(modalPanel);
});
closeBtn.on("click", closeModal);
function openModal(panel) {
modal.css("display", "block");
panel.css("display", "block");
@@ -20,7 +20,7 @@ $(document).ready(function() {
modal.css("opacity", 1);
}, 10);
}
function closeModal() {
modal.css("opacity", 0);
setTimeout(function() {
@@ -28,24 +28,20 @@ $(document).ready(function() {
$("body").removeClass("modal-open"); // Enable body scrolling
}, 300);
}
$(document).on("click", function(event) { // Close the modal when clicking outside of it
if ($(event.target).is(modal)) {
closeModal();
}
if ($(event.target).is(modal)) closeModal();
});
$(document).on("keydown", function(event) { // Close the modal when pressing ESC key
if (event.key === "Escape") {
closeModal();
}
if (event.key === "Escape") closeModal();
});
$(".tuner-mobile-settings").on("click", function () {
togglePopup("#popup-panel-mobile-settings");
});
$("#data-station-others").on("click", function () {
togglePopup("#popup-panel-transmitters");
});
@@ -54,13 +50,13 @@ $(document).ready(function() {
function initPopups() {
$(".popup-window").draggable({
handle: ".popup-header",
containment: "body"
containment: "body"
}).resizable({
minHeight: 330,
minWidth: 350,
containment: "body"
});
$(".popup-close").on("click", function () {
$(".popup-window").fadeOut(200);
});
@@ -69,9 +65,8 @@ function initPopups() {
function togglePopup(targetSelector) {
const $target = $(targetSelector);
if ($target.is(":visible")) {
$target.fadeOut(200);
} else {
if ($target.is(":visible")) $target.fadeOut(200);
else {
$(".popup-window").fadeOut(200);
$target.fadeIn(200);
}
+1 -3
View File
@@ -189,9 +189,7 @@ function loadInitialSettings() {
if(signalParameter && !localStorage.getItem('signalUnit')) {
signalSelector.find('input').val(signalSelector.find('.option[data-value="' + signalParameter + '"]').text());
localStorage.setItem('signalUnit', signalParameter);
} else {
signalSelector.find('input').val(signalSelector.find('.option[data-value="' + savedUnit + '"]').text());
}
} else signalSelector.find('input').val(signalSelector.find('.option[data-value="' + savedUnit + '"]').text());
signalSelector.on('click', '.option', (event) => {
const selectedSignalUnit = $(event.target).data('value');
+2 -6
View File
@@ -27,9 +27,7 @@ function mapCreate() {
zoom: 3,
worldCopyJump: true
});
} else {
map.setZoom(3).panTo([40, 0]);
}
} else map.setZoom(3).panTo([40, 0]);
L.tileLayer(tilesURL, {
attribution: mapAttrib,
@@ -272,9 +270,7 @@ function checkTunnelServers() {
// If this li is the currently selected one, update input text too
// Note: input.val() holds the label, so match by label is safer
if ($li.text() === selectedValue || server.value === selectedValue) {
$input.val(server.label);
}
if ($li.text() === selectedValue || server.value === selectedValue) $input.val(server.label);
}
});
},
+1 -3
View File
@@ -27,8 +27,6 @@ function navigateStep(isNext) {
currentStep.hide();
targetStep.show();
updateProgressBar(targetStep);
} else if (isNext) {
submitConfig();
}
} else if (isNext) submitConfig();
updateWizardContent();
}