You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-27 06:23:53 +01:00
some changes
This commit is contained in:
311
web/js/main.js
311
web/js/main.js
@@ -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 : ' ');
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user