/** * UI Bindings - Verbindet HTML-Elemente mit dem State */ var UiBindings = { elements: {}, init: function() { this.cacheElements(); this.bindEvents(); this.syncFromState(); this.updateVisibility(); this.updatePreview(); this.updateStandaloneArrowPreview(); }, cacheElements: function() { var e = this.elements; // Text & Farben e.textInput = document.getElementById('customText'); e.fontSizeInput = document.getElementById('fontSize'); e.fontSizeNum = document.getElementById('fontSizeNum'); e.fontSizeValue = document.getElementById('fontSizeValue'); e.textColorInput = document.getElementById('textColor'); e.textColorValue = document.getElementById('textColorValue'); e.frameColorInput = document.getElementById('frameColor'); e.frameColorValue = document.getElementById('frameColorValue'); // Rahmen e.frameScaleInput = document.getElementById('frameScale'); e.frameScaleNum = document.getElementById('frameScaleNum'); e.frameScaleValue = document.getElementById('frameScaleValue'); e.frameScaleRow = document.getElementById('frameScaleRow'); // Padding e.paddingAllInput = document.getElementById('paddingAll'); e.paddingAllNum = document.getElementById('paddingAllNum'); e.paddingAllValue = document.getElementById('paddingAllValue'); e.paddingTopInput = document.getElementById('paddingTop'); e.paddingTopValue = document.getElementById('paddingTopValue'); e.paddingRightInput = document.getElementById('paddingRight'); e.paddingRightValue = document.getElementById('paddingRightValue'); e.paddingBottomInput = document.getElementById('paddingBottom'); e.paddingBottomValue = document.getElementById('paddingBottomValue'); e.paddingLeftInput = document.getElementById('paddingLeft'); e.paddingLeftValue = document.getElementById('paddingLeftValue'); e.paddingAllRow = document.getElementById('framePaddingAllRow'); e.paddingRow = document.getElementById('framePaddingRow'); // Pfeil e.arrowLengthInput = document.getElementById('arrowLength'); e.arrowLengthNum = document.getElementById('arrowLengthNum'); e.arrowLengthValue = document.getElementById('arrowLengthValue'); e.arrowAngleInput = document.getElementById('arrowAngle'); e.arrowAngleNum = document.getElementById('arrowAngleNum'); e.arrowAngleValue = document.getElementById('arrowAngleValue'); e.arrowBendInput = document.getElementById('arrowBend'); e.arrowBendNum = document.getElementById('arrowBendNum'); e.arrowBendValue = document.getElementById('arrowBendValue'); e.arrowSizeInput = document.getElementById('arrowSize'); e.arrowSizeNum = document.getElementById('arrowSizeNum'); e.arrowSizeValue = document.getElementById('arrowSizeValue'); e.arrowTipLengthInput = document.getElementById('arrowTipLength'); e.arrowTipLengthNum = document.getElementById('arrowTipLengthNum'); e.arrowTipLengthValue = document.getElementById('arrowTipLengthValue'); e.arrowDetailsRow = document.getElementById('arrowDetailsRow'); e.arrowDetailsRow2 = document.getElementById('arrowDetailsRow2'); // Vorschau e.textPreview = document.getElementById('textPreview'); e.standaloneArrowPreview = document.getElementById('standaloneArrowPreview'); // Text-Ausrichtung e.textAlignRow = document.getElementById('textAlignRow'); e.alignXButtons = document.querySelectorAll('[data-align-x]'); e.alignYButtons = document.querySelectorAll('[data-align-y]'); // Buttons e.shapeButtons = document.querySelectorAll('.shape-btn'); e.arrowButtons = document.querySelectorAll('.arrow-btn'); e.lineStyleButtons = document.querySelectorAll('.line-btn'); e.lineWeightButtons = document.querySelectorAll('.weight-btn'); }, bindEvents: function() { var self = this; var e = this.elements; var state = window.TextGenState; // Text-Input if (e.textInput) { e.textInput.addEventListener('input', function(ev) { state.set('text', ev.target.value); self.updatePreview(); }); } // Schriftgroesse - Slider und Number-Input synchronisieren if (e.fontSizeInput) { e.fontSizeInput.addEventListener('input', function(ev) { var val = parseInt(ev.target.value); state.set('fontSize', val); if (e.fontSizeValue) e.fontSizeValue.textContent = val + 'px'; if (e.fontSizeNum) e.fontSizeNum.value = val; self.updatePreview(); }); } if (e.fontSizeNum) { e.fontSizeNum.addEventListener('input', function(ev) { var val = parseInt(ev.target.value) || 8; val = Math.max(8, Math.min(48, val)); state.set('fontSize', val); if (e.fontSizeInput) e.fontSizeInput.value = val; if (e.fontSizeValue) e.fontSizeValue.textContent = val + 'px'; self.updatePreview(); }); } // Farben if (e.textColorInput) { e.textColorInput.addEventListener('input', function(ev) { state.set('textColor', ev.target.value); if (e.textColorValue) e.textColorValue.textContent = ev.target.value; self.updatePreview(); }); } if (e.frameColorInput) { e.frameColorInput.addEventListener('input', function(ev) { state.set('frameColor', ev.target.value); if (e.frameColorValue) e.frameColorValue.textContent = ev.target.value; self.updatePreview(); }); } // Rahmen-Skalierung - Slider und Number-Input synchronisieren if (e.frameScaleInput) { e.frameScaleInput.addEventListener('input', function(ev) { var val = parseInt(ev.target.value); state.set('frameScale', val); if (e.frameScaleValue) e.frameScaleValue.textContent = val + '%'; if (e.frameScaleNum) e.frameScaleNum.value = val; self.updatePreview(); }); } if (e.frameScaleNum) { e.frameScaleNum.addEventListener('input', function(ev) { var val = parseInt(ev.target.value) || 50; val = Math.max(50, Math.min(200, val)); state.set('frameScale', val); if (e.frameScaleInput) e.frameScaleInput.value = val; if (e.frameScaleValue) e.frameScaleValue.textContent = val + '%'; self.updatePreview(); }); } // Gesamt-Padding - Slider und Number-Input synchronisieren var syncAllPadding = function(val) { state.setMultiple({ paddingTop: val, paddingRight: val, paddingBottom: val, paddingLeft: val }); if (e.paddingAllValue) e.paddingAllValue.textContent = val + 'px'; if (e.paddingAllNum) e.paddingAllNum.value = val; if (e.paddingAllInput) e.paddingAllInput.value = val; if (e.paddingTopInput) e.paddingTopInput.value = val; if (e.paddingTopValue) e.paddingTopValue.textContent = val + 'px'; if (e.paddingRightInput) e.paddingRightInput.value = val; if (e.paddingRightValue) e.paddingRightValue.textContent = val + 'px'; if (e.paddingBottomInput) e.paddingBottomInput.value = val; if (e.paddingBottomValue) e.paddingBottomValue.textContent = val + 'px'; if (e.paddingLeftInput) e.paddingLeftInput.value = val; if (e.paddingLeftValue) e.paddingLeftValue.textContent = val + 'px'; self.updatePreview(); }; if (e.paddingAllInput) { e.paddingAllInput.addEventListener('input', function(ev) { syncAllPadding(parseInt(ev.target.value)); }); } if (e.paddingAllNum) { e.paddingAllNum.addEventListener('input', function(ev) { var val = parseInt(ev.target.value) || 0; val = Math.max(0, Math.min(50, val)); syncAllPadding(val); }); } // Einzelne Paddings this.bindPaddingSlider('paddingTopInput', 'paddingTopValue', 'paddingTop'); this.bindPaddingSlider('paddingRightInput', 'paddingRightValue', 'paddingRight'); this.bindPaddingSlider('paddingBottomInput', 'paddingBottomValue', 'paddingBottom'); this.bindPaddingSlider('paddingLeftInput', 'paddingLeftValue', 'paddingLeft'); // Pfeil-Slider this.bindSlider('arrowLengthInput', 'arrowLengthValue', 'arrowLength', 'px'); this.bindSlider('arrowAngleInput', 'arrowAngleValue', 'arrowAngle', '\u00B0'); this.bindSlider('arrowBendInput', 'arrowBendValue', 'arrowBend', '%'); this.bindSlider('arrowSizeInput', 'arrowSizeValue', 'arrowSize', 'px'); this.bindSlider('arrowTipLengthInput', 'arrowTipLengthValue', 'arrowTipLength', 'px'); // Shape-Buttons e.shapeButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.shapeButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('shape', btn.dataset.shape); self.updateVisibility(); self.updatePreview(); }); }); // Arrow-Buttons e.arrowButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.arrowButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('arrow', btn.dataset.arrow); self.updateVisibility(); self.updatePreview(); self.updateStandaloneArrowPreview(); }); }); // Line-Style-Buttons e.lineStyleButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.lineStyleButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('lineStyle', btn.dataset.style); self.updatePreview(); }); }); // Line-Weight-Buttons e.lineWeightButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.lineWeightButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('lineWeight', parseInt(btn.dataset.weight)); self.updatePreview(); }); }); // Align-X-Buttons (horizontal) e.alignXButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.alignXButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('textAlignX', btn.dataset.alignX); self.updatePreview(); }); }); // Align-Y-Buttons (vertikal) e.alignYButtons.forEach(function(btn) { btn.addEventListener('click', function() { e.alignYButtons.forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); state.set('textAlignY', btn.dataset.alignY); self.updatePreview(); }); }); }, bindSlider: function(inputKey, valueKey, stateKey, unit) { var self = this; var input = this.elements[inputKey]; var valueEl = this.elements[valueKey]; var numKey = inputKey.replace('Input', 'Num'); var numInput = this.elements[numKey]; var state = window.TextGenState; if (input) { input.addEventListener('input', function(ev) { var val = parseInt(ev.target.value); state.set(stateKey, val); if (valueEl) valueEl.textContent = val + unit; if (numInput) numInput.value = val; self.updatePreview(); if (stateKey.indexOf('arrow') === 0) { self.updateStandaloneArrowPreview(); } }); } if (numInput) { var min = input ? parseInt(input.min) : 0; var max = input ? parseInt(input.max) : 100; numInput.addEventListener('input', function(ev) { var val = parseInt(ev.target.value) || min; val = Math.max(min, Math.min(max, val)); state.set(stateKey, val); if (input) input.value = val; if (valueEl) valueEl.textContent = val + unit; self.updatePreview(); if (stateKey.indexOf('arrow') === 0) { self.updateStandaloneArrowPreview(); } }); } }, bindPaddingSlider: function(inputKey, valueKey, stateKey) { var self = this; var input = this.elements[inputKey]; var valueEl = this.elements[valueKey]; var state = window.TextGenState; if (input) { input.addEventListener('input', function(ev) { var val = parseInt(ev.target.value); state.set(stateKey, val); if (valueEl) valueEl.textContent = val + 'px'; self.updatePreview(); }); } }, syncFromState: function() { var e = this.elements; var s = window.TextGenState.current; if (e.textInput) e.textInput.value = s.text; if (e.fontSizeInput) e.fontSizeInput.value = s.fontSize; if (e.fontSizeNum) e.fontSizeNum.value = s.fontSize; if (e.fontSizeValue) e.fontSizeValue.textContent = s.fontSize + 'px'; if (e.textColorInput) e.textColorInput.value = s.textColor; if (e.frameColorInput) e.frameColorInput.value = s.frameColor; if (e.frameScaleInput) e.frameScaleInput.value = s.frameScale; if (e.frameScaleNum) e.frameScaleNum.value = s.frameScale; if (e.frameScaleValue) e.frameScaleValue.textContent = s.frameScale + '%'; // Padding if (e.paddingAllInput) e.paddingAllInput.value = s.paddingTop; if (e.paddingAllNum) e.paddingAllNum.value = s.paddingTop; if (e.paddingAllValue) e.paddingAllValue.textContent = s.paddingTop + 'px'; if (e.paddingTopInput) e.paddingTopInput.value = s.paddingTop; if (e.paddingTopValue) e.paddingTopValue.textContent = s.paddingTop + 'px'; if (e.paddingRightInput) e.paddingRightInput.value = s.paddingRight; if (e.paddingRightValue) e.paddingRightValue.textContent = s.paddingRight + 'px'; if (e.paddingBottomInput) e.paddingBottomInput.value = s.paddingBottom; if (e.paddingBottomValue) e.paddingBottomValue.textContent = s.paddingBottom + 'px'; if (e.paddingLeftInput) e.paddingLeftInput.value = s.paddingLeft; if (e.paddingLeftValue) e.paddingLeftValue.textContent = s.paddingLeft + 'px'; // Pfeil if (e.arrowLengthInput) e.arrowLengthInput.value = s.arrowLength; if (e.arrowLengthNum) e.arrowLengthNum.value = s.arrowLength; if (e.arrowLengthValue) e.arrowLengthValue.textContent = s.arrowLength + 'px'; if (e.arrowAngleInput) e.arrowAngleInput.value = s.arrowAngle; if (e.arrowAngleNum) e.arrowAngleNum.value = s.arrowAngle; if (e.arrowAngleValue) e.arrowAngleValue.textContent = s.arrowAngle + '\u00B0'; if (e.arrowBendInput) e.arrowBendInput.value = s.arrowBend; if (e.arrowBendNum) e.arrowBendNum.value = s.arrowBend; if (e.arrowBendValue) e.arrowBendValue.textContent = s.arrowBend + '%'; if (e.arrowSizeInput) e.arrowSizeInput.value = s.arrowSize; if (e.arrowSizeNum) e.arrowSizeNum.value = s.arrowSize; if (e.arrowSizeValue) e.arrowSizeValue.textContent = s.arrowSize + 'px'; if (e.arrowTipLengthInput) e.arrowTipLengthInput.value = s.arrowTipLength; if (e.arrowTipLengthNum) e.arrowTipLengthNum.value = s.arrowTipLength; if (e.arrowTipLengthValue) e.arrowTipLengthValue.textContent = s.arrowTipLength + 'px'; // Buttons aktivieren this.activateButton(e.shapeButtons, 'shape', s.shape); this.activateButton(e.arrowButtons, 'arrow', s.arrow); this.activateButton(e.lineStyleButtons, 'style', s.lineStyle); this.activateButtonByValue(e.lineWeightButtons, 'weight', s.lineWeight); this.activateButton(e.alignXButtons, 'alignX', s.textAlignX); this.activateButton(e.alignYButtons, 'alignY', s.textAlignY); }, activateButton: function(buttons, dataAttr, value) { buttons.forEach(function(btn) { btn.classList.remove('active'); if (btn.dataset[dataAttr] === value) { btn.classList.add('active'); } }); }, activateButtonByValue: function(buttons, dataAttr, value) { buttons.forEach(function(btn) { btn.classList.remove('active'); if (parseInt(btn.dataset[dataAttr]) === value) { btn.classList.add('active'); } }); }, updateVisibility: function() { var e = this.elements; var s = window.TextGenState.current; var hasShape = s.shape !== 'none'; var hasArrow = s.arrow !== 'none'; if (e.frameScaleRow) e.frameScaleRow.style.display = hasShape ? 'flex' : 'none'; if (e.paddingAllRow) e.paddingAllRow.style.display = hasShape ? 'flex' : 'none'; if (e.paddingRow) e.paddingRow.style.display = hasShape ? 'flex' : 'none'; if (e.textAlignRow) e.textAlignRow.style.display = hasShape ? 'flex' : 'none'; if (e.arrowDetailsRow) e.arrowDetailsRow.style.display = hasArrow ? 'flex' : 'none'; if (e.arrowDetailsRow2) e.arrowDetailsRow2.style.display = hasArrow ? 'flex' : 'none'; }, updatePreview: function() { var e = this.elements; if (e.textPreview && window.SvgGenerator) { var svg = window.SvgGenerator.generate(window.TextGenState.current); e.textPreview.innerHTML = svg; } }, updateStandaloneArrowPreview: function() { var e = this.elements; var s = window.TextGenState.current; if (!e.standaloneArrowPreview) return; if (s.arrow === 'none') { e.standaloneArrowPreview.innerHTML = '

Waehle einen Pfeil aus

'; return; } if (window.SvgGenerator) { var svg = window.SvgGenerator.generateArrowOnly(s); if (svg) { e.standaloneArrowPreview.innerHTML = svg; } } }, resetToDefaults: function() { window.TextGenState.reset(); this.syncFromState(); this.updateVisibility(); this.updatePreview(); this.updateStandaloneArrowPreview(); } }; window.UiBindings = UiBindings;