PluginProbe
Polylang / 3.0.3
Polylang v3.0.3
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / js / build / block-editor.js

block-editor.js in Polylang 3.0.3, at js/build/block-editor.js

355 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ "use strict";
2
3 ;// CONCATENATED MODULE: ./js/lib/confirmation-modal.js
4 /**
5 * @package Polylang
6 */
7
8 const languagesList = jQuery( '.post_lang_choice' );
9
10 // Dialog box for alerting the user about a risky changing.
11 const initializeConfimationModal = () => {
12 // We can't use underscore or lodash in this common code because it depends of the context classic or block editor.
13 // Classic editor underscore is loaded, Block editor lodash is loaded.
14 const { __ } = wp.i18n;
15
16 // Create dialog container.
17 const dialogContainer = jQuery(
18 '<div/>',
19 {
20 id: 'pll-dialog',
21 style: 'display:none;'
22 }
23 ).text( __( 'Are you sure you want to change the language of the current content?', 'polylang' ) );
24
25 // Put it after languages list dropdown.
26 // PHPCS ignore dialogContainer is a new safe HTML code generated above.
27 languagesList.after( dialogContainer ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.after
28
29 const dialogResult = new Promise(
30 ( confirm, cancel ) => {
31 const confirmDialog = ( what ) => { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
32 switch ( what ) { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
33 case 'yes':
34 // Confirm the new language.
35 languagesList.data( 'old-value', languagesList.children( ':selected' )[0].value );
36 confirm();
37 break;
38 case 'no':
39 // Revert to the old language.
40 languagesList.val( languagesList.data( 'old-value' ) );
41 cancel( 'Cancel' );
42 break;
43 }
44 dialogContainer.dialog( 'close' ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
45 } // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
46
47 // Initialize dialog box in the case a language is selected but not added in the list.
48 const dialogOptions = {
49 autoOpen: false,
50 modal: true,
51 draggable: false,
52 resizable: false,
53 title: __( 'Change language', 'polylang' ),
54 minWidth: 600,
55 maxWidth: '100%',
56 open: function( event, ui ) {
57 // Change dialog box position for rtl language
58 if ( jQuery( 'body' ).hasClass( 'rtl' ) ) {
59 jQuery( this ).parent().css(
60 {
61 right: jQuery( this ).parent().css( 'left' ),
62 left: 'auto'
63 }
64 );
65 }
66 },
67 close: function( event, ui ) {
68 // When we're closing the dialog box we need to cancel the language change as we click on Cancel button.
69 confirmDialog( 'no' );
70 },
71 buttons: [
72 {
73 text: __( 'OK', 'polylang' ),
74 click: function( event ) {
75 confirmDialog( 'yes' );
76 }
77 },
78 {
79 text: __( 'Cancel', 'polylang' ),
80 click: function( event ) {
81 confirmDialog( 'no' );
82 }
83 }
84 ]
85 };
86
87 if ( jQuery.ui.version >= '1.12.0' ) {
88 Object.assign( dialogOptions, { classes: { 'ui-dialog': 'pll-confirmation-modal' } } );
89 } else {
90 Object.assign( dialogOptions, { dialogClass: 'pll-confirmation-modal' } ); // jQuery UI 1.11.4 - WP < 5.6
91 }
92
93 dialogContainer.dialog( dialogOptions );
94 }
95 );
96 return { dialogContainer, dialogResult };
97 }
98
99 const initializeLanguageOldValue = () => {
100 // Keep the old language value to be able to compare to the new one and revert to it if necessary.
101 languagesList.attr( 'data-old-value', languagesList.children( ':selected' )[0].value );
102 };
103
104 ;// CONCATENATED MODULE: ./js/block-editor.js
105 /**
106 * @package Polylang
107 */
108
109
110
111 /**
112 * Filter REST API requests to add the language in the request
113 *
114 * @since 2.5
115 */
116 wp.apiFetch.use(
117 function( options, next ) {
118 // If options.url is defined, this is not a REST request but a direct call to post.php for legacy metaboxes.
119 if ( 'undefined' === typeof options.url ) {
120 if ( 'undefined' === typeof options.data || null === options.data ) {
121 // GET
122 options.path += ( ( options.path.indexOf( '?' ) >= 0 ) ? '&lang=' : '?lang=' ) + getCurrentLanguage();
123 } else {
124 // PUT, POST
125 options.data.lang = getCurrentLanguage();
126 }
127 }
128 return next( options );
129 }
130 );
131
132 /**
133 * Get the language from the HTML form
134 *
135 * @since 2.5
136 *
137 * @return {Element.value}
138 */
139 function getCurrentLanguage() {
140 return document.querySelector( '[name=post_lang_choice]' ).value;
141 }
142
143 /**
144 * Handles internals of the metabox:
145 * Language select, autocomplete input field.
146 *
147 * @since 1.5
148 *
149 * Save post after lang choice is done and redirect to the same page for refreshing all the data.
150 *
151 * @since 2.5
152 *
153 * Link post saving after refreshing the metabox.
154 *
155 * @since 3.0
156 */
157 jQuery(
158 function( $ ) {
159 // Initialize current language to be able to compare if it changes.
160 initializeLanguageOldValue();
161
162
163 // Ajax for changing the post's language in the languages metabox
164 $( '.post_lang_choice' ).on(
165 'change',
166 function( event ) {
167 const select = wp.data.select;
168 const dispatch = wp.data.dispatch;
169 const subscribe = wp.data.subscribe;
170 const emptyPost = isEmptyPost();
171
172 // Initialize the confirmation dialog box.
173 const confirmationModal = initializeConfimationModal();
174 const { dialogContainer : dialog } = confirmationModal;
175 let { dialogResult } = confirmationModal;
176 // The selected option in the dropdown list.
177 const selectedOption = event.target;
178
179 // Specific case for empty posts.
180 // Place at the beginning because window.location changing triggers automatically page reloading.
181 if ( location.pathname.match( /post-new.php/gi ) && emptyPost ) {
182 reloadPageForEmptyPost( selectedOption.value );
183 }
184
185 // Otherwise send an ajax request to refresh the legacy metabox and set the post language with the new language.
186 // It needs a confirmation of the user before changing the language.
187 // Need to wait the ajax response before triggering the block editor post save action.
188 if ( $( this ).data( 'old-value' ) !== selectedOption.value && ! emptyPost ) {
189 dialog.dialog( 'open' );
190 } else {
191 // Update the old language with the new one to be able to compare it in the next changing.
192 // Because the page isn't reloaded in this case.
193 initializeLanguageOldValue();
194 dialogResult = Promise.resolve();
195 }
196
197 dialogResult.then(
198 () => {
199 var data = { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
200 action: 'post_lang_choice',
201 lang: selectedOption.value,
202 post_type: $( '#post_type' ).val(),
203 post_id: $( '#post_ID' ).val(),
204 _pll_nonce: $( '#_pll_nonce' ).val()
205 }
206
207 $.post(
208 ajaxurl,
209 data,
210 function( response ) {
211 var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
212 $.each(
213 res.responses,
214 function() {
215 switch ( this.what ) {
216 case 'translations': // Translations fields
217 // Data is built and come from server side and is well escaped when necessary
218 $( '.translations' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
219 init_translations();
220 break;
221 case 'flag': // Flag in front of the select dropdown
222 // Data is built and come from server side and is well escaped when necessary
223 $( '.pll-select-flag' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
224 break;
225 }
226 }
227 );
228 blockEditorSavePostAndReloadPage();
229 }
230 );
231 },
232 () => {} // Do nothing when promise is rejected by clicking the Cancel dialog button.
233 );
234
235 function isEmptyPost() {
236 const editor = wp.data.select( 'core/editor' );
237 const title = editor.getEditedPostAttribute( 'title' ).trim();
238 const content = editor.getEditedPostAttribute( 'content' ).trim();
239 const excerpt = editor.getEditedPostAttribute( 'excerpt' ).trim();
240
241 return ! title && ! content && ! excerpt;
242 }
243
244 /**
245 * Reload the block editor page for empty posts.
246 *
247 * @param {string} lang The target language code.
248 */
249 function reloadPageForEmptyPost( lang ) {
250 // Change the new_lang parameter with the new language value for reloading the page
251 // WPCS location.search is never written in the page, just used to reload page with the right value of new_lang
252 // new_lang input is controlled server side in PHP. The value come from the dropdown list of language returned and escaped server side.
253 // Notice that window.location changing triggers automatically page reloading.
254 if ( -1 != location.search.indexOf( 'new_lang' ) ) {
255 // use regexp non capturing group to replace new_lang parameter no matter where it is and capture other parameters which can be behind it
256 window.location.search = window.location.search.replace( /(?:new_lang=[^&]*)(&)?(.*)/, 'new_lang=' + lang + '$1$2' ); // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
257 } else {
258 window.location.search = window.location.search + ( ( -1 != window.location.search.indexOf( '?' ) ) ? '&' : '?' ) + 'new_lang=' + lang; // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
259 }
260 };
261
262 /**
263 * Triggers block editor post save and reload the block editor page when everything is ok.
264 */
265 function blockEditorSavePostAndReloadPage() {
266
267 let unsubscribe = null;
268
269 // Listen if the savePost is completely done by subscribing to its events.
270 const savePostIsDone = new Promise(
271 function( resolve, reject ) {
272 unsubscribe = subscribe(
273 function() {
274 const isSavePostSucceeded = select( 'core/editor' ).didPostSaveRequestSucceed();
275 const isSavePostFailed = select( 'core/editor' ).didPostSaveRequestFail();
276 if ( isSavePostSucceeded || isSavePostFailed ) {
277 if ( isSavePostFailed ) {
278 reject();
279 } else {
280 resolve();
281 }
282 }
283 }
284 );
285 }
286 );
287
288 // Triggers the post save.
289 dispatch( 'core/editor' ).savePost();
290
291 // Process
292 savePostIsDone.then(
293 function() {
294 // If the post is well saved, we can reload the page
295 window.location.reload();
296 },
297 function() {
298 // If the post save failed
299 unsubscribe();
300 }
301 ).catch(
302 function() {
303 // If an exception is thrown
304 unsubscribe();
305 }
306 );
307 };
308 }
309 );
310
311 // Translations autocomplete input box
312 function init_translations() {
313 $( '.tr_lang' ).each(
314 function(){
315 var tr_lang = $( this ).attr( 'id' ).substring( 8 );
316 var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
317
318 $( this ).autocomplete(
319 {
320 minLength: 0,
321
322 source: ajaxurl + '?action=pll_posts_not_translated' +
323 '&post_language=' + $( '.post_lang_choice' ).val() +
324 '&translation_language=' + tr_lang +
325 '&post_type=' + $( '#post_type' ).val() +
326 '&_pll_nonce=' + $( '#_pll_nonce' ).val(),
327
328 select: function( event, ui ) {
329 $( '#htr_lang_' + tr_lang ).val( ui.item.id );
330 // ui.item.link is built and come from server side and is well escaped when necessary
331 td.html( ui.item.link ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
332 },
333 }
334 );
335
336 // When the input box is emptied
337 $( this ).on(
338 'blur',
339 function() {
340 if ( ! $( this ).val() ) {
341 $( '#htr_lang_' + tr_lang ).val( 0 );
342 // Value is retrieved from HTML already generated server side
343 td.html( td.siblings( '.hidden' ).children().clone() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
344 }
345 }
346 );
347 }
348 );
349 }
350
351 init_translations();
352 }
353 );
354
355