[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
1 /* global switchEditors, autosaveL10n, tinymce, ajaxurl, wpAjax, makeSlugeditClickable, wpCookies */ 2 var autosave, autosavePeriodical, fullscreen, doPreview, 3 autosaveLast = '', 4 autosaveDelayPreview = false, 5 notSaved = true, 6 blockSave = false, 7 autosaveLockRelease = true; 8 9 jQuery(document).ready( function($) { 10 11 if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) { 12 autosaveLast = wp.autosave.getCompareString({ 13 post_title : $('#title').val() || '', 14 content : switchEditors.pre_wpautop( $('#content').val() ) || '', 15 excerpt : $('#excerpt').val() || '' 16 }); 17 } else { 18 autosaveLast = wp.autosave.getCompareString(); 19 } 20 21 autosavePeriodical = $.schedule({time: autosaveL10n.autosaveInterval * 1000, func: function() { autosave(); }, repeat: true, protect: true}); 22 23 //Disable autosave after the form has been submitted 24 $('#post').submit(function() { 25 $.cancel(autosavePeriodical); 26 autosaveLockRelease = false; 27 }); 28 29 $('input[type="submit"], a.submitdelete', '#submitpost').click(function(){ 30 blockSave = true; 31 window.onbeforeunload = null; 32 $(':button, :submit', '#submitpost').each(function(){ 33 var t = $(this); 34 if ( t.hasClass('button-primary') ) 35 t.addClass('button-primary-disabled'); 36 else 37 t.addClass('button-disabled'); 38 }); 39 if ( $(this).attr('id') == 'publish' ) 40 $('#major-publishing-actions .spinner').show(); 41 else 42 $('#minor-publishing .spinner').show(); 43 }); 44 45 window.onbeforeunload = function(){ 46 var editor = typeof(tinymce) != 'undefined' ? tinymce.activeEditor : false, compareString; 47 48 if ( editor && ! editor.isHidden() ) { 49 if ( editor.isDirty() ) 50 return autosaveL10n.saveAlert; 51 } else { 52 if ( fullscreen && fullscreen.settings.visible ) { 53 compareString = wp.autosave.getCompareString({ 54 post_title: $('#wp-fullscreen-title').val() || '', 55 content: $('#wp_mce_fullscreen').val() || '', 56 excerpt: $('#excerpt').val() || '' 57 }); 58 } else { 59 compareString = wp.autosave.getCompareString(); 60 } 61 62 if ( compareString != autosaveLast ) 63 return autosaveL10n.saveAlert; 64 } 65 }; 66 67 $(window).unload( function(e) { 68 if ( ! autosaveLockRelease ) 69 return; 70 71 // unload fires (twice) on removing the Thickbox iframe. Make sure we process only the main document unload. 72 if ( e.target && e.target.nodeName != '#document' ) 73 return; 74 75 $.ajax({ 76 type: 'POST', 77 url: ajaxurl, 78 async: false, 79 data: { 80 action: 'wp-remove-post-lock', 81 _wpnonce: $('#_wpnonce').val(), 82 post_ID: $('#post_ID').val(), 83 active_post_lock: $('#active_post_lock').val() 84 } 85 }); 86 } ); 87 88 // preview 89 $('#post-preview').click(function(){ 90 if ( $('#auto_draft').val() == '1' && notSaved ) { 91 autosaveDelayPreview = true; 92 autosave(); 93 return false; 94 } 95 doPreview(); 96 return false; 97 }); 98 99 doPreview = function() { 100 $('input#wp-preview').val('dopreview'); 101 $('form#post').attr('target', 'wp-preview').submit().attr('target', ''); 102 103 /* 104 * Workaround for WebKit bug preventing a form submitting twice to the same action. 105 * https://bugs.webkit.org/show_bug.cgi?id=28633 106 */ 107 var ua = navigator.userAgent.toLowerCase(); 108 if ( ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1 ) { 109 $('form#post').attr('action', function(index, value) { 110 return value + '?t=' + new Date().getTime(); 111 }); 112 } 113 114 $('input#wp-preview').val(''); 115 }; 116 117 // This code is meant to allow tabbing from Title to Post content. 118 $('#title').on('keydown.editor-focus', function(e) { 119 var ed; 120 121 if ( e.which != 9 ) 122 return; 123 124 if ( !e.ctrlKey && !e.altKey && !e.shiftKey ) { 125 if ( typeof(tinymce) != 'undefined' ) 126 ed = tinymce.get('content'); 127 128 if ( ed && !ed.isHidden() ) { 129 $(this).one('keyup', function(){ 130 $('#content_tbl td.mceToolbar > a').focus(); 131 }); 132 } else { 133 $('#content').focus(); 134 } 135 136 e.preventDefault(); 137 } 138 }); 139 140 // autosave new posts after a title is typed but not if Publish or Save Draft is clicked 141 if ( '1' == $('#auto_draft').val() ) { 142 $('#title').blur( function() { 143 if ( !this.value || $('#auto_draft').val() != '1' ) 144 return; 145 delayed_autosave(); 146 }); 147 } 148 149 // When connection is lost, keep user from submitting changes. 150 $(document).on('heartbeat-connection-lost.autosave', function( e, error, status ) { 151 if ( 'timeout' === error || 503 == status ) { 152 var notice = $('#lost-connection-notice'); 153 if ( ! wp.autosave.local.hasStorage ) { 154 notice.find('.hide-if-no-sessionstorage').hide(); 155 } 156 notice.show(); 157 autosave_disable_buttons(); 158 } 159 }).on('heartbeat-connection-restored.autosave', function() { 160 $('#lost-connection-notice').hide(); 161 autosave_enable_buttons(); 162 }); 163 }); 164 165 function autosave_parse_response( response ) { 166 var res = wpAjax.parseAjaxResponse(response, 'autosave'), post_id, sup; 167 168 if ( res && res.responses && res.responses.length ) { 169 if ( res.responses[0].supplemental ) { 170 sup = res.responses[0].supplemental; 171 172 jQuery.each( sup, function( selector, value ) { 173 if ( selector.match(/^replace-/) ) 174 jQuery( '#' + selector.replace('replace-', '') ).val( value ); 175 }); 176 } 177 178 // if no errors: add slug UI and update autosave-message 179 if ( !res.errors ) { 180 if ( post_id = parseInt( res.responses[0].id, 10 ) ) 181 autosave_update_slug( post_id ); 182 183 if ( res.responses[0].data ) // update autosave message 184 jQuery('.autosave-message').text( res.responses[0].data ); 185 } 186 } 187 188 return res; 189 } 190 191 // called when autosaving pre-existing post 192 function autosave_saved(response) { 193 blockSave = false; 194 autosave_parse_response(response); // parse the ajax response 195 autosave_enable_buttons(); // re-enable disabled form buttons 196 } 197 198 // called when autosaving new post 199 function autosave_saved_new(response) { 200 blockSave = false; 201 var res = autosave_parse_response(response), post_id; 202 203 if ( res && res.responses.length && !res.errors ) { 204 // An ID is sent only for real auto-saves, not for autosave=0 "keepalive" saves 205 post_id = parseInt( res.responses[0].id, 10 ); 206 207 if ( post_id ) { 208 notSaved = false; 209 jQuery('#auto_draft').val('0'); // No longer an auto-draft 210 } 211 212 autosave_enable_buttons(); 213 214 if ( autosaveDelayPreview ) { 215 autosaveDelayPreview = false; 216 doPreview(); 217 } 218 } else { 219 autosave_enable_buttons(); // re-enable disabled form buttons 220 } 221 } 222 223 function autosave_update_slug(post_id) { 224 // create slug area only if not already there 225 if ( 'undefined' != makeSlugeditClickable && jQuery.isFunction(makeSlugeditClickable) && !jQuery('#edit-slug-box > *').size() ) { 226 jQuery.post( ajaxurl, { 227 action: 'sample-permalink', 228 post_id: post_id, 229 new_title: fullscreen && fullscreen.settings.visible ? jQuery('#wp-fullscreen-title').val() : jQuery('#title').val(), 230 samplepermalinknonce: jQuery('#samplepermalinknonce').val() 231 }, 232 function(data) { 233 if ( data !== '-1' ) { 234 var box = jQuery('#edit-slug-box'); 235 box.html(data); 236 if (box.hasClass('hidden')) { 237 box.fadeIn('fast', function () { 238 box.removeClass('hidden'); 239 }); 240 } 241 makeSlugeditClickable(); 242 } 243 } 244 ); 245 } 246 } 247 248 function autosave_loading() { 249 jQuery('.autosave-message').html(autosaveL10n.savingText); 250 } 251 252 function autosave_enable_buttons() { 253 jQuery(document).trigger('autosave-enable-buttons'); 254 if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) { 255 // delay that a bit to avoid some rare collisions while the DOM is being updated. 256 setTimeout(function(){ 257 var parent = jQuery('#submitpost'); 258 parent.find(':button, :submit').removeAttr('disabled'); 259 parent.find('.spinner').hide(); 260 }, 500); 261 } 262 } 263 264 function autosave_disable_buttons() { 265 jQuery(document).trigger('autosave-disable-buttons'); 266 jQuery('#submitpost').find(':button, :submit').prop('disabled', true); 267 // Re-enable 5 sec later. Just gives autosave a head start to avoid collisions. 268 setTimeout( autosave_enable_buttons, 5000 ); 269 } 270 271 function delayed_autosave() { 272 setTimeout(function(){ 273 if ( blockSave ) 274 return; 275 autosave(); 276 }, 200); 277 } 278 279 autosave = function() { 280 var post_data = wp.autosave.getPostData(), 281 compareString, 282 successCallback; 283 284 blockSave = true; 285 286 // post_data.content cannot be retrieved at the moment 287 if ( ! post_data.autosave ) 288 return false; 289 290 // No autosave while thickbox is open (media buttons) 291 if ( jQuery('#TB_window').css('display') == 'block' ) 292 return false; 293 294 compareString = wp.autosave.getCompareString( post_data ); 295 296 // Nothing to save or no change. 297 if ( compareString == autosaveLast ) 298 return false; 299 300 autosaveLast = compareString; 301 jQuery(document).triggerHandler('wpcountwords', [ post_data.content ]); 302 303 // Disable buttons until we know the save completed. 304 autosave_disable_buttons(); 305 306 if ( post_data.auto_draft == '1' ) { 307 successCallback = autosave_saved_new; // new post 308 } else { 309 successCallback = autosave_saved; // pre-existing post 310 } 311 312 jQuery.ajax({ 313 data: post_data, 314 beforeSend: autosave_loading, 315 type: 'POST', 316 url: ajaxurl, 317 success: successCallback 318 }); 319 320 return true; 321 }; 322 323 // Autosave in localStorage 324 // set as simple object/mixin for now 325 window.wp = window.wp || {}; 326 wp.autosave = wp.autosave || {}; 327 328 (function($){ 329 // Returns the data for saving in both localStorage and autosaves to the server 330 wp.autosave.getPostData = function() { 331 var ed = typeof tinymce != 'undefined' ? tinymce.activeEditor : null, post_name, parent_id, cats = [], 332 data = { 333 action: 'autosave', 334 autosave: true, 335 post_id: $('#post_ID').val() || 0, 336 autosavenonce: $('#autosavenonce').val() || '', 337 post_type: $('#post_type').val() || '', 338 post_author: $('#post_author').val() || '', 339 excerpt: $('#excerpt').val() || '' 340 }; 341 342 if ( ed && !ed.isHidden() ) { 343 // Don't run while the tinymce spellcheck is on. It resets all found words. 344 if ( ed.plugins.spellchecker && ed.plugins.spellchecker.active ) { 345 data.autosave = false; 346 return data; 347 } else { 348 if ( 'mce_fullscreen' == ed.id ) 349 tinymce.get('content').setContent(ed.getContent({format : 'raw'}), {format : 'raw'}); 350 351 tinymce.triggerSave(); 352 } 353 } 354 355 if ( typeof fullscreen != 'undefined' && fullscreen.settings.visible ) { 356 data.post_title = $('#wp-fullscreen-title').val() || ''; 357 data.content = $('#wp_mce_fullscreen').val() || ''; 358 } else { 359 data.post_title = $('#title').val() || ''; 360 data.content = $('#content').val() || ''; 361 } 362 363 /* 364 // We haven't been saving tags with autosave since 2.8... Start again? 365 $('.the-tags').each( function() { 366 data[this.name] = this.value; 367 }); 368 */ 369 370 $('input[id^="in-category-"]:checked').each( function() { 371 cats.push(this.value); 372 }); 373 data.catslist = cats.join(','); 374 375 if ( post_name = $('#post_name').val() ) 376 data.post_name = post_name; 377 378 if ( parent_id = $('#parent_id').val() ) 379 data.parent_id = parent_id; 380 381 if ( $('#comment_status').prop('checked') ) 382 data.comment_status = 'open'; 383 384 if ( $('#ping_status').prop('checked') ) 385 data.ping_status = 'open'; 386 387 if ( $('#auto_draft').val() == '1' ) 388 data.auto_draft = '1'; 389 390 return data; 391 }; 392 393 // Concatenate title, content and excerpt. Used to track changes when auto-saving. 394 wp.autosave.getCompareString = function( post_data ) { 395 if ( typeof post_data === 'object' ) { 396 return ( post_data.post_title || '' ) + '::' + ( post_data.content || '' ) + '::' + ( post_data.excerpt || '' ); 397 } 398 399 return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' ); 400 }; 401 402 wp.autosave.local = { 403 404 lastSavedData: '', 405 blog_id: 0, 406 hasStorage: false, 407 408 // Check if the browser supports sessionStorage and it's not disabled 409 checkStorage: function() { 410 var test = Math.random(), result = false; 411 412 try { 413 sessionStorage.setItem('wp-test', test); 414 result = sessionStorage.getItem('wp-test') == test; 415 sessionStorage.removeItem('wp-test'); 416 } catch(e) {} 417 418 this.hasStorage = result; 419 return result; 420 }, 421 422 /** 423 * Initialize the local storage 424 * 425 * @return mixed False if no sessionStorage in the browser or an Object containing all post_data for this blog 426 */ 427 getStorage: function() { 428 var stored_obj = false; 429 // Separate local storage containers for each blog_id 430 if ( this.hasStorage && this.blog_id ) { 431 stored_obj = sessionStorage.getItem( 'wp-autosave-' + this.blog_id ); 432 433 if ( stored_obj ) 434 stored_obj = JSON.parse( stored_obj ); 435 else 436 stored_obj = {}; 437 } 438 439 return stored_obj; 440 }, 441 442 /** 443 * Set the storage for this blog 444 * 445 * Confirms that the data was saved successfully. 446 * 447 * @return bool 448 */ 449 setStorage: function( stored_obj ) { 450 var key; 451 452 if ( this.hasStorage && this.blog_id ) { 453 key = 'wp-autosave-' + this.blog_id; 454 sessionStorage.setItem( key, JSON.stringify( stored_obj ) ); 455 return sessionStorage.getItem( key ) !== null; 456 } 457 458 return false; 459 }, 460 461 /** 462 * Get the saved post data for the current post 463 * 464 * @return mixed False if no storage or no data or the post_data as an Object 465 */ 466 getData: function() { 467 var stored = this.getStorage(), post_id = $('#post_ID').val(); 468 469 if ( !stored || !post_id ) 470 return false; 471 472 return stored[ 'post_' + post_id ] || false; 473 }, 474 475 /** 476 * Set (save or delete) post data in the storage. 477 * 478 * If stored_data evaluates to 'false' the storage key for the current post will be removed 479 * 480 * $param stored_data The post data to store or null/false/empty to delete the key 481 * @return bool 482 */ 483 setData: function( stored_data ) { 484 var stored = this.getStorage(), post_id = $('#post_ID').val(); 485 486 if ( !stored || !post_id ) 487 return false; 488 489 if ( stored_data ) 490 stored[ 'post_' + post_id ] = stored_data; 491 else if ( stored.hasOwnProperty( 'post_' + post_id ) ) 492 delete stored[ 'post_' + post_id ]; 493 else 494 return false; 495 496 return this.setStorage(stored); 497 }, 498 499 /** 500 * Save post data for the current post 501 * 502 * Runs on a 15 sec. schedule, saves when there are differences in the post title or content. 503 * When the optional data is provided, updates the last saved post data. 504 * 505 * $param data optional Object The post data for saving, minimum 'post_title' and 'content' 506 * @return bool 507 */ 508 save: function( data ) { 509 var result = false, post_data, compareString; 510 511 if ( ! data ) { 512 post_data = wp.autosave.getPostData(); 513 } else { 514 post_data = this.getData() || {}; 515 $.extend( post_data, data ); 516 post_data.autosave = true; 517 } 518 519 // Cannot get the post data at the moment 520 if ( ! post_data.autosave ) 521 return false; 522 523 compareString = wp.autosave.getCompareString( post_data ); 524 525 // If the content, title and excerpt did not change since the last save, don't save again 526 if ( compareString == this.lastSavedData ) 527 return false; 528 529 post_data.save_time = (new Date()).getTime(); 530 post_data.status = $('#post_status').val() || ''; 531 result = this.setData( post_data ); 532 533 if ( result ) 534 this.lastSavedData = compareString; 535 536 return result; 537 }, 538 539 // Initialize and run checkPost() on loading the script (before TinyMCE init) 540 init: function( settings ) { 541 var self = this; 542 543 // Check if the browser supports sessionStorage and it's not disabled 544 if ( ! this.checkStorage() ) 545 return; 546 547 // Don't run if the post type supports neither 'editor' (textarea#content) nor 'excerpt'. 548 if ( ! $('#content').length && ! $('#excerpt').length ) 549 return; 550 551 if ( settings ) 552 $.extend( this, settings ); 553 554 if ( !this.blog_id ) 555 this.blog_id = typeof window.autosaveL10n != 'undefined' ? window.autosaveL10n.blog_id : 0; 556 557 $(document).ready( function(){ self.run(); } ); 558 }, 559 560 // Run on DOM ready 561 run: function() { 562 var self = this; 563 564 // Check if the local post data is different than the loaded post data. 565 this.checkPost(); 566 567 // Set the schedule 568 this.schedule = $.schedule({ 569 time: 15 * 1000, 570 func: function() { wp.autosave.local.save(); }, 571 repeat: true, 572 protect: true 573 }); 574 575 $('form#post').on('submit.autosave-local', function() { 576 var editor = typeof tinymce != 'undefined' && tinymce.get('content'), post_id = $('#post_ID').val() || 0; 577 578 if ( editor && ! editor.isHidden() ) { 579 // Last onSubmit event in the editor, needs to run after the content has been moved to the textarea. 580 editor.onSubmit.add( function() { 581 wp.autosave.local.save({ 582 post_title: $('#title').val() || '', 583 content: $('#content').val() || '', 584 excerpt: $('#excerpt').val() || '' 585 }); 586 }); 587 } else { 588 self.save({ 589 post_title: $('#title').val() || '', 590 content: $('#content').val() || '', 591 excerpt: $('#excerpt').val() || '' 592 }); 593 } 594 595 wpCookies.set( 'wp-saving-post-' + post_id, 'check' ); 596 }); 597 }, 598 599 // Strip whitespace and compare two strings 600 compare: function( str1, str2 ) { 601 function remove( string ) { 602 return string.toString().replace(/[\x20\t\r\n\f]+/g, ''); 603 } 604 605 return ( remove( str1 || '' ) == remove( str2 || '' ) ); 606 }, 607 608 /** 609 * Check if the saved data for the current post (if any) is different than the loaded post data on the screen 610 * 611 * Shows a standard message letting the user restore the post data if different. 612 * 613 * @return void 614 */ 615 checkPost: function() { 616 var self = this, post_data = this.getData(), content, post_title, excerpt, notice, 617 post_id = $('#post_ID').val() || 0, cookie = wpCookies.get( 'wp-saving-post-' + post_id ); 618 619 if ( ! post_data ) 620 return; 621 622 if ( cookie ) { 623 wpCookies.remove( 'wp-saving-post-' + post_id ); 624 625 if ( cookie == 'saved' ) { 626 // The post was saved properly, remove old data and bail 627 this.setData( false ); 628 return; 629 } 630 } 631 632 // There is a newer autosave. Don't show two "restore" notices at the same time. 633 if ( $('#has-newer-autosave').length ) 634 return; 635 636 content = $('#content').val() || ''; 637 post_title = $('#title').val() || ''; 638 excerpt = $('#excerpt').val() || ''; 639 640 if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) 641 content = switchEditors.pre_wpautop( content ); 642 643 // cookie == 'check' means the post was not saved properly, always show #local-storage-notice 644 if ( cookie != 'check' && this.compare( content, post_data.content ) && this.compare( post_title, post_data.post_title ) && this.compare( excerpt, post_data.excerpt ) ) { 645 return; 646 } 647 648 this.restore_post_data = post_data; 649 this.undo_post_data = { 650 content: content, 651 post_title: post_title, 652 excerpt: excerpt 653 }; 654 655 notice = $('#local-storage-notice'); 656 $('.wrap h2').first().after( notice.addClass('updated').show() ); 657 658 notice.on( 'click', function(e) { 659 var target = $( e.target ); 660 661 if ( target.hasClass('restore-backup') ) { 662 self.restorePost( self.restore_post_data ); 663 target.parent().hide(); 664 $(this).find('p.undo-restore').show(); 665 } else if ( target.hasClass('undo-restore-backup') ) { 666 self.restorePost( self.undo_post_data ); 667 target.parent().hide(); 668 $(this).find('p.local-restore').show(); 669 } 670 671 e.preventDefault(); 672 }); 673 }, 674 675 // Restore the current title, content and excerpt from post_data. 676 restorePost: function( post_data ) { 677 var editor; 678 679 if ( post_data ) { 680 // Set the last saved data 681 this.lastSavedData = wp.autosave.getCompareString( post_data ); 682 683 if ( $('#title').val() != post_data.post_title ) 684 $('#title').focus().val( post_data.post_title || '' ); 685 686 $('#excerpt').val( post_data.excerpt || '' ); 687 editor = typeof tinymce != 'undefined' && tinymce.get('content'); 688 689 if ( editor && ! editor.isHidden() && typeof switchEditors != 'undefined' ) { 690 // Make sure there's an undo level in the editor 691 editor.undoManager.add(); 692 editor.setContent( post_data.content ? switchEditors.wpautop( post_data.content ) : '' ); 693 } else { 694 // Make sure the Text editor is selected 695 $('#content-html').click(); 696 $('#content').val( post_data.content ); 697 } 698 699 return true; 700 } 701 702 return false; 703 } 704 }; 705 706 wp.autosave.local.init(); 707 708 }(jQuery));
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |