Changeset 26169
- Timestamp:
- 11/14/2013 06:40:03 PM (11 years ago)
- Location:
- trunk/src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/post.php
r25868 r26169 1186 1186 $user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true ); 1187 1187 1188 $time_window = apply_filters( 'wp_check_post_lock_window', 1 20 );1188 $time_window = apply_filters( 'wp_check_post_lock_window', 150 ); 1189 1189 1190 1190 if ( $time && $time > time() - $time_window && $user != get_current_user_id() ) -
trunk/src/wp-admin/js/inline-edit-post.js
r26123 r26169 326 326 if ( check.length ) 327 327 data['wp-check-locked-posts'] = check; 328 }).ready( function() { 329 // Set the heartbeat interval to 15 sec. 330 if ( typeof wp !== 'undefined' && wp.heartbeat ) { 331 wp.heartbeat.setInterval( 15 ); 332 } 328 333 }); 329 334 -
trunk/src/wp-admin/js/post.js
r24528 r26169 371 371 } 372 372 }).filter(':visible').find('.wp-tab-first').focus(); 373 374 // Set the heartbeat interval to 15 sec. if post lock dialogs are enabled 375 if ( typeof wp !== 'undefined' && wp.heartbeat && $('#post-lock-dialog').length ) { 376 wp.heartbeat.setInterval( 15 ); 377 } 373 378 374 379 // multi-taxonomies -
trunk/src/wp-includes/js/heartbeat.js
r25874 r26169 7 7 * 8 8 * Heartbeat is a simple server polling API that sends XHR requests to 9 * the server every 15 seconds and triggers events (or callbacks) upon9 * the server every 15 - 60 seconds and triggers events (or callbacks) upon 10 10 * receiving data. Currently these 'ticks' handle transports for post locking, 11 11 * login-expiration warnings, and related tasks while a user is logged in. 12 12 * 13 * Available filters in ajax-actions.php:13 * Available PHP filters (in ajax-actions.php): 14 14 * - heartbeat_received 15 15 * - heartbeat_send … … 20 20 * @see wp_ajax_nopriv_heartbeat(), wp_ajax_heartbeat() 21 21 * 22 * Custom jQuery events: 23 * - heartbeat-send 24 * - heartbeat-tick 25 * - heartbeat-error 26 * - heartbeat-connection-lost 27 * - heartbeat-connection-restored 28 * - heartbeat-nonces-expired 29 * 22 30 * @since 3.6.0 23 31 */ 24 32 25 // Ensure the global `wp` object exists. 26 window.wp = window.wp || {}; 27 28 (function($){ 33 ( function( $, window, undefined ) { 29 34 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 = null; 49 50 /** 51 * Returns a boolean that's indicative of whether or not there is a connection error 52 * 53 * @returns boolean 54 */ 55 this.hasConnectionError = function() { 56 return !! hasConnectionError; 57 }; 58 59 if ( typeof( window.heartbeatSettings ) == 'object' ) { 60 settings = $.extend( {}, window.heartbeatSettings ); 61 62 // Add private vars 63 url = settings.ajaxurl || url; 64 delete settings.ajaxurl; 65 delete settings.nonce; 66 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; 74 75 interval = interval * 1000; 76 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; 80 81 // Add or overwrite public vars 82 $.extend( this, settings ); 83 } 84 85 function time(s) { 86 if ( s ) 87 return parseInt( (new Date()).getTime() / 1000 ); 88 35 var $document = $(document), 36 settings = { 37 // Used to stop the "beat" 38 isRunning: true, 39 40 // Current screen id, defaults to the JS global 'pagenow' when present (in the admin) or 'front' 41 screenId: '', 42 43 // XHR request URL, defaults to the JS global 'ajaxurl' when present 44 url: '', 45 46 // Timestamp, start of the last connection request 47 lastTick: 0, 48 49 // Container for the enqueued items 50 queue: {}, 51 52 // Connect interval (in seconds) 53 mainInterval: 60, 54 55 // Used when the interval is set to 5 sec. temporarily 56 tempInterval: 0, 57 58 // Used when the interval is reset 59 originalInterval: 0, 60 61 // Used together with tempInterval 62 countdown: 0, 63 64 // Whether a connection is currently in progress 65 connecting: false, 66 67 // Whether a connection error occured 68 connectionError: false, 69 70 // Used to track non-critical errors 71 errorcount: 0, 72 73 // Whether at least one connection has completed successfully 74 hasConnected: false, 75 76 // Whether the current browser window is in focus and the user is active 77 hasFocus: true, 78 79 // Timestamp, last time the user was active. Checked every 30 sec. 80 userActivity: 0, 81 82 // Flags whether events tracking user activity were set 83 userActivityEvents: false, 84 85 // References to various timeouts 86 beatTimer: 0, 87 winBlurTimer: 0, 88 frameBlurTimer: 0 89 }; 90 91 /** 92 * Set local vars and events, then start 93 * 94 * @access private 95 * 96 * @return void 97 */ 98 function initialize() { 99 if ( typeof window.pagenow === 'string' ) { 100 settings.screenId = window.pagenow; 101 } 102 103 if ( typeof window.ajaxurl === 'string' ) { 104 settings.url = window.ajaxurl; 105 } 106 107 // Pull in options passed from PHP 108 if ( typeof window.heartbeatSettings === 'object' ) { 109 var options = window.heartbeatSettings; 110 111 // The XHR URL can be passed as option when window.ajaxurl is not set 112 if ( ! settings.url && options.ajaxurl ) { 113 settings.url = options.ajaxurl; 114 } 115 116 // The interval can be from 15 to 60 sec. and can be set temporarily to 5 sec. 117 if ( options.interval ) { 118 settings.mainInterval = options.interval; 119 120 if ( settings.mainInterval < 15 ) { 121 settings.mainInterval = 15; 122 } else if ( settings.mainInterval > 60 ) { 123 settings.mainInterval = 60; 124 } 125 } 126 127 // 'screenId' can be added from settings on the front-end where the JS global 'pagenow' is not set 128 if ( ! settings.screenId ) { 129 settings.screenId = options.screenId || 'front'; 130 } 131 } 132 133 // Convert to milliseconds 134 settings.mainInterval = settings.mainInterval * 1000; 135 settings.originalInterval = settings.mainInterval; 136 137 // Set focus/blur events on the window 138 $(window).on( 'blur.wp-heartbeat-focus', function() { 139 setFrameFocusEvents(); 140 // We don't know why the 'blur' was fired. Either the user clicked in an iframe or outside the browser. 141 // Running blurred() after some timeout lets us cancel it if the user clicked in an iframe. 142 settings.winBlurTimer = window.setTimeout( function(){ blurred(); }, 500 ); 143 }).on( 'focus.wp-heartbeat-focus', function() { 144 removeFrameFocusEvents(); 145 focused(); 146 }).on( 'unload.wp-heartbeat', function() { 147 // Don't connect any more 148 settings.isRunning = false; 149 }); 150 151 // Check for user activity every 30 seconds. 152 window.setInterval( function(){ checkUserActivity(); }, 30000 ); 153 154 // Start one tick after DOM ready 155 $document.ready( function() { 156 settings.lastTick = time(); 157 scheduleNextTick(); 158 }); 159 } 160 161 /** 162 * Return the current time according to the browser 163 * 164 * @access private 165 * 166 * @return int 167 */ 168 function time() { 89 169 return (new Date()).getTime(); 90 170 } 91 171 172 /** 173 * Check if the iframe is from the same origin 174 * 175 * @access private 176 * 177 * @return bool 178 */ 92 179 function isLocalFrame( frame ) { 93 180 var origin, src = frame.src; 94 181 182 // Need to compare strings as WebKit doesn't throw JS errors when iframes have different origin. 183 // It throws uncatchable exceptions. 95 184 if ( src && /^https?:\/\//.test( src ) ) { 96 185 origin = window.location.origin ? window.location.origin : window.location.protocol + '//' + window.location.host; 97 186 98 if ( src.indexOf( origin ) !== 0 ) 187 if ( src.indexOf( origin ) !== 0 ) { 99 188 return false; 189 } 100 190 } 101 191 102 192 try { 103 if ( frame.contentWindow.document ) 193 if ( frame.contentWindow.document ) { 104 194 return true; 195 } 105 196 } catch(e) {} 106 197 … … 108 199 } 109 200 110 // Set error state and fire an event on XHR errors or timeout 111 function errorstate( error, status ) { 201 /** 202 * Set error state and fire an event on XHR errors or timeout 203 * 204 * @access private 205 * 206 * @param string error The error type passed from the XHR 207 * @param int status The HTTP status code passed from jqXHR (200, 404, 500, etc.) 208 * @return void 209 */ 210 function setErrorState( error, status ) { 112 211 var trigger; 113 212 … … 121 220 trigger = true; 122 221 break; 222 case 'error': 223 if ( 503 === status && settings.hasConnected ) { 224 trigger = true; 225 break; 226 } 227 // Pass through other error statuses 123 228 case 'parsererror': 124 case 'error':125 229 case 'empty': 126 230 case 'unknown': 127 errorcount++;128 129 if ( errorcount > 2 )231 settings.errorcount++; 232 233 if ( settings.errorcount > 2 && settings.hasConnected ) { 130 234 trigger = true; 235 } 131 236 132 237 break; 133 238 } 134 239 135 if ( 503 == status && false === hasConnectionError ) { 136 trigger = true; 137 } 138 139 if ( trigger && ! self.hasConnectionError() ) { 140 hasConnectionError = true; 240 if ( trigger && ! hasConnectionError() ) { 241 settings.connectionError = true; 141 242 $(document).trigger( 'heartbeat-connection-lost', [error, status] ); 142 243 } 143 } else if ( self.hasConnectionError() ) { 144 errorcount = 0; 145 hasConnectionError = false; 146 $(document).trigger( 'heartbeat-connection-restored' ); 147 } else if ( null === hasConnectionError ) { 148 hasConnectionError = false; 149 } 150 } 151 244 } 245 } 246 247 /** 248 * Clear the error state and fire an event 249 * 250 * @access private 251 * 252 * @return void 253 */ 254 function clearErrorState() { 255 // Has connected successfully 256 settings.hasConnected = true; 257 258 if ( hasConnectionError() ) { 259 settings.errorcount = 0; 260 settings.connectionError = false; 261 $document.trigger( 'heartbeat-connection-restored' ); 262 } 263 } 264 265 /** 266 * Gather the data and connect to the server 267 * 268 * @access private 269 * 270 * @return void 271 */ 152 272 function connect() { 153 var send = {}, data, i, empty = true, 154 nonce = typeof window.heartbeatSettings == 'object' ? window.heartbeatSettings.nonce : ''; 155 tick = time(); 156 157 data = $.extend( {}, queue ); 273 var ajaxData, heartbeatData; 274 275 // If the connection to the server is slower than the interval, 276 // heartbeat connects as soon as the previous connection's response is received. 277 if ( settings.connecting ) { 278 return; 279 } 280 281 settings.lastTick = time(); 282 283 heartbeatData = $.extend( {}, settings.queue ); 158 284 // Clear the data queue, anything added after this point will be send on the next tick 159 queue = {}; 160 161 $(document).trigger( 'heartbeat-send', [data] ); 162 163 for ( i in data ) { 164 if ( data.hasOwnProperty( i ) ) { 165 empty = false; 166 break; 167 } 168 } 169 170 // If nothing to send (nothing is expecting a response), 171 // schedule the next tick and bail 172 if ( empty && ! self.hasConnectionError() ) { 173 connecting = false; 174 next(); 175 return; 176 } 177 178 send.data = data; 179 send.interval = interval / 1000; 180 send._nonce = nonce; 181 send.action = 'heartbeat'; 182 send.screen_id = screenId; 183 send.has_focus = hasFocus; 184 185 connecting = true; 186 self.xhr = $.ajax({ 187 url: url, 285 settings.queue = {}; 286 287 $document.trigger( 'heartbeat-send', [ heartbeatData ] ); 288 289 ajaxData = { 290 data: heartbeatData, 291 interval: settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000, 292 _nonce: typeof window.heartbeatSettings === 'object' ? window.heartbeatSettings.nonce : '', 293 action: 'heartbeat', 294 screen_id: settings.screenId, 295 has_focus: settings.hasFocus 296 }; 297 298 settings.connecting = true; 299 settings.xhr = $.ajax({ 300 url: settings.url, 188 301 type: 'post', 189 302 timeout: 30000, // throw an error if not completed after 30 sec. 190 data: send,303 data: ajaxData, 191 304 dataType: 'json' 305 }).always( function() { 306 settings.connecting = false; 307 scheduleNextTick(); 192 308 }).done( function( response, textStatus, jqXHR ) { 193 var new _interval;194 195 if ( ! response ) 196 return errorstate( 'empty' );197 198 // Clear error state199 if ( self.hasConnectionError() ) 200 errorstate();309 var newInterval; 310 311 if ( ! response ) { 312 setErrorState( 'empty' ); 313 return; 314 } 315 316 clearErrorState(); 201 317 202 318 if ( response.nonces_expired ) { 203 $ (document).trigger( 'heartbeat-nonces-expired' );319 $document.trigger( 'heartbeat-nonces-expired' ); 204 320 return; 205 321 } … … 207 323 // Change the interval from PHP 208 324 if ( response.heartbeat_interval ) { 209 new _interval = response.heartbeat_interval;325 newInterval = response.heartbeat_interval; 210 326 delete response.heartbeat_interval; 211 327 } 212 328 213 self.tick( response, textStatus, jqXHR ); 214 215 // do this last, can trigger the next XHR if connection time > 5 sec. and new_interval == 'fast' 216 if ( new_interval ) 217 self.interval.call( self, new_interval ); 218 }).always( function() { 219 connecting = false; 220 next(); 329 $document.trigger( 'heartbeat-tick', [response, textStatus, jqXHR] ); 330 331 // Do this last, can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast' 332 if ( newInterval ) { 333 setInterval( newInterval ); 334 } 221 335 }).fail( function( jqXHR, textStatus, error ) { 222 errorstate( textStatus || 'unknown', jqXHR.status );223 self.error( jqXHR, textStatus, error);336 setErrorState( textStatus || 'unknown', jqXHR.status ); 337 $document.trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); 224 338 }); 225 339 } 226 340 227 function next() { 228 var delta = time() - tick, t = interval; 229 230 if ( ! running ) 341 /** 342 * Schedule the next connection 343 * 344 * Fires immediately if the connection time is longer than the interval. 345 * 346 * @access private 347 * 348 * @return void 349 */ 350 function scheduleNextTick() { 351 var delta = time() - settings.lastTick, 352 interval = settings.mainInterval; 353 354 if ( ! settings.isRunning ) { 231 355 return; 232 233 if ( ! hasFocus ) { 234 t = 100000; // 100 sec. Post locks expire after 120 sec. 235 } else if ( countdown > 0 && tempInterval ) { 236 t = tempInterval; 237 countdown--; 238 } 239 240 window.clearTimeout(beat); 241 242 if ( delta < t ) { 243 beat = window.setTimeout( 244 function(){ 245 if ( running ) 356 } 357 358 if ( ! settings.hasFocus ) { 359 interval = 120000; // 120 sec. Post locks expire after 150 sec. 360 } else if ( settings.countdown > 0 && settings.tempInterval ) { 361 interval = settings.tempInterval; 362 settings.countdown--; 363 364 if ( settings.countdown < 1 ) { 365 settings.tempInterval = 0; 366 } 367 } 368 369 window.clearTimeout( settings.beatTimer ); 370 371 if ( delta < interval ) { 372 settings.beatTimer = window.setTimeout( 373 function() { 246 374 connect(); 247 375 }, 248 t- delta376 interval - delta 249 377 ); 250 378 } else { … … 253 381 } 254 382 383 /** 384 * Set the internal state when the browser window looses focus 385 * 386 * @access private 387 * 388 * @return void 389 */ 255 390 function blurred() { 256 window.clearTimeout(winBlurTimeout); 257 window.clearTimeout(frameBlurTimeout); 258 winBlurTimeout = frameBlurTimeout = 0; 259 260 hasFocus = false; 261 } 262 391 clearFocusTimers(); 392 settings.hasFocus = false; 393 } 394 395 /** 396 * Set the internal state when the browser window is focused 397 * 398 * @access private 399 * 400 * @return void 401 */ 263 402 function focused() { 264 window.clearTimeout(winBlurTimeout); 265 window.clearTimeout(frameBlurTimeout); 266 winBlurTimeout = frameBlurTimeout = 0; 267 268 isUserActive = time(); 269 270 if ( hasFocus ) 271 return; 272 273 hasFocus = true; 274 window.clearTimeout(beat); 275 276 if ( ! connecting ) 277 next(); 278 } 279 280 function setFrameEvents() { 281 $('iframe').each( function( i, frame ){ 282 if ( ! isLocalFrame( frame ) ) 403 clearFocusTimers(); 404 settings.userActivity = time(); 405 406 if ( ! settings.hasFocus ) { 407 settings.hasFocus = true; 408 scheduleNextTick(); 409 } 410 } 411 412 /** 413 * Add focus/blur events to all local iframes 414 * 415 * Used to detect when focus is moved from the main window to an iframe 416 * 417 * @access private 418 * 419 * @return void 420 */ 421 function setFrameFocusEvents() { 422 $('iframe').each( function( i, frame ) { 423 if ( ! isLocalFrame( frame ) ) { 283 424 return; 284 285 if ( $.data( frame, 'wp-heartbeat-focus' ) ) 425 } 426 427 if ( $.data( frame, 'wp-heartbeat-focus' ) ) { 286 428 return; 429 } 287 430 288 431 $.data( frame, 'wp-heartbeat-focus', 1 ); 289 432 290 $( frame.contentWindow ).on( 'focus.wp-heartbeat-focus', function( e) {433 $( frame.contentWindow ).on( 'focus.wp-heartbeat-focus', function() { 291 434 focused(); 292 }).on('blur.wp-heartbeat-focus', function(e) { 293 setFrameEvents(); 294 frameBlurTimeout = window.setTimeout( function(){ blurred(); }, 500 ); 435 }).on('blur.wp-heartbeat-focus', function() { 436 setFrameFocusEvents(); 437 // We don't know why 'blur' was fired. Either the user clicked in the main window or outside the browser. 438 // Running blurred() after some timeout lets us cancel it if the user clicked in the main window. 439 settings.frameBlurTimer = window.setTimeout( function(){ blurred(); }, 500 ); 295 440 }); 296 441 }); 297 442 } 298 443 299 $(window).on( 'blur.wp-heartbeat-focus', function(e) { 300 setFrameEvents(); 301 winBlurTimeout = window.setTimeout( function(){ blurred(); }, 500 ); 302 }).on( 'focus.wp-heartbeat-focus', function() { 444 /** 445 * Remove the focus/blur events to all local iframes 446 * 447 * @access private 448 * 449 * @return void 450 */ 451 function removeFrameFocusEvents() { 303 452 $('iframe').each( function( i, frame ) { 304 if ( ! isLocalFrame( frame ) )453 if ( ! isLocalFrame( frame ) ) { 305 454 return; 455 } 306 456 307 457 $.removeData( frame, 'wp-heartbeat-focus' ); 308 458 $( frame.contentWindow ).off( '.wp-heartbeat-focus' ); 309 459 }); 310 311 focused(); 312 }); 313 460 } 461 462 /** 463 * Clear the reset timers for focus/blur events on the window and iframes 464 * 465 * @access private 466 * 467 * @return void 468 */ 469 function clearFocusTimers() { 470 window.clearTimeout( settings.winBlurTimer ); 471 window.clearTimeout( settings.frameBlurTimer ); 472 } 473 474 /** 475 * Runs when the user becomes active after a period of inactivity 476 * 477 * @access private 478 * 479 * @return void 480 */ 314 481 function userIsActive() { 315 userActiveEvents = false; 316 $(document).off( '.wp-heartbeat-active' ); 482 settings.userActivityEvents = false; 483 $document.off( '.wp-heartbeat-active' ); 484 317 485 $('iframe').each( function( i, frame ) { 318 if ( ! isLocalFrame( frame ) ) 486 if ( ! isLocalFrame( frame ) ) { 319 487 return; 488 } 320 489 321 490 $( frame.contentWindow ).off( '.wp-heartbeat-active' ); … … 325 494 } 326 495 327 // Set 'hasFocus = true' if user is active and the window is in the background. 328 // Set 'hasFocus = false' if the user has been inactive (no mouse or keyboard activity) for 5 min. even when the window has focus. 329 function checkUserActive() { 330 var lastActive = isUserActive ? time() - isUserActive : 0; 331 332 // Throttle down when no mouse or keyboard activity for 5 min 333 if ( lastActive > 300000 && hasFocus ) 334 blurred(); 335 336 if ( ! userActiveEvents ) { 337 $(document).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 496 /** 497 * Check for user activity 498 * 499 * Runs every 30 sec. 500 * Sets 'hasFocus = true' if user is active and the window is in the background. 501 * Set 'hasFocus = false' if the user has been inactive (no mouse or keyboard activity) 502 * for 5 min. even when the window has focus. 503 * 504 * @access private 505 * 506 * @return void 507 */ 508 function checkUserActivity() { 509 var lastActive = settings.userActivity ? time() - settings.userActivity : 0; 510 511 if ( lastActive > 300000 && settings.hasFocus ) { 512 // Throttle down when no mouse or keyboard activity for 5 min 513 blurred(); 514 } 515 516 if ( ! settings.userActivityEvents ) { 517 $document.on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 338 518 339 519 $('iframe').each( function( i, frame ) { 340 if ( ! isLocalFrame( frame ) ) 520 if ( ! isLocalFrame( frame ) ) { 341 521 return; 522 } 342 523 343 524 $( frame.contentWindow ).on( 'mouseover.wp-heartbeat-active keyup.wp-heartbeat-active', function(){ userIsActive(); } ); 344 525 }); 345 526 346 userActiveEvents = true; 347 } 348 } 349 350 // Check for user activity every 30 seconds. 351 window.setInterval( function(){ checkUserActive(); }, 30000 ); 352 $(document).ready( function() { 353 // Start one tick (15 sec) after DOM ready 354 running = true; 355 tick = time(); 356 next(); 357 }); 358 359 this.hasFocus = function() { 360 return hasFocus; 361 }; 527 settings.userActivityEvents = true; 528 } 529 } 530 531 // Public methods 532 533 /** 534 * Whether the window (or any local iframe in it) has focus, or the user is active 535 * 536 * @return bool 537 */ 538 function hasFocus() { 539 return settings.hasFocus; 540 } 541 542 /** 543 * Whether there is a connection error 544 * 545 * @return bool 546 */ 547 function hasConnectionError() { 548 return settings.connectionError; 549 } 550 551 /** 552 * Connect asap regardless of 'hasFocus' 553 * 554 * Will not open two concurrent connections. If a connection is in progress, 555 * will connect again immediately after the current connection completes. 556 * 557 * @return void 558 */ 559 function connectNow() { 560 settings.lastTick = 0; 561 scheduleNextTick(); 562 } 362 563 363 564 /** 364 565 * Get/Set the interval 365 566 * 366 * When setting to 'fast', the interval is 5 sec. for the next 30 ticks (for 2 min and 30 sec). 567 * When setting to 'fast' or 5, by default interval is 5 sec. for the next 30 ticks (for 2 min and 30 sec). 568 * In this case the number of 'ticks' can be passed as second argument. 367 569 * If the window doesn't have focus, the interval slows down to 2 min. 368 570 * 369 * @param string speed Interval speed: 'fast' (5sec), 'standard' (15sec) default, 'slow' (60sec)370 * @param string ticks Used with speed = 'fast' , how many ticks before the speedreverts back571 * @param mixed speed Interval: 'fast' or 5, 15, 30, 60 572 * @param string ticks Used with speed = 'fast' or 5, how many ticks before the interval reverts back 371 573 * @return int Current interval in seconds 372 574 */ 373 this.interval = function( speed, ticks ) { 374 var reset, seconds; 375 ticks = parseInt( ticks, 10 ) || 30; 376 ticks = ticks < 1 || ticks > 30 ? 30 : ticks; 575 function setInterval( speed, ticks ) { 576 var interval, oldInerval = settings.tempInterval ? settings.tempInterval : settings.mainInterval; 377 577 378 578 if ( speed ) { 379 579 switch ( speed ) { 380 580 case 'fast': 381 seconds = 5;382 countdown = ticks;581 case 5: 582 interval = 5000; 383 583 break; 384 case 'slow': 385 seconds = 60; 386 countdown = 0; 584 case 15: 585 interval = 15000; 586 break; 587 case 30: 588 interval = 30000; 589 break; 590 case 60: 591 interval = 60000; 387 592 break; 388 593 case 'long-polling': 389 594 // Allow long polling, (experimental) 390 interval = 0;595 settings.mainInterval = 0; 391 596 return 0; 392 597 break; 393 598 default: 394 seconds = 15;395 countdown = 0;396 } 397 398 // Reset when the new interval value is lower than the current one399 reset = seconds * 1000 < interval;400 401 if ( countdown > 0 ) {402 tempInterval = seconds * 1000;599 interval = settings.originalInterval; 600 } 601 602 if ( 5000 === interval ) { 603 ticks = parseInt( ticks, 10 ) || 30; 604 ticks = ticks < 1 || ticks > 30 ? 30 : ticks; 605 606 settings.countdown = ticks; 607 settings.tempInterval = interval; 403 608 } else { 404 interval = seconds * 1000; 405 tempInterval = 0; 406 } 407 408 if ( reset ) 409 next(); 410 } 411 412 if ( ! hasFocus ) 413 return 120; 414 415 return tempInterval ? tempInterval / 1000 : interval / 1000; 416 }; 609 settings.countdown = 0; 610 settings.tempInterval = 0; 611 settings.mainInterval = interval; 612 } 613 614 // Change the next connection time if new interval has been set. 615 // Will connect immediately if the time since the last connection 616 // is greater than the new interval. 617 if ( interval !== oldInerval ) { 618 scheduleNextTick(); 619 } 620 } 621 622 return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000; 623 } 417 624 418 625 /** 419 626 * Enqueue data to send with the next XHR 420 627 * 421 * As the data is sen t later, this function doesn't return the XHR response.628 * As the data is send asynchronously, this function doesn't return the XHR response. 422 629 * To see the response, use the custom jQuery event 'heartbeat-tick' on the document, example: 423 630 * $(document).on( 'heartbeat-tick.myname', function( event, data, textStatus, jqXHR ) { … … 429 636 * $param string handle Unique handle for the data. The handle is used in PHP to receive the data. 430 637 * $param mixed data The data to send. 431 * $param bool dont_overwrite Whether to overwrite existing data in the queue.638 * $param bool noOverwrite Whether to overwrite existing data in the queue. 432 639 * $return bool Whether the data was queued or not. 433 640 */ 434 this.enqueue = function( handle, data, dont_overwrite ) {641 function enqueue( handle, data, noOverwrite ) { 435 642 if ( handle ) { 436 if ( dont_overwrite && this.isQueued( handle ) )643 if ( noOverwrite && this.isQueued( handle ) ) { 437 644 return false; 438 439 queue[handle] = data; 645 } 646 647 settings.queue[handle] = data; 440 648 return true; 441 649 } 442 650 return false; 443 } ;651 } 444 652 445 653 /** … … 449 657 * $return bool Whether some data is queued with this handle 450 658 */ 451 this.isQueued = function( handle ) { 452 if ( handle ) 453 return queue.hasOwnProperty( handle ); 454 }; 659 function isQueued( handle ) { 660 if ( handle ) { 661 return settings.queue.hasOwnProperty( handle ); 662 } 663 } 455 664 456 665 /** … … 460 669 * $return void 461 670 */ 462 this.dequeue = function( handle ) { 463 if ( handle ) 464 delete queue[handle]; 465 }; 671 function dequeue( handle ) { 672 if ( handle ) { 673 delete settings.queue[handle]; 674 } 675 } 466 676 467 677 /** … … 471 681 * $return mixed The data or undefined 472 682 */ 473 this.getQueuedItem = function( handle ) { 474 if ( handle ) 475 return this.isQueued( handle ) ? queue[handle] : undefined; 683 function getQueuedItem( handle ) { 684 if ( handle ) { 685 return this.isQueued( handle ) ? settings.queue[handle] : undefined; 686 } 687 } 688 689 initialize(); 690 691 // Expose public methods 692 return { 693 hasFocus: hasFocus, 694 connectNow: connectNow, 695 setInterval: setInterval, 696 hasConnectionError: hasConnectionError, 697 enqueue: enqueue, 698 dequeue: dequeue, 699 isQueued: isQueued, 700 getQueuedItem: getQueuedItem 476 701 }; 477 702 }; 478 703 479 $.extend( Heartbeat.prototype, { 480 tick: function( data, textStatus, jqXHR ) { 481 $(document).trigger( 'heartbeat-tick', [data, textStatus, jqXHR] ); 482 }, 483 error: function( jqXHR, textStatus, error ) { 484 $(document).trigger( 'heartbeat-error', [jqXHR, textStatus, error] ); 485 } 486 }); 487 488 wp.heartbeat = new Heartbeat(); 489 490 }(jQuery)); 704 // Ensure the global `wp` object exists. 705 window.wp = window.wp || {}; 706 window.wp.heartbeat = new Heartbeat(); 707 708 }( jQuery, window ));
Note: See TracChangeset
for help on using the changeset viewer.