1/** 2 * Image Text Block Enhancement 3 * 4 * Handles conditional logic for image shape and border color fields 5 * - Disables round option when border color is not "none" 6 * - Enables round option when border color is "none" 7 * 8 * @package StudioSwift 9 */ 10 11(function($) { 12 'use strict'; 13 14 /** 15 * Get the scoped block container from a field element 16 */ 17 function getBlockScope($fieldEl) { 18 // Walk up to the nearest ACF block fields wrapper 19 var $scope = $fieldEl.closest('.acf-block-fields, .acf-block-component, [data-block]'); 20 return $scope.length ? $scope : $fieldEl.closest('.acf-fields'); 21 } 22 23 /** 24 * Get border color value scoped to a block 25 */ 26 function getBorderColorValue($scope) { 27 var $checked = $scope.find('[data-name="image_border_color"] input[type="radio"]:checked'); 28 return $checked.length ? $checked.val() : 'none'; 29 } 30 31 /** 32 * Set border color value scoped to a block 33 */ 34 function setBorderColorValue($scope, value) { 35 var $radio = $scope.find('[data-name="image_border_color"] input[type="radio"][value="' + value + '"]'); 36 if ($radio.length) { 37 $radio.prop('checked', true).trigger('change'); 38 } 39 } 40 41 /** 42 * Get image shape value scoped to a block 43 */ 44 function getImageShapeValue($scope) { 45 var $checked = $scope.find('[data-name="image_shape"] input[type="radio"]:checked, [data-name="image_shape"] input:checked'); 46 if ($checked.length) { 47 return $checked.val(); 48 } 49 return 'is-square'; 50 } 51 52 /** 53 * Set image shape value scoped to a block 54 */ 55 function setImageShapeValue($scope, value) { 56 var $field = $scope.find('[data-name="image_shape"]'); 57 if (!$field.length) return; 58 59 var acfField = acf.getField($field); 60 if (acfField) { 61 acfField.val(value); 62 return; 63 } 64 var $radio = $field.find('input[type="radio"][value="' + value + '"]'); 65 if ($radio.length) { 66 $radio.prop('checked', true).trigger('change'); 67 } 68 } 69 70 /** 71 * Get media type value scoped to a block 72 */ 73 function getMediaTypeValue($scope) { 74 var $checked = $scope.find('[data-name="media_type"] input[type="radio"]:checked, [data-name="media_type"] button.active'); 75 if ($checked.length) { 76 return $checked.val() || $checked.data('value') || 'image'; 77 } 78 return 'image'; 79 } 80 81 /** 82 * Enable round option scoped to a block 83 */ 84 function enableRoundOption($scope) { 85 var $roundInput = $scope.find('[data-name="image_shape"] input[value="is-rounded"]');
86 if (!$roundInput.length) return; 87 88 $roundInput.prop('disabled', false); 89 var $label = $roundInput.closest('label'); 90 ($label.length ? $label : $roundInput.parent()).css({ 91 'opacity': '1', 92 'cursor': 'pointer', 93 'pointer-events': 'auto' 94 }).removeClass('disabled'); 95 } 96 97 /** 98 * Disable round option scoped to a block 99 */ 100 function disableRoundOption($scope) { 101 var $roundInput = $scope.find('[data-name="image_shape"] input[value="is-rounded"]'); 102 if (!$roundInput.length) return; 103 104 $roundInput.prop('disabled', true); 105 var $label = $roundInput.closest('label'); 106 ($label.length ? $label : $roundInput.parent()).css({ 107 'opacity': '0.5', 108 'cursor': 'not-allowed', 109 'pointer-events': 'none' 110 }).addClass('disabled'); 111 } 112 113 /** 114 * Disable border color options except "none", scoped to a block 115 */ 116 function disableBorderColorOptions($scope) { 117 $scope.find('[data-name="image_border_color"] input[type="radio"]').each(function() { 118 var $radio = $(this); 119 var isNone = $radio.val() === 'none'; 120 $radio.prop('disabled', !isNone); 121 $radio.closest('label').css({ 122 'opacity': isNone ? '1' : '0.5', 123 'cursor': isNone ? 'pointer' : 'not-allowed', 124 'pointer-events': isNone ? 'auto' : 'none' 125 }); 126 }); 127 } 128 129 /** 130 * Enable all border color options, scoped to a block 131 */ 132 function enableBorderColorOptions($scope) { 133 $scope.find('[data-name="image_border_color"] input[type="radio"]').each(function() { 134 var $radio = $(this); 135 $radio.prop('disabled', false); 136 $radio.closest('label').css({ 137 'opacity': '1', 138 'cursor': 'pointer', 139 'pointer-events': 'auto' 140 }); 141 }); 142 } 143 144 /** 145 * Apply the full conditional logic for a given block scope. 146 * This is the single source of truth â called on init and on any change. 147 */ 148 function applyBlockLogic($scope) {
149 var borderColor = getBorderColorValue($scope); 150 var mediaType = getMediaTypeValue($scope); 151 var imageShape = getImageShapeValue($scope); 152 153 if (borderColor === 'none') { 154 // Border is none: round is allowed 155 enableRoundOption($scope); 156 enableBorderColorOptions($scope); 157 158 // Only disable border color options when image is rounded 159 if (mediaType === 'image' && imageShape === 'is-rounded') { 160 disableBorderColorOptions($scope); 161 } 162 } else { 163 // Border is coloured: round is not allowed 164 disableRoundOption($scope); 165 enableBorderColorOptions($scope); 166 167 // If somehow rounded is still selected, reset to square 168 if (imageShape === 'is-rounded') { 169 setImageShapeValue($scope, 'is-square'); 170 } 171 } 172 } 173 174 /** 175 * Bind change listeners scoped to a specific block container 176 */ 177 function bindBlockListeners($scope) { 178 // Prevent double-binding 179 if ($scope.data('image-text-bound')) return; 180 $scope.data('image-text-bound', true); 181 182 // Border color change 183 $scope.on('change', '[data-name="image_border_color"] input[type="radio"]', function() { 184 setTimeout(function() { applyBlockLogic($scope); }, 50); 185 }); 186 187 // Image shape change 188 $scope.on('change', '[data-name="image_shape"] input[type="radio"]', function() { 189 setTimeout(function() { applyBlockLogic($scope); }, 50); 190 }); 191 192 // Media type change 193 $scope.on('change', '[data-name="media_type"] input[type="radio"]', function() { 194 setTimeout(function() { applyBlockLogic($scope); }, 200); 195 }); 196 } 197 198 /** 199 * Initialize logic for all image-text blocks currently in the DOM 200 */ 201 function initAllBlocks() { 202 // Find every block that contains our fields 203 $('[data-name="image_border_color"]').each(function() { 204 var $scope = getBlockScope($(this)); 205 if ($scope.length) { 206 bindBlockListeners($scope); 207 applyBlockLogic($scope); 208 } 209 }); 210 } 211 212 /** 213 * Hook into ACF field ready events to also catch single-field init 214 */ 215 function initImageTextEnhancements() { 216 // Delay slightly to let the full block render into DOM 217 setTimeout(initAllBlocks, 300); 218 } 219 220 // Initialize when ACF is ready and whenever a block is appended 221 acf.addAction('ready', initImageTextEnhancements); 222 acf.addAction('append', initImageTextEnhancements); 223 224})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.