[ Index ] |
PHP Cross Reference of GlotPress |
[Summary view] [Print] [Text view]
1 /* global $gp_editor_options, $gp */ 2 /* eslint camelcase: "off" */ 3 $gp.editor = ( 4 function( $ ) { 5 return { 6 current: null, 7 orginal_translations: null, 8 init: function( table ) { 9 var $previewRows; 10 11 $gp.init(); 12 $gp.editor.table = table; 13 $gp.editor.install_hooks(); 14 15 // Open the first editor if the current table has only one. 16 $previewRows = $gp.editor.table.find( 'tr.preview' ); 17 if ( 1 === $previewRows.length ) { 18 $gp.editor.show( $previewRows.eq( 0 ) ); 19 } 20 }, 21 original_id_from_row_id: function( row_id ) { 22 return row_id.split( '-' )[ 0 ]; 23 }, 24 translation_id_from_row_id: function( row_id ) { 25 return row_id.split( '-' )[ 1 ]; 26 }, 27 show: function( element ) { 28 var row_id = element.closest( 'tr' ).attr( 'row' ); 29 var editor = $( '#editor-' + row_id ); 30 var gmt_date_added = $( '#gmt-date-added-' + row_id ); 31 var local_date_added = $( '#local-date-added-' + row_id ); 32 var offset = new Date().getTimezoneOffset(); 33 var gmt_date = new Date( gmt_date_added.text() ); 34 var local_date = new Date( ( gmt_date - ( offset * 60 * 1000 ) ) ); 35 36 if ( ! editor.length ) { 37 return; 38 } 39 if ( $gp.editor.current ) { 40 $gp.editor.hide(); 41 } 42 editor.preview = $( '#preview-' + row_id ); 43 editor.row_id = row_id; 44 editor.original_id = $gp.editor.original_id_from_row_id( row_id ); 45 editor.translation_id = $gp.editor.translation_id_from_row_id( row_id ); 46 47 editor.orginal_translations = $( 'textarea[name="translation[' + editor.original_id + '][]"]', editor ).map( function() { 48 return this.value; 49 } ).get(); 50 51 $gp.editor.current = editor; 52 53 local_date_added.text( local_date.toLocaleDateString() + ' ' + local_date.toLocaleTimeString() ); 54 55 editor.show(); 56 editor.preview.hide(); 57 $( 'textarea:first', editor ).focus(); 58 }, 59 prev: function() { 60 var prev; 61 if ( ! $gp.editor.current ) { 62 return; 63 } 64 65 // TODO: go to previous page if needed 66 prev = $gp.editor.current.prevAll( 'tr.editor' ); 67 if ( prev.length ) { 68 $gp.editor.show( prev.eq( 0 ) ); 69 } else { 70 $gp.editor.hide(); 71 } 72 }, 73 next: function() { 74 var next; 75 76 if ( ! $gp.editor.current ) { 77 return; 78 } 79 80 // TODO: go to next page if needed. 81 next = $gp.editor.current.nextAll( 'tr.editor' ); 82 if ( next.length ) { 83 $gp.editor.show( next.eq( 0 ) ); 84 } else { 85 $gp.editor.hide(); 86 } 87 }, 88 hide: function( editor ) { 89 editor = editor ? editor : $gp.editor.current; 90 if ( ! editor ) { 91 return; 92 } 93 editor.hide(); 94 editor.preview.show(); 95 $gp.editor.current = null; 96 }, 97 install_hooks: function() { 98 $( $gp.editor.table ) 99 .on( 'click', 'a.edit', $gp.editor.hooks.show ) 100 .on( 'dblclick', 'tr.preview td', $gp.editor.hooks.show ) 101 .on( 'change', 'select.priority', $gp.editor.hooks.set_priority ) 102 .on( 'click', 'button.close', $gp.editor.hooks.cancel ) 103 .on( 'click', 'a.discard-warning', $gp.editor.hooks.discard_warning ) 104 .on( 'click', 'button.copy', $gp.editor.hooks.copy ) 105 .on( 'click', 'button.inserttab', $gp.editor.hooks.tab ) 106 .on( 'click', 'button.insertnl', $gp.editor.hooks.newline ) 107 .on( 'click', 'button.approve', $gp.editor.hooks.set_status_current ) 108 .on( 'click', 'button.reject', $gp.editor.hooks.set_status_rejected ) 109 .on( 'click', 'button.fuzzy', $gp.editor.hooks.set_status_fuzzy ) 110 .on( 'click', 'button.ok', $gp.editor.hooks.ok ) 111 .on( 'keydown', 'tr.editor textarea', $gp.editor.hooks.keydown ); 112 $( '#translations' ).tooltip( { 113 items: '.glossary-word', 114 content: function() { 115 var content = $( '<ul>' ); 116 $.each( $( this ).data( 'translations' ), function( i, e ) { 117 var def = $( '<li>' ); 118 if ( e.locale_entry ) { 119 def.append( $( '<span>', { text: e.locale_entry } ).addClass( 'locale-entry bubble' ) ); 120 } 121 def.append( $( '<span>', { text: e.pos } ).addClass( 'pos' ) ); 122 def.append( $( '<span>', { text: e.translation } ).addClass( 'translation' ) ); 123 def.append( $( '<span>', { text: e.comment } ).addClass( 'comment' ) ); 124 content.append( def ); 125 } ); 126 return content; 127 }, 128 hide: false, 129 show: false, 130 } ); 131 132 $.valHooks.textarea = { 133 get: function( elem ) { 134 return elem.value.replace( /\r?\n/g, '\r\n' ); 135 }, 136 }; 137 }, 138 keydown: function( e ) { 139 var target, container, approve, reject, copy; 140 141 if ( 27 === e.keyCode || ( 90 === e.keyCode && e.shiftKey && e.ctrlKey ) ) { // Escape or Ctrl-Shift-Z = Cancel. 142 $gp.editor.hide(); 143 } else if ( 33 === e.keyCode || ( 38 === e.keyCode && e.ctrlKey ) ) { // Page Up or Ctrl-Up Arrow = Previous editor. 144 $gp.editor.prev(); 145 } else if ( 34 === e.keyCode || ( 40 === e.keyCode && e.ctrlKey ) ) { // Page Down or Ctrl-Down Arrow = Next editor. 146 $gp.editor.next(); 147 } else if ( 13 === e.keyCode && e.shiftKey ) { // Shift-Enter = Save. 148 target = $( e.target ); 149 150 if ( 0 === e.altKey && target.val().length ) { 151 container = target.closest( '.textareas' ).prev(); 152 153 if ( container.children() ) { 154 target.val( container.find( '.original' ).text() ); 155 } else { 156 target.val( container.text() ); 157 } 158 } 159 160 if ( target.nextAll( 'textarea' ).length ) { 161 target.nextAll( 'textarea' ).eq( 0 ).focus(); 162 } else { 163 $gp.editor.save( target.parents( 'tr.editor' ).find( 'button.ok' ) ); 164 } 165 } else if ( ( 13 === e.keyCode && e.ctrlKey ) || ( 66 === e.keyCode && e.shiftKey && e.ctrlKey ) ) { // Ctrl-Enter or Ctrl-Shift-B = Copy original. 166 copy = $( '.editor:visible' ).find( '.copy' ); 167 168 if ( copy.length > 0 ) { 169 copy.trigger( 'click' ); 170 } 171 } else if ( ( 107 === e.keyCode && e.ctrlKey ) || ( 65 === e.keyCode && e.shiftKey && e.ctrlKey ) ) { // Ctrl-+ or Ctrl-Shift-A = Approve. 172 approve = $( '.editor:visible' ).find( '.approve' ); 173 174 if ( approve.length > 0 ) { 175 approve.trigger( 'click' ); 176 } 177 } else if ( ( 109 === e.keyCode && e.ctrlKey ) || ( 82 === e.keyCode && e.shiftKey && e.ctrlKey ) ) { // Ctrl-- or Ctrl-Shift-R = Reject. 178 reject = $( '.editor:visible' ).find( '.reject' ); 179 180 if ( reject.length > 0 ) { 181 reject.trigger( 'click' ); 182 } 183 } else if ( ( 192 === e.keyCode && e.ctrlKey ) || ( 192 === e.keyCode && e.shiftKey && e.ctrlKey ) ) { // Ctrl-~ or Ctrl-Shift-~ = Fuzzy. 184 reject = $( '.editor:visible' ).find( '.fuzzy' ); 185 186 if ( reject.length > 0 ) { 187 reject.trigger( 'click' ); 188 } 189 } else { 190 return true; 191 } 192 193 return false; 194 }, 195 replace_current: function( html ) { 196 var old_current; 197 198 if ( ! $gp.editor.current ) { 199 return; 200 } 201 $gp.editor.current.after( html ); 202 old_current = $gp.editor.current; 203 old_current.attr( 'id', old_current.attr( 'id' ) + '-old' ); 204 old_current.preview.attr( 'id', old_current.preview.attr( 'id' ) + '-old' ); 205 $gp.editor.next(); 206 old_current.preview.remove(); 207 old_current.remove(); 208 }, 209 save: function( button ) { 210 var editor, textareaName, 211 data = [], 212 translations; 213 214 if ( ! $gp.editor.current ) { 215 return; 216 } 217 218 editor = $gp.editor.current; 219 button.prop( 'disabled', true ); 220 $gp.notices.notice( 'Saving…' ); 221 222 data = { 223 original_id: editor.original_id, 224 _gp_route_nonce: button.data( 'nonce' ), 225 }; 226 227 textareaName = 'translation[' + editor.original_id + '][]'; 228 translations = $( 'textarea[name="' + textareaName + '"]', editor ).map( function() { 229 return this.value; 230 } ).get(); 231 232 data[ textareaName ] = translations; 233 234 $.ajax( { 235 type: 'POST', 236 url: $gp_editor_options.url, 237 data: data, 238 dataType: 'json', 239 success: function( response ) { 240 var original_id; 241 242 button.prop( 'disabled', false ); 243 $gp.notices.success( 'Saved!' ); 244 245 for ( original_id in response ) { 246 $gp.editor.replace_current( response[ original_id ] ); 247 } 248 249 if ( $gp.editor.current.hasClass( 'no-warnings' ) ) { 250 $gp.editor.next(); 251 } 252 }, 253 error: function( xhr, msg ) { 254 button.prop( 'disabled', false ); 255 msg = xhr.responseText ? 'Error: ' + xhr.responseText : 'Error saving the translation!'; 256 $gp.notices.error( msg ); 257 }, 258 } ); 259 }, 260 set_priority: function( select ) { 261 var editor, data; 262 263 if ( ! $gp.editor.current ) { 264 return; 265 } 266 267 editor = $gp.editor.current; 268 select.prop( 'disabled', true ); 269 $gp.notices.notice( 'Setting priority…' ); 270 271 data = { 272 priority: $( 'option:selected', select ).val(), 273 _gp_route_nonce: select.data( 'nonce' ), 274 }; 275 276 $.ajax( { 277 type: 'POST', 278 url: $gp_editor_options.set_priority_url.replace( '%original-id%', editor.original_id ), 279 data: data, 280 success: function() { 281 var new_priority_class; 282 283 select.prop( 'disabled', false ); 284 $gp.notices.success( 'Priority set!' ); 285 new_priority_class = 'priority-' + $( 'option:selected', select ).text(); 286 $gp.editor.current.addClass( new_priority_class ); 287 $gp.editor.current.preview.addClass( new_priority_class ); 288 }, 289 error: function( xhr, msg ) { 290 select.prop( 'disabled', false ); 291 msg = xhr.responseText ? 'Error: ' + xhr.responseText : 'Error setting the priority!'; 292 $gp.notices.error( msg ); 293 }, 294 } ); 295 }, 296 set_status: function( button, status ) { 297 var editor, data, 298 translationChanged = false; 299 300 if ( ! $gp.editor.current || ! $gp.editor.current.translation_id ) { 301 return; 302 } 303 304 editor = $gp.editor.current; 305 306 $( '[id*="translation_' + editor.original_id + '_"]' ).each( function() { 307 if ( this.value !== this.defaultValue ) { 308 translationChanged = true; 309 } 310 } ); 311 312 if ( translationChanged ) { 313 $gp.notices.error( 'Translation has changed! Please add the new translation before changing its status.' ); 314 return; 315 } 316 317 button.prop( 'disabled', true ); 318 $gp.notices.notice( 'Setting status to “' + status + '”…' ); 319 320 data = { 321 translation_id: editor.translation_id, 322 status: status, 323 _gp_route_nonce: button.data( 'nonce' ), 324 }; 325 326 $.ajax( { 327 type: 'POST', 328 url: $gp_editor_options.set_status_url, 329 data: data, 330 success: function( response ) { 331 button.prop( 'disabled', false ); 332 $gp.notices.success( 'Status set!' ); 333 $gp.editor.replace_current( response ); 334 $gp.editor.next(); 335 }, 336 error: function( xhr, msg ) { 337 button.prop( 'disabled', false ); 338 msg = xhr.responseText ? 'Error: ' + xhr.responseText : 'Error setting the status!'; 339 $gp.notices.error( msg ); 340 }, 341 } ); 342 }, 343 discard_warning: function( link ) { 344 var data; 345 if ( ! $gp.editor.current ) { 346 return; 347 } 348 349 $gp.notices.notice( 'Discarding…' ); 350 351 data = { 352 translation_id: $gp.editor.current.translation_id, 353 key: link.data( 'key' ), 354 index: link.data( 'index' ), 355 _gp_route_nonce: link.data( 'nonce' ), 356 357 }; 358 359 $.ajax( { 360 type: 'POST', 361 url: $gp_editor_options.discard_warning_url, 362 data: data, 363 success: function( response ) { 364 $gp.notices.success( 'Saved!' ); 365 $gp.editor.replace_current( response ); 366 }, 367 error: function( xhr, msg ) { 368 msg = xhr.responseText ? 'Error: ' + xhr.responseText : 'Error saving the translation!'; 369 $gp.notices.error( msg ); 370 }, 371 } ); 372 }, 373 copy: function( link ) { 374 var chunks = link.parents( '.textareas' ).find( 'textarea' ).attr( 'id' ).split( '_' ); 375 var original_index = Math.min( parseInt( chunks[ chunks.length - 1 ], 10 ), 1 ); 376 var original_texts = link.parents( '.strings' ).find( '.original_raw' ); 377 var original_text = original_texts.eq( original_index ).text(); 378 379 link.parents( '.textareas' ).find( 'textarea' ).val( original_text ).focus(); 380 }, 381 tab: function( link ) { 382 var text_area = link.parents( '.textareas' ).find( 'textarea' ); 383 var cursorPos = text_area.prop( 'selectionStart' ); 384 var v = text_area.val(); 385 var textBefore = v.substring( 0, cursorPos ); 386 var textAfter = v.substring( cursorPos, v.length ); 387 388 text_area.val( textBefore + '\t' + textAfter ); 389 390 text_area.focus(); 391 text_area[ 0 ].selectionEnd = cursorPos + 1; 392 }, 393 newline: function( link ) { 394 var text_area = link.parents( '.textareas' ).find( 'textarea' ); 395 var cursorPos = text_area.prop( 'selectionStart' ); 396 var v = text_area.val(); 397 var textBefore = v.substring( 0, cursorPos ); 398 var textAfter = v.substring( cursorPos, v.length ); 399 400 text_area.val( textBefore + '\n' + textAfter ); 401 402 text_area.focus(); 403 text_area[ 0 ].selectionEnd = cursorPos + 1; 404 }, 405 hooks: { 406 show: function() { 407 $gp.editor.show( $( this ) ); 408 return false; 409 }, 410 hide: function() { 411 $gp.editor.hide(); 412 return false; 413 }, 414 ok: function() { 415 $gp.editor.save( $( this ) ); 416 return false; 417 }, 418 cancel: function() { 419 var i = 0; 420 421 for ( i = 0; i < $gp.editor.current.orginal_translations.length; i++ ) { 422 $( 'textarea[id="translation_' + $gp.editor.current.original_id + '_' + i + '"]' ).val( $gp.editor.current.orginal_translations[ i ] ); 423 } 424 425 $gp.editor.hide(); 426 427 return false; 428 }, 429 keydown: function( e ) { 430 return $gp.editor.keydown( e ); 431 }, 432 copy: function() { 433 $gp.editor.copy( $( this ) ); 434 return false; 435 }, 436 tab: function() { 437 $gp.editor.tab( $( this ) ); 438 return false; 439 }, 440 newline: function() { 441 $gp.editor.newline( $( this ) ); 442 return false; 443 }, 444 discard_warning: function() { 445 $gp.editor.discard_warning( $( this ) ); 446 return false; 447 }, 448 set_status_current: function() { 449 $gp.editor.set_status( $( this ), 'current' ); 450 return false; 451 }, 452 set_status_rejected: function() { 453 $gp.editor.set_status( $( this ), 'rejected' ); 454 return false; 455 }, 456 set_status_fuzzy: function() { 457 $gp.editor.set_status( $( this ), 'fuzzy' ); 458 return false; 459 }, 460 set_priority: function() { 461 $gp.editor.set_priority( $( this ) ); 462 return false; 463 }, 464 }, 465 }; 466 }( jQuery ) 467 ); 468 469 jQuery( function( $ ) { 470 $gp.editor.init( $( '#translations' ) ); 471 } );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:01:07 2024 | Cross-referenced by PHPXref 0.7.1 |