diff --git a/src/wp-admin/includes/misc.php b/src/wp-admin/includes/misc.php index 2a8eba2d63..8b0549dea6 100644 --- a/src/wp-admin/includes/misc.php +++ b/src/wp-admin/includes/misc.php @@ -739,3 +739,19 @@ function wp_refresh_post_nonces( $response, $data, $screen_id ) { return $response; } add_filter( 'heartbeat_received', 'wp_refresh_post_nonces', 10, 3 ); + +/** + * Disable suspending of Heartbeat on the Add/Edit Post screens + * + * @since 3.8 + */ +function wp_disable_heartbeat_suspend( $settings ) { + global $pagenow; + + if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) { + $settings['suspend'] = 'disable'; + } + + return $settings; +} +add_filter( 'heartbeat_settings', 'wp_disable_heartbeat_suspend' ); diff --git a/src/wp-includes/js/heartbeat.js b/src/wp-includes/js/heartbeat.js index 3f5e64adee..bc0faa4b5a 100644 --- a/src/wp-includes/js/heartbeat.js +++ b/src/wp-includes/js/heartbeat.js @@ -34,8 +34,11 @@ var Heartbeat = function() { var $document = $(document), settings = { - // Used to stop the "beat" - isRunning: true, + // Suspend/resume + suspend: false, + + // Whether suspending is enabled + suspendEnabled: true, // Current screen id, defaults to the JS global 'pagenow' when present (in the admin) or 'front' screenId: '', @@ -128,6 +131,10 @@ if ( ! settings.screenId ) { settings.screenId = options.screenId || 'front'; } + + if ( options.suspend === 'disable' ) { + settings.suspendEnabled = false; + } } // Convert to milliseconds @@ -145,7 +152,12 @@ focused(); }).on( 'unload.wp-heartbeat', function() { // Don't connect any more - settings.isRunning = false; + settings.suspend = true; + + // Abort the last request if not completed + if ( settings.xhr && settings.xhr.readyState !== 4 ) { + settings.xhr.abort(); + } }); // Check for user activity every 30 seconds. @@ -274,7 +286,7 @@ // If the connection to the server is slower than the interval, // heartbeat connects as soon as the previous connection's response is received. - if ( settings.connecting ) { + if ( settings.connecting || settings.suspend ) { return; } @@ -351,7 +363,7 @@ var delta = time() - settings.lastTick, interval = settings.mainInterval; - if ( ! settings.isRunning ) { + if ( settings.suspend ) { return; } @@ -403,6 +415,9 @@ clearFocusTimers(); settings.userActivity = time(); + // Resume if suspended + settings.suspend = false; + if ( ! settings.hasFocus ) { settings.hasFocus = true; scheduleNextTick(); @@ -513,6 +528,11 @@ blurred(); } + if ( settings.suspendEnabled && lastActive > 1200000 ) { + // Suspend after 20 min. of inactivity + settings.suspend = true; + } + if ( ! settings.userActivityEvents ) { $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); @@ -561,6 +581,19 @@ scheduleNextTick(); } + /** + * Disable suspending + * + * Should be used only when Heartbeat is performing critical tasks like autosave, post-locking, etc. + * Using this on many screens may overload the user's hosting account if several + * browser windows/tabs are left open for a long time. + * + * @return void + */ + function disableSuspend() { + settings.suspendEnabled = false; + } + /** * Get/Set the interval * @@ -691,6 +724,7 @@ return { hasFocus: hasFocus, connectNow: connectNow, + disableSuspend: disableSuspend, setInterval: setInterval, hasConnectionError: hasConnectionError, enqueue: enqueue,