|
1 | | -/* global document, jQuery, ef_week_first_day */ |
| 1 | +/* global document, jQuery, ef_week_first_day, wp */ |
2 | 2 |
|
3 | | -jQuery( document ).ready( function() { |
4 | | - const dateTimePicks = jQuery( '.date-time-pick' ); |
| 3 | +jQuery( document ).ready( function( $ ) { |
| 4 | + /** |
| 5 | + * Check if we're in the Gutenberg editor. |
| 6 | + * |
| 7 | + * @return {boolean} True if Gutenberg is available. |
| 8 | + */ |
| 9 | + function isGutenberg() { |
| 10 | + return typeof wp !== 'undefined' && wp.data && wp.data.dispatch && wp.data.select; |
| 11 | + } |
5 | 12 |
|
6 | | - dateTimePicks.each( function() { |
7 | | - const $dTP = jQuery( this ); |
| 13 | + /** |
| 14 | + * Check if Gutenberg post entity is ready for meta updates. |
| 15 | + * |
| 16 | + * @return {boolean} True if ready. |
| 17 | + */ |
| 18 | + function isGutenbergReady() { |
| 19 | + if ( ! isGutenberg() ) { |
| 20 | + return false; |
| 21 | + } |
| 22 | + try { |
| 23 | + const postType = wp.data.select( 'core/editor' ).getCurrentPostType(); |
| 24 | + return !! postType; |
| 25 | + } catch ( e ) { |
| 26 | + return false; |
| 27 | + } |
| 28 | + } |
8 | 29 |
|
9 | | - $dTP.datetimepicker( { |
10 | | - dateFormat: 'M dd yy', |
11 | | - firstDay: ef_week_first_day, |
12 | | - alwaysSetTime: false, |
13 | | - controlType: 'select', |
14 | | - altField: '#' + $dTP.prop( 'id' ) + '_hidden', |
15 | | - altFieldTimeOnly: false, |
16 | | - altFormat: 'yy-mm-dd', |
17 | | - altTimeFormat: 'HH:mm', |
18 | | - } ); |
19 | | - } ); |
| 30 | + /** |
| 31 | + * Update Gutenberg's data store with the meta value. |
| 32 | + * This ensures that when the user saves, the REST API includes our updated meta. |
| 33 | + * |
| 34 | + * @param {string} metaKey The post meta key. |
| 35 | + * @param {*} metaValue The value to save (will be converted to string). |
| 36 | + */ |
| 37 | + function updateGutenbergMeta( metaKey, metaValue ) { |
| 38 | + if ( ! isGutenbergReady() ) { |
| 39 | + return; |
| 40 | + } |
| 41 | + |
| 42 | + const meta = {}; |
| 43 | + // Convert to string since REST API expects string type. |
| 44 | + meta[ metaKey ] = String( metaValue ); |
| 45 | + |
| 46 | + wp.data.dispatch( 'core/editor' ).editPost( { meta: meta } ); |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * Update the hidden field with combined date and time values. |
| 51 | + * The hidden field stores the value in 'Y-m-d H:i' format for PHP processing. |
| 52 | + * Also updates Gutenberg's data store with the Unix timestamp. |
| 53 | + * |
| 54 | + * @param {jQuery} $dateInput The date input element. |
| 55 | + * @param {boolean} updateGutenberg Whether to update Gutenberg store (default true). |
| 56 | + */ |
| 57 | + function updateHiddenField( $dateInput, updateGutenberg ) { |
| 58 | + if ( typeof updateGutenberg === 'undefined' ) { |
| 59 | + updateGutenberg = true; |
| 60 | + } |
| 61 | + |
| 62 | + // Derive related element IDs from the date input ID. |
| 63 | + // Date input: {key}_date, Time input: {key}_time, Hidden: {key}_hidden |
| 64 | + const baseId = $dateInput.attr( 'id' ).replace( /_date$/, '' ); |
| 65 | + const $timeInput = $( '#' + baseId + '_time' ); |
| 66 | + const $hiddenInput = $( '#' + baseId + '_hidden' ); |
| 67 | + |
| 68 | + if ( ! $hiddenInput.length ) { |
| 69 | + return; |
| 70 | + } |
20 | 71 |
|
21 | | - const datePicks = jQuery( '.date-pick' ); |
22 | | - datePicks.each( function() { |
23 | | - const $datePicker = jQuery( this ); |
| 72 | + // Get the date value from the datepicker's altField mechanism or parse it. |
| 73 | + let dateValue = $dateInput.datepicker( 'getDate' ); |
| 74 | + if ( ! dateValue ) { |
| 75 | + $hiddenInput.val( '' ); |
| 76 | + if ( updateGutenberg ) { |
| 77 | + updateGutenbergMeta( baseId, '' ); |
| 78 | + } |
| 79 | + return; |
| 80 | + } |
| 81 | + |
| 82 | + // Format date as Y-m-d. |
| 83 | + const year = dateValue.getFullYear(); |
| 84 | + const month = String( dateValue.getMonth() + 1 ).padStart( 2, '0' ); |
| 85 | + const day = String( dateValue.getDate() ).padStart( 2, '0' ); |
| 86 | + const formattedDate = year + '-' + month + '-' + day; |
| 87 | + |
| 88 | + // Get time value (HH:mm format from HTML5 time input). |
| 89 | + let timeValue = $timeInput.val() || '00:00'; |
| 90 | + |
| 91 | + // Combine into 'Y-m-d H:i' format for the hidden field. |
| 92 | + $hiddenInput.val( formattedDate + ' ' + timeValue ); |
| 93 | + |
| 94 | + if ( updateGutenberg ) { |
| 95 | + // Calculate Unix timestamp for Gutenberg. |
| 96 | + const timeParts = timeValue.split( ':' ); |
| 97 | + const hours = parseInt( timeParts[ 0 ], 10 ) || 0; |
| 98 | + const minutes = parseInt( timeParts[ 1 ], 10 ) || 0; |
| 99 | + |
| 100 | + // Create a new Date object with the combined date and time. |
| 101 | + const combinedDate = new Date( year, dateValue.getMonth(), dateValue.getDate(), hours, minutes, 0 ); |
| 102 | + const timestamp = Math.floor( combinedDate.getTime() / 1000 ); |
| 103 | + |
| 104 | + // Update Gutenberg's data store with the Unix timestamp (as string). |
| 105 | + updateGutenbergMeta( baseId, timestamp ); |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | + // Initialize jQuery UI datepicker on .date-pick elements. |
| 110 | + const $datePicks = $( '.date-pick' ); |
| 111 | + |
| 112 | + $datePicks.each( function() { |
| 113 | + const $datePicker = $( this ); |
24 | 114 |
|
25 | 115 | $datePicker.datepicker( { |
| 116 | + dateFormat: 'M dd yy', |
26 | 117 | firstDay: ef_week_first_day, |
27 | | - altField: '#' + $datePicker.prop( 'id' ) + '_hidden', |
28 | | - altFormat: 'yy-mm-dd', |
29 | 118 | showButtonPanel: true, |
| 119 | + onSelect: function() { |
| 120 | + updateHiddenField( $datePicker, true ); |
| 121 | + }, |
30 | 122 | } ); |
| 123 | + |
| 124 | + // Update hidden field when date input changes (e.g., manual input). |
| 125 | + $datePicker.on( 'change', function() { |
| 126 | + updateHiddenField( $datePicker, true ); |
| 127 | + } ); |
| 128 | + } ); |
| 129 | + |
| 130 | + // Update hidden field when time input changes. |
| 131 | + $( '.time-pick' ).on( 'change', function() { |
| 132 | + const $timeInput = $( this ); |
| 133 | + // Derive the date input from the time input ID. |
| 134 | + const baseId = $timeInput.attr( 'id' ).replace( /_time$/, '' ); |
| 135 | + const $dateInput = $( '#' + baseId + '_date' ); |
| 136 | + |
| 137 | + if ( $dateInput.length ) { |
| 138 | + updateHiddenField( $dateInput, true ); |
| 139 | + } |
31 | 140 | } ); |
| 141 | + |
| 142 | + // Initialize hidden fields with current values on page load. |
| 143 | + // Do NOT update Gutenberg here - just set up the hidden field for form submission. |
| 144 | + $datePicks.each( function() { |
| 145 | + const $datePicker = $( this ); |
| 146 | + if ( $datePicker.val() ) { |
| 147 | + updateHiddenField( $datePicker, false ); |
| 148 | + } |
| 149 | + } ); |
| 150 | + |
| 151 | + /** |
| 152 | + * Sync all Editorial Metadata fields to Gutenberg. |
| 153 | + * This handles text, paragraph, checkbox, user, number, and location fields. |
| 154 | + */ |
| 155 | + function setupMetaboxSync() { |
| 156 | + const $metaBox = $( '#ef_editorial_meta_meta_box' ); |
| 157 | + |
| 158 | + if ( ! $metaBox.length || ! isGutenberg() ) { |
| 159 | + return; |
| 160 | + } |
| 161 | + |
| 162 | + // Text, paragraph, number, and location inputs. |
| 163 | + $metaBox.find( 'input[type="text"]:not(.date-pick), textarea, select' ).on( 'change input', function() { |
| 164 | + const $input = $( this ); |
| 165 | + const name = $input.attr( 'name' ); |
| 166 | + |
| 167 | + // Skip hidden fields and fields without names. |
| 168 | + if ( ! name || name.endsWith( '_hidden' ) ) { |
| 169 | + return; |
| 170 | + } |
| 171 | + |
| 172 | + updateGutenbergMeta( name, $input.val() ); |
| 173 | + } ); |
| 174 | + |
| 175 | + // Checkbox inputs. |
| 176 | + $metaBox.find( 'input[type="checkbox"]' ).on( 'change', function() { |
| 177 | + const $input = $( this ); |
| 178 | + const name = $input.attr( 'name' ); |
| 179 | + |
| 180 | + if ( ! name ) { |
| 181 | + return; |
| 182 | + } |
| 183 | + |
| 184 | + // Store as '1' or '' to match PHP behavior. |
| 185 | + const value = $input.is( ':checked' ) ? '1' : ''; |
| 186 | + updateGutenbergMeta( name, value ); |
| 187 | + } ); |
| 188 | + } |
| 189 | + |
| 190 | + // Set up metabox sync for Gutenberg. |
| 191 | + setupMetaboxSync(); |
32 | 192 | } ); |
0 commit comments