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/term.js +72 -44 3.0.3 → trunk View file →
@@ -5,33 +5,40 @@
5 5 /**
6 6 * Quick edit
7 7 */
8 8 jQuery(
9 - function( $ ) {
10 - $( document ).on(
11 - 'DOMNodeInserted',
12 - function( e ) {
13 - var t = $( e.target );
9 + function ( $ ) {
10 + const handleQuickEditInsertion = ( mutationsList ) => {
11 + for ( const mutation of mutationsList ) {
12 + const addedNodes = Array.from( mutation.addedNodes ).filter( el => el.nodeType === Node.ELEMENT_NODE )
13 + const form = addedNodes[0];
14 + if ( 0 < mutation.addedNodes.length && form.classList.contains( 'inline-edit-row' ) ) {
15 + // WordPress has inserted the quick edit form.
16 + const term_id = Number( form.id.substring( 5 ) );
14 17
15 - // WP inserts the quick edit from
16 - if ( 'inline-edit' == t.attr( 'id' ) ) {
17 - var term_id = t.prev().attr( 'id' ).replace( "tag-", "" );
18 -
19 18 if ( term_id > 0 ) {
20 - // language dropdown
21 - var select = t.find( ':input[name="inline_lang_choice"]' );
22 - var lang = $( '#lang_' + term_id ).html();
23 - select.val( lang ); // populates the dropdown
19 + // Get the language dropdown.
20 + const select = form.querySelector( 'select[name="inline_lang_choice"]' );
21 + const lang = document.querySelector( '#lang_' + String( term_id ) ).innerHTML;
22 + select.value = lang; // Populates the dropdown with the post language.
24 23
25 - // disable the language dropdown for default categories
26 - var default_cat = $( '#default_cat_' + term_id ).html();
24 + // Disable the language dropdown for default categories.
25 + const default_cat = document.querySelector( `#default_cat_${term_id}` )?.innerHTML;
27 26 if ( term_id == default_cat ) {
28 - select.prop( 'disabled', true );
27 + select.disabled = true;
29 28 }
30 29 }
31 30 }
32 31 }
33 - );
32 + }
33 + const table = document.getElementById( 'the-list' );
34 + if ( null !== table ) {
35 + // Ensure the table is displayed before listening to any change.
36 + const config = { childList: true, subtree: true };
37 + const observer = new MutationObserver( handleQuickEditInsertion );
38 +
39 + observer.observe( table, config);
40 + }
34 41 }
35 42 );
36 43
37 44 /**
@@ -38,16 +45,16 @@
38 45 * Update rows of translated terms when adding / deleting a translation or when the language is modified in quick edit.
39 46 * Acts on ajaxSuccess event.
40 47 */
41 48 jQuery(
42 - function( $ ) {
49 + function ( $ ) {
43 50 $( document ).ajaxSuccess(
44 - function( event, xhr, settings ) {
51 + function ( event, xhr, settings ) {
45 52 function update_rows( term_id ) {
46 53 // collect old translations
47 54 var translations = new Array();
48 55 $( '.translation_' + term_id ).each(
49 - function() {
56 + function () {
50 57 translations.push( $( this ).parent().parent().attr( 'id' ).substring( 4 ) );
51 58 }
52 59 );
53 60
@@ -64,19 +71,20 @@
64 71 // get the modified rows in ajax and update them
65 72 $.post(
66 73 ajaxurl,
67 74 data,
68 - function( response ) {
75 + function ( response ) {
69 76 if ( response ) {
70 - var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
77 + // Target a non existing WP HTML id to avoid a conflict with WP ajax requests.
78 + var res = wpAjax.parseAjaxResponse( response, 'pll-ajax-response' );
71 79 $.each(
72 80 res.responses,
73 - function() {
81 + function () {
74 82 if ( 'row' == this.what ) {
75 83 // data is built with a call to WP_Terms_List_Table::single_row method
76 84 // which uses internally other WordPress methods which escape correctly values.
77 85 // For Polylang language columns the HTML code is correctly escaped in PLL_Admin_Filters_Columns::term_column method.
78 - $( "#tag-" + this.supplemental.term_id ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
86 + $( "#tag-" + this.supplemental.term_id ).replaceWith( this.data );
79 87 }
80 88 }
81 89 );
82 90 }
@@ -88,12 +96,13 @@
88 96 if ( 'undefined' != typeof( data['action'] ) ) {
89 97 switch ( data['action'] ) {
90 98 // when adding a term, the new term_id is in the ajax response
91 99 case 'add-tag':
92 - res = wpAjax.parseAjaxResponse( xhr.responseXML, 'ajax-response' );
100 + // Target a non existing WP HTML id to avoid a conflict with WP ajax requests.
101 + res = wpAjax.parseAjaxResponse( xhr.responseXML, 'pll-ajax-response' );
93 102 $.each(
94 103 res.responses,
95 - function() {
104 + function () {
96 105 if ( 'term' == this.what ) {
97 106 update_rows( this.supplemental.term_id );
98 107 }
99 108 }
@@ -119,13 +128,13 @@
119 128 }
120 129 );
121 130
122 131 jQuery(
123 - function( $ ) {
132 + function ( $ ) {
124 133 // translations autocomplete input box
125 134 function init_translations() {
126 135 $( '.tr_lang' ).each(
127 - function(){
136 + function () {
128 137 var tr_lang = $( this ).attr( 'id' ).substring( 8 );
129 138 var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
130 139
131 140 $( this ).autocomplete(
@@ -137,12 +146,12 @@
137 146 '&taxonomy=' + $( "input[name='taxonomy']" ).val() +
138 147 '&translation_language=' + tr_lang +
139 148 '&post_type=' + typenow +
140 149 '&_pll_nonce=' + $( '#_pll_nonce' ).val(),
141 - select: function( event, ui ) {
150 + select: function ( event, ui ) {
142 151 $( '#htr_lang_' + tr_lang ).val( ui.item.id );
143 152 // ui.item.link is built and come from server side and is well escaped when necessary
144 - td.html( ui.item.link ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
153 + td.html( ui.item.link );
145 154 },
146 155 }
147 156 );
148 157
@@ -148,13 +157,13 @@
148 157
149 158 // when the input box is emptied
150 159 $( this ).on(
151 160 'blur',
152 - function() {
161 + function () {
153 162 if ( ! $( this ).val() ) {
154 163 $( '#htr_lang_' + tr_lang ).val( 0 );
155 164 // Value is retrieved from HTML already generated server side
156 - td.html( td.siblings( '.hidden' ).children().clone() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
165 + td.html( td.siblings( '.hidden' ).children().clone() );
157 166 }
158 167 }
159 168 );
160 169 }
@@ -165,12 +174,12 @@
165 174
166 175 // ajax for changing the term's language
167 176 $( '#term_lang_choice' ).on(
168 177 'change',
169 - function() {
178 + function () {
170 179 var value = $( this ).val();
171 - var lang = $( this ).children( 'option[value="' + value + '"]' ).attr( 'lang' );
172 - var dir = $( '.pll-translation-column > span[lang="' + lang + '"]' ).attr( 'dir' );
180 + // The selected option in the dropdown list.
181 + const selectedOption = event.target;
173 182
174 183 var data = {
175 184 action: 'term_lang_choice',
176 185 lang: value,
@@ -183,39 +192,58 @@
183 192
184 193 $.post(
185 194 ajaxurl,
186 195 data,
187 - function( response ) {
188 - var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
196 + function ( response ) {
197 + // Target a non existing WP HTML id to avoid a conflict with WP ajax requests.
198 + var res = wpAjax.parseAjaxResponse( response, 'pll-ajax-response' );
189 199 $.each(
190 200 res.responses,
191 - function() {
201 + function () {
192 202 switch ( this.what ) {
193 203 case 'translations': // translations fields
194 204 // Data is built and come from server side and is well escaped when necessary
195 - $( "#term-translations" ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
205 + $( "#term-translations" ).html( this.data );
196 206 init_translations();
197 207 break;
198 208 case 'parent': // parent dropdown list for hierarchical taxonomies
199 209 // data correctly escaped in PLL_Admin_Filters_Term::term_lang_choice method which uses wp_dropdown_categories function.
200 - $( '#parent' ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
210 + $( '#parent' ).replaceWith( this.data );
201 211 break;
202 212 case 'tag_cloud': // popular items
203 213 // data correctly escaped in PLL_Admin_Filters_Term::term_lang_choice method which uses wp_tag_cloud and wp_generate_tag_cloud functions.
204 - $( '.tagcloud' ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
214 + $( '.tagcloud' ).replaceWith( this.data );
205 215 break;
206 216 case 'flag': // flag in front of the select dropdown
207 217 // Data is built and come from server side and is well escaped when necessary
208 - $( '.pll-select-flag' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
218 + $( '.pll-select-flag' ).html( this.data );
209 219 break;
210 220 }
211 221 }
212 222 );
213 223
214 - // Modifies the text direction
215 - $( 'body' ).removeClass( 'pll-dir-rtl' ).removeClass( 'pll-dir-ltr' ).addClass( 'pll-dir-' + dir );
224 + // Creates an event once the language has been successfully changed.
225 + const onTermLangChoice = new CustomEvent(
226 + "onTermLangChoice",
227 + {
228 + detail: {
229 + lang: JSON.parse( selectedOption.options[selectedOption.options.selectedIndex].getAttribute( 'data-lang' ) )
230 + },
231 + }
232 + );
233 + document.dispatchEvent( onTermLangChoice );
216 234 }
217 235 );
236 + }
237 + );
238 +
239 + // Listen to `onTermLangChoice` to perform actions after the language has been changed.
240 + document.addEventListener(
241 + 'onTermLangChoice',
242 + ( e ) => {
243 + // Modifies the text direction.
244 + let dir = e.detail.lang.is_rtl ? 'rtl' : 'ltr'
245 + $( 'body' ).removeClass( 'pll-dir-rtl' ).removeClass( 'pll-dir-ltr' ).addClass( 'pll-dir-' + dir );
218 246 }
219 247 );
220 248 }
221 249 );