Feb/092
The one real reason to not use JQuery
JQuery is a very nice for DOM manipulation and access. As I mentioned in my last post, JQuery uses standard CSS selectors by default which is very nice. You can create fairly complex actions with very few lines of code.
What it does not have that MooTools and Prototype.js both have is a rich set of object oriented oriented development functions. JQuery is ver DOM centric and does not have much in the way of utilities that are not directly related to accessing and manipulating the DOM. You can greatly extend the functions of elements in the DOM or add elements to the DOM. Once you are working with pure JavaScript objects JQuery does not have much to offer. This begins to become eveident right away when compairing the core sections of both MooTools and JQuery. In JQuery’s core the first things are DOM element access and creation functions; where MooTools’ core is all JavaScript and OO featrues. The Extend function is a good example, extend is a core componenet of MooTools and a Utility in Jquery.
Beyond that the true reason for using MooTools is the the object oriented programming features. The Function and Class features of MooTools are simply not implimented in JQuery. This makes taking advantage of Encapsulation, Inheritance and Polymorphism very difficult with JQuery, which pretty much leaves all of the work of implementation of those features up to you.
That being said you can use the JQuery’s noConflict() function and use both MooTools and JQuery. I have not explored how the two will play together when writing object oriented code with Mootools functions and accessing the DOM with JQuery, but I do plan to give this a try in the near future.
Jan/092
Three real good reasons to use JQuery, from a Mootools lover
I have been an avid mootools user for many years. A couple of times I have looked at JQuery and turned up my nose. That being said I am a firm believer that one should reassess ones knowledge/opinions/assumptions periodically just to make sure the world has not changed while you were not looking. This is one time that the reassessment did indeed change what I believe, and here are 3 things making that change:
Community Support
JQuery has a large community of active users. This makes finding information supplementary to the JQuery official documentation very easy. JQuery’s community also means that when you post a question some where you will not wait long for an answer.
Selectors
JQuery uses the same selectors as CSS. When working with a team of both developers and designers this is wonderful. When it comes to addressing the DOM with JQuery both the designers and the developers are speaking the same language. Every bridge you can build between your developers and designers makes for a stronger team. Not to mention using CSS selectors is just easier than all the hoops you have to jump through in other frameworks.
Speed
With the release of version 1.3 of the JQuery framework, many of the functions are faster than any other JavaScript framework. With the ever increasing amount of JavaScript executing on a page the speed is a welcome relief.
These are three very important reasons to take another look at JQuery.
I have done a little more playing around with JQuery and have found one major draw back when compared to Mootools
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.