Ticket #25073: 25073.3.patch
File 25073.3.patch, 23.0 KB (added by , 11 years ago) |
---|
-
wp-admin/includes/post.php
1177 1177 $time = $lock[0]; 1178 1178 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true ); 1179 1179 1180 $time_window = apply_filters( 'wp_check_post_lock_window', 1 20 );1180 $time_window = apply_filters( 'wp_check_post_lock_window', 150 ); 1181 1181 1182 1182 if ( $time && $time > time() - $time_window && $user != get_current_user_id() ) 1183 1183 return $user; -
wp-includes/js/heartbeat.js
22 22 * @since 3.6.0 23 23 */ 24 24 25 // Ensure the global `wp` object exists. 26 window.wp = window.wp || {}; 27 28 (function($){ 25 ( function( $, window, undefined ) { 29 26 var Heartbeat = function() { 30 var self = this, 31 running, 32 beat, 33 screenId = typeof pagenow != 'undefined' ? pagenow : '', 34 url = typeof ajaxurl != 'undefined' ? ajaxurl : '', 35 settings, 36 tick = 0, 37 queue = {}, 38 interval, 39 connecting, 40 countdown = 0, 41 errorcount = 0, 42 tempInterval, 43 hasFocus = true, 44 isUserActive, 45 userActiveEvents, 46 winBlurTimeout, 47 frameBlurTimeout = -1, 48 hasConnectionError = false; 27 var $document = $(document); 28 var settings = { 29 isRunning: true, 30 screenId: '', 31 url: '', 32 lastTick: 0, 33 queue: {}, 34 mainInterval: 0, 35 tempInterval: 0, 36 connecting: false, 37 countdown: 0, 38 errorcount: 0, 39 hasFocus: true, 40 userActivity: 0, 41 userActiveEvents: false, 42 connectionError: false, 43 beatTimer: 0, 44 winBlurTimer: 0, 45 frameBlurTimer: 0 46 }; 49 47 50 48 /** 51 * Returns a boolean that's indicative of whether or not there is a connection error49 * Set local vars and events, then start 52 50 * 53 * @returns boolean 51 * @access private 52 * 53 * @return void 54 54 */ 55 this.hasConnectionError = function() { 56 return hasConnectionError; 57 }; 55 function initialize() { 56 if ( typeof window.pagenow != 'undefined' ) { 57 settings.screenId = window.pagenow; 58 } 58 59 59 if ( typeof( window.heartbeatSettings ) == 'object' ) { 60 settings = $.extend( {}, window.heartbeatSettings ); 60 if ( typeof window.ajaxurl != 'undefined' ) { 61 settings.url = window.ajaxurl; 62 } 61 63 62 // Add private vars 63 url = settings.ajaxurl || url; 64 delete settings.ajaxurl; 65 delete settings.nonce; 64 // Pull in options passed from PHP 65 if ( typeof window.heartbeatSettings === 'object' ) { 66 var options = window.heartbeatSettings; 66 67 67 interval = settings.interval || 15; // default interval 68 delete settings.interval; 69 // The interval can be from 15 to 60 sec. and can be set temporarily to 5 sec. 70 if ( interval < 15 ) 71 interval = 15; 72 else if ( interval > 60 ) 73 interval = 60; 68 // The XHR URL can be passed as option when window.ajaxurl is not set 69 if ( ! settings.url && options.ajaxurl ) { 70 settings.url = options.ajaxurl; 71 } 74 72 75 interval = interval * 1000; 73 // The interval can be from 15 to 60 sec. and can be set temporarily to 5 sec. 74 settings.mainInterval = options.interval || 15; 76 75 77 // 'screenId' can be added from settings on the front-end where the JS global 'pagenow' is not set 78 screenId = screenId || settings.screenId || 'front'; 79 delete settings.screenId; 76 if ( settings.mainInterval < 15 ) { 77 settings.mainInterval = 15; 78 } else if ( settings.mainInterval > 60 ) { 79 settings.mainInterval = 60; 80 } 80 81 81 // Add or overwrite public vars 82 $.extend( this, settings ); 82 // Convert to milliseconds 83 settings.mainInterval = settings.mainInterval * 1000; 84 85 // 'screenId' can be added from settings on the front-end where the JS global 'pagenow' is not set 86 if ( ! settings.screenId ) { 87 settings.screenId = options.screenId || 'front'; 88 } 89 } 90 91 // Set focus/blur events on the window 92 $(window).on( 'blur.wp-heartbeat-focus', function() { 93 setFrameFocusEvents(); 94 // We don't know why the 'blur' was fired. Either the user clicked in an iframe or outside the browser. 95 // Running blurred() after some timeout lets us cancel it if the user clicked in an iframe. 96 settings.winBlurTimer = window.setTimeout( function(){ blurred(); }, 500 ); 97 }).on( 'focus.wp-heartbeat-focus', function() { 98 removeFrameFocusEvents(); 99 focused(); 100 }).on( 'unload.wp-heartbeat', function() { 101 // Don't connect any more 102 settings.isRunning = false; 103 }); 104 105 // Check for user activity every 30 seconds. 106 window.setInterval( function(){ checkUserActive(); }, 30000 ); 107 108 // Start one tick after DOM ready 109 $document.ready( function() { 110 settings.lastTick = time(); 111 next(); 112 }); 83 113 } 84 114 85 function time(s) { 86 if ( s ) 87 return parseInt( (new Date()).getTime() / 1000 ); 88 115 /** 116 * Return the current time according to the browser 117 * 118 * @access private 119 * 120 * @return int 121 */ 122 function time() { 89 123 return (new Date()).getTime(); 90 124 } 91 125 126 /** 127 * Check if the iframe is from the same origin 128 * 129 * @access private 130 * 131 * @return bool 132 */ 92 133 function isLocalFrame( frame ) { 93 134 var origin, src = frame.src; 94 135 … … 95 136 if ( src && /^https?:\/\//.test( src ) ) { 96 137 origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host; 97 138 98 if ( src.indexOf( origin ) !== 0 ) 139 if ( src.indexOf( origin ) !== 0 ) { 99 140 return false; 141 } 100 142 } 101 143 102 144 try { 103 if ( frame.contentWindow.document ) 145 if ( frame.contentWindow.document ) { 104 146 return true; 147 } 105 148 } catch(e) {} 106 149 107 150 return false; 108 151 } 109 152 110 // Set error state and fire an event on XHR errors or timeout 111 function errorstate( error ) { 153 /** 154 * Set error state and fire an event on XHR errors or timeout 155 * 156 * @access private 157 * 158 * @param string error The error type passed from the XHR 159 * @return void 160 */ 161 function setErrorState( error ) { 112 162 var trigger; 113 163 114 164 if ( error ) { … … 124 174 case 'error': 125 175 case 'empty': 126 176 case 'unknown': 127 errorcount++;177 settings.errorcount++; 128 178 129 if ( errorcount > 2 )179 if ( settings.errorcount > 2 ) { 130 180 trigger = true; 181 } 131 182 132 183 break; 133 184 } 134 185 135 if ( trigger && ! self.hasConnectionError() ) {136 hasConnectionError = true;137 $ (document).trigger( 'heartbeat-connection-lost', [error] );186 if ( trigger && ! hasConnectionError() ) { 187 settings.connectionError = true; 188 $document.trigger( 'heartbeat-connection-lost', [error] ); 138 189 } 139 } else if ( self.hasConnectionError() ) {140 errorcount = 0;141 hasConnectionError = false;142 $(document).trigger( 'heartbeat-connection-restored' );143 190 } 144 191 } 145 192 193 /** 194 * Clear the error state and fire an event 195 * 196 * @access private 197 * 198 * @return void 199 */ 200 function clearErrorState() { 201 if ( hasConnectionError() ) { 202 settings.errorcount = 0; 203 settings.connectionError = false; 204 $document.trigger( 'heartbeat-connection-restored' ); 205 } 206 } 207 208 /** 209 * Gather the data and connect to the server 210 * 211 * @access private 212 * 213 * @return void 214 */ 146 215 function connect() { 147 var send = {}, data, i, empty = true, 148 nonce = typeof window.heartbeatSettings == 'object' ? window.heartbeatSettings.nonce : ''; 149 tick = time(); 216 var ajaxData, heartbeatData, i, empty = true; 150 217 151 data = $.extend( {}, queue ); 218 // If the connection to the server is slower than the interval, 219 // heartbeat connects as soon as the previous connection's response is received. 220 if ( settings.connecting ) { 221 return; 222 } 223 224 settings.lastTick = time(); 225 226 heartbeatData = $.extend( {}, settings.queue ); 152 227 // Clear the data queue, anything added after this point will be send on the next tick 153 queue = {};228 settings.queue = {}; 154 229 155 $ (document).trigger( 'heartbeat-send', [data] );230 $document.trigger( 'heartbeat-send', [ heartbeatData ] ); 156 231 157 for ( i in data ) {158 if ( data.hasOwnProperty( i ) ) {232 for ( i in heartbeatData ) { 233 if ( heartbeatData.hasOwnProperty( i ) ) { 159 234 empty = false; 160 235 break; 161 236 } … … 163 238 164 239 // If nothing to send (nothing is expecting a response), 165 240 // schedule the next tick and bail 166 if ( empty && ! self.hasConnectionError() ) { 167 connecting = false; 241 if ( empty && ! hasConnectionError() ) { 168 242 next(); 169 243 return; 170 244 } 171 245 172 send.data = data; 173 send.interval = interval / 1000; 174 send._nonce = nonce; 175 send.action = 'heartbeat'; 176 send.screen_id = screenId; 177 send.has_focus = hasFocus; 246 ajaxData = { 247 data: heartbeatData, 248 interval: settings.mainInterval / 1000, 249 _nonce: typeof window.heartbeatSettings === 'object' ? window.heartbeatSettings.nonce : '', 250 action: 'heartbeat', 251 screen_id: settings.screenId, 252 has_focus: settings.hasFocus 253 }; 178 254 179 connecting = true;180 se lf.xhr = $.ajax({181 url: url,255 settings.connecting = true; 256 settings.xhr = $.ajax({ 257 url: settings.url, 182 258 type: 'post', 183 259 timeout: 30000, // throw an error if not completed after 30 sec. 184 data: send,260 data: ajaxData, 185 261 dataType: 'json' 262 }).always( function() { 263 settings.connecting = false; 264 next(); 186 265 }).done( function( response, textStatus, jqXHR ) { 187 266 var new_interval; 188 267 189 if ( ! response ) 190 return errorstate( 'empty' ); 268 if ( ! response ) { 269 setErrorState( 'empty' ); 270 return; 271 } 191 272 192 // Clear error state 193 if ( self.hasConnectionError() ) 194 errorstate(); 273 clearErrorState(); 195 274 196 275 if ( response.nonces_expired ) { 197 $ (document).trigger( 'heartbeat-nonces-expired' );276 $document.trigger( 'heartbeat-nonces-expired' ); 198 277 return; 199 278 } 200 279 … … 204 283 delete response.heartbeat_interval; 205 284 } 206 285 207 self.tick( response, textStatus, jqXHR);286 $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] ); 208 287 209 // do this last, can trigger the next XHR if connection time > 5 sec. and new_interval == 'fast' 210 if ( new_interval ) 211 self.interval.call( self, new_interval ); 212 }).always( function() { 213 connecting = false; 214 next(); 288 // Do this last, can trigger the next XHR if connection time > 5 sec. and new_interval == 'fast' 289 if ( new_interval ) { 290 setInterval( new_interval ); 291 } 215 292 }).fail( function( jqXHR, textStatus, error ) { 216 errorstate( textStatus || 'unknown' );217 self.error( jqXHR, textStatus, error);293 setErrorState( textStatus || 'unknown' ); 294 $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); 218 295 }); 219 296 } 220 297 298 /** 299 * Schedule the next connection 300 * 301 * Fires immediately if the connection time is longer than the interval. 302 * 303 * @access private 304 * 305 * @return void 306 */ 221 307 function next() { 222 var delta = time() - tick, t = interval;308 var delta = time() - settings.lastTick, interval = settings.mainInterval; 223 309 224 if ( ! running )310 if ( ! settings.isRunning ) { 225 311 return; 312 } 226 313 227 if ( ! hasFocus ) {228 t = 100000; // 100 sec. Post locks expire after 120 sec.229 } else if ( countdown > 0 &&tempInterval ) {230 t =tempInterval;231 countdown--;314 if ( ! settings.hasFocus ) { 315 interval = 120000; // 120 sec. Post locks expire after 150 sec. 316 } else if ( settings.countdown > 0 && settings.tempInterval ) { 317 interval = settings.tempInterval; 318 settings.countdown--; 232 319 } 233 320 234 window.clearTimeout( beat);321 window.clearTimeout( settings.beatTimer ); 235 322 236 if ( delta < t) {237 beat= window.setTimeout(323 if ( delta < interval ) { 324 settings.beatTimer = window.setTimeout( 238 325 function(){ 239 if ( running )326 if ( settings.isRunning ) { 240 327 connect(); 328 } 241 329 }, 242 t- delta330 interval - delta 243 331 ); 244 332 } else { 245 333 connect(); … … 246 334 } 247 335 } 248 336 249 function blurred() { 250 window.clearTimeout(winBlurTimeout); 251 window.clearTimeout(frameBlurTimeout); 252 winBlurTimeout = frameBlurTimeout = 0; 337 /** 338 * Set the internal state when the browser window looses focus 339 * 340 * @access private 341 * 342 * @return void 343 */ 344 function blurred() { 253 345 254 hasFocus = false; 346 clearFocusTimers(); 347 settings.hasFocus = false; 255 348 } 256 349 350 /** 351 * Set the internal state when the browser window is focused 352 * 353 * @access private 354 * 355 * @return void 356 */ 257 357 function focused() { 258 window.clearTimeout(winBlurTimeout); 259 window.clearTimeout(frameBlurTimeout); 260 winBlurTimeout = frameBlurTimeout = 0; 358 clearFocusTimers(); 359 settings.userActivity = time(); 261 360 262 isUserActive = time(); 263 264 if ( hasFocus ) 265 return; 266 267 hasFocus = true; 268 window.clearTimeout(beat); 269 270 if ( ! connecting ) 361 if ( ! settings.hasFocus ) { 362 settings.hasFocus = true; 271 363 next(); 364 } 272 365 } 273 366 274 function setFrameEvents() { 367 /** 368 * Add focus/blur events to all local iframes 369 * 370 * Used to detect when focus is moved from the main window to an iframe 371 * 372 * @access private 373 * 374 * @return void 375 */ 376 function setFrameFocusEvents() { 275 377 $('iframe').each( function( i, frame ){ 276 if ( ! isLocalFrame( frame ) ) 378 if ( ! isLocalFrame( frame ) ) { 277 379 return; 380 } 278 381 279 if ( $.data( frame, 'wp-heartbeat-focus' ) ) 382 if ( $.data( frame, 'wp-heartbeat-focus' ) ) { 280 383 return; 384 } 281 385 282 386 $.data( frame, 'wp-heartbeat-focus', 1 ); 283 387 284 $( frame.contentWindow ).on( 'focus.wp-heartbeat-focus', function( e) {388 $( frame.contentWindow ).on( 'focus.wp-heartbeat-focus', function() { 285 389 focused(); 286 }).on('blur.wp-heartbeat-focus', function(e) { 287 setFrameEvents(); 288 frameBlurTimeout = window.setTimeout( function(){ blurred(); }, 500 ); 390 }).on('blur.wp-heartbeat-focus', function() { 391 setFrameFocusEvents(); 392 // We don't know why the 'blur' was fired. Either the user clicked in the main window or outside the browser. 393 // Running blurred() after some timeout lets us cancel it if the user clicked in the main window. 394 settings.frameBlurTimer = window.setTimeout( function(){ blurred(); }, 500 ); 289 395 }); 290 396 }); 291 397 } 292 293 $(window).on( 'blur.wp-heartbeat-focus', function(e) { 294 setFrameEvents(); 295 winBlurTimeout = window.setTimeout( function(){ blurred(); }, 500 ); 296 }).on( 'focus.wp-heartbeat-focus', function() { 398 399 /** 400 * Remove the focus/blur events to all local iframes 401 * 402 * @access private 403 * 404 * @return void 405 */ 406 function removeFrameFocusEvents() { 297 407 $('iframe').each( function( i, frame ) { 298 if ( ! isLocalFrame( frame ) )408 if ( ! isLocalFrame( frame ) ) { 299 409 return; 410 } 300 411 301 412 $.removeData( frame, 'wp-heartbeat-focus' ); 302 413 $( frame.contentWindow ).off( '.wp-heartbeat-focus' ); 303 414 }); 415 } 304 416 305 focused(); 306 }); 417 /** 418 * Clear the reset timers for focus/blur events on the window and iframes 419 * 420 * @access private 421 * 422 * @return void 423 */ 424 function clearFocusTimers() { 425 window.clearTimeout( settings.winBlurTimer ); 426 window.clearTimeout( settings.frameBlurTimer ); 427 } 307 428 429 /** 430 * Runs when the user becomes active after a period of inactivity 431 * 432 * @access private 433 * 434 * @return void 435 */ 308 436 function userIsActive() { 309 userActiveEvents = false; 310 $(document).off( '.wp-heartbeat-active' ); 437 settings.isRunning = true; 438 settings.userActiveEvents = false; 439 $document.off( '.wp-heartbeat-active' ); 440 311 441 $('iframe').each( function( i, frame ) { 312 if ( ! isLocalFrame( frame ) ) 442 if ( ! isLocalFrame( frame ) ) { 313 443 return; 444 } 314 445 315 446 $( frame.contentWindow ).off( '.wp-heartbeat-active' ); 316 447 }); … … 318 449 focused(); 319 450 } 320 451 321 // Set 'hasFocus = true' if user is active and the window is in the background. 322 // Set 'hasFocus = false' if the user has been inactive (no mouse or keyboard activity) for 5 min. even when the window has focus. 452 /** 453 * Check for user activity 454 * 455 * Runs every 30 sec. 456 * Sets 'hasFocus = true' if user is active and the window is in the background. 457 * Set 'hasFocus = false' if the user has been inactive (no mouse or keyboard activity) 458 * for 5 min. even when the window has focus. 459 * 460 * @access private 461 * 462 * @return void 463 */ 323 464 function checkUserActive() { 324 var lastActive = isUserActive ? time() - isUserActive: 0;465 var lastActive = settings.userActivity ? time() - settings.userActivity : 0; 325 466 326 // Throttle down when no mouse or keyboard activity for 5 min 327 if ( lastActive > 300000 && hasFocus ) 328 blurred(); 467 if ( lastActive > 300000 && settings.hasFocus ) { 468 // Throttle down when no mouse or keyboard activity for 5 min 469 blurred(); 470 } 329 471 330 if ( ! userActiveEvents ) { 331 $(document).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 472 if ( lastActive > 900000 ) { 473 // The user has been inactive for 15 min. Disable heartbeat. 474 // This will also release the post lock. 475 // When the user becomes active again, heartbeat will connect straight away. 476 settings.isRunning = false; 477 } 332 478 479 if ( ! settings.userActiveEvents ) { 480 $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 481 333 482 $('iframe').each( function( i, frame ) { 334 if ( ! isLocalFrame( frame ) ) 483 if ( ! isLocalFrame( frame ) ) { 335 484 return; 485 } 336 486 337 487 $( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 338 488 }); 339 489 340 userActiveEvents = true;490 settings.userActiveEvents = true; 341 491 } 342 492 } 343 493 344 // Check for user activity every 30 seconds. 345 window.setInterval( function(){ checkUserActive(); }, 30000 ); 346 $(document).ready( function() { 347 // Start one tick (15 sec) after DOM ready 348 running = true; 349 tick = time(); 350 next(); 351 }); 494 // Public methods 352 495 353 this.hasFocus = function() { 354 return hasFocus; 355 }; 496 /** 497 * Whether the window (or any local iframe in it) has focus, or the user is active 498 * 499 * @return bool 500 */ 501 function hasFocus() { 502 return settings.hasFocus; 503 } 356 504 357 505 /** 506 * Whether there is a connection error 507 * 508 * @return bool 509 */ 510 function hasConnectionError() { 511 return settings.connectionError; 512 } 513 514 /** 515 * Connect asap regardless of 'hasFocus' 516 * 517 * Will not open two concurrent connections. If a connection is in progress, 518 * will connect again immediately after the current connection completes. 519 * 520 * @return void 521 */ 522 function connectNow() { 523 settings.lastTick = 0; 524 next(); 525 } 526 527 /** 358 528 * Get/Set the interval 359 529 * 360 530 * When setting to 'fast', the interval is 5 sec. for the next 30 ticks (for 2 min and 30 sec). … … 364 534 * @param string ticks Used with speed = 'fast', how many ticks before the speed reverts back 365 535 * @return int Current interval in seconds 366 536 */ 367 this.interval = function( speed, ticks ) { 368 var reset, seconds; 537 function setInterval( speed, ticks ) { 538 var seconds, oldInerval = settings.mainInterval; 539 369 540 ticks = parseInt( ticks, 10 ) || 30; 370 541 ticks = ticks < 1 || ticks > 30 ? 30 : ticks; 371 542 … … 373 544 switch ( speed ) { 374 545 case 'fast': 375 546 seconds = 5; 376 countdown = ticks;547 settings.countdown = ticks; 377 548 break; 378 549 case 'slow': 379 550 seconds = 60; 380 countdown = 0;551 settings.countdown = 0; 381 552 break; 382 553 case 'long-polling': 383 554 // Allow long polling, (experimental) 384 interval = 0;555 settings.mainInterval = 0; 385 556 return 0; 386 557 break; 387 558 default: 388 559 seconds = 15; 389 countdown = 0;560 settings.countdown = 0; 390 561 } 391 562 392 // Reset when the new interval value is lower than the current one 393 reset = seconds * 1000 < interval; 394 395 if ( countdown > 0 ) { 396 tempInterval = seconds * 1000; 563 if ( settings.countdown > 0 ) { 564 settings.tempInterval = seconds * 1000; 397 565 } else { 398 interval = seconds * 1000;399 tempInterval = 0;566 settings.mainInterval = seconds * 1000; 567 settings.tempInterval = 0; 400 568 } 401 569 402 if ( reset ) 570 // Change the next connection time if the new interval is different 571 if ( seconds * 1000 != oldInerval ) { 572 settings.lastTick = settings.lastTick - ( oldInerval - seconds * 1000 ); 403 573 next(); 574 } 404 575 } 405 576 406 if ( ! hasFocus )577 if ( ! settings.hasFocus ) { 407 578 return 120; 579 } 408 580 409 return tempInterval ? tempInterval / 1000 : interval / 1000;410 } ;581 return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000; 582 } 411 583 412 584 /** 413 585 * Enqueue data to send with the next XHR … … 425 597 * $param bool dont_overwrite Whether to overwrite existing data in the queue. 426 598 * $return bool Whether the data was queued or not. 427 599 */ 428 this.enqueue = function( handle, data, dont_overwrite ) {600 function enqueue( handle, data, dont_overwrite ) { 429 601 if ( handle ) { 430 if ( dont_overwrite && this.isQueued( handle ) ) 602 if ( dont_overwrite && this.isQueued( handle ) ) { 431 603 return false; 604 } 432 605 433 queue[handle] = data;606 settings.queue[handle] = data; 434 607 return true; 435 608 } 436 609 return false; 437 } ;610 } 438 611 439 612 /** 440 613 * Check if data with a particular handle is queued … … 442 615 * $param string handle The handle for the data 443 616 * $return bool Whether some data is queued with this handle 444 617 */ 445 this.isQueued = function( handle ) { 446 if ( handle ) 447 return queue.hasOwnProperty( handle ); 448 }; 618 function isQueued( handle ) { 619 if ( handle ) { 620 return settings.queue.hasOwnProperty( handle ); 621 } 622 } 449 623 450 624 /** 451 625 * Remove data with a particular handle from the queue … … 453 627 * $param string handle The handle for the data 454 628 * $return void 455 629 */ 456 this.dequeue = function( handle ) { 457 if ( handle ) 458 delete queue[handle]; 459 }; 630 function dequeue( handle ) { 631 if ( handle ) { 632 delete settings.queue[handle]; 633 } 634 } 460 635 461 636 /** 462 637 * Get data that was enqueued with a particular handle … … 464 639 * $param string handle The handle for the data 465 640 * $return mixed The data or undefined 466 641 */ 467 this.getQueuedItem = function( handle ) {468 if ( handle ) 642 function getQueuedItem( handle ) { 643 if ( handle ) { 469 644 return this.isQueued( handle ) ? queue[handle] : undefined; 645 } 646 } 647 648 initialize(); 649 650 // Expose publick methods 651 return { 652 hasFocus: hasFocus, 653 connectNow: connectNow, 654 setInterval: setInterval, 655 hasConnectionError: hasConnectionError, 656 enqueue: enqueue, 657 dequeue: dequeue, 658 isQueued: isQueued, 659 getQueuedItem: getQueuedItem 470 660 }; 471 661 }; 472 662 473 $.extend( Heartbeat.prototype, { 474 tick: function( data, textStatus, jqXHR ) { 475 $(document).trigger( 'heartbeat-tick', [data, textStatus, jqXHR] ); 476 }, 477 error: function( jqXHR, textStatus, error ) { 478 $(document).trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); 479 } 480 }); 663 // Ensure the global `wp` object exists. 664 window.wp = window.wp || {}; 665 window.wp.heartbeat = new Heartbeat(); 481 666 482 wp.heartbeat = new Heartbeat(); 483 484 }(jQuery)); 667 }( jQuery, window ));