PluginProbe
Polylang / 3.0.1
Polylang v3.0.1
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 / block-editor.js

block-editor.js in Polylang 3.0.1, at js/block-editor.js

253 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * @package Polylang
3 */
4
5 import {
6 initializeLanguageOldValue,
7 initializeConfimationModal
8 } from './lib/confirmation-modal';
9
10 /**
11 * Filter REST API requests to add the language in the request
12 *
13 * @since 2.5
14 */
15 wp.apiFetch.use(
16 function( options, next ) {
17 // If options.url is defined, this is not a REST request but a direct call to post.php for legacy metaboxes.
18 if ( 'undefined' === typeof options.url ) {
19 if ( 'undefined' === typeof options.data || null === options.data ) {
20 // GET
21 options.path += ( ( options.path.indexOf( '?' ) >= 0 ) ? '&lang=' : '?lang=' ) + getCurrentLanguage();
22 } else {
23 // PUT, POST
24 options.data.lang = getCurrentLanguage();
25 }
26 }
27 return next( options );
28 }
29 );
30
31 /**
32 * Get the language from the HTML form
33 *
34 * @since 2.5
35 *
36 * @return {Element.value}
37 */
38 function getCurrentLanguage() {
39 return document.querySelector( '[name=post_lang_choice]' ).value;
40 }
41
42 /**
43 * Handles internals of the metabox:
44 * Language select, autocomplete input field.
45 *
46 * @since 1.5
47 *
48 * Save post after lang choice is done and redirect to the same page for refreshing all the data.
49 *
50 * @since 2.5
51 *
52 * Link post saving after refreshing the metabox.
53 *
54 * @since 3.0
55 */
56 jQuery(
57 function( $ ) {
58 // Initialize current language to be able to compare if it changes.
59 initializeLanguageOldValue();
60
61
62 // Ajax for changing the post's language in the languages metabox
63 $( '.post_lang_choice' ).on(
64 'change',
65 function( event ) {
66 const select = wp.data.select;
67 const dispatch = wp.data.dispatch;
68 const subscribe = wp.data.subscribe;
69 const emptyPost = isEmptyPost();
70
71 // Initialize the confirmation dialog box.
72 const confirmationModal = initializeConfimationModal();
73 const { dialogContainer : dialog } = confirmationModal;
74 let { dialogResult } = confirmationModal;
75 // The selected option in the dropdown list.
76 const selectedOption = event.target;
77
78 // Specific case for empty posts.
79 // Place at the beginning because window.location changing triggers automatically page reloading.
80 if ( location.pathname.match( /post-new.php/gi ) && emptyPost ) {
81 reloadPageForEmptyPost( selectedOption.value );
82 }
83
84 // Otherwise send an ajax request to refresh the legacy metabox and set the post language with the new language.
85 // It needs a confirmation of the user before changing the language.
86 // Need to wait the ajax response before triggering the block editor post save action.
87 if ( $( this ).data( 'old-value' ) !== selectedOption.value && ! emptyPost ) {
88 dialog.dialog( 'open' );
89 } else {
90 // Update the old language with the new one to be able to compare it in the next changing.
91 // Because the page isn't reloaded in this case.
92 initializeLanguageOldValue();
93 dialogResult = Promise.resolve();
94 }
95
96 dialogResult.then(
97 () => {
98 var data = { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
99 action: 'post_lang_choice',
100 lang: selectedOption.value,
101 post_type: $( '#post_type' ).val(),
102 post_id: $( '#post_ID' ).val(),
103 _pll_nonce: $( '#_pll_nonce' ).val()
104 }
105
106 $.post(
107 ajaxurl,
108 data,
109 function( response ) {
110 var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
111 $.each(
112 res.responses,
113 function() {
114 switch ( this.what ) {
115 case 'translations': // Translations fields
116 // Data is built and come from server side and is well escaped when necessary
117 $( '.translations' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
118 init_translations();
119 break;
120 case 'flag': // Flag in front of the select dropdown
121 // Data is built and come from server side and is well escaped when necessary
122 $( '.pll-select-flag' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
123 break;
124 }
125 }
126 );
127 blockEditorSavePostAndReloadPage();
128 }
129 );
130 },
131 () => {} // Do nothing when promise is rejected by clicking the Cancel dialog button.
132 );
133
134 function isEmptyPost() {
135 const editor = wp.data.select( 'core/editor' );
136 const title = editor.getEditedPostAttribute( 'title' ).trim();
137 const content = editor.getEditedPostAttribute( 'content' ).trim();
138 const excerpt = editor.getEditedPostAttribute( 'excerpt' ).trim();
139
140 return ! title && ! content && ! excerpt;
141 }
142
143 /**
144 * Reload the block editor page for empty posts.
145 *
146 * @param {string} lang The target language code.
147 */
148 function reloadPageForEmptyPost( lang ) {
149 // Change the new_lang parameter with the new language value for reloading the page
150 // WPCS location.search is never written in the page, just used to reload page with the right value of new_lang
151 // new_lang input is controlled server side in PHP. The value come from the dropdown list of language returned and escaped server side.
152 // Notice that window.location changing triggers automatically page reloading.
153 if ( -1 != location.search.indexOf( 'new_lang' ) ) {
154 // use regexp non capturing group to replace new_lang parameter no matter where it is and capture other parameters which can be behind it
155 window.location.search = window.location.search.replace( /(?:new_lang=[^&]*)(&)?(.*)/, 'new_lang=' + lang + '$1$2' ); // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
156 } else {
157 window.location.search = window.location.search + ( ( -1 != window.location.search.indexOf( '?' ) ) ? '&' : '?' ) + 'new_lang=' + lang; // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
158 }
159 };
160
161 /**
162 * Triggers block editor post save and reload the block editor page when everything is ok.
163 */
164 function blockEditorSavePostAndReloadPage() {
165
166 let unsubscribe = null;
167
168 // Listen if the savePost is completely done by subscribing to its events.
169 const savePostIsDone = new Promise(
170 function( resolve, reject ) {
171 unsubscribe = subscribe(
172 function() {
173 const isSavePostSucceeded = select( 'core/editor' ).didPostSaveRequestSucceed();
174 const isSavePostFailed = select( 'core/editor' ).didPostSaveRequestFail();
175 if ( isSavePostSucceeded || isSavePostFailed ) {
176 if ( isSavePostFailed ) {
177 reject();
178 } else {
179 resolve();
180 }
181 }
182 }
183 );
184 }
185 );
186
187 // Triggers the post save.
188 dispatch( 'core/editor' ).savePost();
189
190 // Process
191 savePostIsDone.then(
192 function() {
193 // If the post is well saved, we can reload the page
194 window.location.reload();
195 },
196 function() {
197 // If the post save failed
198 unsubscribe();
199 }
200 ).catch(
201 function() {
202 // If an exception is thrown
203 unsubscribe();
204 }
205 );
206 };
207 }
208 );
209
210 // Translations autocomplete input box
211 function init_translations() {
212 $( '.tr_lang' ).each(
213 function(){
214 var tr_lang = $( this ).attr( 'id' ).substring( 8 );
215 var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
216
217 $( this ).autocomplete(
218 {
219 minLength: 0,
220
221 source: ajaxurl + '?action=pll_posts_not_translated' +
222 '&post_language=' + $( '.post_lang_choice' ).val() +
223 '&translation_language=' + tr_lang +
224 '&post_type=' + $( '#post_type' ).val() +
225 '&_pll_nonce=' + $( '#_pll_nonce' ).val(),
226
227 select: function( event, ui ) {
228 $( '#htr_lang_' + tr_lang ).val( ui.item.id );
229 // ui.item.link is built and come from server side and is well escaped when necessary
230 td.html( ui.item.link ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
231 },
232 }
233 );
234
235 // When the input box is emptied
236 $( this ).on(
237 'blur',
238 function() {
239 if ( ! $( this ).val() ) {
240 $( '#htr_lang_' + tr_lang ).val( 0 );
241 // Value is retrieved from HTML already generated server side
242 td.html( td.siblings( '.hidden' ).children().clone() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
243 }
244 }
245 );
246 }
247 );
248 }
249
250 init_translations();
251 }
252 );
253