I currently have an Ajax-based chat, which I am trying to streamline by only loading the chat script when an update occurs. Thus, nothing needs to keep loading if nothing has changed in the database.
My current logic says:
JavaScript function fires every 1/2 second to get chat logs (setInterval())
If nothing has changed, though, it seems fairly inefficient to keep calling it. Instead, what I'd like to do is:
JavaScript function checks if there are any new logs in the database
If YES - load the new logs, if NO - leave the currently displayed logs alone.
How would I go about this, though? The function I am currently using is:
function updateShouts() {
$('#chatArea').load('chat.php'); // load chat logs
}
setInterval("updateShouts()", 500); // call function every half a second
I would pass timestamps (or message_ids) along with any chat messages that the server-side script sends to a client. Then the client simply asks for new messages, and the server sends only what's new.
So, imagine that each chat message has an ID. I'd design my chat.php to accept a parameter like so:
chat.php?since=12345
12345 would be the id of the last message the client has seen. chat.php essentially does something like:
SELECT * FROM chatmessages WHERE id > $since
... and passes back a nice little data structure (an array of objects, encoded in JSON, let's say).
So, if there are no new chat messages, the server is just passing back an empty array.
I don't think you can be any more efficient than that.
EDIT:
I realize that doing it this way requires a little more client-side coding. You're no longer just updating some div with the whole chat history. You'll also need to have a handler on your ajax call that iterates over the results, and for each message, programatically construct a div for that line, then appends it to your chat div.
One relatively simple way to do this is to use AJAX to fetch a page that simply tells you if there has been any update. So for example, you could fetch a page like checkForUpdate.php that has a 1 or a 0 to indicate if there is anything new in the chat. If you got a 1 back, you could go ahead and load the full chat.php page.
(If you haven't used AJAX before, this is a pretty good tutorial: http://www.tizag.com/ajaxTutorial/)
Another solution (and one that I think is probably better) is to load a page that only has the most recent chat lines. For example, say you are currently displaying lines 1-14 of the chat. You could then use AJAX to fetch the content of, for example, getLines.php?s=14. This page would only display the lines of the chat after line 14. You would then just append those lines to the end of the current chat window.
As you know the .load function fills an element with the output returned by your chat.php file. This .load function does two steps: It makes an ajax request to the chat.php and then sets the value of the element to the output of chat.php. What you want to do is just the first step. To do this use the .ajax function
http://api.jquery.com/jQuery.ajax/
Instead of using the chat.php file I would suggest calling a different script like isChatUpdated.php. That script will do just like the name suggests and check if there has been any changes in the chat. You can then use that result to figure out whether you need to call your .load function.
Either way you need to query the db in the server side, so is almost irrelevant if it returns log data or a single value.
You can decide not to update #chatArea, based on a return value, but you have to make another call to retrieve the logs, otherwise.
I would first create a file called for example messages.php that looked something like this:
<?php header('Content-Type: application/json');
$messages_since = !empty($_POST['since'])
? mysql_real_escape($_POST['since'])
: '0000-00-00 00:00:00');
// Get all messages from database since the $messages_since date_time
echo json_encode($array_with_messages);
Then on the client side using jQuery or something like that I would do something like this:
Get messages using something like $.post('messages.php', new_messages_handler)
In the handler I would create html for each new message we got back and append/prepend it to the chat container as well as store what time the latest message was created.
Wait a while
Get new messages using something like $.post('messages.php', {since: latest_datetime_we_have}, new_messages_handler)
Go to 2
At least it works pretty nicely in my head :p
Related
I have a page that uses ajax to show users their current assignments. Instead of having to refresh the page to see if there are any updates, I'm using ajax to update the data every 4 seconds. It's been requested that I change the document title to show something like "Number of Tasks: 4" and have that update as well when the user either completes a new task, or gets assigned another one. I tried using a simple "setInterval" javascript function, but since PHP is server side, the variable piece doesn't update...
I've also tried setting "document.title" from within the ajax code, but that just plain didn't work.
Is there a simple way to update the document title to show the number of tasks assigned to the user viewing the page?
Return the value from the $_SESSION in the data sent with the AJAX response to the client Javascript code. Once you have it on the client side set whatever you need to it with javascript.
You'd have to call with ajax a php dedicated to return you only the number of tasks (and other information you may want).
To change the title you can just call document.title = "the data returned in ajax";.
And put all this code (ajax call and title set) inside a function with setinterval as you mentioned.
I'm making a Social networking website for my friends. i wanted to know how i would Update a Div containing few inserted records of the database, when a new record is added in the database. In short you must have seen the live notifications of facebook, which fade in when someone does something . this all happens without the refreshing of the whole live notification div. only the new notification is prepend to the div.
I would like to do this using jquery and AJAX as i have good knowledge about them. and PHP as the server side language.
Thank you in Advance.
P.S : I have searched many websites for the solution, but couldnt find it anywhere. i Even tried going through facebook's Source code but couldnt find it there too ! I hope someone helps me here ! *crossed fingers*
You can either use Ajax Push to send a notification that the post is updated, or you can make it pull-driven. The latter would probably be easier for you if you already know jquery and Ajax with PHP.
Periodically check for new records on an interval (using setInterval, for example) and if you find them, load them to the DOM and fade them in. The interval doesn't have to be very small and waste resources .. maybe something as long as every 30 seconds will do.
setInterval('checkForUpdates', 30000);
var lastTime = (new Date()).getTime();
function checkForUpdates() {
$.get('/php-page-that-checks-for-updates.php?timestamp=' . lastTime
, function (results) {
if (results) { /* fade into dom */ }
}
);
lastTime = (new Date()).getTime();
}
PHP page:
$timestamp = $_REQUEST['timestamp'];
$results = query('SELECT post FROM posts WHERE postTime > "$timestamp"');
echo fetch($results);
As others suggested, you can also mark posts as "read" and use that as an indicator instead of the timestamp, which will also solve a time zone problem with my example. I wouldn't want to add an extra column just to do this, but if you already have one for some other reason it'd be a good idea.
EDIT: This is a pretty old answer, but if you can still do it I would use WebSockets instead of any kind of ajax long polling. I don't think that PHP is a great language (I would suggest using socket.io with Node.js), but it is possible.
Basically it goes something like this:
Create a javascript function on your page that makes an ajax call (with jquery or native xhr or what not) to a php page. The php page keeps track of "new stuff" and returns it when called. The js function, when receiving data, add new tags (divs or whatever) to the notification bar. The function is called every once in a while with javascript's setTimeout function.
If some of these steps are confusing to you please ask a more specific question.
You can use jQuery's $.getJSON() method to access a PHP page. This PHP page would grab all unread notifications (you could add a column in your notifications table called "read" and set it to 0 for unread and 1 for unread) and return them as a JSON feed.
Parse the JSON and make each one a div that shows up on the page. Then wrap this all in a setInterval() and run it every millisecond (or half a second, or quarter of a second, it's up to you).
Also, to mark them as read, set up a click event on these divs that you created from the JSON notification feed. On click, it will contact another PHP page (you can use $.post or $.get) which will receive the id of the notification, for example, and change the read column to 1.
This is more of curiosity that anything, but I can think of several places (mainly in admin sections) where this could be useful. I know the title is confusing so this is what I mean:
Say you have a form that posts to example_cb.php. example_cb.php is a very large callback page that generates multiple thumbnails of an image, puts them in their respective directories, adds them to a database, etc. You already have the form posting by jquery with a function like this
$.post('example_cb.php', $(this).serialize(), function(data) {
// Success
}, 'json');
Before posting it updates a div to say "processing" of something. Then after it successfully completes the div fades out. However you want the div to show what is happening on the server side. i.e. Converting 200X200 thumb > Converting 350x350 thumb > Adding Records to Database > etc.
How can you accomplish this?
I know it's a loaded question, but I'm confident there are people on here smart enough to figure it out. If you need more info please comment :)
You could do something like -
Write each 'event' update to a database table
Write a page that retrieves the last n events from table
Use something like 'load' to call page update an onscreen div
with the updated progress.
Use 'setTimeout` to keep updating.
This could be accomplished most easily with using the push method, but I'm not too familiar with ajax push or comet technology, so I'll give you a pull solution.
Basically you need to create the initial ajax request to start the processing. Then, you need to have another request running in a tight loop that checks against a php page for the current status. For example, on the php page doing the processing, you can update a _SESSION key that stores the current processing information (like "Converting 200X200 thumb") at each step. Another php page will exist purely to print that information and you can retrieve it with the JS running in a loop.
pusher like services may be used for bi-directional communication.
I'm putting it down for reference, though this would be overkill for such a simple scenerio.
Context
I'm working on a project that I'd like to make more dynamic with PHP + AJAX.
I'm using jQuery for the AJAX part because I totally suck in Javascript, and anyway it seems to be worth something.
I reached a point where my application needs to use a form to send a post, and I want to use an ajax call to perform this action. In the page I'd like to send the post, there is also a list of the most recent 15 posts submitted.
First question: Should I just forget about it and use just PHP?
The action
The user writes something in the <textarea></textarea> and clicks on a <a id="myPostSubmit">Submit</a> that is the handler that I'll manage on the jQuery script with something like $("#myPostSubmit").live('click', function() { /* here i make the ajax call */ });. If the post is successfully submitted we are going to do something (I'll talk about it in the next section), either we will alert the user using my showAlert(text) function, that shows a black box for 4 seconds with the text in it.
Second question: Should I manage the click event in any other ways? Should I create a function, such as sendpost(post) and attach it into the HTML onclick="" event?
If the post is successfully sent
I'd open a discussion about 2 options:
We refresh the page [not actually
loading the entire page but making
another ajax call that retrieves the
posts lists and makes disappear the
old one, load the PHP file to
retrieve the new posts (including
the one we just sent), and then make
the post list appear]. Pro: 1) We are sure that what the user is reading after the post list is loaded is the real post sent. So it actually double checks the action. 2) We load also some possible posts sent in the mean while. Cons: 1) We have to create a PHP file that gets the post list template, slicing the template of that page in 2 files. 2) It doesn't really seems that smooth to me.
We just use Javascript to get the post template, add it to the list. Pro: 1) We make it really smooth, without reloading the entire page. 2) We don't need of any PHP file to reload the page. We just use Javascript (jQuery). Cons: 1) How do we get the post html template to add it to the list? 2) How do we get the user (logged) informations without PHP?
Third question: Is it better the 1st or the 2nd solution? Would you provide a even better 3rd solution?
The PHP page
The PHP page that will receive this AJAX call is : ?p=action&a=sendpost. The page require $_POST['myMessage'] to be set and not empty and nothing else. The page itself will get all the user infos from the cookies and will manage to perform the needed query.
The application
It is divided in 3 parts: App, Template, Library. Basically each page of the application has its own .app.php and .tpl.php file.
The .app.php file manages the building
of the basis of the page, using classes
and other stuff from the library. In
our case it retrieves datas from the
database and put them into
variable.
The Template is called at the end of the .app.php file. The .app.php file send to the template the retrieved data and the .tpl.php file outputs them.
The library is used to contain the classes and functions we need in the application file.
Fourth question: Is this a good way of manage my web application?
Edit: What about returning the alert message to the user?
I read about an option, inside $.ajax() that will manage the response on success or in error. The documentation about it is very simple and I didn't get it.
Fifth question: How should I return (from the PHP file) the error
or the success?
First question: Should i just forget about it and use just PHP?
Well, you application will relay on JavaScript if you use ajax, this days i think it just fine ;)
Second question: Should i manage the click event in any other ways? Should i create a function, such as sendpost(post) and attach it into the HTML onclick="" event?
Create a function and bind onclick. Code will be more readable ;)
Third question: Is it better the 1st or the 2nd solution? Would you provide a even better 3rd solution?
My solution: ajax submit the form and on callback insert new comment in to the list or display error message if user can't comment.
Check jQuery serilize() for submitting forms data with ajax.
Fourth question: Is this a good way of manage my web application?
It's just fine ;) When you application get's bigger you will have to redesign it, but don't do it know, do it when current solution becomes to hard to work with.
Read some good book on building MVC framework. And on programming patterns in general.
You seem to be on the right track with everything. There are lot of opinions called "best practices" about how to exactly attach event handlers, how to reload the data on the page and how to organize your application, etc, but I personally would rather build more software instead of worrying about details like that. The details will come to you eventually.
I personally find that updating whole chunks of server-side-rendered HTML on the page is more robust solution, but I have seen people getting excellent results with templates.
I have a run.php that has a button on it called "Run". Clicking it does a jQuery $.get() AJAX call back to a response.php on the server, and sends the result to a Javascript callback function getResponse(sData) inside run.php's HTML for display back on the browser. I want to have things such that as response.php runs through a list of tasks, it echoes a response back with the echo command and for getResponse to update a DIV with that status as it moves along. So, let's say I have 5 steps inside response.php, and therefore 5 echo statements back to getResponse().
I tried to get this to work, but what happens is that jQuery waits and then sends one single response all at once, rather than sending as it goes along with the 5 responses.
What's the technique?
The reason I ask is that I have a script that does something to a bunch of files. The first thing it does is a file count, so it updates my progress bar. Then, as it runs through files, it needs to increment my progress bar like every 1000 files.
I think there's no way to make that ajax call to have multiple response in just one call... but what I could suggest is you make a session on php... and in every steps on your tasks function, update that session... then make another ajax call that checks that session if any updates happened... if there is update then do what you have to do....
As you can't really get progress with xmlhttprequest, I suggest you can look into other ways of doing AJAX calls. One of them is through iframe. You can create hidden iframe, set it's sources to request.php and then periodically just check it's content. It should be possible since it's all it the same domain and restrictions does not apply.
iframe might work because it's not that different from normal browser window, meaning that it periodically applies data it gets into DOM even if request hasn't been finished yet. There's potentially might be problems with how different browsers do that, i.e. IE shows new content only if it got more than 4K or something. But it is possible to overcome that, I'm sure.
So, create new hidden iframe, add src attibute to your php script, make that script periodically write something to the client and on the client check what have been written and convert it to shiny GUI stuff.