Archive for the 'JavaScript' Category

Increasing appendChild Performance with DOM Tricks

Tuesday, July 22nd, 2008

A recent blog post by John Resig has outlined a performance sensitive method of appending many elements to your document. His suggestion, using DocumentFragment as the container object to which to append all child nodes, is backed by some pretty impressive benchmarks. The most drastic performance improvements by using this method of appending objects to the document are witnessed by Internet Explorer and Safari, IE6 improved by 65%, IE7 by 73% and Safari by 71%.

In looking at his code used to test this, some users argued that his test cases were slightly skewed as the container object was handled in two different manners. In the case using appendChild for each childNode, the container object was looked up on the gathered div array using the loops index to point to the value. Why not store it they asked? This led to accusations that in the case that switches to using the DocumentFragment, the benefit may be derived from the idea that the container object is accessed as a stored value inside the loop. This also lead to questioning that, in his second case, the majority of the content was being appended to an object not yet living in the DOM.

This begs the questions– Does the perceived performance increase being witnessed in this case come from the fact that the container object is detached from the DOM while being appended? I decided to dive in…

The Procedure

To do this, I set up three cases and tested in both Firefox 2 and Internet Explorer 7. Knowing that the original idea, looping through the divs and accessing the container as div[i], was the least desirable, I decided to toss that out the window from the get go.

For my first case, "Appending to Attached Div", I stuck with the structure of John's control case, in which the nodes are appended directly to an element still active in the DOM. The one tweak I did make, was to store a reference to the container div rather than using div[i]. This was as simple as setting var container = div[i] inside the first loop. This resulted in:

var div = document.getElementsByTagName("div");
   
    for ( var i = 0; i < div.length; i++ ) {
        var container = div[i];
            for ( var e = 0; e < elems.length; e++ ) {
                    container.appendChild( elems[e].cloneNode(true) );
            }
    }

Case 2 involved using John's DocumentFragment method verbatim. This presented an element of control to my test in relation to his.

In the 3rd case, I decided to use the method just like in case 2, however rather than using createDocumentFragment() I created a table element with createElement("table"). This was stored as the container to which to append the children elements.

var div = document.getElementsByTagName("div");
   
    var container = document.createElement("table");
    for ( var e = 0; e < elems.length; e++ ) {
            container.appendChild( elems[e] );
    }
   
    for ( var i = 0; i < div.length; i++ ) {
            div[i].appendChild( container.cloneNode(true) );
    }

My Results

The results are as follow, with time to execute represented (in seconds).

Appending to Attached Div Appending to Document Fragment Appending to Table
FF2 2.046 .430 .481
IE7 4.134 3.256 3.715

In Conclusion

After going through this test, I decided that John was definitely onto something. He found the most optimized way to approach this method. Between the two cases in which I appended the content to an object that was not yet in the DOM (for the elems array), the DocumentFragment method proved to be more efficient by about 10%. The one thing I would like to add–that I feel my test proved–is that when you are doing the majority of your appending, you should be doing it to an object that is not currently contained within the DOM. You can then later append that object to its destination container.

P.S. On a humorous note, the original case that John was using in his test took far too long for me to run with the sheer volume of div's I was trying to populate. In fact, it caused Firefox to prompt me to stop the script and Internet Explorer just locked up… Definitely make sure you use one of these presented solutions for appending nodes to improve your performance!

Select All Checkboxes with Prototype JS

Thursday, July 10th, 2008

If you are a looking for an easy way to select all checkboxes on a page, there are a number of ways you can quickly accomplish this with the Prototype JS library.

Let's say your HTML looks like this:


  <form id="options">
    <fieldset><input type="text" value="test"></fieldset>
    <fieldset><input type="checkbox" value=0> 0</fieldset>
    <fieldset><input type="checkbox" value=1> 1</fieldset>
    <fieldset><input type="checkbox" value=2> 2</fieldset>
    <fieldset><input type="checkbox" value=3> 3</fieldset>
  </form>

It's fairly straight forward to grab all of the input elements of type "checkbox" without also getting the element of type "text".

In both cases we will store our results as objects in an array, named checkboxes.

var checkboxes = [];

Now that we have this array ready for our objects, let's select them.

The first method, uses the $$ operator to select all inputs on the page. Then we use the each() method to iterate through each input element and check the type. If our type is equal to the string 'checkbox', store it to our array checkboxes.

checkboxes = $$('input').each(function(e){ if(e.type == 'checkbox') checkboxes.push(e) });

The second method, uses the hand Form object method called getInputs(). To use this method, first we need to select the form object. In this example, we do so by used the $ operator and the id attribute of the form. Once we have that object, we call the getInputs() method and pass it the argument 'checkbox', which will define the input type we are seeking.

var form = $('options');
checkboxes = form.getInputs('checkbox');

In both of these cases, checkboxes will be equal to:

checkboxes // ---> returns "[input 0, input 1, input 2, input 3]"

If you would like to check all of these checkboxes, you can do so with this line of code:

checkboxes.each(function(e){ e.checked = 0 });

You can also assign it to a link with this HTML:

<a href="#" onclick="checkboxes.each(function(e){ e.checked = 0 });">Select All</a>

First Letter of a String in JavaScript: test.CharAt() vs test[]

Thursday, April 24th, 2008

