PageSourceSearch

https://www.justborn.com/wp-content/themes/studioswift/blocks/image-text/script.js

js justborn.com collected 2026-10-02 08:01:00 UTC 6,445 bytes, 224 lines download raw bytes

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.