| @@ -1,34 +1,74 @@ | ||
| 1 | 1 | /** |
| 2 | - * Adds one biography input field per language in the user profile. | |
| 3 | - * | |
| 4 | - * @package Polylang | |
| 2 | + * Adds one biography textarea field per language in the user profile. | |
| 5 | 3 | */ |
| 6 | 4 | |
| 7 | -jQuery( | |
| 8 | - function( $ ) { | |
| 9 | - // biography | |
| 10 | - // FIXME there is probably a more efficient way to do this | |
| 11 | - var td = $( '#description' ).parent(); | |
| 12 | - var d = $( '#description' ).clone(); | |
| 13 | - var span = td.children( '.description' ).clone(); | |
| 14 | - td.children().remove(); | |
| 5 | +const pllDescription = { | |
| 6 | + /** | |
| 7 | + * Init. | |
| 8 | + */ | |
| 9 | + init: () => { | |
| 10 | + if ( ! pllDescriptionData ) { | |
| 11 | + return; | |
| 12 | + } | |
| 13 | + if ( document.readyState !== 'loading' ) { | |
| 14 | + pllDescription.ready(); | |
| 15 | + } else { | |
| 16 | + document.addEventListener( | |
| 17 | + 'DOMContentLoaded', | |
| 18 | + pllDescription.ready | |
| 19 | + ); | |
| 20 | + } | |
| 21 | + }, | |
| 15 | 22 | |
| 16 | - $( '.biography' ).each( | |
| 17 | - function(){ | |
| 18 | - lang = $( this ).attr( 'name' ).split( '___' ); | |
| 19 | - desc = d.clone(); | |
| 20 | - desc.attr( 'name', 'description_' + lang[0] ); | |
| 21 | - desc.attr( 'id', 'description_' + lang[0] ); | |
| 22 | - // Whitelist because description and lang value is already escaped by the side of PHP | |
| 23 | - desc.html( $( this ).val() ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html | |
| 24 | - td.append( $( '<div></div>' ).text( lang[1] ) ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.append | |
| 25 | - td.append( desc ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.append | |
| 23 | + /** | |
| 24 | + * Called when the DOM is ready. | |
| 25 | + */ | |
| 26 | + ready: () => { | |
| 27 | + const originTextarea = document.getElementById( 'description' ); | |
| 28 | + | |
| 29 | + if ( ! originTextarea ) { | |
| 30 | + return; | |
| 31 | + } | |
| 32 | + | |
| 33 | + const rows = []; | |
| 34 | + | |
| 35 | + pllDescriptionData.forEach( ( data ) => { | |
| 36 | + const wrapper = document.createElement( 'div' ); | |
| 37 | + wrapper.setAttribute( 'lang', data.lang ); | |
| 38 | + | |
| 39 | + const label = document.createElement( 'label' ); | |
| 40 | + label.setAttribute( 'for', `description_${ data.slug }` ); | |
| 41 | + label.setAttribute( 'dir', data.direction ); | |
| 42 | + | |
| 43 | + if ( data.flag.src ) { | |
| 44 | + const img = document.createElement( 'img' ); | |
| 45 | + img.setAttribute( 'alt', '' ); | |
| 46 | + img.setAttribute( 'src', data.flag.src ); | |
| 47 | + if ( data.flag.width ) { | |
| 48 | + img.setAttribute( 'width', data.flag.width ); | |
| 49 | + } | |
| 50 | + if ( data.flag.height ) { | |
| 51 | + img.setAttribute( 'height', data.flag.height ); | |
| 52 | + } | |
| 53 | + label.textContent = ` ${ data.name }`; | |
| 54 | + label.prepend( img ); | |
| 55 | + } else { | |
| 56 | + label.textContent = data.name; | |
| 26 | 57 | } |
| 27 | - ); | |
| 28 | 58 | |
| 29 | - td.append( '<br />' ); | |
| 30 | - // Whitelist because description come from html code generated by WordPress | |
| 31 | - td.append( span ); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.append | |
| 32 | - } | |
| 33 | -); | |
| 59 | + const textarea = originTextarea.cloneNode( true ); | |
| 60 | + textarea.setAttribute( 'id', `description_${ data.slug }` ); | |
| 61 | + textarea.setAttribute( 'name', `description_${ data.slug }` ); | |
| 62 | + textarea.setAttribute( 'dir', data.direction ); | |
| 63 | + textarea.innerHTML = data.description; | |
| 64 | + | |
| 65 | + wrapper.append( label, document.createElement( 'br' ), textarea ); | |
| 66 | + rows.push( wrapper ); | |
| 67 | + } ); | |
| 68 | + | |
| 69 | + originTextarea.replaceWith( ...rows ); | |
| 70 | + }, | |
| 71 | +}; | |
| 72 | + | |
| 73 | +pllDescription.init(); | |
| 34 | 74 | |