When we use a programming language everyday, now and then we find ourselves stumbling upon intricacies of that language that need some clarification. Today I encountered this as I was using JavaScript to convert an object to an XML string. While working through the object, there was a particular piece of the code that needed to evaluate the first character of a string. For those of you versed in JavaScript, you understand that there are actually a number of ways to accomplish this, most effectively by treating the string like an array [because JavaScript doesn't mind] or by using the handy charAt() function. Both seem to work fine… but what's the difference you might ask?

var test = 'string';
    test[0];
    // ---> returns "s"

var test = 'string';
    test.charAt(0);
    // ---> returns "s"

Doesn't seem to be a difference here. I was pretty stumped until my colleague, Nathan, suggested I try an invalid index.

var test = 'string';
    test[5];
    // ---> returns ""

var test = 'string';
    test.charAt(5);
    // ---> returns null

A-ha!

As you can see, charAt() returns a string regardless of the argument actually being a valid index or not. This is extremely useful in the case that you need the returned value to be a string for later usage.

Grabbing the value directly from the string as you would do with an array is also a useful technique if you need to know that it is indeed an invalid index.

Also, could one assume that comparing against null performs better than performing a string comparison?

Update: As it turns out, IE does not support the test[] method of accessing the value. It is advised that you always use test.CharAt().

DHTML Yellow Fade Technique

Wednesday, January 10th, 2007

In the world of buzzwords like Web 2.0 and Ajax, everybody is trying to get a grasp on the stylish quirks you see from website to website.  Back in the tutorial Getting Ready for Web 2.0 effects with Scriptaculous we talked about firing up a JavaScript effects framework on your server for future UI and display purposes.  Scriptaculous is immensely powerful and today I'd like to show you a quick example of how this framework can make your life easier.

One ever-so-popular effect that you commonly see used across the web is the highlighting of an HTML element with a nice yellow highlight fading back to the original background.  I have recently run across some interesting techniques that individuals were using to create this effect.  I briefly skimmed over this particular tutorial in question and was absolutely amazed at the amount of effort this individual had put in to create a multiple step animation sequence for changing the background colors of a DOM element.  (Basically, somebody needs to introduce this guy to the Scriptaculous library.)

In case you're in the dark on how to create a nice Highlight effect, here's an easy manner in which to do so using the form we created in the Error Output With Scriptaculous

Simply find the line:

<input type="text" size="30" id="email" />

Take this line and change it to:

<input type="text" size="30" id="email" onblur="new Effect.Highlight(this, {startcolor: '#ffff00', restorecolor: 'true'})"/>

What's going on here?  Well we are using the onblur element listener to trigger JavaScript when the user moves their focus from the input box in question.  The JavaScript included in the quotation marks simple creates a new Effect called Highlight and sets a few arguments.  "this" is used to identify the HTML element we are running the effect on.  (We can use "this" since we are defining the JavaScript in-line.)  The options "startcolor" and "restorecolor" are set in the next part of the JavaScript declaration.  Using a hex code, we can tell Scriptaculous exactly what color we want the animation to start with.  The "restorecolor" parameter is handy because it will return the background color of the element to its original color without us having to worry about what the initial value was.

View Yellow Fade Technique Example. The effect will trigger when you place your cursor in the "email" box and tab to the next field or click elsewhere on the page.

Note** There are other options you can define here, refer to the official Scriptaculous documentation for more information.

New Scriptaculous 1.7.0 Beta Unveils Morph Effect

Saturday, January 6th, 2007

With the release of the new Scriptaculous 1.7.0 Beta, Thomas Fuchs has introduced a new effect, morph.  The syntax for this new feature is quite easy to grasp.  Simply call the function on the element you wish to morph.

$('my_element').morph();

You can also pass this function arguments to define CSS properties on the fly.

$('my_element').morph({fontSize: '12px', color: '#7F1123'});

Here is an example of the Scriptaculous morph function and how it can be used.

The code I used in my example was quite simple.  I set some default values in CSS for the element I was going to morph.  Then I created some anchor text, in which I tacked on a onclick behavior that called the morph() function.  This is what my markup looks like:

<div id="change_me">Watch me morph!  Click Below!</div>
<a href="#" onclick="$('change_me').morph({fontSize:'36px',color:'#7F1123'}); return false;">Click Here</a>

The magic is primarily done in defining the initial CSS values and passing your new ones to the function.  Pretty handy!

Note– using this method requires the newest beta release of Scriptaculous.  The download is available toward the bottom of this page on mir.aculo.us.  Direct download link.

New Tutorial - Error Output with Scriptaculous

Saturday, January 6th, 2007

In this tutorial, Error Output with Scriptaculous, we discuss how to get a basic Scriptaculous effect up and running. This tutorial shows how to properly set up HTML markup so that JavaScript can effectively interact with the DOM and use the Effect.Appear method to display error output. This example centers around a simple login form that validates user input.

New Tutorial - Getting Ready for Web 2.0 Effects with Scriptaculous

Saturday, January 6th, 2007

A new tutorial has been added entitled Getting Ready for Web 2.0 Effects with Scriptaculous. In this tutorial, you can gain a general overview of the Scriptaculous library for JavaScript and what it is used for. Then, the tutorial gives you detailed instructions on how to get Scriptaculous up and running on your web server. It's pretty easy so get started today!