PluginProbe
Parse.ly / 3.18.0
Parse.ly v3.18.0
3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 All 105 releases
wp-parsely / src / js / admin-settings.ts

admin-settings.ts in Parse.ly 3.18.0, at src/js/admin-settings.ts

227 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 document.addEventListener( 'DOMContentLoaded', (): void => {
2 addContentHelperTabEventHandlers();
3 setActiveTab();
4 window.addEventListener( 'hashchange', setActiveTab );
5 document.querySelector( '.media-single-image button.browse' )?.addEventListener( 'click', selectImage );
6 } );
7
8 function setActiveTab(): void {
9 const activeTab = location.hash !== '' ? location.hash.substring( 1 ) : 'basic-section';
10
11 document.querySelectorAll( '.nav-tab' )?.forEach( ( t: Element ): void => {
12 if ( t.classList.contains( activeTab + '-tab' ) ) {
13 t.classList.add( 'nav-tab-active' );
14 } else {
15 t.classList.remove( 'nav-tab-active' );
16 }
17 } );
18
19 document.querySelectorAll( '.tab-content' )?.forEach( ( t: Element ): void => {
20 if ( t.classList.contains( activeTab ) ) {
21 t.setAttribute( 'style', 'display: initial' );
22 } else {
23 t.setAttribute( 'style', 'display: none' );
24 }
25 } );
26
27 const form = document.querySelector( 'form[name="parsely"]' );
28 if ( form ) {
29 form.removeAttribute( 'hidden' );
30 form.setAttribute( 'action', `options.php#${ activeTab }` );
31 }
32 }
33
34 function selectImage( event: Event ) {
35 const optionName = ( event.target as HTMLButtonElement ).dataset.option;
36
37 const imageFrame = window.wp.media( {
38 multiple: false,
39 library: {
40 type: 'image',
41 },
42 } );
43
44 imageFrame.on( 'select', function() {
45 const url = imageFrame.state().get( 'selection' ).first().toJSON().url;
46 const inputSelector: string = '#media-single-image-' + optionName + ' input.file-path';
47
48 const inputElement: HTMLInputElement | null = document.querySelector( inputSelector );
49 if ( inputElement ) {
50 inputElement.value = url;
51 }
52 } );
53
54 imageFrame.open();
55 }
56
57 /**
58 * Adds the necessary event handlers to the Content Helper tab.
59 *
60 * @since 3.16.0
61 */
62 function addContentHelperTabEventHandlers(): void {
63 // Selector for the checkbox that enables/disables all AI features.
64 const aiFeaturesCheckbox = document.querySelector<HTMLInputElement>(
65 'input#content_helper_ai_features_enabled'
66 );
67
68 // Selector for the checkboxes that enable/disable individual AI features.
69 const featureCheckboxes = document.querySelectorAll<HTMLInputElement>(
70 'input#content_helper_smart_linking_enabled, ' +
71 'input#content_helper_title_suggestions_enabled, ' +
72 'input#content_helper_excerpt_suggestions_enabled'
73 );
74
75 // Selector for all fieldsets in the Content Helper section.
76 const fieldsets = document.querySelectorAll(
77 'div.content-helper-section fieldset'
78 );
79
80 // Event handlers.
81 enableAllFormFieldsOnSubmit();
82 updateAllFeatureSections(); // Must run on load to update the UI.
83
84 aiFeaturesCheckbox?.addEventListener( 'change', (): void => {
85 updateAllFeatureSections();
86 } );
87
88 featureCheckboxes.forEach( ( checkbox ): void => {
89 checkbox.addEventListener( 'change', (): void => {
90 updateFeatureSection( checkbox );
91 } );
92 } );
93
94 /**
95 * Turns on/off all AI feature sections in the UI.
96 *
97 * @since 3.16.0
98 */
99 function updateAllFeatureSections(): void {
100 if ( ! aiFeaturesCheckbox ) {
101 return;
102 }
103
104 if ( aiFeaturesCheckbox.checked ) {
105 // Enable all applicable fieldsets.
106 fieldsets.forEach( ( fieldset: Element ): void => {
107 setDisabled( fieldset, false );
108
109 featureCheckboxes.forEach( ( checkbox ): void => {
110 updateFeatureSection( checkbox );
111 } );
112 } );
113 } else {
114 // Disable all fieldsets.
115 fieldsets.forEach( ( fieldset: Element ): void => {
116 if ( ! fieldset.querySelector( `#${ aiFeaturesCheckbox.id }` ) ) {
117 setDisabled( fieldset );
118 }
119 } );
120
121 // Disable "Enabled" labels.
122 document.querySelectorAll( 'label.prevent-disable' )
123 .forEach( ( label: Element ): void => {
124 setPreventDisable( label, false );
125 } );
126 }
127 }
128
129 /**
130 * Turns on/off a specific feature section in the UI.
131 *
132 * @since 3.16.0
133 *
134 * @param {HTMLInputElement} checkbox The checkbox controlling the feature.
135 */
136 function updateFeatureSection( checkbox: HTMLInputElement ): void {
137 const userRolesFieldset = checkbox
138 .closest( 'fieldset' )?.nextSibling?.nextSibling as HTMLElement;
139
140 if ( checkbox.checked ) {
141 setDisabled( [ checkbox, userRolesFieldset ], false );
142 } else {
143 setDisabled( userRolesFieldset );
144
145 // Keep enabled styling on "Enabled" labels for visibility.
146 const enabledLabel = checkbox.parentElement as HTMLLabelElement;
147 setPreventDisable( enabledLabel );
148 }
149 }
150
151 /**
152 * Allows or prevents an element from being shown as disabled.
153 *
154 * This is done by injecting a class into the element, which is used in CSS.
155 *
156 * @since 3.16.0
157 *
158 * @param {Element} element The target element.
159 * @param {boolean} status true to prevent disabled style, false to allow.
160 */
161 function setPreventDisable( element: Element, status: boolean = true ): void {
162 if ( status ) {
163 element.classList.add( 'prevent-disable' );
164 } else {
165 element.classList.remove( 'prevent-disable' );
166 }
167 }
168
169 /**
170 * Sets the disabled attribute on an element.
171 *
172 * @since 3.16.0
173 *
174 * @param {Element | Element[]} element The target element.
175 * @param {boolean} status true to disable, false to enable.
176 */
177 function setDisabled( element: Element | Element[], status: boolean = true ): void {
178 if ( ! Array.isArray( element ) ) {
179 element = [ element ];
180 }
181
182 element.forEach( ( el: Element ): void => {
183 if ( status ) {
184 el.setAttribute( 'disabled', 'disabled' );
185 } else {
186 el.removeAttribute( 'disabled' );
187 }
188 } );
189 }
190
191 /**
192 * Allows the form to post its whole data.
193 *
194 * When elements are disabled, they are not included when submitting the
195 * form, resulting in missing data.
196 *
197 * This workaround removes any disabled attribute so the form can submit its
198 * whole data. It also prevents styling changes while the data is being
199 * submitted, in order to avoid visual glitches.
200 *
201 * @since 3.16.0
202 */
203 function enableAllFormFieldsOnSubmit(): void {
204 document.querySelector( '.wp-admin form[name="parsely"]' )
205 ?.addEventListener( 'submit', (): void => {
206 const baseSelector = '.wp-admin .content-helper-section fieldset';
207
208 document.querySelectorAll( `${ baseSelector }[disabled]` )
209 .forEach( ( fieldset: Element ): void => {
210 // Style the whole setting table row as disabled.
211 fieldset.parentElement?.parentElement?.classList.add(
212 'disabled-before-posting'
213 );
214
215 // Avoid disabled checkbox styling changes.
216 fieldset.querySelectorAll(
217 `${ baseSelector } label input[type="checkbox"]`
218 ).forEach( ( input: Element ): void => {
219 input.classList.add( 'disabled' );
220 } );
221
222 fieldset.removeAttribute( 'disabled' );
223 } );
224 } );
225 }
226 }
227