Fly Yahoo UI
Here goes the rhyme:
Make your content management application fly
with the Yahoo library of JavaScript UI...
Making fancy UI stuff has never been easier. Google released their JavaScript XSLT library, Prototype is everywhere, others too... now Yahoo! released their UI library. I took a look at Y! stuff, let me show you what I did.
» Before you continue, feel free to check the demo at any time
CMS
OK, let the first one who has never coded some sort of Content Management System throw a stone. Yep, that's what I thought. Writing a CMS is like the new Hello World
A very simplistic CMS would have a bunch of data records and options to add new records, to modify existing entries or to delete them. Let's see how to do the deletion fly, web 2.0. style.
The table
The records are stored in a very, very basic table that has its markup to the bare minimum. The table has an ID "records" and every link also has an id like "delete-1", "delete-2", etc, where the numbers are the record IDs from the database table. The beauty of this is that the links go to delete.php, a server side script that will delete the requested record and return something. So this will work even for JS-disabled browsers. For those that are enabled though, we'll make the links not navigate to delete.php, but send a small AJAX request to that same server-side script.
Here's the table markup, as you can see, very minimalist.
<table id="records" align="center"> <caption>Table with records in it</caption> <tbody> <tr> <th>Last Name</th> <th>First Name</th> <th> </th> </tr> <tr> <td>Man</td> <td>Super</td> <td><a href="delete.php?id=1" class="delete" id="delete-1">delete</a></td> </tr> <tr> <td>Woman</td> <td>Cat</td> <td><a href="delete.php?id=2" class="delete" id="delete-2">delete</a></td> </tr> <tr> <td>Man</td> <td>Invisible, The</td> <td><a href="delete.php?id=3" class="delete" id="delete-3">delete</a></td> </tr> </tbody> </table>
Attach an event
To make the links call a JavaScript function, we'll have to attach an event to them. For this, let's use Y!s event library (event.js). Here's all that's needed:
// add an onclick listener to the records table YAHOO.util.Event.addListener('records','click',clickHandler);
Very simple, right? Now we've attached an event to the whole table. That's far more convenient than attaching an event to each and every link. With the line above we stated our desire that whenever there is a click somewhere inside the table, the function clickHandler() is executed. Let's see what's in there.
clickHandler()
function clickHandler(e) { // make sure the default event (vistiting the link) is not executed YAHOO.util.Event.preventDefault(e); // which element was clicked (target is in W3C, srcElement is in IE) var target = (e.srcElement) ? e.srcElement : e.target; // if the target element has class named "delete", that's our dude if (target.className == 'delete') { if (confirm('Sure you wanna delete?')) { // be polite, ask first // figure out which record to delete var id_to_delete = target.id.replace('delete-',''); // the ajax stuff YAHOO.util.Connect.initHeader('my_ajax','oh yes it is'); YAHOO.util.Connect.asyncRequest ( 'GET', 'delete.php?id=' + id_to_delete, {success: removeRow, failure: function (xhr) { alert('Errortry later...'); }, cell_id: target.id } ); } } }
As you see, I've put quite a bit of comments to illustrate what's going on at each line. Maybe the AJAX part will still need some more details though.
First, the header setting. Using YAHOO.util.Connect.initHeader we'll send an additional HTTP header, called my_ajax with some funny value. The purpose of this exercise is to tell our server-size delete.php script that this is an AJAX request and it will return a different response once it does its thing.
The actual request is made using YAHOO.util.Connect.asyncRequest. We pass the request method (GET), the URL (delete.php?id=12345) and then we pass an object to tell that if the request was successful, the function removeRow() should be called. On failure, an anonymous function is executed to simply alert that something's wrong.
The success and failure methods form the so-called callback object. You need a callback to instruct the AJAX call what to execute next. In the callback object you can also pass anything you like, like the property cell_id for example.
removeRow()
This function will be executed once the AJAX call completes successfully. In the function we'll:
- Check if the server-side returned "ok" response.
- Paint the row to be removed red
- Animate the row until it fades
- Remove the row completely
You may think that part 1 of this plan is funny? Laugh all you want, but if you think about it, it may start making sense
I mean you're right, it's AJAX, it should be Asynchronous JAvascript and XML. But we don't need no stinkin' XML for such a minor thing. A simple, friendly 'ok' is all it takes. No <root>s, no getElementsByTagName().item() end so on.
One hiccup in the plan is that the Yahoo UI doesn't yet support color animation. But we can use opacity animation. Good, great. Only that animating the opacity of a table row doesn't work in IE6. Shoot! Solution? Loop though the cells of the row and animate them. It will work.
Once all is animated and done, the last thing is to remove the row. It's easy, but we want to make sure it's done only after the animation is completed. Hence the "subscription" the Y! library provides.
Here's the function in its whole, see the comments.
function removeRow (xhr) { if (xhr.responseText != 'ok') { alert('Error, try later...'); return; } // now let's remove the row that contained the record var row = document.getElementById(this.cell_id).parentNode.parentNode; row.style.backgroundColor = '#ff0000'; // make it red // will make the removal animated var attributes = {opacity:{from:1, to:0}}; // will animate until opacity is 0 // loop through each cell and animate it // animating the opacity of a row (not all cells) is preferable, // but it's not happening on IE for(var i=0, thecells = row.cells; i < thecells.length; i++) { var anim = new YAHOO.util.Anim( thecells[i], // animate what attributes, // animate how 1, // for how long YAHOO.util.Easing.easeOut // and a dynamics touch ); if (i == thecells.length - 1) { anim.onComplete.subscribe( // execute on completion function(){ row.parentNode.removeChild(row); // remove the row } ); } anim.animate(); } }
The server-side check
As mentioned earlier, delete.php will delete the row regardless of how it's called - directly from the browser or through the AJAX call. The difference is that the response will be different. How does delete.php know how to respond? Looking at the extra header we sent, of course! Here goes:
// First off, do the actual record deletion // check for permissions, etc // When it comes to reporting, // respond differently if called with AJAX request or normally if (!empty($_SERVER['HTTP_MY_AJAX'])) { // this is an AJAX request // the response can be XML, JSON, whatever // for my purposes, a simple status reply is enough echo 'ok'; } else { // a normal browser request // do something, like header('Location: ...') for example }
Conclusion
So that's it, hope you enjoyed the trip. Once again, the demo is here, the Yahoo UI is here and ... have fun with the Y! library! Though despite the excitement of the new toy, please do not forget to sleep daily, it's important (I hear)
This entry was posted on Tuesday, March 28th, 2006 and is filed under Ajax, JavaScript, yui. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Get notification for future posts: follow me on Twitter or subscribe to my RSS feed

March 28th, 2006 at 9:37 am
No dice in Safari. I didn’t have time to find out why.
March 28th, 2006 at 9:49 am
Weird. I checked on Safari 2.0.3. and it worked as expected.
March 28th, 2006 at 10:04 am
hey nice work.. I am trying to use the Y UI for various purposes, will certainly let you know the outcome.
THanks
March 28th, 2006 at 10:25 am
@Rajat – don’t mention it. I personally fell in love with the thing, I did a whole other project top-to-bottom using YUI as a fatter client and a very, very thin server. I cannot release the code unfortunatelly, not for now, but it was a pleasure to do the animations and the AJAX stuff. Personally I was opposed to the idea of using any JS libraries for things like simple AJAX calls (like this – http://www.sitepoint.com/article/take-command-ajax), but now I’m a convert
March 28th, 2006 at 11:03 am
this is quite ugly..
March 28th, 2006 at 11:37 am
Sorry to hear that, Baldo
Is there anything in particular that you find ugly, I mean the colors, or the code, or the concept?
March 28th, 2006 at 4:27 pm
safari 2.0.3 works for me too
March 28th, 2006 at 8:13 pm
[...] read more | digg story [...]
March 30th, 2006 at 1:49 am
[...] phpied.com It’s your responsibility to die() if necessary… – PHP Manual « Fly Yahoo UI [...]
November 26th, 2006 at 9:34 am
Thank you a lot! Very helpful article!
January 10th, 2007 at 6:22 pm
Perhaps someone sees my error;
I’m using this code:
YAHOO.util.Connect.asyncRequest (
‘GET’,
‘page.php?id=’ + row_id,
{success: test,
failure: function no (row_id) {
alert(‘Error try later…’);
}
I’m doing nothing in the success function “test” but am wanting to grab the id with $rowID = $_REQUEST['id'] from the URL ‘page.php?id=’ + row_id but this seems to do nothing am I missing something? Using the example code i surounded my request grab with the if(!empty($_SERVER['HTTP_MY_AJAX']) still nothing … any ideas?
January 10th, 2007 at 6:33 pm
found my problem
January 19th, 2007 at 11:19 pm
thanks for this great article
Suggest minor refactoring:
- var target = (e.srcElement) ? e.srcElement : e.target;
+ var target = YAHOO.util.Event.getTarget(e);