22 * - heartbeat-connection-lost |
22 * - heartbeat-connection-lost |
23 * - heartbeat-connection-restored |
23 * - heartbeat-connection-restored |
24 * - heartbeat-nonces-expired |
24 * - heartbeat-nonces-expired |
25 * |
25 * |
26 * @since 3.6.0 |
26 * @since 3.6.0 |
|
27 * @output wp-includes/js/heartbeat.js |
27 */ |
28 */ |
28 |
29 |
29 ( function( $, window, undefined ) { |
30 ( function( $, window, undefined ) { |
|
31 |
|
32 /** |
|
33 * Constructs the Heartbeat API. |
|
34 * |
|
35 * @since 3.6.0 |
|
36 * |
|
37 * @returns {Object} An instance of the Heartbeat class. |
|
38 * @constructor |
|
39 */ |
30 var Heartbeat = function() { |
40 var Heartbeat = function() { |
31 var $document = $(document), |
41 var $document = $(document), |
32 settings = { |
42 settings = { |
33 // Suspend/resume |
43 // Suspend/resume. |
34 suspend: false, |
44 suspend: false, |
35 |
45 |
36 // Whether suspending is enabled |
46 // Whether suspending is enabled. |
37 suspendEnabled: true, |
47 suspendEnabled: true, |
38 |
48 |
39 // Current screen id, defaults to the JS global 'pagenow' when present (in the admin) or 'front' |
49 // Current screen id, defaults to the JS global 'pagenow' when present |
|
50 // (in the admin) or 'front'. |
40 screenId: '', |
51 screenId: '', |
41 |
52 |
42 // XHR request URL, defaults to the JS global 'ajaxurl' when present |
53 // XHR request URL, defaults to the JS global 'ajaxurl' when present. |
43 url: '', |
54 url: '', |
44 |
55 |
45 // Timestamp, start of the last connection request |
56 // Timestamp, start of the last connection request. |
46 lastTick: 0, |
57 lastTick: 0, |
47 |
58 |
48 // Container for the enqueued items |
59 // Container for the enqueued items. |
49 queue: {}, |
60 queue: {}, |
50 |
61 |
51 // Connect interval (in seconds) |
62 // Connect interval (in seconds). |
52 mainInterval: 60, |
63 mainInterval: 60, |
53 |
64 |
54 // Used when the interval is set to 5 sec. temporarily |
65 // Used when the interval is set to 5 sec. temporarily. |
55 tempInterval: 0, |
66 tempInterval: 0, |
56 |
67 |
57 // Used when the interval is reset |
68 // Used when the interval is reset. |
58 originalInterval: 0, |
69 originalInterval: 0, |
59 |
70 |
60 // Used to limit the number of AJAX requests. |
71 // Used to limit the number of AJAX requests. |
61 minimalInterval: 0, |
72 minimalInterval: 0, |
62 |
73 |
63 // Used together with tempInterval |
74 // Used together with tempInterval. |
64 countdown: 0, |
75 countdown: 0, |
65 |
76 |
66 // Whether a connection is currently in progress |
77 // Whether a connection is currently in progress. |
67 connecting: false, |
78 connecting: false, |
68 |
79 |
69 // Whether a connection error occurred |
80 // Whether a connection error occurred. |
70 connectionError: false, |
81 connectionError: false, |
71 |
82 |
72 // Used to track non-critical errors |
83 // Used to track non-critical errors. |
73 errorcount: 0, |
84 errorcount: 0, |
74 |
85 |
75 // Whether at least one connection has completed successfully |
86 // Whether at least one connection has been completed successfully. |
76 hasConnected: false, |
87 hasConnected: false, |
77 |
88 |
78 // 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. |
79 hasFocus: true, |
90 hasFocus: true, |
80 |
91 |
81 // Timestamp, last time the user was active. Checked every 30 sec. |
92 // Timestamp, last time the user was active. Checked every 30 sec. |
82 userActivity: 0, |
93 userActivity: 0, |
83 |
94 |
84 // Flags whether events tracking user activity were set |
95 // Flag whether events tracking user activity were set. |
85 userActivityEvents: false, |
96 userActivityEvents: false, |
86 |
97 |
|
98 // Timer that keeps track of how long a user has focus. |
87 checkFocusTimer: 0, |
99 checkFocusTimer: 0, |
|
100 |
|
101 // Timer that keeps track of how long needs to be waited before connecting to |
|
102 // the server again. |
88 beatTimer: 0 |
103 beatTimer: 0 |
89 }; |
104 }; |
90 |
105 |
91 /** |
106 /** |
92 * Set local vars and events, then start |
107 * Sets local variables and events, then starts the heartbeat. |
93 * |
108 * |
94 * @access private |
109 * @access private |
95 * |
110 * |
96 * @return void |
111 * @since 3.8.0 |
|
112 * |
|
113 * @returns {void} |
97 */ |
114 */ |
98 function initialize() { |
115 function initialize() { |
99 var options, hidden, visibilityState, visibilitychange; |
116 var options, hidden, visibilityState, visibilitychange; |
100 |
117 |
101 if ( typeof window.pagenow === 'string' ) { |
118 if ( typeof window.pagenow === 'string' ) { |
104 |
121 |
105 if ( typeof window.ajaxurl === 'string' ) { |
122 if ( typeof window.ajaxurl === 'string' ) { |
106 settings.url = window.ajaxurl; |
123 settings.url = window.ajaxurl; |
107 } |
124 } |
108 |
125 |
109 // Pull in options passed from PHP |
126 // Pull in options passed from PHP. |
110 if ( typeof window.heartbeatSettings === 'object' ) { |
127 if ( typeof window.heartbeatSettings === 'object' ) { |
111 options = window.heartbeatSettings; |
128 options = window.heartbeatSettings; |
112 |
129 |
113 // The XHR URL can be passed as option when window.ajaxurl is not set |
130 // The XHR URL can be passed as option when window.ajaxurl is not set. |
114 if ( ! settings.url && options.ajaxurl ) { |
131 if ( ! settings.url && options.ajaxurl ) { |
115 settings.url = options.ajaxurl; |
132 settings.url = options.ajaxurl; |
116 } |
133 } |
117 |
134 |
118 // The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec. |
135 /* |
119 // It can be set in the initial options or changed later from JS and/or from PHP. |
136 * The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec. |
|
137 * It can be set in the initial options or changed later through JS and/or |
|
138 * through PHP. |
|
139 */ |
120 if ( options.interval ) { |
140 if ( options.interval ) { |
121 settings.mainInterval = options.interval; |
141 settings.mainInterval = options.interval; |
122 |
142 |
123 if ( settings.mainInterval < 15 ) { |
143 if ( settings.mainInterval < 15 ) { |
124 settings.mainInterval = 15; |
144 settings.mainInterval = 15; |
125 } else if ( settings.mainInterval > 120 ) { |
145 } else if ( settings.mainInterval > 120 ) { |
126 settings.mainInterval = 120; |
146 settings.mainInterval = 120; |
127 } |
147 } |
128 } |
148 } |
129 |
149 |
130 // Used to limit the number of AJAX requests. Overrides all other intervals if they are shorter. |
150 /* |
131 // Needed for some hosts that cannot handle frequent requests and the user may exceed the allocated server CPU time, etc. |
151 * Used to limit the number of AJAX requests. Overrides all other intervals if |
132 // The minimal interval can be up to 600 sec. however setting it to longer than 120 sec. will limit or disable |
152 * they are shorter. Needed for some hosts that cannot handle frequent requests |
133 // some of the functionality (like post locks). |
153 * and the user may exceed the allocated server CPU time, etc. The minimal |
134 // Once set at initialization, minimalInterval cannot be changed/overridden. |
154 * interval can be up to 600 sec. however setting it to longer than 120 sec. |
|
155 * will limit or disable some of the functionality (like post locks). Once set |
|
156 * at initialization, minimalInterval cannot be changed/overridden. |
|
157 */ |
135 if ( options.minimalInterval ) { |
158 if ( options.minimalInterval ) { |
136 options.minimalInterval = parseInt( options.minimalInterval, 10 ); |
159 options.minimalInterval = parseInt( options.minimalInterval, 10 ); |
137 settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0; |
160 settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0; |
138 } |
161 } |
139 |
162 |
140 if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) { |
163 if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) { |
141 settings.mainInterval = settings.minimalInterval; |
164 settings.mainInterval = settings.minimalInterval; |
142 } |
165 } |
143 |
166 |
144 // 'screenId' can be added from settings on the front end where the JS global 'pagenow' is not set |
167 // 'screenId' can be added from settings on the front end where the JS global |
|
168 // 'pagenow' is not set. |
145 if ( ! settings.screenId ) { |
169 if ( ! settings.screenId ) { |
146 settings.screenId = options.screenId || 'front'; |
170 settings.screenId = options.screenId || 'front'; |
147 } |
171 } |
148 |
172 |
149 if ( options.suspension === 'disable' ) { |
173 if ( options.suspension === 'disable' ) { |
150 settings.suspendEnabled = false; |
174 settings.suspendEnabled = false; |
151 } |
175 } |
152 } |
176 } |
153 |
177 |
154 // Convert to milliseconds |
178 // Convert to milliseconds. |
155 settings.mainInterval = settings.mainInterval * 1000; |
179 settings.mainInterval = settings.mainInterval * 1000; |
156 settings.originalInterval = settings.mainInterval; |
180 settings.originalInterval = settings.mainInterval; |
157 |
181 |
158 // Switch the interval to 120 sec. by using the Page Visibility API. |
182 /* |
159 // If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the interval |
183 * Switch the interval to 120 seconds by using the Page Visibility API. |
160 // will be increased to 120 sec. after 5 min. of mouse and keyboard inactivity. |
184 * If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the |
|
185 * interval will be increased to 120 seconds after 5 minutes of mouse and keyboard |
|
186 * inactivity. |
|
187 */ |
161 if ( typeof document.hidden !== 'undefined' ) { |
188 if ( typeof document.hidden !== 'undefined' ) { |
162 hidden = 'hidden'; |
189 hidden = 'hidden'; |
163 visibilitychange = 'visibilitychange'; |
190 visibilitychange = 'visibilitychange'; |
164 visibilityState = 'visibilityState'; |
191 visibilityState = 'visibilityState'; |
165 } else if ( typeof document.msHidden !== 'undefined' ) { // IE10 |
192 } else if ( typeof document.msHidden !== 'undefined' ) { // IE10 |
194 if ( document.hasFocus ) { |
221 if ( document.hasFocus ) { |
195 settings.checkFocusTimer = window.setInterval( checkFocus, 10000 ); |
222 settings.checkFocusTimer = window.setInterval( checkFocus, 10000 ); |
196 } |
223 } |
197 |
224 |
198 $(window).on( 'unload.wp-heartbeat', function() { |
225 $(window).on( 'unload.wp-heartbeat', function() { |
199 // Don't connect any more |
226 // Don't connect anymore. |
200 settings.suspend = true; |
227 settings.suspend = true; |
201 |
228 |
202 // Abort the last request if not completed |
229 // Abort the last request if not completed. |
203 if ( settings.xhr && settings.xhr.readyState !== 4 ) { |
230 if ( settings.xhr && settings.xhr.readyState !== 4 ) { |
204 settings.xhr.abort(); |
231 settings.xhr.abort(); |
205 } |
232 } |
206 }); |
233 }); |
207 |
234 |
208 // Check for user activity every 30 seconds. |
235 // Check for user activity every 30 seconds. |
209 window.setInterval( checkUserActivity, 30000 ); |
236 window.setInterval( checkUserActivity, 30000 ); |
210 |
237 |
211 // Start one tick after DOM ready |
238 // Start one tick after DOM ready. |
212 $document.ready( function() { |
239 $document.ready( function() { |
213 settings.lastTick = time(); |
240 settings.lastTick = time(); |
214 scheduleNextTick(); |
241 scheduleNextTick(); |
215 }); |
242 }); |
216 } |
243 } |
217 |
244 |
218 /** |
245 /** |
219 * Return the current time according to the browser |
246 * Returns the current time according to the browser. |
220 * |
247 * |
221 * @access private |
248 * @access private |
222 * |
249 * |
223 * @return int |
250 * @since 3.6.0 |
|
251 * |
|
252 * @returns {number} Returns the current time. |
224 */ |
253 */ |
225 function time() { |
254 function time() { |
226 return (new Date()).getTime(); |
255 return (new Date()).getTime(); |
227 } |
256 } |
228 |
257 |
229 /** |
258 /** |
230 * Check if the iframe is from the same origin |
259 * Checks if the iframe is from the same origin. |
231 * |
260 * |
232 * @access private |
261 * @access private |
233 * |
262 * |
234 * @return bool |
263 * @since 3.6.0 |
|
264 * |
|
265 * @returns {boolean} Returns whether or not the iframe is from the same origin. |
235 */ |
266 */ |
236 function isLocalFrame( frame ) { |
267 function isLocalFrame( frame ) { |
237 var origin, src = frame.src; |
268 var origin, src = frame.src; |
238 |
269 |
239 // Need to compare strings as WebKit doesn't throw JS errors when iframes have different origin. |
270 /* |
240 // It throws uncatchable exceptions. |
271 * Need to compare strings as WebKit doesn't throw JS errors when iframes have |
|
272 * different origin. It throws uncatchable exceptions. |
|
273 */ |
241 if ( src && /^https?:\/\//.test( src ) ) { |
274 if ( src && /^https?:\/\//.test( src ) ) { |
242 origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host; |
275 origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host; |
243 |
276 |
244 if ( src.indexOf( origin ) !== 0 ) { |
277 if ( src.indexOf( origin ) !== 0 ) { |
245 return false; |
278 return false; |
254 |
287 |
255 return false; |
288 return false; |
256 } |
289 } |
257 |
290 |
258 /** |
291 /** |
259 * Check if the document's focus has changed |
292 * Checks if the document's focus has changed. |
260 * |
293 * |
261 * @access private |
294 * @access private |
262 * |
295 * |
263 * @return void |
296 * @since 4.1.0 |
|
297 * |
|
298 * @returns {void} |
264 */ |
299 */ |
265 function checkFocus() { |
300 function checkFocus() { |
266 if ( settings.hasFocus && ! document.hasFocus() ) { |
301 if ( settings.hasFocus && ! document.hasFocus() ) { |
267 blurred(); |
302 blurred(); |
268 } else if ( ! settings.hasFocus && document.hasFocus() ) { |
303 } else if ( ! settings.hasFocus && document.hasFocus() ) { |
269 focused(); |
304 focused(); |
270 } |
305 } |
271 } |
306 } |
272 |
307 |
273 /** |
308 /** |
274 * Set error state and fire an event on XHR errors or timeout |
309 * Sets error state and fires an event on XHR errors or timeout. |
275 * |
310 * |
276 * @access private |
311 * @access private |
277 * |
312 * |
278 * @param string error The error type passed from the XHR |
313 * @since 3.8.0 |
279 * @param int status The HTTP status code passed from jqXHR (200, 404, 500, etc.) |
314 * |
280 * @return void |
315 * @param {string} error The error type passed from the XHR. |
|
316 * @param {number} status The HTTP status code passed from jqXHR |
|
317 * (200, 404, 500, etc.). |
|
318 * |
|
319 * @returns {void} |
281 */ |
320 */ |
282 function setErrorState( error, status ) { |
321 function setErrorState( error, status ) { |
283 var trigger; |
322 var trigger; |
284 |
323 |
285 if ( error ) { |
324 if ( error ) { |
286 switch ( error ) { |
325 switch ( error ) { |
287 case 'abort': |
326 case 'abort': |
288 // do nothing |
327 // Do nothing. |
289 break; |
328 break; |
290 case 'timeout': |
329 case 'timeout': |
291 // no response for 30 sec. |
330 // No response for 30 sec. |
292 trigger = true; |
331 trigger = true; |
293 break; |
332 break; |
294 case 'error': |
333 case 'error': |
295 if ( 503 === status && settings.hasConnected ) { |
334 if ( 503 === status && settings.hasConnected ) { |
296 trigger = true; |
335 trigger = true; |
310 } |
349 } |
311 |
350 |
312 if ( trigger && ! hasConnectionError() ) { |
351 if ( trigger && ! hasConnectionError() ) { |
313 settings.connectionError = true; |
352 settings.connectionError = true; |
314 $document.trigger( 'heartbeat-connection-lost', [error, status] ); |
353 $document.trigger( 'heartbeat-connection-lost', [error, status] ); |
315 } |
354 wp.hooks.doAction( 'heartbeat.connection-lost', error, status ); |
316 } |
355 } |
317 } |
356 } |
318 |
357 } |
319 /** |
358 |
320 * Clear the error state and fire an event |
359 /** |
321 * |
360 * Clears the error state and fires an event if there is a connection error. |
322 * @access private |
361 * |
323 * |
362 * @access private |
324 * @return void |
363 * |
|
364 * @since 3.8.0 |
|
365 * |
|
366 * @returns {void} |
325 */ |
367 */ |
326 function clearErrorState() { |
368 function clearErrorState() { |
327 // Has connected successfully |
369 // Has connected successfully. |
328 settings.hasConnected = true; |
370 settings.hasConnected = true; |
329 |
371 |
330 if ( hasConnectionError() ) { |
372 if ( hasConnectionError() ) { |
331 settings.errorcount = 0; |
373 settings.errorcount = 0; |
332 settings.connectionError = false; |
374 settings.connectionError = false; |
333 $document.trigger( 'heartbeat-connection-restored' ); |
375 $document.trigger( 'heartbeat-connection-restored' ); |
334 } |
376 wp.hooks.doAction( 'heartbeat.connection-restored' ); |
335 } |
377 } |
336 |
378 } |
337 /** |
379 |
338 * Gather the data and connect to the server |
380 /** |
339 * |
381 * Gathers the data and connects to the server. |
340 * @access private |
382 * |
341 * |
383 * @access private |
342 * @return void |
384 * |
|
385 * @since 3.6.0 |
|
386 * |
|
387 * @returns {void} |
343 */ |
388 */ |
344 function connect() { |
389 function connect() { |
345 var ajaxData, heartbeatData; |
390 var ajaxData, heartbeatData; |
346 |
391 |
347 // If the connection to the server is slower than the interval, |
392 // If the connection to the server is slower than the interval, |
391 |
437 |
392 clearErrorState(); |
438 clearErrorState(); |
393 |
439 |
394 if ( response.nonces_expired ) { |
440 if ( response.nonces_expired ) { |
395 $document.trigger( 'heartbeat-nonces-expired' ); |
441 $document.trigger( 'heartbeat-nonces-expired' ); |
|
442 wp.hooks.doAction( 'heartbeat.nonces-expired' ); |
396 } |
443 } |
397 |
444 |
398 // Change the interval from PHP |
445 // Change the interval from PHP |
399 if ( response.heartbeat_interval ) { |
446 if ( response.heartbeat_interval ) { |
400 newInterval = response.heartbeat_interval; |
447 newInterval = response.heartbeat_interval; |
401 delete response.heartbeat_interval; |
448 delete response.heartbeat_interval; |
402 } |
449 } |
403 |
450 |
|
451 // Update the heartbeat nonce if set. |
|
452 if ( response.heartbeat_nonce && typeof window.heartbeatSettings === 'object' ) { |
|
453 window.heartbeatSettings.nonce = response.heartbeat_nonce; |
|
454 delete response.heartbeat_nonce; |
|
455 } |
|
456 |
|
457 // Update the Rest API nonce if set and wp-api loaded. |
|
458 if ( response.rest_nonce && typeof window.wpApiSettings === 'object' ) { |
|
459 window.wpApiSettings.nonce = response.rest_nonce; |
|
460 // This nonce is required for api-fetch through heartbeat.tick. |
|
461 // delete response.rest_nonce; |
|
462 } |
|
463 |
404 $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] ); |
464 $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] ); |
405 |
465 wp.hooks.doAction( 'heartbeat.tick', response, textStatus, jqXHR ); |
406 // Do this last, can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast' |
466 |
|
467 // Do this last. Can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast'. |
407 if ( newInterval ) { |
468 if ( newInterval ) { |
408 interval( newInterval ); |
469 interval( newInterval ); |
409 } |
470 } |
410 }).fail( function( jqXHR, textStatus, error ) { |
471 }).fail( function( jqXHR, textStatus, error ) { |
411 setErrorState( textStatus || 'unknown', jqXHR.status ); |
472 setErrorState( textStatus || 'unknown', jqXHR.status ); |
412 $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); |
473 $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); |
|
474 wp.hooks.doAction( 'heartbeat.error', jqXHR, textStatus, error ); |
413 }); |
475 }); |
414 } |
476 } |
415 |
477 |
416 /** |
478 /** |
417 * Schedule the next connection |
479 * Schedules the next connection. |
418 * |
480 * |
419 * Fires immediately if the connection time is longer than the interval. |
481 * Fires immediately if the connection time is longer than the interval. |
420 * |
482 * |
421 * @access private |
483 * @access private |
422 * |
484 * |
423 * @return void |
485 * @since 3.8.0 |
|
486 * |
|
487 * @returns {void} |
424 */ |
488 */ |
425 function scheduleNextTick() { |
489 function scheduleNextTick() { |
426 var delta = time() - settings.lastTick, |
490 var delta = time() - settings.lastTick, |
427 interval = settings.mainInterval; |
491 interval = settings.mainInterval; |
428 |
492 |
550 |
621 |
551 settings.userActivityEvents = true; |
622 settings.userActivityEvents = true; |
552 } |
623 } |
553 } |
624 } |
554 |
625 |
555 // Public methods |
626 // Public methods. |
556 |
627 |
557 /** |
628 /** |
558 * Whether the window (or any local iframe in it) has focus, or the user is active |
629 * Checks whether the window (or any local iframe in it) has focus, or the user |
559 * |
630 * is active. |
560 * @return bool |
631 * |
|
632 * @since 3.6.0 |
|
633 * @memberOf wp.heartbeat.prototype |
|
634 * |
|
635 * @returns {boolean} True if the window or the user is active. |
561 */ |
636 */ |
562 function hasFocus() { |
637 function hasFocus() { |
563 return settings.hasFocus; |
638 return settings.hasFocus; |
564 } |
639 } |
565 |
640 |
566 /** |
641 /** |
567 * Whether there is a connection error |
642 * Checks whether there is a connection error. |
568 * |
643 * |
569 * @return bool |
644 * @since 3.6.0 |
|
645 * |
|
646 * @memberOf wp.heartbeat.prototype |
|
647 * |
|
648 * @returns {boolean} True if a connection error was found. |
570 */ |
649 */ |
571 function hasConnectionError() { |
650 function hasConnectionError() { |
572 return settings.connectionError; |
651 return settings.connectionError; |
573 } |
652 } |
574 |
653 |
575 /** |
654 /** |
576 * Connect asap regardless of 'hasFocus' |
655 * Connects as soon as possible regardless of 'hasFocus' state. |
577 * |
656 * |
578 * Will not open two concurrent connections. If a connection is in progress, |
657 * Will not open two concurrent connections. If a connection is in progress, |
579 * will connect again immediately after the current connection completes. |
658 * will connect again immediately after the current connection completes. |
580 * |
659 * |
581 * @return void |
660 * @since 3.8.0 |
|
661 * |
|
662 * @memberOf wp.heartbeat.prototype |
|
663 * |
|
664 * @returns {void} |
582 */ |
665 */ |
583 function connectNow() { |
666 function connectNow() { |
584 settings.lastTick = 0; |
667 settings.lastTick = 0; |
585 scheduleNextTick(); |
668 scheduleNextTick(); |
586 } |
669 } |
587 |
670 |
588 /** |
671 /** |
589 * Disable suspending |
672 * Disables suspending. |
590 * |
673 * |
591 * Should be used only when Heartbeat is performing critical tasks like autosave, post-locking, etc. |
674 * Should be used only when Heartbeat is performing critical tasks like |
592 * Using this on many screens may overload the user's hosting account if several |
675 * autosave, post-locking, etc. Using this on many screens may overload the |
593 * browser windows/tabs are left open for a long time. |
676 * user's hosting account if several browser windows/tabs are left open for a |
594 * |
677 * long time. |
595 * @return void |
678 * |
|
679 * @since 3.8.0 |
|
680 * |
|
681 * @memberOf wp.heartbeat.prototype |
|
682 * |
|
683 * @returns {void} |
596 */ |
684 */ |
597 function disableSuspend() { |
685 function disableSuspend() { |
598 settings.suspendEnabled = false; |
686 settings.suspendEnabled = false; |
599 } |
687 } |
600 |
688 |
601 /** |
689 /** |
602 * Get/Set the interval |
690 * Gets/Sets the interval. |
603 * |
691 * |
604 * When setting to 'fast' or 5, by default interval is 5 sec. for the next 30 ticks (for 2 min and 30 sec). |
692 * When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks |
605 * In this case the number of 'ticks' can be passed as second argument. |
693 * (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks' |
606 * If the window doesn't have focus, the interval slows down to 2 min. |
694 * can be passed as second argument. If the window doesn't have focus, the |
607 * |
695 * interval slows down to 2 min. |
608 * @param mixed speed Interval: 'fast' or 5, 15, 30, 60, 120 |
696 * |
609 * @param string ticks Used with speed = 'fast' or 5, how many ticks before the interval reverts back |
697 * @since 3.6.0 |
610 * @return int Current interval in seconds |
698 * |
|
699 * @memberOf wp.heartbeat.prototype |
|
700 * |
|
701 * @param {string|number} speed Interval: 'fast' or 5, 15, 30, 60, 120. Fast |
|
702 * equals 5. |
|
703 * @param {string} ticks Tells how many ticks before the interval reverts |
|
704 * back. Used with speed = 'fast' or 5. |
|
705 * |
|
706 * @returns {number} Current interval in seconds. |
611 */ |
707 */ |
612 function interval( speed, ticks ) { |
708 function interval( speed, ticks ) { |
613 var newInterval, |
709 var newInterval, |
614 oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval; |
710 oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval; |
615 |
711 |
665 |
761 |
666 return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000; |
762 return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000; |
667 } |
763 } |
668 |
764 |
669 /** |
765 /** |
670 * Enqueue data to send with the next XHR |
766 * Enqueues data to send with the next XHR. |
671 * |
767 * |
672 * As the data is send asynchronously, this function doesn't return the XHR response. |
768 * As the data is send asynchronously, this function doesn't return the XHR |
673 * To see the response, use the custom jQuery event 'heartbeat-tick' on the document, example: |
769 * response. To see the response, use the custom jQuery event 'heartbeat-tick' |
|
770 * on the document, example: |
674 * $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) { |
771 * $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) { |
675 * // code |
772 * // code |
676 * }); |
773 * }); |
677 * If the same 'handle' is used more than once, the data is not overwritten when the third argument is 'true'. |
774 * If the same 'handle' is used more than once, the data is not overwritten when |
678 * Use wp.heartbeat.isQueued('handle') to see if any data is already queued for that handle. |
775 * the third argument is 'true'. Use `wp.heartbeat.isQueued('handle')` to see if |
679 * |
776 * any data is already queued for that handle. |
680 * $param string handle Unique handle for the data. The handle is used in PHP to receive the data. |
777 * |
681 * $param mixed data The data to send. |
778 * @since 3.6.0 |
682 * $param bool noOverwrite Whether to overwrite existing data in the queue. |
779 * |
683 * $return bool Whether the data was queued or not. |
780 * @memberOf wp.heartbeat.prototype |
|
781 * |
|
782 * @param {string} handle Unique handle for the data, used in PHP to |
|
783 * receive the data. |
|
784 * @param {*} data The data to send. |
|
785 * @param {boolean} noOverwrite Whether to overwrite existing data in the queue. |
|
786 * |
|
787 * @returns {boolean} True if the data was queued. |
684 */ |
788 */ |
685 function enqueue( handle, data, noOverwrite ) { |
789 function enqueue( handle, data, noOverwrite ) { |
686 if ( handle ) { |
790 if ( handle ) { |
687 if ( noOverwrite && this.isQueued( handle ) ) { |
791 if ( noOverwrite && this.isQueued( handle ) ) { |
688 return false; |
792 return false; |
693 } |
797 } |
694 return false; |
798 return false; |
695 } |
799 } |
696 |
800 |
697 /** |
801 /** |
698 * Check if data with a particular handle is queued |
802 * Checks if data with a particular handle is queued. |
699 * |
803 * |
700 * $param string handle The handle for the data |
804 * @since 3.6.0 |
701 * $return bool Whether some data is queued with this handle |
805 * |
|
806 * @param {string} handle The handle for the data. |
|
807 * |
|
808 * @returns {boolean} True if the data is queued with this handle. |
702 */ |
809 */ |
703 function isQueued( handle ) { |
810 function isQueued( handle ) { |
704 if ( handle ) { |
811 if ( handle ) { |
705 return settings.queue.hasOwnProperty( handle ); |
812 return settings.queue.hasOwnProperty( handle ); |
706 } |
813 } |
707 } |
814 } |
708 |
815 |
709 /** |
816 /** |
710 * Remove data with a particular handle from the queue |
817 * Removes data with a particular handle from the queue. |
711 * |
818 * |
712 * $param string handle The handle for the data |
819 * @since 3.7.0 |
713 * $return void |
820 * |
|
821 * @memberOf wp.heartbeat.prototype |
|
822 * |
|
823 * @param {string} handle The handle for the data. |
|
824 * |
|
825 * @returns {void} |
714 */ |
826 */ |
715 function dequeue( handle ) { |
827 function dequeue( handle ) { |
716 if ( handle ) { |
828 if ( handle ) { |
717 delete settings.queue[handle]; |
829 delete settings.queue[handle]; |
718 } |
830 } |
719 } |
831 } |
720 |
832 |
721 /** |
833 /** |
722 * Get data that was enqueued with a particular handle |
834 * Gets data that was enqueued with a particular handle. |
723 * |
835 * |
724 * $param string handle The handle for the data |
836 * @since 3.7.0 |
725 * $return mixed The data or undefined |
837 * |
|
838 * @memberOf wp.heartbeat.prototype |
|
839 * |
|
840 * @param {string} handle The handle for the data. |
|
841 * |
|
842 * @returns {*} The data or undefined. |
726 */ |
843 */ |
727 function getQueuedItem( handle ) { |
844 function getQueuedItem( handle ) { |
728 if ( handle ) { |
845 if ( handle ) { |
729 return this.isQueued( handle ) ? settings.queue[handle] : undefined; |
846 return this.isQueued( handle ) ? settings.queue[handle] : undefined; |
730 } |
847 } |
731 } |
848 } |
732 |
849 |
733 initialize(); |
850 initialize(); |
734 |
851 |
735 // Expose public methods |
852 // Expose public methods. |
736 return { |
853 return { |
737 hasFocus: hasFocus, |
854 hasFocus: hasFocus, |
738 connectNow: connectNow, |
855 connectNow: connectNow, |
739 disableSuspend: disableSuspend, |
856 disableSuspend: disableSuspend, |
740 interval: interval, |
857 interval: interval, |