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 /* |
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; |
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(); |
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 ) { |
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 |
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; |