jquery Send Heartbeat when Viewing Page - php

I've written the following Jquery to send a Heartbeat back to PHP every 3 seconds and it works fine. The reason I'm doing this is to understand what users are currently logged in and using the site.
setInterval(function () {
$.post('includes/heartbeat.php', {'heartBeatConfirmation': '1'});
},3000);
The catch I'm finding is it continues to heartbeat when users aren't looking at the site - eg: they still have the browser open but are looking at other pages or doing something else.
Is there a way to update this so it only sends the AJAX heartbeat if the user is using the site?

You can check if window is focused and only heartbeat if it's focused.
Try this:
$(window).focus(function() {
heartbeat = setInterval(function () {
$.post('includes/heartbeat.php', {'heartBeatConfirmation': '1'});
},3000);
})
.blur(function() {
clearInterval(heartbeat);
});
$(window).focus();

$(document).ready(function(){
heartBeatInterval = null;
$(window).focus(function() {
if(heartBeatInterval == null){
heartBeatInterval = setInterval(function () {
$.post('includes/heartbeat.php',
{'heartBeatConfirmation': '1'}
);
console.log('We have the fouces of the active tab');
},1000);
}
});
$(window).blur(function() {
heartBeatInterval = null;
console.log('We have the lost the focus of the active tab');
});
});

It is just a matter of taste I guess:
$(window)
.on('mouseleave', function(){
clearInterval(inside);
})
.on('mouseenter', function(){
inside = setInterval(function () {
$.post('includes/heartbeat.php', {'heartBeatConfirmation': '1'})
}, 3000)
})
JSFIDDLE ( Reminder: window is "Result" Frame ).

Related

Update div after jquery ajax request only if content is new

I've recently started learning jQuery and I'm trying to make a little messaging system, I've gotten the messages to update every 2 seconds. However, I don't want the messages to update if there aren't any new messages. This is my current message updating code.
$(document).ready(function () {
setInterval(function() {
$.get("get_messages.php", function (result) {
if ($('.messages').html() != result){
$('.messages').html(result);
}
});
}, 2000);
});
The if statement doesn't seem to be working even though the div and result should be the same.
I hope that you have timestamp or messageID on server that could tell your script if there are new messages after last check.
ex.
var lastMessageID = 0;
function checkMessages(){
$.ajax(url,{
data:{
last_message_id:lastMessageID
},
success:function(data){
// Count new messages
if (Object.keys(data).length > 0){
$.each(data,function(index, item){
$('.messages').prepend("<span class='message'>"+item.message+"</span>");
});
// We suggest that this is our last message
lastMessageId = data[Object.keys(data).length-1].id;
}
}
});
}
var intervalM = setInterval(function(){
checkMessages();
},2000);
And please save some trees by using gziped JSON data. :)

JQuery SetTimeout before running code

I'm trying to run a function in JQuery that basically shuts down or starts up a server. The code I have so far is this -
$(".stopServer").click(function(){
$.post("controller.php",{stop: 'true', server: this.name});
$('#test'+this.name).load('controller.php?status=true&server='+this.name);
});
The problem is obviously it stops the server fine but it updates the status div ('#test'+this.name) straight away. This is no good because the server takes a period of time to shut down. I've been trying to get SetTimeout to work but can't figure it out... Any help would be appreciated.
Thanks guys, you're the best :)
UPDATE:
Full functions are here:
$(document).ready(function() {
$(".startServer").click(function(){
$.post("controller.php",{server: this.name});
setTimeout("showStatus('"+this.name+"')", 3000);
});
$(".stopServer").click(function(){
$.post("controller.php",{stop: 'true', server: this.name});
setTimeout("showStatus('"+this.name+"')", 3000);
});
function showStatus(name) {
alert(name);
$('#test'+name).load('controller.php?status=true&server='+name);
}
});
UPDATE
Given up on the idea of it, instead the status is polled for every second instead.
var refreshId = setInterval(function()
{
$('.status').each(function() {
var $name = $(this).attr('name');
$(this).load("controller.php?status=true&server=" + $name);
});
}, 1000);
I've added a quick sample of wrapping the function in a setTimeout
​$(document).ready(function(){
$('#test').click(function(){
var message = 'hello';
setTimeout(function(){ callback(message) },1000);
});
function callback(name){
alert(name);
}
});​
JSFiddle DEMO
I dont know if you will get a response from 'controller.php' when the server actually shuts down, in case you don't, try this...
$(".stopServer").click(function(){
$.post("controller.php",{stop: 'true', server: this.name});
setTimeout("showStatus('"+this.name+"')", 10000);
});
function showStatus(name) {
$command = $('#test'+name).load('controller.php?status=true&server='+name);
}
ajax calls are asynchronous. the $.post() call returns immediately and lets the actual post work be done in the background. either change it to a synchronous call (usually not a good idea), or put the subsequent code in the "success" part of the .post call, e.g.
$.post('controller.php', success: function(data) {
$command = etc....
});

