WordPress/wp-includes/js/heartbeat.js

179 lines
3.4 KiB
JavaScript
Raw Normal View History

/**
* Heartbeat API
*/
// Ensure the global `wp` object exists.
window.wp = window.wp || {};
(function($){
var Heartbeat = function() {
var self = this,
running,
timeout,
nonce,
screen = typeof pagenow != 'undefined' ? pagenow : '',
settings,
tick = 0,
queue = {},
interval,
lastconnect = 0;
this.url = typeof ajaxurl != 'undefined' ? ajaxurl : 'wp-admin/admin-ajax.php';
this.autostart = true;
if ( typeof( window.heartbeatSettings != 'undefined' ) ) {
settings = $.extend( {}, window.heartbeatSettings );
delete window.heartbeatSettings;
// Add private vars
nonce = settings.nonce || '';
delete settings.nonce;
interval = settings.interval || 15000; // default interval
delete settings.interval;
// todo: needed?
// 'pagenow' can be added from settings if not already defined
screen = screen || settings.pagenow;
delete settings.pagenow;
// Add public vars
$.extend( this, settings );
}
function time(s) {
if ( s )
return parseInt( (new Date()).getTime() / 1000 );
return (new Date()).getTime();
}
// Set error state and fire an event if it persists for over 3 min
function errorstate() {
var since;
if ( lastconnect ) {
since = time() - lastconnect;
if ( since > 180000 ) {
self.connectionLost = true;
$(document).trigger( 'heartbeat-connection-lost', parseInt(since / 1000) );
} else if ( self.connectionLost ) {
self.connectionLost = false;
$(document).trigger( 'heartbeat-connection-restored' );
}
}
}
function connect() {
var data = {};
tick = time();
data.data = $.extend( {}, queue );
queue = {};
data.interval = interval / 1000;
data._nonce = nonce;
data.action = 'heartbeat';
data.pagenow = screen;
self.xhr = $.post( self.url, data, function(r){
lastconnect = time();
// Clear error state
if ( self.connectionLost )
errorstate();
self.tick(r);
}, 'json' ).always( function(){
next();
}).fail( function(r){
errorstate();
self.error(r);
});
};
function next() {
var delta = time() - tick;
if ( !running )
return;
if ( delta < interval ) {
timeout = window.setTimeout(
function(){
if ( running )
connect();
},
interval - delta
);
} else {
window.clearTimeout(timeout); // this has already expired?
connect();
}
};
this.interval = function(seconds) {
if ( seconds ) {
// Limit
if ( 5 > seconds || seconds > 60 )
return false;
interval = seconds * 1000;
} else if ( seconds === 0 ) {
// Allow long polling to be turned on
interval = 0;
}
return interval / 1000;
};
this.start = function() {
// start only once
if ( running )
return false;
running = true;
connect();
return true;
};
this.stop = function() {
if ( !running )
return false;
if ( self.xhr )
self.xhr.abort();
running = false;
return true;
}
this.send = function(action, data) {
if ( action )
queue[action] = data;
}
if ( this.autostart ) {
$(document).ready( function(){
// Start one tick (15 sec) after DOM ready
running = true;
tick = time();
next();
});
}
}
$.extend( Heartbeat.prototype, {
tick: function(r) {
$(document).trigger( 'heartbeat-tick', r );
},
error: function(r) {
$(document).trigger( 'heartbeat-error', r );
}
});
wp.heartbeat = new Heartbeat();
}(jQuery));