Add antenna conversion tab

This commit is contained in:
Eskimue
2026-07-24 13:13:32 +02:00
parent 1bfb3c4982
commit 2bf2848905
+152
View File
@@ -246,6 +246,7 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
<button type="button" class="astro-conv-tab" data-tab-target="timeTab" role="tab" aria-selected="false">Zeit</button>
<button type="button" class="astro-conv-tab" data-tab-target="coordinatesTab" role="tab" aria-selected="false">Koordinaten</button>
<button type="button" class="astro-conv-tab" data-tab-target="angleTab" role="tab" aria-selected="false">Winkel</button>
<button type="button" class="astro-conv-tab" data-tab-target="antennaTab" role="tab" aria-selected="false">Antennen</button>
<button type="button" class="astro-conv-tab" data-tab-target="toolsTab" role="tab" aria-selected="false">Diverse Tools</button>
</div>
@@ -517,6 +518,49 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
</div>
</section>
<section class="card astro-conv-panel astro-conv-tab-panel" id="antennaTab" role="tabpanel">
<h2>Antennen-Umrechner</h2>
<p>Frequenz und Wellenlaenge ineinander umrechnen sowie Richtwerte fuer einen Halbwellendipol berechnen.</p>
<div class="astro-conv-grid" id="antennaConverter">
<div class="astro-conv-field">
<label for="antennaFrequencyMhz">Frequenz (MHz)</label>
<input class="astro-conv-input" id="antennaFrequencyMhz" type="text" inputmode="decimal" value="145">
</div>
<div class="astro-conv-field">
<label for="antennaWavelengthM">Wellenlaenge (m)</label>
<input class="astro-conv-input" id="antennaWavelengthM" type="text" inputmode="decimal">
</div>
<div class="astro-conv-field">
<label for="antennaWavelengthCm">Wellenlaenge (cm)</label>
<input class="astro-conv-input" id="antennaWavelengthCm" type="text" readonly>
</div>
<div class="astro-conv-field">
<label for="antennaHalfwaveTotalM"><span class="astro-conv-label-help" title="Theoretische Gesamtlaenge eines Halbwellendipols: Lambda / 2.">Dipol gesamt theoretisch (m)</span></label>
<input class="astro-conv-input" id="antennaHalfwaveTotalM" type="text" readonly>
</div>
<div class="astro-conv-field">
<label for="antennaHalfwavePracticalM"><span class="astro-conv-label-help" title="Praxisnaher Richtwert mit Verkuerzungsfaktor 0,95 fuer einen einfachen Drahtdipol.">Dipol gesamt praktisch (m)</span></label>
<input class="astro-conv-input" id="antennaHalfwavePracticalM" type="text" readonly>
</div>
<div class="astro-conv-field">
<label for="antennaLegLengthM"><span class="astro-conv-label-help" title="Laenge eines einzelnen Dipol-Schenkels. Praktischer Richtwert: Lambda x 0,95 / 4.">Ein Schenkel (m)</span></label>
<input class="astro-conv-input" id="antennaLegLengthM" type="text" readonly>
</div>
</div>
<div class="astro-conv-actions">
<button type="button" class="btn btn-secondary" id="antennaClear">Leeren</button>
<button type="button" class="btn btn-primary" id="antenna2m">2-m-Band</button>
<button type="button" class="btn btn-primary" id="antennaCb">CB-Funk</button>
</div>
</section>
<section class="card astro-conv-panel astro-conv-tab-panel" id="toolsTab" role="tabpanel">
<h2>Diverse Tools</h2>
<p>Sonnenstand für den Standard-Standort aus dem Header berechnen. Datum und Uhrzeit werden in der lokalen Zeitzone des Standorts interpretiert.</p>
@@ -647,6 +691,14 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
arcsec: document.getElementById('angleArcsec'),
rad: document.getElementById('angleRad')
};
const antennaFields = {
frequencyMhz: document.getElementById('antennaFrequencyMhz'),
wavelengthM: document.getElementById('antennaWavelengthM'),
wavelengthCm: document.getElementById('antennaWavelengthCm'),
halfwaveTotalM: document.getElementById('antennaHalfwaveTotalM'),
halfwavePracticalM: document.getElementById('antennaHalfwavePracticalM'),
legLengthM: document.getElementById('antennaLegLengthM')
};
const toolFields = {
dateTimeLocal: document.getElementById('toolsDateTimeLocal'),
locationName: document.getElementById('toolsLocationName'),
@@ -664,6 +716,7 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
let timeRequestId = 0;
let coordinateRequestId = 0;
let angleRequestId = 0;
let antennaRequestId = 0;
let toolRequestId = 0;
const DECIMAL_DIVISION_PRECISION = 32;
@@ -1088,6 +1141,12 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
wireTooltipHover(field);
});
const antennaFieldEntries = Object.entries(antennaFields);
antennaFieldEntries.forEach(function ([unit, field]) {
attachTooltip(field, 'antenna-' + unit);
wireTooltipHover(field);
});
const updateDistanceFrom = async function (sourceUnit) {
const rawValue = distanceFields[sourceUnit].value.trim();
if (rawValue === '') {
@@ -1661,6 +1720,98 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
updateAngleFrom('arcsec');
});
const formatNumber = function (value, maxFractionDigits) {
if (!Number.isFinite(value)) {
return '';
}
return value.toLocaleString('de-DE', {
maximumFractionDigits: maxFractionDigits,
useGrouping: true
});
};
const clearAntennaOutputs = function () {
['wavelengthCm', 'halfwaveTotalM', 'halfwavePracticalM', 'legLengthM'].forEach(function (key) {
antennaFields[key].value = '';
updateTooltip(antennaFields[key]);
});
};
const updateAntennaFrom = function (sourceUnit) {
const sourceField = antennaFields[sourceUnit];
if (!sourceField) {
return;
}
const rawValue = sourceField.value.trim();
if (rawValue === '') {
Object.entries(antennaFields).forEach(function ([key, field]) {
if (key !== sourceUnit) {
field.value = '';
updateTooltip(field);
}
});
return;
}
const parsedValue = parseDecimalInput(rawValue);
const numericValue = parsedValue ? decimalToNumber(parsedValue) : Number.NaN;
if (!Number.isFinite(numericValue) || numericValue <= 0) {
clearAntennaOutputs();
return;
}
const requestId = ++antennaRequestId;
const wavelengthMeters = sourceUnit === 'frequencyMhz'
? 299.792458 / numericValue
: numericValue;
const frequencyMhz = sourceUnit === 'wavelengthM'
? 299.792458 / numericValue
: numericValue;
if (requestId !== antennaRequestId || !Number.isFinite(wavelengthMeters) || wavelengthMeters <= 0) {
clearAntennaOutputs();
return;
}
const practicalFactor = 0.95;
antennaFields.frequencyMhz.value = formatNumber(frequencyMhz, 6);
antennaFields.wavelengthM.value = formatNumber(wavelengthMeters, 6);
antennaFields.wavelengthCm.value = formatNumber(wavelengthMeters * 100, 2);
antennaFields.halfwaveTotalM.value = formatNumber(wavelengthMeters / 2, 4);
antennaFields.halfwavePracticalM.value = formatNumber((wavelengthMeters / 2) * practicalFactor, 4);
antennaFields.legLengthM.value = formatNumber((wavelengthMeters / 4) * practicalFactor, 4);
Object.values(antennaFields).forEach(function (field) {
updateTooltip(field);
});
};
['frequencyMhz', 'wavelengthM'].forEach(function (key) {
antennaFields[key].addEventListener('input', function () {
updateAntennaFrom(key);
});
});
document.getElementById('antennaClear').addEventListener('click', function () {
Object.values(antennaFields).forEach(function (field) {
field.value = '';
updateTooltip(field);
});
antennaFields.frequencyMhz.focus();
});
document.getElementById('antenna2m').addEventListener('click', function () {
antennaFields.frequencyMhz.value = '145';
updateAntennaFrom('frequencyMhz');
});
document.getElementById('antennaCb').addEventListener('click', function () {
antennaFields.frequencyMhz.value = '27,2';
updateAntennaFrom('frequencyMhz');
});
const clearToolOutputs = function () {
toolFields.dateTimeUtc.value = '';
toolFields.altitude.value = '';
@@ -1752,6 +1903,7 @@ $toolDefaultLocalDateTime = (new DateTimeImmutable('now', new DateTimeZone($tool
updateTimeFrom('utc');
updateCoordinatesFrom('equatorial');
updateAngleFrom('deg');
updateAntennaFrom('frequencyMhz');
updateSolarTool();
})();
</script>