wp/wp-includes/js/heartbeat.js
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    32 	/**
    32 	/**
    33 	 * Constructs the Heartbeat API.
    33 	 * Constructs the Heartbeat API.
    34 	 *
    34 	 *
    35 	 * @since 3.6.0
    35 	 * @since 3.6.0
    36 	 *
    36 	 *
    37 	 * @returns {Object} An instance of the Heartbeat class.
    37 	 * @return {Object} An instance of the Heartbeat class.
    38 	 * @constructor
    38 	 * @constructor
    39 	 */
    39 	 */
    40 	var Heartbeat = function() {
    40 	var Heartbeat = function() {
    41 		var $document = $(document),
    41 		var $document = $(document),
    42 			settings = {
    42 			settings = {
    60 				queue: {},
    60 				queue: {},
    61 
    61 
    62 				// Connect interval (in seconds).
    62 				// Connect interval (in seconds).
    63 				mainInterval: 60,
    63 				mainInterval: 60,
    64 
    64 
    65 				// Used when the interval is set to 5 sec. temporarily.
    65 				// Used when the interval is set to 5 seconds temporarily.
    66 				tempInterval: 0,
    66 				tempInterval: 0,
    67 
    67 
    68 				// Used when the interval is reset.
    68 				// Used when the interval is reset.
    69 				originalInterval: 0,
    69 				originalInterval: 0,
    70 
    70 
    71 				// Used to limit the number of AJAX requests.
    71 				// Used to limit the number of Ajax requests.
    72 				minimalInterval: 0,
    72 				minimalInterval: 0,
    73 
    73 
    74 				// Used together with tempInterval.
    74 				// Used together with tempInterval.
    75 				countdown: 0,
    75 				countdown: 0,
    76 
    76 
    87 				hasConnected: false,
    87 				hasConnected: false,
    88 
    88 
    89 				// Whether the current browser window is in focus and the user is active.
    89 				// Whether the current browser window is in focus and the user is active.
    90 				hasFocus: true,
    90 				hasFocus: true,
    91 
    91 
    92 				// Timestamp, last time the user was active. Checked every 30 sec.
    92 				// Timestamp, last time the user was active. Checked every 30 seconds.
    93 				userActivity: 0,
    93 				userActivity: 0,
    94 
    94 
    95 				// Flag whether events tracking user activity were set.
    95 				// Flag whether events tracking user activity were set.
    96 				userActivityEvents: false,
    96 				userActivityEvents: false,
    97 
    97 
   104 			};
   104 			};
   105 
   105 
   106 		/**
   106 		/**
   107 		 * Sets local variables and events, then starts the heartbeat.
   107 		 * Sets local variables and events, then starts the heartbeat.
   108 		 *
   108 		 *
   109 		 * @access private
       
   110 		 *
       
   111 		 * @since 3.8.0
   109 		 * @since 3.8.0
   112 		 *
   110 		 * @access private
   113 		 * @returns {void}
   111 		 *
       
   112 		 * @return {void}
   114 		 */
   113 		 */
   115 		function initialize() {
   114 		function initialize() {
   116 			var options, hidden, visibilityState, visibilitychange;
   115 			var options, hidden, visibilityState, visibilitychange;
   117 
   116 
   118 			if ( typeof window.pagenow === 'string' ) {
   117 			if ( typeof window.pagenow === 'string' ) {
   131 				if ( ! settings.url && options.ajaxurl ) {
   130 				if ( ! settings.url && options.ajaxurl ) {
   132 					settings.url = options.ajaxurl;
   131 					settings.url = options.ajaxurl;
   133 				}
   132 				}
   134 
   133 
   135 				/*
   134 				/*
   136 				 * The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec.
   135 				 * The interval can be from 15 to 120 seconds and can be set temporarily to 5 seconds.
   137 				 * It can be set in the initial options or changed later through JS and/or
   136 				 * It can be set in the initial options or changed later through JS and/or through PHP.
   138 				 * through PHP.
       
   139 				 */
   137 				 */
   140 				if ( options.interval ) {
   138 				if ( options.interval ) {
   141 					settings.mainInterval = options.interval;
   139 					settings.mainInterval = options.interval;
   142 
   140 
   143 					if ( settings.mainInterval < 15 ) {
   141 					if ( settings.mainInterval < 15 ) {
   146 						settings.mainInterval = 120;
   144 						settings.mainInterval = 120;
   147 					}
   145 					}
   148 				}
   146 				}
   149 
   147 
   150 				/*
   148 				/*
   151 				 * Used to limit the number of AJAX requests. Overrides all other intervals if
   149 				 * Used to limit the number of Ajax requests. Overrides all other intervals
   152 				 * they are shorter. Needed for some hosts that cannot handle frequent requests
   150 				 * if they are shorter. Needed for some hosts that cannot handle frequent requests
   153 				 * and the user may exceed the allocated server CPU time, etc. The minimal
   151 				 * and the user may exceed the allocated server CPU time, etc. The minimal interval
   154 				 * interval can be up to 600 sec. however setting it to longer than 120 sec.
   152 				 * can be up to 600 seconds, however setting it to longer than 120 seconds
   155 				 * will limit or disable some of the functionality (like post locks). Once set
   153 				 * will limit or disable some of the functionality (like post locks).
   156 				 * at initialization, minimalInterval cannot be changed/overridden.
   154 				 * Once set at initialization, minimalInterval cannot be changed/overridden.
   157 				 */
   155 				 */
   158 				if ( options.minimalInterval ) {
   156 				if ( options.minimalInterval ) {
   159 					options.minimalInterval = parseInt( options.minimalInterval, 10 );
   157 					options.minimalInterval = parseInt( options.minimalInterval, 10 );
   160 					settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0;
   158 					settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0;
   161 				}
   159 				}
   187 			 */
   185 			 */
   188 			if ( typeof document.hidden !== 'undefined' ) {
   186 			if ( typeof document.hidden !== 'undefined' ) {
   189 				hidden = 'hidden';
   187 				hidden = 'hidden';
   190 				visibilitychange = 'visibilitychange';
   188 				visibilitychange = 'visibilitychange';
   191 				visibilityState = 'visibilityState';
   189 				visibilityState = 'visibilityState';
   192 			} else if ( typeof document.msHidden !== 'undefined' ) { // IE10
   190 			} else if ( typeof document.msHidden !== 'undefined' ) { // IE10.
   193 				hidden = 'msHidden';
   191 				hidden = 'msHidden';
   194 				visibilitychange = 'msvisibilitychange';
   192 				visibilitychange = 'msvisibilitychange';
   195 				visibilityState = 'msVisibilityState';
   193 				visibilityState = 'msVisibilityState';
   196 			} else if ( typeof document.webkitHidden !== 'undefined' ) { // Android
   194 			} else if ( typeof document.webkitHidden !== 'undefined' ) { // Android.
   197 				hidden = 'webkitHidden';
   195 				hidden = 'webkitHidden';
   198 				visibilitychange = 'webkitvisibilitychange';
   196 				visibilitychange = 'webkitvisibilitychange';
   199 				visibilityState = 'webkitVisibilityState';
   197 				visibilityState = 'webkitVisibilityState';
   200 			}
   198 			}
   201 
   199 
   243 		}
   241 		}
   244 
   242 
   245 		/**
   243 		/**
   246 		 * Returns the current time according to the browser.
   244 		 * Returns the current time according to the browser.
   247 		 *
   245 		 *
   248 		 * @access private
   246 		 * @since 3.6.0
   249 		 *
   247 		 * @access private
   250 		 * @since 3.6.0
   248 		 *
   251 		 *
   249 		 * @return {number} Returns the current time.
   252 		 * @returns {number} Returns the current time.
       
   253 		 */
   250 		 */
   254 		function time() {
   251 		function time() {
   255 			return (new Date()).getTime();
   252 			return (new Date()).getTime();
   256 		}
   253 		}
   257 
   254 
   258 		/**
   255 		/**
   259 		 * Checks if the iframe is from the same origin.
   256 		 * Checks if the iframe is from the same origin.
   260 		 *
   257 		 *
   261 		 * @access private
   258 		 * @since 3.6.0
   262 		 *
   259 		 * @access private
   263 		 * @since 3.6.0
   260 		 *
   264 		 *
   261 		 * @return {boolean} Returns whether or not the iframe is from the same origin.
   265 		 * @returns {boolean} Returns whether or not the iframe is from the same origin.
       
   266 		 */
   262 		 */
   267 		function isLocalFrame( frame ) {
   263 		function isLocalFrame( frame ) {
   268 			var origin, src = frame.src;
   264 			var origin, src = frame.src;
   269 
   265 
   270 			/*
   266 			/*
   289 		}
   285 		}
   290 
   286 
   291 		/**
   287 		/**
   292 		 * Checks if the document's focus has changed.
   288 		 * Checks if the document's focus has changed.
   293 		 *
   289 		 *
   294 		 * @access private
       
   295 		 *
       
   296 		 * @since 4.1.0
   290 		 * @since 4.1.0
   297 		 *
   291 		 * @access private
   298 		 * @returns {void}
   292 		 *
       
   293 		 * @return {void}
   299 		 */
   294 		 */
   300 		function checkFocus() {
   295 		function checkFocus() {
   301 			if ( settings.hasFocus && ! document.hasFocus() ) {
   296 			if ( settings.hasFocus && ! document.hasFocus() ) {
   302 				blurred();
   297 				blurred();
   303 			} else if ( ! settings.hasFocus && document.hasFocus() ) {
   298 			} else if ( ! settings.hasFocus && document.hasFocus() ) {
   306 		}
   301 		}
   307 
   302 
   308 		/**
   303 		/**
   309 		 * Sets error state and fires an event on XHR errors or timeout.
   304 		 * Sets error state and fires an event on XHR errors or timeout.
   310 		 *
   305 		 *
   311 		 * @access private
       
   312 		 *
       
   313 		 * @since 3.8.0
   306 		 * @since 3.8.0
       
   307 		 * @access private
   314 		 *
   308 		 *
   315 		 * @param {string} error  The error type passed from the XHR.
   309 		 * @param {string} error  The error type passed from the XHR.
   316 		 * @param {number} status The HTTP status code passed from jqXHR
   310 		 * @param {number} status The HTTP status code passed from jqXHR
   317 		 *                        (200, 404, 500, etc.).
   311 		 *                        (200, 404, 500, etc.).
   318 		 *
   312 		 *
   319 		 * @returns {void}
   313 		 * @return {void}
   320 		 */
   314 		 */
   321 		function setErrorState( error, status ) {
   315 		function setErrorState( error, status ) {
   322 			var trigger;
   316 			var trigger;
   323 
   317 
   324 			if ( error ) {
   318 			if ( error ) {
   325 				switch ( error ) {
   319 				switch ( error ) {
   326 					case 'abort':
   320 					case 'abort':
   327 						// Do nothing.
   321 						// Do nothing.
   328 						break;
   322 						break;
   329 					case 'timeout':
   323 					case 'timeout':
   330 						// No response for 30 sec.
   324 						// No response for 30 seconds.
   331 						trigger = true;
   325 						trigger = true;
   332 						break;
   326 						break;
   333 					case 'error':
   327 					case 'error':
   334 						if ( 503 === status && settings.hasConnected ) {
   328 						if ( 503 === status && settings.hasConnected ) {
   335 							trigger = true;
   329 							trigger = true;
   357 		}
   351 		}
   358 
   352 
   359 		/**
   353 		/**
   360 		 * Clears the error state and fires an event if there is a connection error.
   354 		 * Clears the error state and fires an event if there is a connection error.
   361 		 *
   355 		 *
   362 		 * @access private
       
   363 		 *
       
   364 		 * @since 3.8.0
   356 		 * @since 3.8.0
   365 		 *
   357 		 * @access private
   366 		 * @returns {void}
   358 		 *
       
   359 		 * @return {void}
   367 		 */
   360 		 */
   368 		function clearErrorState() {
   361 		function clearErrorState() {
   369 			// Has connected successfully.
   362 			// Has connected successfully.
   370 			settings.hasConnected = true;
   363 			settings.hasConnected = true;
   371 
   364 
   378 		}
   371 		}
   379 
   372 
   380 		/**
   373 		/**
   381 		 * Gathers the data and connects to the server.
   374 		 * Gathers the data and connects to the server.
   382 		 *
   375 		 *
   383 		 * @access private
   376 		 * @since 3.6.0
   384 		 *
   377 		 * @access private
   385 		 * @since 3.6.0
   378 		 *
   386 		 *
   379 		 * @return {void}
   387 		 * @returns {void}
       
   388 		 */
   380 		 */
   389 		function connect() {
   381 		function connect() {
   390 			var ajaxData, heartbeatData;
   382 			var ajaxData, heartbeatData;
   391 
   383 
   392 			// If the connection to the server is slower than the interval,
   384 			// If the connection to the server is slower than the interval,
   419 
   411 
   420 			settings.connecting = true;
   412 			settings.connecting = true;
   421 			settings.xhr = $.ajax({
   413 			settings.xhr = $.ajax({
   422 				url: settings.url,
   414 				url: settings.url,
   423 				type: 'post',
   415 				type: 'post',
   424 				timeout: 30000, // throw an error if not completed after 30 sec.
   416 				timeout: 30000, // Throw an error if not completed after 30 seconds.
   425 				data: ajaxData,
   417 				data: ajaxData,
   426 				dataType: 'json'
   418 				dataType: 'json'
   427 			}).always( function() {
   419 			}).always( function() {
   428 				settings.connecting = false;
   420 				settings.connecting = false;
   429 				scheduleNextTick();
   421 				scheduleNextTick();
   440 				if ( response.nonces_expired ) {
   432 				if ( response.nonces_expired ) {
   441 					$document.trigger( 'heartbeat-nonces-expired' );
   433 					$document.trigger( 'heartbeat-nonces-expired' );
   442 					wp.hooks.doAction( 'heartbeat.nonces-expired' );
   434 					wp.hooks.doAction( 'heartbeat.nonces-expired' );
   443 				}
   435 				}
   444 
   436 
   445 				// Change the interval from PHP
   437 				// Change the interval from PHP.
   446 				if ( response.heartbeat_interval ) {
   438 				if ( response.heartbeat_interval ) {
   447 					newInterval = response.heartbeat_interval;
   439 					newInterval = response.heartbeat_interval;
   448 					delete response.heartbeat_interval;
   440 					delete response.heartbeat_interval;
   449 				}
   441 				}
   450 
   442 
   462 				}
   454 				}
   463 
   455 
   464 				$document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] );
   456 				$document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] );
   465 				wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR );
   457 				wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR );
   466 
   458 
   467 				// Do this last. Can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast'.
   459 				// Do this last. Can trigger the next XHR if connection time > 5 seconds and newInterval == 'fast'.
   468 				if ( newInterval ) {
   460 				if ( newInterval ) {
   469 					interval( newInterval );
   461 					interval( newInterval );
   470 				}
   462 				}
   471 			}).fail( function( jqXHR, textStatus, error ) {
   463 			}).fail( function( jqXHR, textStatus, error ) {
   472 				setErrorState( textStatus || 'unknown', jqXHR.status );
   464 				setErrorState( textStatus || 'unknown', jqXHR.status );
   478 		/**
   470 		/**
   479 		 * Schedules the next connection.
   471 		 * Schedules the next connection.
   480 		 *
   472 		 *
   481 		 * Fires immediately if the connection time is longer than the interval.
   473 		 * Fires immediately if the connection time is longer than the interval.
   482 		 *
   474 		 *
   483 		 * @access private
       
   484 		 *
       
   485 		 * @since 3.8.0
   475 		 * @since 3.8.0
   486 		 *
   476 		 * @access private
   487 		 * @returns {void}
   477 		 *
       
   478 		 * @return {void}
   488 		 */
   479 		 */
   489 		function scheduleNextTick() {
   480 		function scheduleNextTick() {
   490 			var delta = time() - settings.lastTick,
   481 			var delta = time() - settings.lastTick,
   491 				interval = settings.mainInterval;
   482 				interval = settings.mainInterval;
   492 
   483 
   493 			if ( settings.suspend ) {
   484 			if ( settings.suspend ) {
   494 				return;
   485 				return;
   495 			}
   486 			}
   496 
   487 
   497 			if ( ! settings.hasFocus ) {
   488 			if ( ! settings.hasFocus ) {
   498 				interval = 120000; // 120 sec. Post locks expire after 150 sec.
   489 				interval = 120000; // 120 seconds. Post locks expire after 150 seconds.
   499 			} else if ( settings.countdown > 0 && settings.tempInterval ) {
   490 			} else if ( settings.countdown > 0 && settings.tempInterval ) {
   500 				interval = settings.tempInterval;
   491 				interval = settings.tempInterval;
   501 				settings.countdown--;
   492 				settings.countdown--;
   502 
   493 
   503 				if ( settings.countdown < 1 ) {
   494 				if ( settings.countdown < 1 ) {
   524 		}
   515 		}
   525 
   516 
   526 		/**
   517 		/**
   527 		 * Sets the internal state when the browser window becomes hidden or loses focus.
   518 		 * Sets the internal state when the browser window becomes hidden or loses focus.
   528 		 *
   519 		 *
   529 		 * @access private
   520 		 * @since 3.6.0
   530 		 *
   521 		 * @access private
   531 		 * @since 3.6.0
   522 		 *
   532 		 *
   523 		 * @return {void}
   533 		 * @returns {void}
       
   534 		 */
   524 		 */
   535 		function blurred() {
   525 		function blurred() {
   536 			settings.hasFocus = false;
   526 			settings.hasFocus = false;
   537 		}
   527 		}
   538 
   528 
   539 		/**
   529 		/**
   540 		 * Sets the internal state when the browser window becomes visible or is in focus.
   530 		 * Sets the internal state when the browser window becomes visible or is in focus.
   541 		 *
   531 		 *
   542 		 * @access private
   532 		 * @since 3.6.0
   543 		 *
   533 		 * @access private
   544 		 * @since 3.6.0
   534 		 *
   545 		 *
   535 		 * @return {void}
   546 		 * @returns {void}
       
   547 		 */
   536 		 */
   548 		function focused() {
   537 		function focused() {
   549 			settings.userActivity = time();
   538 			settings.userActivity = time();
   550 
   539 
   551 			// Resume if suspended
   540 			// Resume if suspended.
   552 			settings.suspend = false;
   541 			settings.suspend = false;
   553 
   542 
   554 			if ( ! settings.hasFocus ) {
   543 			if ( ! settings.hasFocus ) {
   555 				settings.hasFocus = true;
   544 				settings.hasFocus = true;
   556 				scheduleNextTick();
   545 				scheduleNextTick();
   558 		}
   547 		}
   559 
   548 
   560 		/**
   549 		/**
   561 		 * Runs when the user becomes active after a period of inactivity.
   550 		 * Runs when the user becomes active after a period of inactivity.
   562 		 *
   551 		 *
   563 		 * @access private
   552 		 * @since 3.6.0
   564 		 *
   553 		 * @access private
   565 		 * @since 3.6.0
   554 		 *
   566 		 *
   555 		 * @return {void}
   567 		 * @returns {void}
       
   568 		 */
   556 		 */
   569 		function userIsActive() {
   557 		function userIsActive() {
   570 			settings.userActivityEvents = false;
   558 			settings.userActivityEvents = false;
   571 			$document.off( '.wp-heartbeat-active' );
   559 			$document.off( '.wp-heartbeat-active' );
   572 
   560 
   580 		}
   568 		}
   581 
   569 
   582 		/**
   570 		/**
   583 		 * Checks for user activity.
   571 		 * Checks for user activity.
   584 		 *
   572 		 *
   585 		 * Runs every 30 sec. Sets 'hasFocus = true' if user is active and the window is
   573 		 * Runs every 30 seconds. Sets 'hasFocus = true' if user is active and the window
   586 		 * in the background. Sets 'hasFocus = false' if the user has been inactive
   574 		 * is in the background. Sets 'hasFocus = false' if the user has been inactive
   587 		 * (no mouse or keyboard activity) for 5 min. even when the window has focus.
   575 		 * (no mouse or keyboard activity) for 5 minutes even when the window has focus.
   588 		 *
       
   589 		 * @access private
       
   590 		 *
   576 		 *
   591 		 * @since 3.8.0
   577 		 * @since 3.8.0
   592 		 *
   578 		 * @access private
   593 		 * @returns {void}
   579 		 *
       
   580 		 * @return {void}
   594 		 */
   581 		 */
   595 		function checkUserActivity() {
   582 		function checkUserActivity() {
   596 			var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
   583 			var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
   597 
   584 
   598 			// Throttle down when no mouse or keyboard activity for 5 min.
   585 			// Throttle down when no mouse or keyboard activity for 5 minutes.
   599 			if ( lastActive > 300000 && settings.hasFocus ) {
   586 			if ( lastActive > 300000 && settings.hasFocus ) {
   600 				blurred();
   587 				blurred();
   601 			}
   588 			}
   602 
   589 
   603 			// Suspend after 10 min. of inactivity when suspending is enabled.
   590 			// Suspend after 10 minutes of inactivity when suspending is enabled.
   604 			// Always suspend after 60 min. of inactivity. This will release the post lock, etc.
   591 			// Always suspend after 60 minutes of inactivity. This will release the post lock, etc.
   605 			if ( ( settings.suspendEnabled && lastActive > 600000 ) || lastActive > 3600000 ) {
   592 			if ( ( settings.suspendEnabled && lastActive > 600000 ) || lastActive > 3600000 ) {
   606 				settings.suspend = true;
   593 				settings.suspend = true;
   607 			}
   594 			}
   608 
   595 
   609 			if ( ! settings.userActivityEvents ) {
   596 			if ( ! settings.userActivityEvents ) {
   630 		 * is active.
   617 		 * is active.
   631 		 *
   618 		 *
   632 		 * @since 3.6.0
   619 		 * @since 3.6.0
   633 		 * @memberOf wp.heartbeat.prototype
   620 		 * @memberOf wp.heartbeat.prototype
   634 		 *
   621 		 *
   635 		 * @returns {boolean} True if the window or the user is active.
   622 		 * @return {boolean} True if the window or the user is active.
   636 		 */
   623 		 */
   637 		function hasFocus() {
   624 		function hasFocus() {
   638 			return settings.hasFocus;
   625 			return settings.hasFocus;
   639 		}
   626 		}
   640 
   627 
   643 		 *
   630 		 *
   644 		 * @since 3.6.0
   631 		 * @since 3.6.0
   645 		 *
   632 		 *
   646 		 * @memberOf wp.heartbeat.prototype
   633 		 * @memberOf wp.heartbeat.prototype
   647 		 *
   634 		 *
   648 		 * @returns {boolean} True if a connection error was found.
   635 		 * @return {boolean} True if a connection error was found.
   649 		 */
   636 		 */
   650 		function hasConnectionError() {
   637 		function hasConnectionError() {
   651 			return settings.connectionError;
   638 			return settings.connectionError;
   652 		}
   639 		}
   653 
   640 
   659 		 *
   646 		 *
   660 		 * @since 3.8.0
   647 		 * @since 3.8.0
   661 		 *
   648 		 *
   662 		 * @memberOf wp.heartbeat.prototype
   649 		 * @memberOf wp.heartbeat.prototype
   663 		 *
   650 		 *
   664 		 * @returns {void}
   651 		 * @return {void}
   665 		 */
   652 		 */
   666 		function connectNow() {
   653 		function connectNow() {
   667 			settings.lastTick = 0;
   654 			settings.lastTick = 0;
   668 			scheduleNextTick();
   655 			scheduleNextTick();
   669 		}
   656 		}
   670 
   657 
   671 		/**
   658 		/**
   672 		 * Disables suspending.
   659 		 * Disables suspending.
   673 		 *
   660 		 *
   674 		 * Should be used only when Heartbeat is performing critical tasks like
   661 		 * Should be used only when Heartbeat is performing critical tasks like
   675 		 * autosave, post-locking, etc. Using this on many screens may overload the
   662 		 * autosave, post-locking, etc. Using this on many screens may overload
   676 		 * user's hosting account if several browser windows/tabs are left open for a
   663 		 * the user's hosting account if several browser windows/tabs are left open
   677 		 * long time.
   664 		 * for a long time.
   678 		 *
   665 		 *
   679 		 * @since 3.8.0
   666 		 * @since 3.8.0
   680 		 *
   667 		 *
   681 		 * @memberOf wp.heartbeat.prototype
   668 		 * @memberOf wp.heartbeat.prototype
   682 		 *
   669 		 *
   683 		 * @returns {void}
   670 		 * @return {void}
   684 		 */
   671 		 */
   685 		function disableSuspend() {
   672 		function disableSuspend() {
   686 			settings.suspendEnabled = false;
   673 			settings.suspendEnabled = false;
   687 		}
   674 		}
   688 
   675 
   689 		/**
   676 		/**
   690 		 * Gets/Sets the interval.
   677 		 * Gets/Sets the interval.
   691 		 *
   678 		 *
   692 		 * When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
   679 		 * When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
   693 		 * (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
   680 		 * (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
   694 		 * can be passed as second argument. If the window doesn't have focus, the
   681 		 * can be passed as second argument. If the window doesn't have focus,
   695 		 * interval slows down to 2 min.
   682 		 * the interval slows down to 2 minutes.
   696 		 *
   683 		 *
   697 		 * @since 3.6.0
   684 		 * @since 3.6.0
   698 		 *
   685 		 *
   699 		 * @memberOf wp.heartbeat.prototype
   686 		 * @memberOf wp.heartbeat.prototype
   700 		 *
   687 		 *
   701 		 * @param {string|number} speed Interval: 'fast' or 5, 15, 30, 60, 120. Fast
   688 		 * @param {string|number} speed Interval: 'fast' or 5, 15, 30, 60, 120.
   702 		 *                              equals 5.
   689 		 *                              Fast equals 5.
   703 		 * @param {string}        ticks Tells how many ticks before the interval reverts
   690 		 * @param {string}        ticks Tells how many ticks before the interval reverts
   704 		 *                              back. Used with speed = 'fast' or 5.
   691 		 *                              back. Used with speed = 'fast' or 5.
   705 		 *
   692 		 *
   706 		 * @returns {number} Current interval in seconds.
   693 		 * @return {number} Current interval in seconds.
   707 		 */
   694 		 */
   708 		function interval( speed, ticks ) {
   695 		function interval( speed, ticks ) {
   709 			var newInterval,
   696 			var newInterval,
   710 				oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
   697 				oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
   711 
   698 
   726 						break;
   713 						break;
   727 					case 120:
   714 					case 120:
   728 						newInterval = 120000;
   715 						newInterval = 120000;
   729 						break;
   716 						break;
   730 					case 'long-polling':
   717 					case 'long-polling':
   731 						// Allow long polling, (experimental)
   718 						// Allow long polling (experimental).
   732 						settings.mainInterval = 0;
   719 						settings.mainInterval = 0;
   733 						return 0;
   720 						return 0;
   734 					default:
   721 					default:
   735 						newInterval = settings.originalInterval;
   722 						newInterval = settings.originalInterval;
   736 				}
   723 				}
   749 					settings.countdown = 0;
   736 					settings.countdown = 0;
   750 					settings.tempInterval = 0;
   737 					settings.tempInterval = 0;
   751 					settings.mainInterval = newInterval;
   738 					settings.mainInterval = newInterval;
   752 				}
   739 				}
   753 
   740 
   754 				// Change the next connection time if new interval has been set.
   741 				/*
   755 				// Will connect immediately if the time since the last connection
   742 				 * Change the next connection time if new interval has been set.
   756 				// is greater than the new interval.
   743 				 * Will connect immediately if the time since the last connection
       
   744 				 * is greater than the new interval.
       
   745 				 */
   757 				if ( newInterval !== oldInterval ) {
   746 				if ( newInterval !== oldInterval ) {
   758 					scheduleNextTick();
   747 					scheduleNextTick();
   759 				}
   748 				}
   760 			}
   749 			}
   761 
   750 
   782 		 * @param {string}  handle      Unique handle for the data, used in PHP to
   771 		 * @param {string}  handle      Unique handle for the data, used in PHP to
   783 		 *                              receive the data.
   772 		 *                              receive the data.
   784 		 * @param {*}       data        The data to send.
   773 		 * @param {*}       data        The data to send.
   785 		 * @param {boolean} noOverwrite Whether to overwrite existing data in the queue.
   774 		 * @param {boolean} noOverwrite Whether to overwrite existing data in the queue.
   786 		 *
   775 		 *
   787 		 * @returns {boolean} True if the data was queued.
   776 		 * @return {boolean} True if the data was queued.
   788 		 */
   777 		 */
   789 		function enqueue( handle, data, noOverwrite ) {
   778 		function enqueue( handle, data, noOverwrite ) {
   790 			if ( handle ) {
   779 			if ( handle ) {
   791 				if ( noOverwrite && this.isQueued( handle ) ) {
   780 				if ( noOverwrite && this.isQueued( handle ) ) {
   792 					return false;
   781 					return false;
   803 		 *
   792 		 *
   804 		 * @since 3.6.0
   793 		 * @since 3.6.0
   805 		 *
   794 		 *
   806 		 * @param {string} handle The handle for the data.
   795 		 * @param {string} handle The handle for the data.
   807 		 *
   796 		 *
   808 		 * @returns {boolean} True if the data is queued with this handle.
   797 		 * @return {boolean} True if the data is queued with this handle.
   809 		 */
   798 		 */
   810 		function isQueued( handle ) {
   799 		function isQueued( handle ) {
   811 			if ( handle ) {
   800 			if ( handle ) {
   812 				return settings.queue.hasOwnProperty( handle );
   801 				return settings.queue.hasOwnProperty( handle );
   813 			}
   802 			}
   820 		 *
   809 		 *
   821 		 * @memberOf wp.heartbeat.prototype
   810 		 * @memberOf wp.heartbeat.prototype
   822 		 *
   811 		 *
   823 		 * @param {string} handle The handle for the data.
   812 		 * @param {string} handle The handle for the data.
   824 		 *
   813 		 *
   825 		 * @returns {void}
   814 		 * @return {void}
   826 		 */
   815 		 */
   827 		function dequeue( handle ) {
   816 		function dequeue( handle ) {
   828 			if ( handle ) {
   817 			if ( handle ) {
   829 				delete settings.queue[handle];
   818 				delete settings.queue[handle];
   830 			}
   819 			}
   837 		 *
   826 		 *
   838 		 * @memberOf wp.heartbeat.prototype
   827 		 * @memberOf wp.heartbeat.prototype
   839 		 *
   828 		 *
   840 		 * @param {string} handle The handle for the data.
   829 		 * @param {string} handle The handle for the data.
   841 		 *
   830 		 *
   842 		 * @returns {*} The data or undefined.
   831 		 * @return {*} The data or undefined.
   843 		 */
   832 		 */
   844 		function getQueuedItem( handle ) {
   833 		function getQueuedItem( handle ) {
   845 			if ( handle ) {
   834 			if ( handle ) {
   846 				return this.isQueued( handle ) ? settings.queue[handle] : undefined;
   835 				return this.isQueued( handle ) ? settings.queue[handle] : undefined;
   847 			}
   836 			}