PluginProbe
Polylang / 3.7.7
Polylang v3.7.7
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 / term.js

term.js in Polylang 3.7.7, at js/build/term.js

251 lines 8.4 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 /**
6 * Quick edit
7 */
8 jQuery(
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 ) );
17
18 if ( term_id > 0 ) {
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.
23
24 // Disable the language dropdown for default categories.
25 const default_cat = document.querySelector( `#default_cat_${term_id}` )?.innerHTML;
26 if ( term_id == default_cat ) {
27 select.disabled = true;
28 }
29 }
30 }
31 }
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 }
41 }
42 );
43
44 /**
45 * Update rows of translated terms when adding / deleting a translation or when the language is modified in quick edit.
46 * Acts on ajaxSuccess event.
47 */
48 jQuery(
49 function ( $ ) {
50 $( document ).ajaxSuccess(
51 function ( event, xhr, settings ) {
52 function update_rows( term_id ) {
53 // collect old translations
54 var translations = new Array();
55 $( '.translation_' + term_id ).each(
56 function () {
57 translations.push( $( this ).parent().parent().attr( 'id' ).substring( 4 ) );
58 }
59 );
60
61 var data = {
62 action: 'pll_update_term_rows',
63 term_id: term_id,
64 translations: translations.join( ',' ),
65 taxonomy: $( "input[name='taxonomy']" ).val(),
66 post_type: $( "input[name='post_type']" ).val(),
67 screen: $( "input[name='screen']" ).val(),
68 _pll_nonce: $( '#_pll_nonce' ).val()
69 };
70
71 // get the modified rows in ajax and update them
72 $.post(
73 ajaxurl,
74 data,
75 function ( response ) {
76 if ( 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' );
79 $.each(
80 res.responses,
81 function () {
82 if ( 'row' == this.what ) {
83 // data is built with a call to WP_Terms_List_Table::single_row method
84 // which uses internally other WordPress methods which escape correctly values.
85 // For Polylang language columns the HTML code is correctly escaped in PLL_Admin_Filters_Columns::term_column method.
86 $( "#tag-" + this.supplemental.term_id ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
87 }
88 }
89 );
90 }
91 }
92 );
93 }
94
95 var data = wpAjax.unserialize( settings.data ); // what were the data sent by the ajax request?
96 if ( 'undefined' != typeof( data['action'] ) ) {
97 switch ( data['action'] ) {
98 // when adding a term, the new term_id is in the ajax response
99 case 'add-tag':
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' );
102 $.each(
103 res.responses,
104 function () {
105 if ( 'term' == this.what ) {
106 update_rows( this.supplemental.term_id );
107 }
108 }
109 );
110
111 // and also reset translations hidden input fields
112 $( '.htr_lang' ).val( 0 );
113 break;
114
115 // when deleting a term
116 case 'delete-tag':
117 update_rows( data['tag_ID'] );
118 break;
119
120 // in case the language is modified in quick edit and breaks translations
121 case 'inline-save-tax':
122 update_rows( data['tax_ID'] );
123 break;
124 }
125 }
126 }
127 );
128 }
129 );
130
131 jQuery(
132 function ( $ ) {
133 // translations autocomplete input box
134 function init_translations() {
135 $( '.tr_lang' ).each(
136 function () {
137 var tr_lang = $( this ).attr( 'id' ).substring( 8 );
138 var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
139
140 $( this ).autocomplete(
141 {
142 minLength: 0,
143 source: ajaxurl + '?action=pll_terms_not_translated' +
144 '&term_language=' + $( '#term_lang_choice' ).val() +
145 '&term_id=' + $( "input[name='tag_ID']" ).val() +
146 '&taxonomy=' + $( "input[name='taxonomy']" ).val() +
147 '&translation_language=' + tr_lang +
148 '&post_type=' + typenow +
149 '&_pll_nonce=' + $( '#_pll_nonce' ).val(),
150 select: function ( event, ui ) {
151 $( '#htr_lang_' + tr_lang ).val( ui.item.id );
152 // ui.item.link is built and come from server side and is well escaped when necessary
153 td.html( ui.item.link ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
154 },
155 }
156 );
157
158 // when the input box is emptied
159 $( this ).on(
160 'blur',
161 function () {
162 if ( ! $( this ).val() ) {
163 $( '#htr_lang_' + tr_lang ).val( 0 );
164 // Value is retrieved from HTML already generated server side
165 td.html( td.siblings( '.hidden' ).children().clone() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
166 }
167 }
168 );
169 }
170 );
171 }
172
173 init_translations();
174
175 // ajax for changing the term's language
176 $( '#term_lang_choice' ).on(
177 'change',
178 function () {
179 var value = $( this ).val();
180 // The selected option in the dropdown list.
181 const selectedOption = event.target;
182
183 var data = {
184 action: 'term_lang_choice',
185 lang: value,
186 from_tag: $( "input[name='from_tag']" ).val(),
187 term_id: $( "input[name='tag_ID']" ).val(),
188 taxonomy: $( "input[name='taxonomy']" ).val(),
189 post_type: typenow,
190 _pll_nonce: $( '#_pll_nonce' ).val()
191 };
192
193 $.post(
194 ajaxurl,
195 data,
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' );
199 $.each(
200 res.responses,
201 function () {
202 switch ( this.what ) {
203 case 'translations': // translations fields
204 // Data is built and come from server side and is well escaped when necessary
205 $( "#term-translations" ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
206 init_translations();
207 break;
208 case 'parent': // parent dropdown list for hierarchical taxonomies
209 // data correctly escaped in PLL_Admin_Filters_Term::term_lang_choice method which uses wp_dropdown_categories function.
210 $( '#parent' ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
211 break;
212 case 'tag_cloud': // popular items
213 // data correctly escaped in PLL_Admin_Filters_Term::term_lang_choice method which uses wp_tag_cloud and wp_generate_tag_cloud functions.
214 $( '.tagcloud' ).replaceWith( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.replaceWith
215 break;
216 case 'flag': // flag in front of the select dropdown
217 // Data is built and come from server side and is well escaped when necessary
218 $( '.pll-select-flag' ).html( this.data ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
219 break;
220 }
221 }
222 );
223
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 );
234 }
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 );
246 }
247 );
248 }
249 );
250
251