slides and bubbles (jquery event delegation)

I wanted to improve my slideshow with image preloading. What I wanted was something that resembles a queue for preloading.

On a blog I found a piece by Rebecca Murphey, she seems a very smart programmer. I picked up on the idea of triggering events, then read some remarks on binding data to an element, and on event delegation.

Being a noob, I concocted thus :

Each element I use to run the ‘slideshow’ has three basic functions,

  • AjaxLoadImages : loads the xml data ( image urls) into $(elem).data()
  • displayImage : replaces the css background-image url
  • preLoad : creates an img element in the document with the image url as source, to force the browser to download the picture so once I put it in the css background the image file is already downloaded, that stops the flickering

The latter two run on a timer, more about that later on in the post.

With bind(), I tie the event handler function to an element, and can use my own events. I can delegate the handling of events up the dom tree by leaving the handler of the lower elements void and binding a handler with the same name to a higher level element, like body.

          $("div").bind('preLoad', function(e) {});  $("div").bind('displayImage', function(e){});  $("div").bind('AjaxLoadImages', function(e){});  

In ‘bubbling up’ the element data of the element where the event was triggered is sent along. I can access that elements .data() (with my image list etc.) through the generic $( object.

  //AjaxLoadImages is a http-get that retrieves  //an xml file, and adds the links in it to the .data()  //attribute of the div  //I trigger the event on the div, which is handed upward  //to this function, with the div as 'target'   $("body").bind('AjaxLoadImages', function(e, fname) {  var target = $(;  $.get(fname, {}, function(xml)  {  var counter = 0;  $('entry', xml).each(function(i) {  counter++;  //key = (x + counter)  $('x'+counter).toString(), $(this).find("link").text());  });  //some general data  $("preload", "0");  $("currentimage", "1");  $("countimage", counter.toString());  });  });  //displayImage retrieves the 'currentimage' value   //which, with an added X,   //is the key of the imageurl in the .data() element  //(which is key=>value array)   //Once I have it, I can replace the background image url  //in the css  $("body").bind('displayImage', function(e) {  var target = $(;  $('background-image', 'url(' + $('x'+"currentimage") ).toString()) +  ')');  });		  //preload does the same trick, with the source attribute  //of an image I add to force the browser to preload  $("body").bind('preLoad', function(e) {  $('').attr({  src: $('x' + $("currentimage")).toString()) });  });  

the xml file is plain :
<?xml version=”1.0″ encoding=”UTF-8″?>


That sets up the basic data and functions for the div elements.

Now to make it run.

Timing, even with the SetInterval method, was gonna be a pain as it seems I can not tie SetInterval to an element. Luckily (blair mitchelmore?) was so kind as to write a jQuery plugin to handle multiple timers.

With that, I can write one event handler on body level that assigns each element that comes bubbling up a function on a timer interval to handle the display and preloading, as if it were a loop.

  //binding the event with void handler  $("div").bind('ScheduleSlides', function(e){});  ///...then binding the actual event handler to body,  //param holds the interval  $('body').bind("ScheduleSlides", function(e, param) {  var target = $(;  //runs a function on set intervals for the target element  target.everyTime(param, function(i) {  //display the current image by triggering displayImage,  //which bubbles up to the body event handler  var imgcount ="currentimage");  target.trigger('displayImage');  //increase the functions internal counter  imgcount++;  //set currentimage to the increased counter"currentimage", (imgcount).toString());  //if at the end of the image list,  //reset currentimage  //and end preloading  if("currentimage") =="countimage") ) {"preload", "1");"currentimage", "1");  };  //preload the new image if necessary  if("preload") == "0") {  target.trigger('preLoad');  };  });  });

All that remains is to load an xml file and trigger the scheduling…

  $("#dia_show").trigger(  "AjaxLoadImages",  ""  );  $("#dia_show").trigger('ScheduleSlides', 1000);  

and another one…

  $("#dia_show_2").trigger(  "AjaxLoadImages",  ""  );  $("#dia_show_2").trigger('ScheduleSlides', 2000);

I really wonder why I wrote it that way, but it seems to work without the flickering bit and without having to code the links in css or in the source.

I put the test page and the source of it on the server.

I read some remarks on other blogs that after adding 14 img elements IE throws a stack overflow, I haven’t looked into that.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top