Destroy a dialog in jQuery UI

I'm working on a system using jQuery UI that opens a dialog which basically loads a continually refreshing tail of a log file. It works great, but the problem is that when you close it, it doesn't kill off the dialog, so it still continues to send traffic to you with the tail of the file. Obviously it is not a good practice.
Anyway, the code I have so far to try and tackle the problem is as follows.
var $console = $('<div title=" Server Console"></div>')
.dialog({
height: 720,
width: 1000,
resizable: false,
autoOpen: false
});
$(".consoleOpen").click(function(){
$console.dialog('open').load("console.php?console="+this.name);
});
$console.bind('dialogclose', function(event) {
$console.remove();
});
This is the refresh function in console.php:
(function($)
{
$(document).ready(function()
{
var $container = $("#responsecontainer");
$container.load("console_class.php?console=<?php echo $console; ?>");
var refreshId = setInterval(function()
{
$container.load('console_class.php?console=<?php echo $console; ?>');
}, <?php echo $consoleRefresh;?>);
});
})(jQuery);
Look at the API function destroy()
$console.bind('dialogclose', function(event) {
$console.dialog('destroy').remove();
});
You also need to use clearInterval or else it will keep running as long as the page is open.
$console.bind('dialogclose', function(event) {
$console.dialog('destroy').remove();
clearInterval(refreshID);
});
Try this:
$console.bind('dialogclose', function(event) {
$console.dialog( "destroy" );
});
or read this jQuery Dialog
You mentioned it already
$console.dialog("destroy");
The dialog is not the issue here - it's the interval that's making the call.
Where you declare refreshId do it like this...
var window.refreshId = setInterval(function()
Then where you remove the dialog, add a clearInterval...
$console.bind('dialogclose', function(event) {
$console.remove();
clearInterval(window.refreshId);
});
That makes the variable refreshId global so that it can be accessed elsewhere in your code. You can then use it to clear the interval that is making the repeated call.
I've had this same problem...
See:
jQuery UI dialog close doesn't clear dialog (Stack Overflow question)
Creating dialogs on demand (blog entry)
You need to call $('#dialog_id').dialog("destroy");.

Re-Initialize jQuery after XMLHttpRequest

I'm using Twitter Bootstrap's Popover feature on a sidebar. The sidebar is fetched and reloads the content every 30 seconds. I'm suing XMLHttpRequest to reload the content of the sidebar by fetching a file called stats.php.
The following code is the "refresh" code which resides in the header of the page.
function onIndexLoad()
{
setInterval(onTimerCallback, 30000);
}
function onTimerCallback()
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
document.getElementById("stats").style.opacity = 0;
setTimeout(function() {
document.getElementById("stats").innerHTML = request.responseText;
document.getElementById("stats").style.opacity = 100;
}, 1000);
}
}
request.open("GET", "stats.php", true);
request.send();
}
The above code works flawlessly, however, after it reloads the #stats div, the popover no long does what it's supposed to - popup.
The popover code is in the stats.php in a foreach() loop because I have multiple popover scripts I need because there are multiple popovers on the sidebar.
Here's my popover code:
$(document).ready(function() {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
The $id and $title are dynamic as they are pulled from the foreach() loop.
How can I fix it so after the div reloads, the popover function will reinitialize?
$("a[rel=popover_controller_$cid]").on({
mouseenter: function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
}
});
I have also tried:
$("a[rel=popover_controller_$cid]").on("mouseover", function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
.live is depreciated. use .on delegation
try something like this:
$('#stats').on("mouseenter", "a[rel=popover_controller_$cid]",function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
This delegates the mouseenter event from #stats to a[rel=popover_controller_$cid] and because the event is delegated it will still fire when #stats contents are replaced.
be careful - you will keep initializing popover on each mouseover. that might be bad.
while you are at it - you should use jquery's ajax instead of native xhr. its easier and more cross browser.
$.get('stats.php', function(d){
$('#stats').html(d);
};
--
setInterval(function(){
$.get('stats.php', function(data) {
$('#stats').html(data);
});
}, 30000);

jQuery animations don't work correctly if Ajax request is too fast

I've looked around a bit and haven't found an answer to this yet.
I have an ajax request that when you click the button it sends info to the server and hides the current div and loads a loading gif. I have it set so when the server responds it gets rid of loading gif and shows the content from the server.
code:
$("#submit").click(function(e){
e.preventDefault();
var $domain = $.fn.HTTP($('#domain').val());
if(!$.fn.ValidURL($domain)){
$('#domainerror').fadeIn(500);
return false;
}
if($('#domainerror').css('display')!=='none'){
$('#domainerror').fadeOut(350);
}
$('#question').hide(500, function(){
$('#waiting').show(350);
});
$.getJSON('http://localhost/file.php',
{
i: $domain
},
function(data){
$('#answer').html(data.message + $('#trybutton').html());
$('#waiting').hide(350, function(){
$('#answer').show(350);
});
});
});
The problem is jQuery receives the response from the server too fast and the loading gif doesn't disappear.
However if I tell the server to sleep for 3 seconds it works just fine. This is not the solution I want.
Any ideas?
Surely it's a good thing your users aren't having to see a loading animation because it's so fast?!
Anyway, the problem is that the animation is taking at least 500ms - animations are processed asynchronously, at the same time as your AJAX request. Instead of making the server sleep, which is arguably a waste of CPU, make the browser wait instead, before you send the AJAX request.
Put the call in a setTimeout() function, this example will make it wait 3 seconds:
setTimeout(function() {
$.getJSON('http://localhost/file.php',
{
i: $domain
},
function(data){
$('#answer').html(data.message + $('#trybutton').html());
$('#waiting').hide(350, function(){
$('#answer').show(350);
});
});
}, 3000);
The ideal solution however would be to not use animation effects and just use show() and hide().
Get rid of the delay in showing the waiting animation, so it's not still showing up when the request returned.
$('#question').hide() //was 500
$('#waiting').show(); //was 350
If you add all up that's almost a second later. By that time the ajax request may have returned in most systems, so it's not worth to be still animating by that point
Use Javascript's setTimeout. Code may look something (perhaps not exactly) like this:
setTimeout("getResponse()", 3000);
function getResponse() {
$.getJSON('http://localhost/file.php',
{
i: $domain
},
function(data){
$('#answer').html(data.message + $('#trybutton').html());
$('#waiting').hide(350, function(){
$('#answer').show(350);
});
});
}
That way you've got your AJAX request still sending your i variable to the server, processing the code in file.php and sending back data which you can handle. The only trick is to put this in a function (not required, but it certainly makes the setTimeout function look prettier) and call it after 3000 milliseconds.
Seems like the ajax callback is executed before the question hiding ends, and the $('#waiting').show(350); comes after $('#waiting').hide(350, ...). You have three possibilities to solve that:
If you'd show the #waiting img immidiately (not waiting for the question to fade out), this won't happen; the answer should then also not wait for #waiting to hide.
Or you use a variable to indicate that the answer is already fading in when the question has faded out, and show no animation then:
var answered = false,
waiting = false;
$('#question').hide(500, function(){
if (!answered) {
waiting = true;
$('#waiting').show(350);
}
});
$.getJSON('http://localhost/file.php', {
i: $domain
}, function(data){
$('#answer').html(data.message + $('#trybutton').html());
answered = true;
if (waiting) {
$('#waiting').stop().hide(350, function(){
$('#answer').show(350);
});
} else {
$('#answer').show(350);
}
});
If you want the four animations to show always and consecutively (at least 1550ms), you'd need to code them manually:
var showanswer = false;
$('#question').hide(500, function() {
$('#waiting').show(350, function() {
if (showanswer) // already loaded
showanswer(); // execute callback
else
showanswer = true; // mark as shown
});
});
$.getJSON('http://localhost/file.php', {
i: $domain
}, function(data){
$('#answer').html(data.message + $('#trybutton').html());
function animate() {
$('#waiting').hide(350, function(){
$('#answer').show(350);
});
}
if (showanswer) // waiting image shown
animate();
else
showanswer = animate; // set as callback
});

Categories