Using the jQuery Cluetip plugin with dynamic content
jQuery is a wonderful tool. It's easy coding demands and the plethora of plugins make most complex web application tasks nice and easy. Tonight I had the luxury of avoiding a great deal of custom code and was able to provide an interactive popup detail area driven by dynamic data in a handful of lines. I used the clueTip plugin to do this.
Starting out with a new plugin can sometimes be a little daunting and/or frustrating. Especially so with the more complex type of plugin. However this is more due to lack of knowledge than a failing in the plugin. After working with other plugins I thought I was ready to tackle clueTip quickly, but the rules changed on me. Things make sense when you "get it", but until then it could be easy to get frustrated. In my case I was expecting clueTip to be like most other plugins (and it is in a lot of ways), but the dynamic part of it threw me for a little while. Hopefully this post will help someone avoid those frustrations.
NOTE: I'm going to assume that anyone who reads further is familiary with jQuery, jQuery's $.ajax() method (though not quite as important), with jQuery plugins, and with web application development in general. Filling in all these details would require a full book, rather than a simple blog posting. :) Feel free to read on if you don't have all this background, but please be aware we're not talking about a simple web page here.
Here's the problem I had to solve:
- I had a task calendar type of application. The displayed tasks were only a summary of the info for the first task on a given day. I needed to provide full details for ALL tasks on a given day when the summary was hovered over.
- The tasks are generated on the fly (it's an Ajax driven application, rather than a simple database driven page). So I could not say for certain what tasks would appear where. I needed to extract details from the task I was hovering over (such as the person and the date), pass this detail to a server side page (the Ajax call), and display the results in a meaningful manner.
- The popup div needed to behave as you would expect - disapear on mouse out, or when another popup was displayed. Yet I needed to allow interaction within the popup as well - the user could ask to edit one of the listed tasks.
This may sound like a simple task, but I promise you there is a whole lot of details involved here. Especially dealing with the position of the popup and it's behavior. I've written a similar tool for a previous incarnation of this application and the details just didn't stop coming (which translates into high maintenance needs). Well, I can tell you clueTip made life easy for me tonight. Here's how to get it done.
- First download the clueTip library, and set it up on your page with the pertinent script tags (and the stylesheets too). There are excellent instructions for this on the clueTip home page.
- In my case the element that would trigger the popup when it was hovered over was dynamically created. So after the trigger was added to the page I had to tell it that I wanted it to be a trigger. I used code something like this:
$("#mytrigger").attr("rel", "xhr/mypage.php").cluetip();This sets a value for the "rel" attribute of the trigger. Cluetip uses that value as either the page to call (Ajax call), or a local jQuery selector if a local element is being used (not what we are after here).
- There are some extra settings we need to get the clueTip to behave as we would like it. The full list of options can be seen at the API page. In our case, we needed to modify our call to look something like this:
$("#mytrigger").attr("rel", "xhr/mypage.php").cluetip({
closePosition : "title",
sticky : true,
mouseOutClose : true
});This simply makes the clueTip "sticky" (it won't close automatically), places the "Close" link in the title area, and triggers the close if the mouse moves inside and then outside the clueTip area.
- But I needed to pass dynamic data to my server side page. The clueTip author (Karl Swedberg) has kindly thought of this. We can make use of the "ajaxSettings" parameter to pass some details to the Ajax call:
$(".triggerAreas").each( function () {
var employee_id = $(this).attr("id").toString().split("-")[0];
var dt = $(this).attr("id").toString().split("-")[1];
$("#mytrigger").attr("rel", "xhr/mypage.php").cluetip({
closePosition : "title",
sticky : true,
mouseOutClose : true,
ajaxSettings : {
type : "POST",
data : "employee=" + employee_id + "&date=" + dt
}
});
});I've wrapped the clueTip call in a .each() function. This allows me to say make ALL my trigger areas a clueTip trigger with one command. In doing so, I'm extracting the employee ID and the desired date from the trigger element's ID value. (in the form of employee_id-date). This *should* make for a unique ID in my case. Now that we have the pertinent data we pass it to the Ajax call via the "data" parameter. ajaxSettings allows all the usual parameters for the $.ajax() method except the url, success, error, and complete options. (this part will make sense in a moment.)
- Now, I originally started off retrieving JSON code from the server side page. This needed further processing once the results were brought back. This is handled via the ajaxProcess method. This method needs to return a string representing the content of the displayed clueTip. But it gives us a chance to create that content on the fly, or modify existing content:
$(".triggerAreas").each( function () {
var employee_id = $(this).attr("id").toString().split("-")[0];
var dt = $(this).attr("id").toString().split("-")[1];
$("#mytrigger").attr("rel", "xhr/mypage.php").cluetip({
closePosition : "title",
sticky : true,
mouseOutClose : true,
ajaxSettings : {
type : "POST",
data : "employee=" + employee_id + "&date=" + dt
},
ajaxProcess : function (data) {
return "<h2>" + data + "</h2>";
}
});
});This is a bit of a contrived example - but clearly shows that you can manipulate the data you retrieved. By default clueTip will expect an HTML value to be passed in as the data parameter. If you had set the "dataType" option of the ajaxSettings to be "json", then our data parameter would be a json object. Essentially this ajaxProcess function becomes the "success" function of an $.ajax() call. If this part confuses you, take a look at the $.ajax() method options. Once you feel comfortable with $.ajax(), this will all make sense.
- Now, once the clueTip is displayed, I needed some added behavior. Specifically, if a listed item was clicked, I would trigger the edit routine for the chosen task. Again, the Karl (the clueTip author) has thought of this. We can make use of the onShow parameter. So our code then changes a little more:
$(".triggerAreas").each( function () {
var employee_id = $(this).attr("id").toString().split("-")[0];
var dt = $(this).attr("id").toString().split("-")[1];
$("#mytrigger").attr("rel", "xhr/mypage.php").cluetip({
closePosition : "title",
sticky : true,
mouseOutClose : true,
ajaxSettings : {
type : "POST",
data : "employee=" + employee_id + "&date=" + dt
},
ajaxProcess : function (data) {
return "<h2>" + data + "</h2>";
},
onShow : function (ct, c) {
$(".taskListItem").click(function() {
myTaskObject.edit(this.id);
$("#cluetip-close").click();
});
}
});
});Our onShow method simply says that when a task is clicked (identified by the .taskListItem class), we'll pass it's ID value to the edit routine of my custom task object (which in turn opens a dialog box - which is a whole different writeup). And we end by ensuring our clueTip is closed by calling the click event on the Close link.
And with that, we have a nice popup div that shows dynamic details to us and allows us to interact with those details. All that is left is to change the clueTip stylesheet to fit our own application.
I would strongly recommend the clueTip plugin if you have any need to show details to the user on hover (or on click) of a particular area. Karl is active on the jQuery mailing list - I've seen him reply to almost every (if not all) question about clueTip since I've been on the list myself.
- sgrover's blog
- Login or register to post comments
