diff --git a/assets/js/odw-admin-fields.js b/assets/js/odw-admin-fields.js index 046dc26..bb68bcc 100644 --- a/assets/js/odw-admin-fields.js +++ b/assets/js/odw-admin-fields.js @@ -6,11 +6,14 @@ * 1. Auto-suggest datalist for license_custom (inside distributions) * 2. Auto-suggest datalist for CESSDA topic classification * 3. Composite file-size widget (Zahl + Einheit → Bytes in backing field) + * Widget HTML is built via JS so no CF html-field is needed inside + * the complex field (CF5 React renderer crashes on html fields there). */ ( function () { 'use strict'; var data = ( typeof odwAdminFields !== 'undefined' ) ? odwAdminFields : {}; + var i18n = data.fileSizeWidget || {}; // ------------------------------------------------------------------------- // Utility: set a value on a React-controlled or plain input @@ -77,75 +80,118 @@ // ------------------------------------------------------------------------- // 3. File-size composite widget - // Finds every .odw-filesize-widget and wires up its number+unit inputs - // to write computed bytes into the backing CF field. + // Built dynamically from JS so no CF html-field is needed inside the + // complex field. Finds every hidden [data-odw-backing] input and inserts + // a visible composite widget before its CF field wrapper. // ------------------------------------------------------------------------- - function initFileSizeWidgets() { - document.querySelectorAll( '.odw-filesize-widget' ).forEach( function ( widget ) { - var numberInput = widget.querySelector( '.odw-filesize-number' ); - var unitSelect = widget.querySelector( '.odw-filesize-unit' ); - var hint = widget.querySelector( '.odw-filesize-hint' ); - - // Find the backing CF input (data-odw-backing="byte_size" in same group). - var group = widget.closest( '.carbon-fields-group, .carbon-complex-group, .cf-group, [data-group]' ); - var backing = group - ? group.querySelector( 'input[data-odw-backing="byte_size"]' ) - : null; - - if ( ! numberInput || ! unitSelect ) { - return; - } - - var factors = { KB: 1024, MB: 1048576, GB: 1073741824 }; + function buildWidgetHtml() { + var label = i18n.label || 'Dateigröße'; + var optional = i18n.optional || '(optional)'; + var placeholder = i18n.placeholder || 'z. B. 2.5'; + var ariaNumber = i18n.ariaNumber || 'Dateigröße Zahlenwert'; + var ariaUnit = i18n.ariaUnit || 'Einheit'; + var helpText = i18n.helpText || '1 MB = 1.024 KB'; + + return '
'; + } - function updateBacking() { - var num = parseFloat( numberInput.value ); - var unit = unitSelect.value; - if ( isNaN( num ) || num < 0 ) { - numberInput.setCustomValidity( 'Bitte einen positiven Wert eingeben.' ); - if ( hint ) { - hint.textContent = ''; - } - return; + function wireWidget( widget, backing ) { + var numberInput = widget.querySelector( '.odw-filesize-number' ); + var unitSelect = widget.querySelector( '.odw-filesize-unit' ); + var hint = widget.querySelector( '.odw-filesize-hint' ); + var factors = { KB: 1024, MB: 1048576, GB: 1073741824 }; + + function updateBacking() { + var num = parseFloat( numberInput.value ); + var unit = unitSelect.value; + if ( isNaN( num ) || num < 0 ) { + numberInput.setCustomValidity( 'Bitte einen positiven Wert eingeben.' ); + if ( hint ) { + hint.textContent = ''; } - numberInput.setCustomValidity( '' ); + return; + } + numberInput.setCustomValidity( '' ); - var bytes = Math.round( num * ( factors[ unit ] || 1048576 ) ); + var bytes = Math.round( num * ( factors[ unit ] || 1048576 ) ); - if ( hint ) { - hint.textContent = '= ' + bytes.toLocaleString( 'de-DE' ) + ' Bytes'; - } + if ( hint ) { + hint.textContent = '= ' + bytes.toLocaleString( 'de-DE' ) + ' Bytes'; + } - if ( backing ) { - setInputValue( backing, String( bytes ) ); - } + if ( backing ) { + setInputValue( backing, String( bytes ) ); } + } - numberInput.addEventListener( 'input', updateBacking ); - numberInput.addEventListener( 'change', updateBacking ); - unitSelect.addEventListener( 'change', updateBacking ); - - // Restore display value from stored bytes on page load. - if ( backing && backing.value && backing.value !== '0' && backing.value !== '' ) { - var stored = parseInt( backing.value, 10 ); - if ( ! isNaN( stored ) && stored > 0 ) { - var displayUnit = 'MB'; - var displayVal; - if ( stored >= 1073741824 ) { - displayUnit = 'GB'; - displayVal = stored / 1073741824; - } else if ( stored >= 1048576 ) { - displayUnit = 'MB'; - displayVal = stored / 1048576; - } else { - displayUnit = 'KB'; - displayVal = stored / 1024; - } - numberInput.value = parseFloat( displayVal.toFixed( 2 ) ); - unitSelect.value = displayUnit; - updateBacking(); + numberInput.addEventListener( 'input', updateBacking ); + numberInput.addEventListener( 'change', updateBacking ); + unitSelect.addEventListener( 'change', updateBacking ); + + // Restore display value from stored bytes on page load. + if ( backing && backing.value && backing.value !== '0' && backing.value !== '' ) { + var stored = parseInt( backing.value, 10 ); + if ( ! isNaN( stored ) && stored > 0 ) { + var displayUnit, displayVal; + if ( stored >= 1073741824 ) { + displayUnit = 'GB'; + displayVal = stored / 1073741824; + } else if ( stored >= 1048576 ) { + displayUnit = 'MB'; + displayVal = stored / 1048576; + } else { + displayUnit = 'KB'; + displayVal = stored / 1024; } + numberInput.value = parseFloat( displayVal.toFixed( 2 ) ); + unitSelect.value = displayUnit; + updateBacking(); } + } + } + + function initFileSizeWidget( backing ) { + if ( ! backing || backing.dataset.odwWidgetInit ) { + return; + } + backing.dataset.odwWidgetInit = '1'; + + // Find the CF field wrapper that contains the backing input. + // CF5 uses .cf-field as the wrapper; fall back to closest div. + var fieldWrapper = backing.closest( '.cf-field' ) || + backing.closest( 'div[class]' ) || + backing.parentElement; + + if ( ! fieldWrapper || ! fieldWrapper.parentNode ) { + return; + } + + var widget = document.createElement( 'div' ); + widget.innerHTML = buildWidgetHtml(); + var widgetEl = widget.firstElementChild; + + fieldWrapper.parentNode.insertBefore( widgetEl, fieldWrapper ); + wireWidget( widgetEl, backing ); + } + + function initFileSizeWidgets() { + document.querySelectorAll( 'input[data-odw-backing="byte_size"]' ).forEach( function ( backing ) { + initFileSizeWidget( backing ); } ); } @@ -163,8 +209,8 @@ node.querySelectorAll( 'input[data-odw-autosuggest="license_custom"]' ).forEach( function ( input ) { attachDatalist( input, 'odw-license-datalist', data.licenseOptions || [] ); } ); - node.querySelectorAll( '.odw-filesize-widget' ).forEach( function () { - initFileSizeWidgets(); + node.querySelectorAll( 'input[data-odw-backing="byte_size"]' ).forEach( function ( backing ) { + initFileSizeWidget( backing ); } ); } ); } ); diff --git a/includes/class-admin.php b/includes/class-admin.php index 0977cac..ae6dfac 100644 --- a/includes/class-admin.php +++ b/includes/class-admin.php @@ -306,6 +306,14 @@ public static function enqueue_assets( string $hook ): void { array( 'licenseOptions' => $license_file_options, 'cessdaOptions' => $cessda_options, + 'fileSizeWidget' => array( + 'label' => __( 'Dateigröße', 'open-data-wizard' ), + 'optional' => __( '(optional)', 'open-data-wizard' ), + 'placeholder' => __( 'z. B. 2.5', 'open-data-wizard' ), + 'ariaNumber' => __( 'Dateigröße Zahlenwert', 'open-data-wizard' ), + 'ariaUnit' => __( 'Einheit', 'open-data-wizard' ), + 'helpText' => __( 'Bitte geben Sie die ungefähre Größe der Datei an und wählen Sie die passende Einheit. 1 MB = 1.024 KB', 'open-data-wizard' ), + ), ) ); diff --git a/includes/class-fields.php b/includes/class-fields.php index bf87314..1f234a9 100644 --- a/includes/class-fields.php +++ b/includes/class-fields.php @@ -143,9 +143,6 @@ private static function register_required_fields(): void { ->add_options( self::get_format_options() ) ->set_help_text( __( 'FORMAT (dct:format)', 'open-data-wizard' ) . "\n\n" . __( 'Beispiel: CSV, JSON, PDF', 'open-data-wizard' ) ), - Field::make( 'html', 'byte_size_ui' ) - ->set_html( self::get_filesize_widget_html() ), - Field::make( 'text', 'byte_size', __( 'Dateigröße (Bytes)', 'open-data-wizard' ) ) ->set_attribute( 'type', 'number' ) ->set_attribute( 'min', '0' ) @@ -630,38 +627,6 @@ public static function get_political_geocoding_level_options(): array { * * @return string HTML markup. */ - private static function get_filesize_widget_html(): string { - ob_start(); - ?> - -