diff --git a/wp-includes/js/autosave.js b/wp-includes/js/autosave.js index 9e7fe0f724..33229a324b 100644 --- a/wp-includes/js/autosave.js +++ b/wp-includes/js/autosave.js @@ -7,12 +7,12 @@ jQuery(document).ready( function($) { if ( 'content' == editor.id ) { editor.onLoad.add( function() { editor.save(); - autosaveLast = ( $('#title').val() || '' ) + ( $('#content').val() || '' ); + autosaveLast = wp.autosave.getCompareString(); }); } }); } else { - autosaveLast = ( $('#title').val() || '' ) + ( $('#content').val() || '' ); + autosaveLast = wp.autosave.getCompareString(); } autosavePeriodical = $.schedule({time: autosaveL10n.autosaveInterval * 1000, func: function() { autosave(); }, repeat: true, protect: true}); @@ -40,21 +40,23 @@ jQuery(document).ready( function($) { }); window.onbeforeunload = function(){ - var mce = typeof(tinymce) != 'undefined' ? tinymce.activeEditor : false, title, content; + var editor = typeof(tinymce) != 'undefined' ? tinymce.activeEditor : false, compareString; - if ( mce && !mce.isHidden() ) { - if ( mce.isDirty() ) + if ( editor && ! editor.isHidden() ) { + if ( editor.isDirty() ) return autosaveL10n.saveAlert; } else { if ( fullscreen && fullscreen.settings.visible ) { - title = $('#wp-fullscreen-title').val() || ''; - content = $("#wp_mce_fullscreen").val() || ''; + compareString = wp.autosave.getCompareString({ + post_title: $('#wp-fullscreen-title').val() || '', + content: $('#wp_mce_fullscreen').val() || '', + excerpt: $('#excerpt').val() || '' + }); } else { - title = $('#post #title').val() || ''; - content = $('#post #content').val() || ''; + compareString = wp.autosave.getCompareString(); } - if ( ( title || content ) && title + content != autosaveLast ) + if ( compareString != autosaveLast ) return autosaveL10n.saveAlert; } }; @@ -246,7 +248,7 @@ function autosave_loading() { function autosave_enable_buttons() { jQuery(document).trigger('autosave-enable-buttons'); - if ( ! wp.heartbeat.hasConnectionError() ) { + if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) { // delay that a bit to avoid some rare collisions while the DOM is being updated. setTimeout(function(){ var parent = jQuery('#submitpost'); @@ -273,26 +275,27 @@ function delayed_autosave() { autosave = function() { var post_data = wp.autosave.getPostData(), - doAutoSave = post_data.autosave, + compareString, successCallback; blockSave = true; + // post_data.content cannot be retrieved at the moment + if ( ! post_data.autosave ) + return false; + // No autosave while thickbox is open (media buttons) if ( jQuery("#TB_window").css('display') == 'block' ) - doAutoSave = false; + return false; + + compareString = wp.autosave.getCompareString( post_data ); // Nothing to save or no change. - if ( ( post_data["post_title"].length == 0 && post_data["content"].length == 0 ) || post_data["post_title"] + post_data["content"] == autosaveLast ) { - doAutoSave = false; - } - - if ( doAutoSave ) { - autosaveLast = post_data["post_title"] + post_data["content"]; - jQuery(document).triggerHandler('wpcountwords', [ post_data["content"] ]); - } else { + if ( compareString == autosaveLast ) return false; - } + + autosaveLast = compareString; + jQuery(document).triggerHandler('wpcountwords', [ post_data["content"] ]); // Disable buttons until we know the save completed. autosave_disable_buttons(); @@ -305,7 +308,7 @@ autosave = function() { jQuery.ajax({ data: post_data, - beforeSend: doAutoSave ? autosave_loading : null, + beforeSend: autosave_loading, type: "POST", url: ajaxurl, success: successCallback @@ -382,13 +385,21 @@ wp.autosave.getPostData = function() { data['auto_draft'] = '1'; return data; -} +}; + +// Concatenate title, content and excerpt. Used to track changes when auto-saving. +wp.autosave.getCompareString = function( post_data ) { + if ( typeof post_data === 'object' ) { + return ( post_data.post_title || '' ) + '::' + ( post_data.content || '' ) + '::' + ( post_data.excerpt || '' ); + } + + return ( $('#title').val() || '' ) + '::' + ( $('#content').val() || '' ) + '::' + ( $('#excerpt').val() || '' ); +}; wp.autosave.local = { - lastsaveddata: '', + lastSavedData: '', blog_id: 0, - ajaxurl: window.ajaxurl || 'wp-admin/admin-ajax.php', hasStorage: false, // Check if the browser supports sessionStorage and it's not disabled @@ -492,7 +503,7 @@ wp.autosave.local = { * @return bool */ save: function( data ) { - var result = false; + var result = false, post_data, compareString; if ( ! data ) { post_data = wp.autosave.getPostData(); @@ -502,12 +513,14 @@ wp.autosave.local = { post_data.autosave = true; } - // If the content and title did not change since the last save, don't save again - if ( post_data.post_title + ': ' + post_data.content == this.lastsaveddata ) + // Cannot get the post data at the moment + if ( ! post_data.autosave ) return false; - // Cannot get the post data at the moment - if ( !post_data.autosave ) + compareString = wp.autosave.getCompareString( post_data ); + + // If the content, title and excerpt did not change since the last save, don't save again + if ( compareString == this.lastSavedData ) return false; post_data['save_time'] = (new Date()).getTime(); @@ -515,7 +528,7 @@ wp.autosave.local = { result = this.setData( post_data ); if ( result ) - this.lastsaveddata = post_data.post_title + ': ' + post_data.content; + this.lastSavedData = compareString; return result; }, @@ -524,8 +537,8 @@ wp.autosave.local = { init: function( settings ) { var self = this; - // Check if the browser supports sessionStorage and editor.js is loaded - if ( ! this.checkStorage() || typeof switchEditors == 'undefined' ) + // Check if the browser supports sessionStorage and it's not disabled + if ( ! this.checkStorage() ) return; // Don't run if the post type supports neither 'editor' (textarea#content) nor 'excerpt'. @@ -538,23 +551,15 @@ wp.autosave.local = { if ( !this.blog_id ) this.blog_id = typeof window.autosaveL10n != 'undefined' ? window.autosaveL10n.blog_id : 0; - this.checkPost(); $(document).ready( function(){ self.run(); } ); }, // Run on DOM ready run: function() { - var self = this, post_data; + var self = this; - // Set the comparison string - if ( !this.lastsaveddata ) { - post_data = wp.autosave.getPostData(); - - if ( post_data.content && $('#wp-content-wrap').hasClass('tmce-active') ) - this.lastsaveddata = post_data.post_title + ': ' + switchEditors.pre_wpautop( post_data.content ); - else - this.lastsaveddata = post_data.post_title + ': ' + post_data.content; - } + // Check if the local post data is different than the loaded post data. + this.checkPost(); // Set the schedule this.schedule = $.schedule({ @@ -605,7 +610,7 @@ wp.autosave.local = { * @return void */ checkPost: function() { - var self = this, post_data = this.getData(), content, check_data, strip_tags = false, notice, + var self = this, post_data = this.getData(), content, post_title, excerpt, notice, post_id = $('#post_ID').val() || 0, cookie = wpCookies.get( 'wp-saving-post-' + post_id ); if ( ! post_data ) @@ -625,20 +630,24 @@ wp.autosave.local = { if ( $('#has-newer-autosave').length ) return; + content = $('#content').val() || ''; + post_title = $('#title').val() || ''; + excerpt = $('#excerpt').val() || ''; + + if ( $('#wp-content-wrap').hasClass('tmce-active') && typeof switchEditors != 'undefined' ) + content = switchEditors.pre_wpautop( content ); + // cookie == 'check' means the post was not saved properly, always show #local-storage-notice - if ( cookie != 'check' ) { - content = $('#content').val(); - check_data = $.extend( {}, post_data ); - - if ( $('#wp-content-wrap').hasClass('tmce-active') ) - content = switchEditors.pre_wpautop( content ); - - if ( this.compare( content, check_data.content ) && this.compare( $('#title').val(), check_data.post_title ) && this.compare( $('#excerpt').val(), check_data.excerpt ) ) - return; + if ( cookie != 'check' && this.compare( content, post_data.content ) && this.compare( post_title, post_data.post_title ) && this.compare( excerpt, post_data.excerpt ) ) { + return; } this.restore_post_data = post_data; - this.undo_post_data = wp.autosave.getPostData(); + this.undo_post_data = { + content: content, + post_title: post_title, + excerpt: excerpt + }; notice = $('#local-storage-notice'); $('.wrap h2').first().after( notice.addClass('updated').show() ); @@ -666,7 +675,7 @@ wp.autosave.local = { if ( post_data ) { // Set the last saved data - this.lastsaveddata = post_data.post_title + ': ' + post_data.content; + this.lastSavedData = wp.autosave.getCompareString( post_data ); if ( $('#title').val() != post_data.post_title ) $('#title').focus().val( post_data.post_title || '' ); @@ -674,7 +683,7 @@ wp.autosave.local = { $('#excerpt').val( post_data.excerpt || '' ); editor = typeof tinymce != 'undefined' && tinymce.get('content'); - if ( editor && ! editor.isHidden() ) { + if ( editor && ! editor.isHidden() && typeof switchEditors != 'undefined' ) { // Make sure there's an undo level in the editor editor.undoManager.add(); editor.setContent( post_data.content ? switchEditors.wpautop( post_data.content ) : '' ); @@ -689,7 +698,7 @@ wp.autosave.local = { return false; } -} +}; wp.autosave.local.init(); diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php index 6bc29854c7..626f38bb82 100644 --- a/wp-includes/script-loader.php +++ b/wp-includes/script-loader.php @@ -103,7 +103,7 @@ function wp_default_scripts( &$scripts ) { 'dismiss' => __('Dismiss'), ) ); - $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response', 'editor'), false, 1 ); + $scripts->add( 'autosave', "/wp-includes/js/autosave$suffix.js", array('schedule', 'wp-ajax-response'), false, 1 ); $scripts->add( 'heartbeat', "/wp-includes/js/heartbeat$suffix.js", array('jquery'), false, 1 ); did_action( 'init' ) && $scripts->localize( 'heartbeat', 'heartbeatSettings',