I'm trying to recreate the Gmail 'star' favourite button using AJAX. Unfortunately what I have isn't working and I can't work out why.
I have the following in my HMTL:
<img id="item_1" src="/_images/star_off.gif" onclick="updateStar(this.id)" />
<img id="item_2" src="/_images/star_off.gif" onclick="updateStar(this.id)" />
And I'm using the following Javascript in a seperate file:
function updateStar(id) {
var imgsrc = (document.getElementById(id).src == "/_images/star_off.gif") ? "/_images/star_on.gif" : "/_images/star_off.gif";
var sendId = id.split('_')[1];
var sendStar = (imgsrc == "/_images/star_off.gif") ? false : true;
var objXml = new XMLHttpRequest();
var datasource = "favourite.php";
var params = "id=" + sendId + "&star=" + sendStar;
objXml.open("GET", datasource + "?" + params, true);
objXml.onreadystatechange=function() {
if ((objXml.readyState==4) && (objXml.status==200)) {
alert('status changed.');
}
}
objXml.send(null);
}
The script favourite.php sets inserts the id into a favourites database table (or removes it if star == false).
I can't see what is wrong here but it isn't working. I've also tried the suggestions on jQuery: Gmail Star? but they wont work either. Any suggestions?
I'd check to see if the Xml Http Request is even firing, and if so, what value does it hold when it does. If you have the Safari browser, you can use the Web Inspector to see this. Under Web Inspector, go to Resources/XHR, and click on the url path that corresponds to the path you set in your ajax call. Then click on the Content tab and look at the output there. If it's blank, then you know the ajax call is failing. If it has a value, make sure it's the value you expect.
Though it's hard to see where the problem is if you don't tell exactly what it is that's not working (e.g., the XMLHttpRequest call is never made, the final readyState or status are not reached), I see some flaws in your code. E.g., look at
var imgsrc = (document.getElementById(id).src == "/_images/star_off.gif") ? "/_images/star_on.gif" : "/_images/star_off.gif";
Here you're testing what the current status of the star is depending on the src
property of the image. A quick test revealed that in Firefox 3.6.8 the src
property contains the full URL of the image source, including protocol, domain and full path. So, in my test, the condition
(document.getElementById(id).src == "/_images/star_off.gif")
will always evaluate to false
, always setting imgsrc
to "/_images/star_off.gif"
(so this function will never turn on the star).
A few lines later, you're testing the exact same condition again:
var sendStar = (imgsrc == "/_images/star_off.gif") ? false : true;
Try to avoid this kind of redundancy (e.g., using a boolean from the beginning); that will probably lessen the chance of introducing bugs. Moreover, in this case, the conditional operator (? :
) is not necessary at all; this line could be rewritten to
var sendStar = (imgsrc != "/_images/star_off.gif");
but, as I said, try to avoid these kind of string comparisons to check the state of those stars.
IMHO, it's neater to either use two separate functions that turn on and off your star, so there's no need to test this at all, or send the state using a parameter, e.g.
<img id="item_1" src="/_images/star_off.gif" onclick="updateStar(this.id, true)" />
where true
will turn on the star.
And of course it's neater to bind an event within your JavaScript (or even only show the star using JavaScript, so it's not shown when JS is unavailable).