<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[30293] trunk/src/wp-includes/js/heartbeat.js: Heartbeat:</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/30293">30293</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/30293","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>azaozz</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2014-11-10 01:46:04 +0000 (Mon, 10 Nov 2014)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Heartbeat:
- Use the page visibility API (when available) and document.hasFocus() instead of window.onfocus/onblur. Improves speeding up/slowing down the interval and works for iframes by default.
- Add a setting for minimal interval. Maximum value is 10 min. This overrides all other intervals and cannot be changed after setting it at initialization. Can be used to reduce the frequency of requests on hosts that have low limits for used CPU time, etc.
- Extend the setting of interval to support 120 sec. (60 sec, is still the default).
- Always suspend after one hour of keyboard/mouse/touch inactivity.
Fixes <a href="https://core.trac.wordpress.org/ticket/29779">#29779</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesjsheartbeatjs">trunk/src/wp-includes/js/heartbeat.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesjsheartbeatjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/heartbeat.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/heartbeat.js     2014-11-09 12:03:31 UTC (rev 30292)
+++ trunk/src/wp-includes/js/heartbeat.js       2014-11-10 01:46:04 UTC (rev 30293)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -57,6 +57,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // Used when the interval is reset
</span><span class="cx" style="display: block; padding: 0 10px">                                originalInterval: 0,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // Used to limit the number of AJAX requests.
+                               minimalInterval: 0,
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // Used together with tempInterval
</span><span class="cx" style="display: block; padding: 0 10px">                                countdown: 0,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,10 +84,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // Flags whether events tracking user activity were set
</span><span class="cx" style="display: block; padding: 0 10px">                                userActivityEvents: false,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // References to various timeouts
-                               beatTimer: 0,
-                               winBlurTimer: 0,
-                               frameBlurTimer: 0
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         checkFocusTimer: 0,
+                               beatTimer: 0
</ins><span class="cx" style="display: block; padding: 0 10px">                         };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -95,6 +96,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * @return void
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                function initialize() {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        var options, hidden, visibilityState, visibilitychange;
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( typeof window.pagenow === 'string' ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                settings.screenId = window.pagenow;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -105,24 +108,39 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Pull in options passed from PHP
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( typeof window.heartbeatSettings === 'object' ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                var options = window.heartbeatSettings;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         options = window.heartbeatSettings;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // The XHR URL can be passed as option when window.ajaxurl is not set
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( ! settings.url && options.ajaxurl ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        settings.url = options.ajaxurl;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // The interval can be from 15 to 60 sec. and can be set temporarily to 5 sec.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         // The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec.
+                               // It can be set in the initial options or changed later from JS and/or from PHP.
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( options.interval ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        settings.mainInterval = options.interval;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( settings.mainInterval < 15 ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                settings.mainInterval = 15;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        } else if ( settings.mainInterval > 60 ) {
-                                               settings.mainInterval = 60;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 } else if ( settings.mainInterval > 120 ) {
+                                               settings.mainInterval = 120;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // Used to limit the number of AJAX requests. Overrides all other intervals if they are shorter.
+                               // Needed for some hosts that cannot handle frequent requests and the user may exceed the allocated server CPU time, etc.
+                               // The minimal interval can be up to 600 sec. however setting it to longer than 120 sec. will limit or disable
+                               // some of the functionality (like post locks).
+                               // Once set at initialization, minimalInterval cannot be changed/overriden.
+                               if ( options.minimalInterval ) {
+                                       options.minimalInterval = parseInt( options.minimalInterval, 10 );
+                                       settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0;
+                               }
+
+                               if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) {
+                                       settings.mainInterval = settings.minimalInterval;
+                               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 'screenId' can be added from settings on the front-end where the JS global 'pagenow' is not set
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( ! settings.screenId ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        settings.screenId = options.screenId || 'front';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -137,16 +155,47 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        settings.mainInterval = settings.mainInterval * 1000;
</span><span class="cx" style="display: block; padding: 0 10px">                        settings.originalInterval = settings.mainInterval;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Set focus/blur events on the window
-                       $(window).on( 'blur.wp-heartbeat-focus', function() {
-                               setFrameFocusEvents();
-                               // We don't know why the 'blur' was fired. Either the user clicked in an iframe or outside the browser.
-                               // Running blurred() after some timeout lets us cancel it if the user clicked in an iframe.
-                               settings.winBlurTimer = window.setTimeout( function(){ blurred(); }, 500 );
-                       }).on( 'focus.wp-heartbeat-focus', function() {
-                               removeFrameFocusEvents();
-                               focused();
-                       }).on( 'unload.wp-heartbeat', function() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Switch the interval to 120 sec. by using the Page Visibility API.
+                       // If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the interval
+                       // will be increased to 120 sec. after 5 min. of mouse and keyboard inactivity.
+                       if ( typeof document.hidden !== 'undefined' ) {
+                               hidden = 'hidden';
+                               visibilitychange = 'visibilitychange';
+                               visibilityState = 'visibilityState';
+                       } else if ( typeof document.msHidden !== 'undefined' ) { // IE10
+                               hidden = 'msHidden';
+                               visibilitychange = 'msvisibilitychange';
+                               visibilityState = 'msVisibilityState';
+                       } else if ( typeof document.webkitHidden !== 'undefined' ) { // Android
+                               hidden = 'webkitHidden';
+                               visibilitychange = 'webkitvisibilitychange';
+                               visibilityState = 'webkitVisibilityState';
+                       }
+
+                       if ( hidden ) {
+                               if ( document[hidden] ) {
+                                       settings.hasFocus = false;
+                               }
+
+                               $document.on( visibilitychange + '.wp-heartbeat', function() {
+                                       if ( document[visibilityState] === 'hidden' ) {
+                                               blurred();
+                                               window.clearInterval( settings.checkFocusTimer );
+                                       } else {
+                                               focused();
+                                               if ( document.hasFocus ) {
+                                                       settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
+                                               }
+                                       }
+                               });
+                       }
+
+                       // Use document.hasFocus() if available.
+                       if ( document.hasFocus ) {
+                               settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
+                       }
+
+                       $(window).on( 'unload.wp-heartbeat', function() {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // Don't connect any more
</span><span class="cx" style="display: block; padding: 0 10px">                                settings.suspend = true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -157,7 +206,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Check for user activity every 30 seconds.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        window.setInterval( function(){ checkUserActivity(); }, 30000 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 window.setInterval( checkUserActivity, 30000 );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Start one tick after DOM ready
</span><span class="cx" style="display: block; padding: 0 10px">                        $document.ready( function() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -207,6 +256,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 * Check if the document's focus has changed
+                *
+                * @access private
+                *
+                * @return void
+                */
+               function checkFocus() {
+                       if ( settings.hasFocus && ! document.hasFocus() ) {
+                               blurred();
+                       } else if ( ! settings.hasFocus && document.hasFocus() ) {
+                               focused();
+                       }
+               }
+
+               /**
</ins><span class="cx" style="display: block; padding: 0 10px">                  * Set error state and fire an event on XHR errors or timeout
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @access private
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -374,12 +438,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if ( settings.minimalInterval && interval < settings.minimalInterval ) {
+                               interval = settings.minimalInterval;
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         window.clearTimeout( settings.beatTimer );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( delta < interval ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                settings.beatTimer = window.setTimeout(
</span><span class="cx" style="display: block; padding: 0 10px">                                        function() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        connect();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         connect();
</ins><span class="cx" style="display: block; padding: 0 10px">                                         },
</span><span class="cx" style="display: block; padding: 0 10px">                                        interval - delta
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -389,26 +457,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * Set the internal state when the browser window looses focus
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * Set the internal state when the browser window becomes hidden or loses focus
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @access private
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @return void
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                function blurred() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        clearFocusTimers();
</del><span class="cx" style="display: block; padding: 0 10px">                         settings.hasFocus = false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * Set the internal state when the browser window is focused
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * Set the internal state when the browser window becomes visible or is in focus
</ins><span class="cx" style="display: block; padding: 0 10px">                  *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @access private
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @return void
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                function focused() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        clearFocusTimers();
</del><span class="cx" style="display: block; padding: 0 10px">                         settings.userActivity = time();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Resume if suspended
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -421,68 +487,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * Add focus/blur events to all local iframes
-                *
-                * Used to detect when focus is moved from the main window to an iframe
-                *
-                * @access private
-                *
-                * @return void
-                */
-               function setFrameFocusEvents() {
-                       $('iframe').each( function( i, frame ) {
-                               if ( ! isLocalFrame( frame ) ) {
-                                       return;
-                               }
-
-                               if ( $.data( frame, 'wp-heartbeat-focus' ) ) {
-                                       return;
-                               }
-
-                               $.data( frame, 'wp-heartbeat-focus', 1 );
-
-                               $( frame.contentWindow ).on( 'focus.wp-heartbeat-focus', function() {
-                                       focused();
-                               }).on('blur.wp-heartbeat-focus', function() {
-                                       setFrameFocusEvents();
-                                       // We don't know why 'blur' was fired. Either the user clicked in the main window or outside the browser.
-                                       // Running blurred() after some timeout lets us cancel it if the user clicked in the main window.
-                                       settings.frameBlurTimer = window.setTimeout( function(){ blurred(); }, 500 );
-                               });
-                       });
-               }
-
-               /**
-                * Remove the focus/blur events to all local iframes
-                *
-                * @access private
-                *
-                * @return void
-                */
-               function removeFrameFocusEvents() {
-                       $('iframe').each( function( i, frame ) {
-                               if ( ! isLocalFrame( frame ) ) {
-                                       return;
-                               }
-
-                               $.removeData( frame, 'wp-heartbeat-focus' );
-                               $( frame.contentWindow ).off( '.wp-heartbeat-focus' );
-                       });
-               }
-
-               /**
-                * Clear the reset timers for focus/blur events on the window and iframes
-                *
-                * @access private
-                *
-                * @return void
-                */
-               function clearFocusTimers() {
-                       window.clearTimeout( settings.winBlurTimer );
-                       window.clearTimeout( settings.frameBlurTimer );
-               }
-
-               /**
</del><span class="cx" style="display: block; padding: 0 10px">                  * Runs when the user becomes active after a period of inactivity
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @access private
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -494,11 +498,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $document.off( '.wp-heartbeat-active' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $('iframe').each( function( i, frame ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( ! isLocalFrame( frame ) ) {
-                                       return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( isLocalFrame( frame ) ) {
+                                       $( frame.contentWindow ).off( '.wp-heartbeat-active' );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                               $( frame.contentWindow ).off( '.wp-heartbeat-active' );
</del><span class="cx" style="display: block; padding: 0 10px">                         });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        focused();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -519,25 +521,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">                function checkUserActivity() {
</span><span class="cx" style="display: block; padding: 0 10px">                        var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        // Throttle down when no mouse or keyboard activity for 5 min.
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( lastActive > 300000 && settings.hasFocus ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // Throttle down when no mouse or keyboard activity for 5 min
</del><span class="cx" style="display: block; padding: 0 10px">                                 blurred();
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( settings.suspendEnabled && lastActive > 1200000 ) {
-                               // Suspend after 20 min. of inactivity
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Suspend after 10 min. of inactivity when suspending is enabled.
+                       // Always suspend after 60 min. of inactivity. This will release the post lock, etc.
+                       if ( ( settings.suspendEnabled && lastActive > 600000 ) || lastActive > 3600000 ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 settings.suspend = true;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! settings.userActivityEvents ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
+                                       userIsActive();
+                               });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $('iframe').each( function( i, frame ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ( ! isLocalFrame( frame ) ) {
-                                               return;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ( isLocalFrame( frame ) ) {
+                                               $( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
+                                                       userIsActive();
+                                               });
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                                       $( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } );
</del><span class="cx" style="display: block; padding: 0 10px">                                 });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                settings.userActivityEvents = true;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -597,7 +602,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * In this case the number of 'ticks' can be passed as second argument.
</span><span class="cx" style="display: block; padding: 0 10px">                 * If the window doesn't have focus, the interval slows down to 2 min.
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param mixed speed Interval: 'fast' or 5, 15, 30, 60
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param mixed speed Interval: 'fast' or 5, 15, 30, 60, 120
</ins><span class="cx" style="display: block; padding: 0 10px">                  * @param string ticks Used with speed = 'fast' or 5, how many ticks before the interval reverts back
</span><span class="cx" style="display: block; padding: 0 10px">                 * @return int Current interval in seconds
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -620,6 +625,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        case 60:
</span><span class="cx" style="display: block; padding: 0 10px">                                                newInterval = 60000;
</span><span class="cx" style="display: block; padding: 0 10px">                                                break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        case 120:
+                                               newInterval = 120000;
+                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         case 'long-polling':
</span><span class="cx" style="display: block; padding: 0 10px">                                                // Allow long polling, (experimental)
</span><span class="cx" style="display: block; padding: 0 10px">                                                settings.mainInterval = 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -628,6 +636,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                newInterval = settings.originalInterval;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                if ( settings.minimalInterval && newInterval < settings.minimalInterval ) {
+                                       newInterval = settings.minimalInterval;
+                               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( 5000 === newInterval ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        ticks = parseInt( ticks, 10 ) || 30;
</span><span class="cx" style="display: block; padding: 0 10px">                                        ticks = ticks < 1 || ticks > 30 ? 30 : ticks;
</span></span></pre>
</div>
</div>

</body>
</html>