From 8fdd46beec48df08cd08b2c3ea366da3c2923cc9 Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Thu, 16 Apr 2026 22:05:51 +0200 Subject: [PATCH] feat(calculator): Unit-Converter mit 6 Kategorien --- newtab.html | 1 + src/css/main.css | 61 +++++++ src/js/calc-converter.js | 344 +++++++++++++++++++++++++++++++++++++++ src/js/i18n.js | 16 ++ 4 files changed, 422 insertions(+) create mode 100644 src/js/calc-converter.js diff --git a/newtab.html b/newtab.html index ae73e13..aa1eac3 100644 --- a/newtab.html +++ b/newtab.html @@ -508,6 +508,7 @@ + diff --git a/src/css/main.css b/src/css/main.css index e622a4f..bc0c866 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -1391,6 +1391,67 @@ body.show-desc .bm-desc { display: block; } padding: 2px 0; } +/* Calculator Converter Mode */ +.calc-conv-select { + width: 100%; + padding: 6px 8px; + background: rgba(0,0,0,0.3); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text-primary); + font-size: 13px; + font-family: 'Rajdhani', sans-serif; +} +.calc-conv-row { + display: flex; + gap: 6px; +} +.calc-conv-input { + flex: 1; + padding: 8px; + background: rgba(0,0,0,0.3); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text-primary); + font-size: 16px; + font-family: 'Rajdhani', monospace; +} +.calc-conv-input:read-only { + color: var(--accent); + font-weight: 600; +} +.calc-conv-unit { + width: 80px; + padding: 4px 6px; + background: rgba(0,0,0,0.3); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--text-primary); + font-size: 12px; + font-family: 'Rajdhani', sans-serif; +} +.calc-conv-swap { + align-self: center; + width: 36px; + height: 28px; + background: rgba(255,255,255,0.04); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + color: var(--accent); + font-size: 16px; + cursor: pointer; + transition: all 0.15s; +} +.calc-conv-swap:hover { + background: var(--accent-dim); +} +.calc-conv-ref { + font-size: 11px; + color: var(--text-muted); + padding: 4px 0; + border-top: 1px solid var(--border); +} + /* ============================================ TIMER WIDGET ============================================ */ diff --git a/src/js/calc-converter.js b/src/js/calc-converter.js new file mode 100644 index 0000000..4083bd7 --- /dev/null +++ b/src/js/calc-converter.js @@ -0,0 +1,344 @@ +/* ============================================= + HELLION NEWTAB — calc-converter.js + Unit-Converter Modus für Calculator Widget + ============================================= */ + +(function() { + 'use strict'; + + const CATEGORIES = { + length: { + titleKey: 'calculator.conv.cat.length', + baseUnit: 'm', + units: { + mm: { toBase: v => v / 1000, fromBase: v => v * 1000 }, + cm: { toBase: v => v / 100, fromBase: v => v * 100 }, + m: { toBase: v => v, fromBase: v => v }, + km: { toBase: v => v * 1000, fromBase: v => v / 1000 }, + in: { toBase: v => v * 0.0254, fromBase: v => v / 0.0254 }, + ft: { toBase: v => v * 0.3048, fromBase: v => v / 0.3048 }, + yd: { toBase: v => v * 0.9144, fromBase: v => v / 0.9144 }, + mi: { toBase: v => v * 1609.344, fromBase: v => v / 1609.344 } + } + }, + weight: { + titleKey: 'calculator.conv.cat.weight', + baseUnit: 'g', + units: { + mg: { toBase: v => v / 1000, fromBase: v => v * 1000 }, + g: { toBase: v => v, fromBase: v => v }, + kg: { toBase: v => v * 1000, fromBase: v => v / 1000 }, + t: { toBase: v => v * 1000000, fromBase: v => v / 1000000 }, + oz: { toBase: v => v * 28.3495, fromBase: v => v / 28.3495 }, + lb: { toBase: v => v * 453.592, fromBase: v => v / 453.592 } + } + }, + temperature: { + titleKey: 'calculator.conv.cat.temperature', + baseUnit: null, + units: { '\u00B0C': null, '\u00B0F': null, 'K': null }, + convert(value, from, to) { + if (from === to) return value; + const key = from + '_' + to; + const conversions = { + '\u00B0C_\u00B0F': v => (v * 9 / 5) + 32, + '\u00B0C_K': v => v + 273.15, + '\u00B0F_\u00B0C': v => (v - 32) * 5 / 9, + '\u00B0F_K': v => (v - 32) * 5 / 9 + 273.15, + 'K_\u00B0C': v => v - 273.15, + 'K_\u00B0F': v => (v - 273.15) * 9 / 5 + 32 + }; + const fn = conversions[key]; + return fn ? fn(value) : null; + } + }, + volume: { + titleKey: 'calculator.conv.cat.volume', + baseUnit: 'ml', + units: { + ml: { toBase: v => v, fromBase: v => v }, + L: { toBase: v => v * 1000, fromBase: v => v / 1000 }, + 'm\u00B3':{ toBase: v => v * 1000000, fromBase: v => v / 1000000 }, + 'gal(US)':{ toBase: v => v * 3785.41, fromBase: v => v / 3785.41 }, + 'gal(UK)':{ toBase: v => v * 4546.09, fromBase: v => v / 4546.09 }, + 'ft\u00B3':{ toBase: v => v * 28316.8, fromBase: v => v / 28316.8 } + } + }, + speed: { + titleKey: 'calculator.conv.cat.speed', + baseUnit: 'm/s', + units: { + 'm/s': { toBase: v => v, fromBase: v => v }, + 'km/h': { toBase: v => v / 3.6, fromBase: v => v * 3.6 }, + 'mph': { toBase: v => v * 0.44704, fromBase: v => v / 0.44704 }, + 'kn': { toBase: v => v * 0.514444, fromBase: v => v / 0.514444 } + } + }, + area: { + titleKey: 'calculator.conv.cat.area', + baseUnit: 'm\u00B2', + units: { + 'mm\u00B2': { toBase: v => v / 1000000, fromBase: v => v * 1000000 }, + 'cm\u00B2': { toBase: v => v / 10000, fromBase: v => v * 10000 }, + 'm\u00B2': { toBase: v => v, fromBase: v => v }, + 'km\u00B2': { toBase: v => v * 1000000, fromBase: v => v / 1000000 }, + 'ha': { toBase: v => v * 10000, fromBase: v => v / 10000 }, + 'acre': { toBase: v => v * 4046.86, fromBase: v => v / 4046.86 }, + 'ft\u00B2': { toBase: v => v * 0.092903, fromBase: v => v / 0.092903 }, + 'in\u00B2': { toBase: v => v * 0.00064516, fromBase: v => v / 0.00064516 } + } + } + }; + + const CATEGORY_ORDER = ['length', 'weight', 'temperature', 'volume', 'speed', 'area']; + + let _currentCategory = 'length'; + let _fromUnit = 'cm'; + let _toUnit = 'in'; + let _fromInput = null; + let _toInput = null; + let _refEl = null; + + /** + * Converts a value from one unit to another within the current category. + * @param {number} value + * @param {string} from + * @param {string} to + * @returns {number|null} + */ + function convert(value, from, to) { + const cat = CATEGORIES[_currentCategory]; + if (!cat) return null; + if (cat.convert) return cat.convert(value, from, to); + const fromDef = cat.units[from]; + const toDef = cat.units[to]; + if (!fromDef || !toDef) return null; + const base = fromDef.toBase(value); + return toDef.fromBase(base); + } + + /** + * Recalculates the output field and reference lines based on current input. + */ + function recalc() { + if (!_fromInput || !_toInput) return; + const val = parseFloat(_fromInput.value); + if (isNaN(val)) { + _toInput.value = ''; + updateReference(); + return; + } + const result = convert(val, _fromUnit, _toUnit); + if (result === null) { + _toInput.value = ''; + } else { + _toInput.value = Calculator._formatResult(result); + } + updateReference(); + } + + /** + * Updates the reference conversion lines below the inputs. + */ + function updateReference() { + if (!_refEl) return; + _refEl.textContent = ''; + const r1 = convert(1, _fromUnit, _toUnit); + const r2 = convert(1, _toUnit, _fromUnit); + if (r1 !== null) { + const line1 = document.createElement('div'); + line1.textContent = '1 ' + _fromUnit + ' = ' + Calculator._formatResult(r1) + ' ' + _toUnit; + _refEl.appendChild(line1); + } + if (r2 !== null) { + const line2 = document.createElement('div'); + line2.textContent = '1 ' + _toUnit + ' = ' + Calculator._formatResult(r2) + ' ' + _fromUnit; + _refEl.appendChild(line2); + } + } + + /** + * Populates a unit