PluginProbe
Polylang / trunk
Polylang vtrunk
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
← All changes | js/build/classic-editor.js +123 -102 3.0.3 → trunk View file →
@@ -1,7 +1,7 @@
1 1 /******/ "use strict";
2 2
3 -;// CONCATENATED MODULE: ./js/lib/confirmation-modal.js
3 +;// ./js/src/lib/confirmation-modal.js
4 4 /**
5 5 * @package Polylang
6 6 */
7 7
@@ -7,11 +7,9 @@
7 7
8 8 const languagesList = jQuery( '.post_lang_choice' );
9 9
10 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.
11 +const initializeConfirmationModal = () => {
14 12 const { __ } = wp.i18n;
15 13
16 14 // Create dialog container.
17 15 const dialogContainer = jQuery(
@@ -23,17 +21,17 @@
23 21 ).text( __( 'Are you sure you want to change the language of the current content?', 'polylang' ) );
24 22
25 23 // Put it after languages list dropdown.
26 24 // PHPCS ignore dialogContainer is a new safe HTML code generated above.
27 - languagesList.after( dialogContainer ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.after
25 + languagesList.after( dialogContainer );
28 26
29 27 const dialogResult = new Promise(
30 28 ( confirm, cancel ) => {
31 - const confirmDialog = ( what ) => { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
32 - switch ( what ) { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
29 + const confirmDialog = ( what ) => {
30 + switch ( what ) {
33 31 case 'yes':
34 32 // Confirm the new language.
35 - languagesList.data( 'old-value', languagesList.children( ':selected' )[0].value );
33 + languagesList.data( 'old-value', languagesList.children( ':selected' ).first().val() );
36 34 confirm();
37 35 break;
38 36 case 'no':
39 37 // Revert to the old language.
@@ -40,10 +38,10 @@
40 38 languagesList.val( languagesList.data( 'old-value' ) );
41 39 cancel( 'Cancel' );
42 40 break;
43 41 }
44 - dialogContainer.dialog( 'close' ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
45 - } // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
42 + dialogContainer.dialog( 'close' );
43 + }
46 44
47 45 // Initialize dialog box in the case a language is selected but not added in the list.
48 46 const dialogOptions = {
49 47 autoOpen: false,
@@ -52,9 +50,9 @@
52 50 resizable: false,
53 51 title: __( 'Change language', 'polylang' ),
54 52 minWidth: 600,
55 53 maxWidth: '100%',
56 - open: function( event, ui ) {
54 + open: function ( event, ui ) {
57 55 // Change dialog box position for rtl language
58 56 if ( jQuery( 'body' ).hasClass( 'rtl' ) ) {
59 57 jQuery( this ).parent().css(
60 58 {
@@ -63,9 +61,9 @@
63 61 }
64 62 );
65 63 }
66 64 },
67 - close: function( event, ui ) {
65 + close: function ( event, ui ) {
68 66 // When we're closing the dialog box we need to cancel the language change as we click on Cancel button.
69 67 confirmDialog( 'no' );
70 68 },
71 69 buttons: [
@@ -70,15 +68,15 @@
70 68 },
71 69 buttons: [
72 70 {
73 71 text: __( 'OK', 'polylang' ),
74 - click: function( event ) {
72 + click: function ( event ) {
75 73 confirmDialog( 'yes' );
76 74 }
77 75 },
78 76 {
79 77 text: __( 'Cancel', 'polylang' ),
80 - click: function( event ) {
78 + click: function ( event ) {
81 79 confirmDialog( 'no' );
82 80 }
83 81 }
84 82 ]
@@ -97,23 +95,68 @@
97 95 }
98 96
99 97 const initializeLanguageOldValue = () => {
100 98 // 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 );
99 + languagesList.attr( 'data-old-value', languagesList.children( ':selected' ).first().val() );
102 100 };
103 101
104 -;// CONCATENATED MODULE: ./js/classic-editor.js
102 +;// ./js/src/lib/metabox-autocomplete.js
105 103 /**
106 104 * @package Polylang
107 105 */
108 106
107 +// Translations autocomplete input box.
108 +function initMetaboxAutoComplete() {
109 + jQuery('.tr_lang').each(
110 + function () {
111 + var tr_lang = jQuery(this).attr('id').substring(8);
112 + var td = jQuery(this).parent().parent().siblings('.pll-edit-column');
109 113
114 + jQuery(this).autocomplete(
115 + {
116 + minLength: 0,
117 + source: ajaxurl + '?action=pll_posts_not_translated' +
118 + '&post_language=' + jQuery('.post_lang_choice').val() +
119 + '&translation_language=' + tr_lang +
120 + '&post_type=' + jQuery('#post_type').val() +
121 + '&_pll_nonce=' + jQuery('#_pll_nonce').val(),
122 + select: function (event, ui) {
123 + jQuery('#htr_lang_' + tr_lang).val(ui.item.id);
124 + // ui.item.link is built and come from server side and is well escaped when necessary
125 + td.html(ui.item.link);
126 + },
127 + }
128 + );
110 129
130 + // when the input box is emptied
131 + jQuery(this).on(
132 + 'blur',
133 + function () {
134 + if ( ! jQuery(this).val() ) {
135 + jQuery('#htr_lang_' + tr_lang).val(0);
136 + // Value is retrieved from HTML already generated server side
137 + td.html(td.siblings('.hidden').children().clone());
138 + }
139 + }
140 + );
141 + }
142 + );
143 +}
144 +
145 +;// ./js/src/classic-editor.js
146 +/**
147 + * @package Polylang
148 + */
149 +
150 +
151 +
152 +
153 +
111 154 // tag suggest in metabox
112 155 jQuery(
113 - function( $ ) {
156 + function ( $ ) {
114 157 $.ajaxPrefilter(
115 - function( options, originalOptions, jqXHR ) {
158 + function ( options, originalOptions, jqXHR ) {
116 159 var lang = $( '.post_lang_choice' ).val();
117 160 if ( 'string' === typeof options.data && -1 !== options.url.indexOf( 'action=ajax-tag-search' ) && lang ) {
118 161 options.data = 'lang=' + lang + '&' + options.data;
119 162 }
@@ -123,11 +166,11 @@
123 166 );
124 167
125 168 // overrides tagBox.get
126 169 jQuery(
127 - function( $ ) {
170 + function ( $ ) {
128 171 // overrides function to add the language
129 - tagBox.get = function( id ) {
172 + tagBox.get = function ( id ) {
130 173 var tax = id.substr( id.indexOf( '-' ) + 1 );
131 174
132 175 // add the language in the $_POST variable
133 176 var data = {
@@ -138,9 +181,9 @@
138 181
139 182 $.post(
140 183 ajaxurl,
141 184 data,
142 - function( r, stat ) {
185 + function ( r, stat ) {
143 186 if ( 0 == r || 'success' != stat ) {
144 187 r = wpAjax.broken;
145 188 }
146 189
@@ -145,12 +188,12 @@
145 188 }
146 189
147 190 // @see code from WordPress core https://github.com/WordPress/WordPress/blob/5.2.2/wp-admin/js/tags-box.js#L291
148 191 // @see wp_generate_tag_cloud function which generate the escaped HTML https://github.com/WordPress/WordPress/blob/a02b5cc2a8eecb8e076fbb7cf4de7bd2ec8a8eb1/wp-includes/category-template.php#L966-L975
149 - r = $( '<div />' ).addClass( 'the-tagcloud' ).attr( 'id', 'tagcloud-' + tax ).html( r ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
192 + r = $( '<div />' ).addClass( 'the-tagcloud' ).attr( 'id', 'tagcloud-' + tax ).html( r );
150 193 $( 'a', r ).on(
151 194 'click',
152 - function(){
195 + function () {
153 196 tagBox.flushTags( $( this ).closest( '.inside' ).children( '.tagsdiv' ), this );
154 197 return false;
155 198 }
156 199 );
@@ -155,18 +198,18 @@
155 198 }
156 199 );
157 200
158 201 var tagCloud = $( '#tagcloud-' + tax );
159 - // add an if else condition to allow modifying the tags outputed when switching the language
202 + // add an if else condition to allow modifying the tags outputted when switching the language
160 203 var v = tagCloud.css( 'display' );
161 204 if ( v ) {
162 205 // See the comment above when r variable is created.
163 - $( '#tagcloud-' + tax ).replaceWith( r ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
206 + $( '#tagcloud-' + tax ).replaceWith( r );
164 207 $( '#tagcloud-' + tax ).css( 'display', v );
165 208 }
166 209 else {
167 210 // See the comment above when r variable is created.
168 - $( '#' + id ).after( r ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.after
211 + $( '#' + id ).after( r );
169 212 }
170 213 }
171 214 );
172 215 }
@@ -173,13 +216,13 @@
173 216 }
174 217 );
175 218
176 219 jQuery(
177 - function( $ ) {
220 + function ( $ ) {
178 221 // collect taxonomies - code partly copied from WordPress
179 222 var taxonomies = new Array();
180 223 $( '.categorydiv' ).each(
181 - function(){
224 + function () {
182 225 var this_id = $( this ).attr( 'id' ), taxonomyParts, taxonomy;
183 226
184 227 taxonomyParts = this_id.split( '-' );
185 228 taxonomyParts.shift();
@@ -188,9 +231,9 @@
188 231
189 232 // add our hidden field in the new category form - for each hierarchical taxonomy
190 233 // to set the language when creating a new category
191 234 // html code inserted come from html code itself.
192 - $( '#' + taxonomy + '-add-submit' ).before( // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.before
235 + $( '#' + taxonomy + '-add-submit' ).before(
193 236 $( '<input />' ).attr( 'type', 'hidden' )
194 237 .attr( 'id', taxonomy + '-lang' )
195 238 .attr( 'name', 'term_lang_choice' )
196 239 .attr( 'value', $( '.post_lang_choice' ).val() )
@@ -203,11 +246,11 @@
203 246
204 247 // ajax for changing the post's language in the languages metabox
205 248 $( '.post_lang_choice' ).on(
206 249 'change',
207 - function( event ) {
250 + function ( event ) {
208 251 // Initialize the confirmation dialog box.
209 - const confirmationModal = initializeConfimationModal();
252 + const confirmationModal = initializeConfirmationModal();
210 253 const { dialogContainer: dialog } = confirmationModal;
211 254 let { dialogResult } = confirmationModal;
212 255 // The selected option in the dropdown list.
213 256 const selectedOption = event.target;
@@ -217,15 +260,11 @@
217 260 } else {
218 261 dialogResult = Promise.resolve();
219 262 }
220 263
221 - // phpcs:disable PEAR.Functions.FunctionCallSignature.EmptyLine
222 264 dialogResult.then(
223 265 () => {
224 - var lang = selectedOption.options[selectedOption.options.selectedIndex].lang; // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
225 - var dir = $( '.pll-translation-column > span[lang="' + lang + '"]' ).attr( 'dir' ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
226 -
227 - var data = { // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
266 + var data = {
228 267 action: 'post_lang_choice',
229 268 lang: selectedOption.value,
230 269 post_type: $( '#post_type' ).val(),
231 270 taxonomies: taxonomies,
@@ -235,45 +274,46 @@
235 274
236 275 $.post(
237 276 ajaxurl,
238 277 data,
239 - function( response ) {
240 - var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
278 + function ( response ) {
279 + // Target a non existing WP HTML id to avoid a conflict with WP ajax requests.
280 + var res = wpAjax.parseAjaxResponse( response, 'pll-ajax-response' );
241 281 $.each(
242 282 res.responses,
243 - function() {
283 + function () {
244 284 switch ( this.what ) {
245 285 case 'translations': // translations fields
246 286 // Data is built and come from server side and is well escaped when necessary
247 - $( '.translations' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
248 - init_translations();
287 + $( '.translations' ).html( this.data );
288 + initMetaboxAutoComplete();
249 289 break;
250 290 case 'taxonomy': // categories metabox for posts
251 291 var tax = this.data;
252 292 // @see wp_terms_checklist https://github.com/WordPress/WordPress/blob/5.2.2/wp-admin/includes/template.php#L175
253 293 // @see https://github.com/WordPress/WordPress/blob/5.2.2/wp-admin/includes/class-walker-category-checklist.php#L89-L111
254 - $( '#' + tax + 'checklist' ).html( this.supplemental.all ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
294 + $( '#' + tax + 'checklist' ).html( this.supplemental.all );
255 295 // @see wp_popular_terms_checklist https://github.com/WordPress/WordPress/blob/5.2.2/wp-admin/includes/template.php#L236
256 - $( '#' + tax + 'checklist-pop' ).html( this.supplemental.populars ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
296 + $( '#' + tax + 'checklist-pop' ).html( this.supplemental.populars );
257 297 // @see wp_dropdown_categories https://github.com/WordPress/WordPress/blob/5.5.1/wp-includes/category-template.php#L336
258 298 // which is called by PLL_Admin_Classic_Editor::post_lang_choice to generate supplemental.dropdown
259 - $( '#new' + tax + '_parent' ).replaceWith( this.supplemental.dropdown ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
299 + $( '#new' + tax + '_parent' ).replaceWith( this.supplemental.dropdown );
260 300 $( '#' + tax + '-lang' ).val( $( '.post_lang_choice' ).val() ); // hidden field
261 301 break;
262 302 case 'pages': // parent dropdown list for pages
263 303 // @see wp_dropdown_pages https://github.com/WordPress/WordPress/blob/5.2.2/wp-includes/post-template.php#L1186-L1208
264 304 // @see https://github.com/WordPress/WordPress/blob/5.2.2/wp-includes/class-walker-page-dropdown.php#L88
265 - $( '#parent_id' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
305 + $( '#parent_id' ).html( this.data );
266 306 break;
267 307 case 'flag': // flag in front of the select dropdown
268 308 // Data is built and come from server side and is well escaped when necessary
269 - $( '.pll-select-flag' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
309 + $( '.pll-select-flag' ).html( this.data );
270 310 break;
271 311 case 'permalink': // Sample permalink
272 312 var div = $( '#edit-slug-box' );
273 313 if ( '-1' != this.data && div.children().length ) {
274 314 // @see get_sample_permalink_html https://github.com/WordPress/WordPress/blob/5.2.2/wp-admin/includes/post.php#L1425-L1454
275 - div.html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
315 + div.html( this.data );
276 316 }
277 317 break;
278 318 }
279 319 }
@@ -278,30 +318,23 @@
278 318 }
279 319 }
280 320 );
281 321
282 - // Update the old language with the new one to be able to compare it in the next changing.
283 - initializeLanguageOldValue();
284 - // modifies the language in the tag cloud
285 - $( '.tagcloud-link' ).each(
286 - function() {
287 - var id = $( this ).attr( 'id' );
288 - tagBox.get( id );
322 + // Creates an event once the language has been successfully changed.
323 + const onPostLangChoice = new CustomEvent(
324 + "onPostLangChoice",
325 + {
326 + detail: {
327 + lang: JSON.parse( selectedOption.options[selectedOption.options.selectedIndex].getAttribute( 'data-lang' ) )
328 + },
289 329 }
290 330 );
291 -
292 - // Modifies the text direction
293 - $( 'body' ).removeClass( 'pll-dir-rtl' ).removeClass( 'pll-dir-ltr' ).addClass( 'pll-dir-' + dir );
294 - $( '#content_ifr' ).contents().find( 'html' ).attr( 'lang', lang ).attr( 'dir', dir );
295 - $( '#content_ifr' ).contents().find( 'body' ).attr( 'dir', dir );
296 -
297 - pll.media.resetAllAttachmentsCollections();
331 + document.dispatchEvent( onPostLangChoice );
298 332 }
299 333 )
300 334 },
301 335 () => {} // Do nothing when promise is rejected by clicking the Cancel dialog button.
302 336 );
303 - // phpcs:enable PEAR.Functions.FunctionCallSignature.EmptyLine
304 337
305 338 function isEmptyPost() {
306 339 const title = $( 'input#title' ).val();
307 340 const content = $( 'textarea#content' ).val();
@@ -311,47 +344,35 @@
311 344 }
312 345 }
313 346 );
314 347
315 - // translations autocomplete input box
316 - function init_translations() {
317 - $( '.tr_lang' ).each(
318 - function(){
319 - var tr_lang = $( this ).attr( 'id' ).substring( 8 );
320 - var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
348 + // Listen to `onPostLangChoice` to perform actions after the language has been changed.
349 + document.addEventListener(
350 + 'onPostLangChoice',
351 + ( e ) => {
352 + // Update the old language with the new one to be able to compare it in the next changing.
353 + initializeLanguageOldValue();
321 354
322 - $( this ).autocomplete(
323 - {
324 - minLength: 0,
325 - source: ajaxurl + '?action=pll_posts_not_translated' +
326 - '&post_language=' + $( '.post_lang_choice' ).val() +
327 - '&translation_language=' + tr_lang +
328 - '&post_type=' + $( '#post_type' ).val() +
329 - '&_pll_nonce=' + $( '#_pll_nonce' ).val(),
330 - select: function( event, ui ) {
331 - $( '#htr_lang_' + tr_lang ).val( ui.item.id );
332 - // ui.item.link is built and come from server side and is well escaped when necessary
333 - td.html( ui.item.link ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
334 - },
335 - }
336 - );
355 + // Modifies the language in the tag cloud.
356 + $( '.tagcloud-link' ).each(
357 + function () {
358 + var id = $( this ).attr( 'id' );
359 + tagBox.get( id );
360 + }
361 + );
337 362
338 - // when the input box is emptied
339 - $( this ).on(
340 - 'blur',
341 - function() {
342 - if ( ! $( this ).val() ) {
343 - $( '#htr_lang_' + tr_lang ).val( 0 );
344 - // Value is retrieved from HTML already generated server side
345 - td.html( td.siblings( '.hidden' ).children().clone() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
346 - }
347 - }
348 - );
349 - }
350 - );
351 - }
363 + // Modifies the text direction.
364 + let dir = e.detail.lang.is_rtl ? 'rtl' : 'ltr'
365 + $( 'body' ).removeClass( 'pll-dir-rtl' ).removeClass( 'pll-dir-ltr' ).addClass( 'pll-dir-' + dir );
366 + $( '#content_ifr' ).contents().find( 'html' ).attr( 'lang', e.detail.lang.locale ).attr( 'dir', dir );
367 + $( '#content_ifr' ).contents().find( 'body' ).attr( 'dir', dir );
352 368
353 - init_translations();
369 + // Refresh media libraries.
370 + pll.media.resetAllAttachmentsCollections();
371 + }
372 + );
373 +
374 + initMetaboxAutoComplete();
354 375 }
355 376 );
356 377
357 378 /**
@@ -390,9 +411,9 @@
390 411 *
391 412 * @param {Object} [props]
392 413 * @return {wp.media.model.Attachments}
393 414 */
394 - query: function( props ) {
415 + query: function ( props ) {
395 416 var attachments = pll.media.query.delegate( props );
396 417
397 418 pll.media.attachmentsCollections.push( attachments );
398 419
@@ -398,16 +419,16 @@
398 419
399 420 return attachments;
400 421 },
401 422
402 - resetAllAttachmentsCollections: function() {
423 + resetAllAttachmentsCollections: function () {
403 424 this.attachmentsCollections.forEach(
404 - function( attachmentsCollection ) {
425 + function ( attachmentsCollection ) {
405 426 /**
406 427 * First reset the { @see wp.media.model.Attachments } collection.
407 428 * Then, if it is mirroring a { @see wp.media.model.Query } collection,
408 429 * refresh this one too, so it will fetch new data from the server,
409 - * and then the wp.media.model.Attachments collection will syncrhonize with the new data.
430 + * and then the wp.media.model.Attachments collection will synchronize with the new data.
410 431 */
411 432 attachmentsCollection.reset();
412 433 if (attachmentsCollection.mirroring) {
413 434 attachmentsCollection.mirroring._hasMore = true;