Dec/082
How to: Use MooTools to Fade Between Multiple Images
After I wrote my post “Using MooTools to fade between two images” I have received many request on how to fade between multiple images. So here is “How to: Use MooTools to Fade Between Multiple Images”. We start with the same HTML setup as we do in “Using MooTools to fade between two images” plus a few buttons; setup two DIV tags that are absolutely positioned over one another inside another DIV tag that uses default placement. Then you place your image tags inside each of the absolutely positioned DIV tags. Each of the DIV tags needs to have an id attribute so they can be referenced in your javascript code.
The HTML for the task will look like this:
1 2 3 4 5 6 7 8 | <div id="button1" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 1</div> <div id="button2" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 2</div> <div id="button3" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 3</div> <div id="button4" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 4</div> <div style="height:112px;" > <div id="div1" style="position:absolute; opacity: 0;"><img id="image1" src="image1.jpg" /></div> <div id="div2" style="position:absolute; opacity: 1;"><img id="image2" src="image2.jpg" /></div> </div> |
For fading between multiple images there is some preparation we will need to do before we are ready to start switching images. First you need to create an object to associate buttons to your image source URLs, this makes it easy to change the number of buttons and images they load later. Then iterate that object creating new elements for each image and attaching them to the buttons. Creating new images and attaching them to the buttons does two things, it pre-loads the images and associates the image to the button that will show the image.
creating the object can be done with JavaScript Object Notation:
1 | var buttonsAndImages = {'button1':'image1.jpg','button2':'image2.jpg','button3':'image3.jpg','button4':'image4.jpg'}; |
The loadImages function will take the buttionsAndImages object and create a new image object using the Mootools Element object and attach that image object to its associated button.
1 2 3 4 5 6 | function loadImages(buttonsAndImages){ for(biPairKey in buttonsAndImages) { var image = new Element('img',{ src:buttonsAndImages[biPairKey], style:'margin:3px;' }); $(biPairKey).image = image; } } |
For multiple image switching we will use a function named toggle. In the toggle function we will set the source of the hidden image, start the effect to fade out the visible image and fade in the hidden image, and set a global variable to indicate which div is visible
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function toggle(newSrc){ //stop the current animation if it is running. if($("div1").fx){$("div1").fx.stop();} if($("div2").fx){$("div2").fx.stop();} //Decide which div to hide and which to show. if(visibleDiv == $("div1")){ //change the hidden image's source $("image2").src = newSrc; //fade the visible out and the hidden in. $("div1").fx = new Fx.Style($("div1"), 'opacity', {duration: 2000}).start(0); $("div2").fx = new Fx.Style($("div2"), 'opacity', {duration: 2000}).start(1); //Set which div is visible. visibleDiv = $("div2"); }else{ //change the hidden image's source $("image1").src = newSrc; //fade the visible out and the hidden in. $("div1").fx = new Fx.Style($("div1"), 'opacity', {duration: 2000}).start(1); $("div2").fx = new Fx.Style($("div2"), 'opacity', {duration: 2000}).start(0); //Set which div is visible visibleDiv = $("div1"); } } |
Check out the demo of fading multiple images to see this in action. If you want to create a slide show or other implementation of this that automatically switches the images, read through my post on Delay, Periodical and Closures. Below you will find the source of the example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>Untitled Document</title> </head> <body> <script type="text/javascript" src="js/mootools-release-1.11.js" language="javascript"></script> <script language="javascript"> var visibleDiv = $("div1"); function toggle(newSrc){ if($("div1").fx){$("div1").fx.stop();} if($("div2").fx){$("div2").fx.stop();} if(visibleDiv == $("div1")){ $("image2").src = newSrc; $("div1").fx = new Fx.Style($("div1"), 'opacity', {duration: 2000}).start(0); $("div2").fx = new Fx.Style($("div2"), 'opacity', {duration: 2000}).start(1); visibleDiv = $("div2"); }else{ $("image1").src = newSrc; $("div1").fx = new Fx.Style($("div1"), 'opacity', {duration: 2000}).start(1); $("div2").fx = new Fx.Style($("div2"), 'opacity', {duration: 2000}).start(0); visibleDiv = $("div1"); } } function loadImages(buttonsAndImages){ for(biPairKey in buttonsAndImages) { var image = new Element('img',{ src:buttonsAndImages[biPairKey], style:'margin:3px;' }); $(biPairKey).image = image; } } function faderInit(){ //create an object to store the relationship of the buttons to the images. var buttonsAndImages = {'button1':'image1.jpg','button2':'image2.jpg','button3':'image3.jpg','button4':'image4.jpg'}; loadImages(buttonsAndImages); } window.addEvent("domready", faderInit); </script> <div style="width:453px"> <div id="button1" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 1</div> <div id="button2" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 2</div> <div id="button3" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 3</div> <div id="button4" style="background-color:#aaaaaa; border: 1px solid #444; cursor: pointer;" onclick="toggle(this.image.src);">Image 4</div> <div style="height:112px;"> <div id="div1" style="position:absolute; opacity: 0;"><img id="image1" src="image1.jpg" /></div> <div id="div2" style="position:absolute; opacity: 1;"><img id="image2" src="image2.jpg" /></div> </div> </div> </body> </html> |
Apr/071
The correct way to work with table elements in FireFox, IE and all other browsers
In my last post I talked about the differences between IE and Firefox when creating dynamic tables with the Document Object Model. Thanks to chatdor’s comment to my “Dynamic Tables In JavaScript for IE and Firefox” post, I realized that I was not paying attention to the full DOM. Perhaps many of us, like me, tend to only think of the Element object when thinking about manipulating the DOM, but there are a couple of higher level objects that derive from the Element object, the Table Element, and the Form Element, that make dealing with the more complex Elements easier. The good folks over at Mozilla have a great DOM reference which I almost always have open.
So, all that being said, I would like to post some code on a better way of creating dynamic tables in JavaScript with the DOM. In the following block of code we will use createElement(‘table’), to create our table but from then on we will use the Table Element’s member function insertRow and the Row’s insertCell to build the table.
1
2
3
4
5 var myTable = document.createElement('table');
var myRow = myTable.insertRow(-1);
var myCell = myRow.insertCell(-1);
var myTextNode = document.createTextNode('Hello World!');
myCell.appendChild(myTextNode);
In this block, I pass -1 into the insert functions to append the row or cell to the end of the rows or cells. Also in the example instead of setting the cell’s innerHTML or useing createElement(“text”) to make a text node and append, I instead use document.createTextNode, which is another case where there is a DOM function that is likely better to use than the less specific functions.
By using the higher level Table object and calling functions more specific to an action the code should have better cross-browser functionality.
Apr/072
Dynamic Tables In JavaScript for IE and Firefox
Edit : After reading chatdor’s comment I realized that I was consentrating so much on the Element that I was not seeing the whole DOM. See my new post on the DOM, for a better sample for creating table elements in JavaScript.
Recently I had the “pleasure” of dynamic creating some tables in JavaScript. In the process, I ran into and interesting issue or two. The first issue is that you cannot just append <tr> elements into a <table> element in IE. It will work, but IE will not render the rows. In IE you must create a <tbody> element, append the <tbody> element to the <table> element, then append your rows to your <tbody> element. This does not follow the W3C Row groups specification for the table specification which states that: “Table rows may be grouped into a table head, table foot, and one or more table body sections, using the THEAD, TFOOT and TBODY elements, respectively.” Note that the W3C specification states ‘may be’ whereas IE treats it as “must be.”
So, the following will get you nothing in IE but will work fine in Firefox:
1
2
3
4
5
6 var myTable = document.createElement("table");
var myRow = document.createElement("tr");
var myCell = document.createElement("td");
myCell.innerHTML = "Hello World!";
myTable.appendChild(myRow);
myRow .appendChild(myCell);
This will render a table in both IE and Firefox:
1
2
3
4
5
6
7
8 var myTable = document.createElement("table");
var myTbody = document.createElement("tbody");
var myRow = document.createElement("tr");
var myCell = document.createElement("td");
myCell.innerHTML = "Hello World!";
myTable.appendChild(myTbody);
myTbody.appendChild(myRow);
myRow.appendChild(myCell);
So now we have a table that renders in both IE and Firefox but there is still an issue remaining. Now in Firefox there is a space between the top of the table and the first row that you cannot get rid of. This is not going to be evident in all situations but will be in enough situations to be a problem. The reason for the space is that when you add a <tbody> to a table in Firefox it appears to reserve or auto include the <thead> and <tfoot> elements in the table. This is most likely done because the W3C specification states that you must have a <thead> and <tfoot> if you have a <tbody>. In order to prevent this extra space you need to add the<thead> and the <tfoot> and set their height to 0px or their display to none or something of the sort unless, of course, you are going to use them.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 var myTable = document.createElement("table");
var myThead = document.createElement("thead");
myThead.style.height = 0px;
var myTfoot = document.createElement("tfoot");
myTfoot.style.height = 0px;
var myTbody = document.createElement("tbody");
var myRow = document.createElement("tr");
var myCell = document.createElement("td");
myCell.innerHTML = "Hello World!";
myTable.appendChild(myThead);
myTable.appendChild(myTfoot);
myTable.appendChild(myTbody);
myTbody.appendChild(myRow);
myRow.appendChild(myCell);
This gives you a way to render tables that match in both IE and Firefox with the same code.