PluginProbe
BeyondWords – AI audio for publishers / 7.0.0
BeyondWords – AI audio for publishers v7.0.0
7.1.0 trunk 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.7.0 All 43 releases
speechkit / src / editor / components / settings-fields / classic-metabox.js

classic-metabox.js in BeyondWords – AI audio for publishers 7.0.0, at src/editor/components/settings-fields/classic-metabox.js

197 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global beyondwordsSettingsFields */
2
3 /*
4 * Classic-editor dynamic behaviour for the Content/Format/Player settings
5 * fields (show/hide + Embed recompute). Mirrors settings-panel/helpers.js.
6 */
7 ( function () {
8 'use strict';
9
10 const SOURCE_POST = 'post';
11 const SOURCE_POST_AND_SCRIPT = 'post_and_script';
12
13 const OUTPUT_AUDIO = 'audio';
14 const OUTPUT_VIDEO = 'video';
15 const OUTPUT_AUDIO_AND_VIDEO = 'audio_and_video';
16
17 const EMBED_NONE = 'none';
18
19 const labels =
20 ( typeof beyondwordsSettingsFields !== 'undefined' &&
21 beyondwordsSettingsFields.embedLabels ) ||
22 {};
23
24 // PHP normalises the rendered value, so the select only holds an offered source.
25 const sourceIncludesScript = ( source ) =>
26 source === SOURCE_POST_AND_SCRIPT;
27
28 const outputIncludesAudio = ( output ) =>
29 output === OUTPUT_AUDIO || output === OUTPUT_AUDIO_AND_VIDEO;
30
31 const outputIncludesVideo = ( output ) =>
32 output === OUTPUT_VIDEO || output === OUTPUT_AUDIO_AND_VIDEO;
33
34 /**
35 * Toggle an element's visibility by id.
36 *
37 * @param {string} id The element id.
38 * @param {boolean} show Whether the element should be visible.
39 */
40 const toggle = ( id, show ) => {
41 const el = document.getElementById( id );
42 if ( el ) {
43 el.style.display = show ? '' : 'none';
44 }
45 };
46
47 /**
48 * Derive the valid Embed options from the current Source × Output.
49 *
50 * @param {string} source The current source value.
51 * @param {string} output The current output value.
52 *
53 * @return {Array<{label: string, value: string}>} Embed options.
54 */
55 const getEmbedOptions = ( source, output ) => {
56 const options = [ { label: labels.none || 'None', value: EMBED_NONE } ];
57 const includesScript = sourceIncludesScript( source );
58
59 if ( outputIncludesAudio( output ) ) {
60 options.push( {
61 label: labels.audio_post || 'Audio (post)',
62 value: 'audio_post',
63 } );
64 if ( includesScript ) {
65 options.push( {
66 label: labels.audio_script || 'Audio (script)',
67 value: 'audio_script',
68 } );
69 }
70 }
71
72 if ( outputIncludesVideo( output ) ) {
73 options.push( {
74 label: labels.video_post || 'Video (post)',
75 value: 'video_post',
76 } );
77 if ( includesScript ) {
78 options.push( {
79 label: labels.video_script || 'Video (script)',
80 value: 'video_script',
81 } );
82 }
83 }
84
85 return options;
86 };
87
88 /**
89 * The first produced asset, or None when the options hold no asset.
90 *
91 * @param {Array<{label: string, value: string}>} options The Embed options.
92 *
93 * @return {string} The default embed value.
94 */
95 const getDefaultEmbed = ( options ) => {
96 const asset = options.find( ( option ) => option.value !== EMBED_NONE );
97
98 return asset ? asset.value : EMBED_NONE;
99 };
100
101 const settingsFields = {
102 init() {
103 this.source = document.getElementById( 'beyondwords_source' );
104 this.output = document.getElementById( 'beyondwords_output' );
105 this.embed = document.getElementById( 'beyondwords_embed' );
106 this.embedTouched = document.getElementById(
107 'beyondwords_embed_touched'
108 );
109
110 // Set before the guard below: the flag gates the whole save() write.
111 if ( this.embed && this.embedTouched ) {
112 this.embed.addEventListener( 'change', () => {
113 this.embedTouched.value = '1';
114 } );
115 }
116
117 if ( ! this.source && ! this.output ) {
118 return;
119 }
120
121 if ( this.source ) {
122 this.source.addEventListener( 'change', () => {
123 this.toggleScriptTemplate();
124 this.recomputeEmbed();
125 } );
126 }
127
128 if ( this.output ) {
129 this.output.addEventListener( 'change', () => {
130 this.toggleVideoFields();
131 this.recomputeEmbed();
132 } );
133 }
134
135 // Sync initial visibility in case meta and markup drift.
136 this.toggleScriptTemplate();
137 this.toggleVideoFields();
138 },
139
140 toggleScriptTemplate() {
141 const show = this.source
142 ? sourceIncludesScript( this.source.value )
143 : false;
144 toggle(
145 'beyondwords-metabox-settings--beyondwords-script-template-id',
146 show
147 );
148 },
149
150 toggleVideoFields() {
151 const show = this.output
152 ? outputIncludesVideo( this.output.value )
153 : false;
154 toggle(
155 'beyondwords-metabox-settings--beyondwords-video-template-id',
156 show
157 );
158 toggle(
159 'beyondwords-metabox-settings--beyondwords-video-size',
160 show
161 );
162 },
163
164 recomputeEmbed() {
165 if ( ! this.embed ) {
166 return;
167 }
168
169 const source = this.source ? this.source.value : SOURCE_POST;
170 const output = this.output ? this.output.value : OUTPUT_AUDIO;
171 const options = getEmbedOptions( source, output );
172 const previous = this.embed.value;
173 const stillValid = options.some( ( o ) => o.value === previous );
174 // Only a stale value lands here — None is valid for every combination.
175 const selected = stillValid ? previous : getDefaultEmbed( options );
176
177 this.embed.replaceChildren(
178 ...options.map( ( option ) => {
179 const el = document.createElement( 'option' );
180 el.value = option.value;
181 el.textContent = option.label;
182 el.selected = option.value === selected;
183 return el;
184 } )
185 );
186 },
187 };
188
189 if ( document.readyState !== 'loading' ) {
190 settingsFields.init();
191 } else {
192 document.addEventListener( 'DOMContentLoaded', () =>
193 settingsFields.init()
194 );
195 }
196 } )();
197