January 31st, 2007 Properly degrading JavaScript Effects with Script.aculo.us

I recently decided to use Script.aculo.us in a project that I’m working on. I was actually pretty impressed with it’s cross-browser compatibility and ease of use. I didn’t even think that the 200K size (including the Prototype Framework) was that bad. However, I did run into some issues while trying to make my site function properly for users that have JavaScript disabled, while still allowing the effects for those that do.

In my particular situation, I wanted to make some objects appear with an effect. You will notice that if you apply an Appear effect to an element, it will display, then disappear, the appear with the effect. The solution is to set an inline style with display:none, except that this will cause the element to be missing from users without JavaScript. The solution? Add the display:none style with Javascript.

First, I created a CSS class called effect_appear, with no styles.

 
.effect_appear {
}
 

Then I use Javascript to modify that class, and set the display to none.

 
function getStyleClass (className) {
    if (document.styleSheets.length < 1) {
        return null;
    }
    if (document.styleSheets[0].cssRules) {
        var cssRules = 'cssRules';
    } else {
        var cssRules = 'rules';
    }
    for (var s = 0; s < document.styleSheets.length; s++) {
        for (var r = 0; r < document.styleSheets[s][cssRules].length; r++) {
            if (document.styleSheets[s][cssRules][r].selectorText == '.' + className) {
                return document.styleSheets[s][cssRules][r];
            }
        }
    }
    return null;
}
getStyleClass('effect_appear').style.display = 'none';
 

Now, any element with that class will display normal to a user without JavaScript support, but will be missing for users with JavaScript. Next I added a ‘load’ event handler to the window element, which will make the elements appear with an effect.

 
Event.observe(window, 'load', effects);
function effects() {
    document.getElementsByClassName('effect_appear').each(
        function (el) {
            el.visualEffect('Appear');
        }
    );
}
 

However, there is still one problem. Because the style we created is not inline, it seems to override any effect that we add. The solution is to first remove the classname, and hide() the element (this will remove the class, but keep the element hidden, without the user ever seeing the element). Then we apply the visual effect (in this case, Appear).

 
Event.observe(window, 'load', effects);
function effects() {
    document.getElementsByClassName('effect_appear').each(
        function (el) {
            el.removeClassName('effect_appear').hide().visualEffect('Appear');
        }
    );
}
 

Here is the whole thing. Remember, the class “effect_appear” MUST exist in one of your stylesheets, or in a style tag ABOVE this code.

 
function getStyleClass (className) {
    if (document.styleSheets.length < 1) {
        return null;
    }
    if (document.styleSheets[0].cssRules) {
        var cssRules = 'cssRules';
    } else {
        var cssRules = 'rules';
    }
    for (var s = 0; s < document.styleSheets.length; s++) {
        for (var r = 0; r < document.styleSheets[s][cssRules].length; r++) {
            if (document.styleSheets[s][cssRules][r].selectorText == '.' + className) {
                return document.styleSheets[s][cssRules][r];
            }
        }
    }
    return null;
}
getStyleClass('effect_appear').style.display = 'none';
Event.observe(window, 'load', effects);
function effects() {
    document.getElementsByClassName('effect_appear').each(
        function (el) {
            el.removeClassName('effect_appear').hide().visualEffect('Appear');
        }
    );
}
 

21 Responses to “Properly degrading JavaScript Effects with Script.aculo.us”

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Search