Two-color sIFR

Ed’s note: This is an outdated material. Please visit the article with a new version.

I’m honored to present my fellow colleague Vanja Bertalan to be a guest speaker at my blog. Today’s topic is how to implement two color sIFR, in a way that we did on our recent project, www.24sata.hr. Here’s Vanja’s brief article:

screenshot of two-color-sifr

The whole process basically involves 2 things:

  • modification of the javascript source file to make it understand that <span class="sifr-alt-color"> has a special meaning
  • modification of actionscript source files to handle coloring

sIFR javascript currently understands only <a> and <br> elements within headings, and strips everything else out. I needed additional notation, a marker, that will tell flash to color the text within markers differently. Decision was made to use <span class="sifr-alt-color"> for that purpose. That notation will be transformed to &shy; character, before it’s passed to flash. &shy; is a character very similar to dash (note the difference between &shy; and &#8211;more about en dash).

(Editor’s note: &shy;, which we placed directly in HTML at the 24sata web site is not visible in most Windows browsers–tested in Firefox, IE 5/5.5/6 and Opera 7.54/8.0b. Unfortunately, &shy; is visible in some Mac browsers, but there is small percentage of Mac browsers with JavaScript disabled, so we can live with that.)

Couple of reasons behind this decision:

  • it was more convenient to transform a single character in flash
  • i wanted to get rid of html markup for that purpose (not needed anymore, because we’re not in the browser environment any longer from this point on)
  • didn’t wan’t flash to think it should try to transform html markup on its own

JavaScript

Let’s start with the uncompressed javascript file (from sIFR 2.0 RC3), around line 280, where elements within the heading are handled. Here’s original code:

    if(oSearch.nodeName.toLowerCase() == "a" && !oSearch.getAttribute("href") == false){
        if(oSearch.getAttribute("target")){
            sLinkVars += "&sifr_url_" + nLinkCount + "_target=" + oSearch.getAttribute("target");
        };
        sLinkVars += "&sifr_url_" + nLinkCount + "=" + oSearch.getAttribute("href").replace(/&/g, "%26");
        sContent += '<a href="asfunction:_root.launchURL,' + nLinkCount + '">';
        nLinkCount++;
    } else if(oSearch.nodeName.toLowerCase() == "br"){
        sContent += "<br />";
    };
    if(oSearch.hasChildNodes){
        /*  The childNodes are already copied with this node, so oNewNode = null */
        oResult = fetchContent(oSearch, null, sCase, nLinkCount, sLinkVars);
        sContent += oResult.sContent;
        nLinkCount = oResult.nLinkCount;
        sLinkVars = oResult.sLinkVars;
    };
    if(oSearch.nodeName.toLowerCase() == "a"){
        sContent += "</a>";
    };

Modified code:

    if(oSearch.nodeName.toLowerCase() == "a" && !oSearch.getAttribute("href") == false){
        if(oSearch.getAttribute("target")){
            sLinkVars += "&sifr_url_" + nLinkCount + "_target=" + oSearch.getAttribute("target");
        };
        sLinkVars += "&sifr_url_" + nLinkCount + "=" + oSearch.getAttribute("href").replace(/&/g, "%26");
        sContent += '<a href="asfunction:_root.launchURL,' + nLinkCount + '">';
        nLinkCount++;
    } else if(oSearch.nodeName.toLowerCase() == "span" && oSearch.getAttribute("class") == "sifr-alt-color"){
        sContent += "­­";  //IMPORTANT! between double quotes, there is &shy; character, which is not visible in browser
    } else if(oSearch.nodeName.toLowerCase() == "br"){
        sContent += "<br />";
    };
    if(oSearch.hasChildNodes){
        /*  The childNodes are already copied with this node, so oNewNode = null */
        oResult = fetchContent(oSearch, null, sCase, nLinkCount, sLinkVars);
        sContent += oResult.sContent;
        nLinkCount = oResult.nLinkCount;
        sLinkVars = oResult.sLinkVars;
    };
    if(oSearch.nodeName.toLowerCase() == "a"){
        sContent += "</a>";
    } else if(oSearch.nodeName.toLowerCase() == "span" && oSearch.getAttribute("class") == "sifr-alt-color"){
        sContent += "­­"; //IMPORTANT! between double quotes, there is &shy; character, which is not visible in browser
    };

It basically says, if <span> node with class attribute "sifr-alt-color" is found, remove it and prepend/append the shy character to node content. That’s all that has to be done at the javascript level.

On to flash

First we change customize_me.as. Couple of new variables are introduced here, which i’ll use in dont_customize_me.as later on:

    colorDelimiter = "­­";                       // shy character, begin/end marker for block of different color IMPORTANT! between double quotes, there is &shy; character, which is not visible in browser
    colorDelimiterLen = colorDelimiter.length;  // not mandatory, but used on couple of places in main file, so this was convenient
    alternateColor = "#CE0005";                 // self explanatory

All done here, let’s move to dont_customize_me.as. In plain English, find the ­­text­ ­(note: text is shy-enclosed, but &shy itself isn’t visible in browser) and replace it with <font color="alternateColor">text</font>.

Here is how to do it. At the end of the file, before "holder._alpha = 100;" add:

    placeholder = holder.txtF.htmlText;
    if (placeholder.indexOf(colorDelimiter) > -1) {
        // replace shy-enclosed blocks with <font> enclosed blocks
        tempBlock = "";
        breaker3 = 0;
        while (placeholder.indexOf(colorDelimiter) > -1 && breaker3 < 300) {
            tempString = placeholder.substring(placeholder.indexOf(colorDelimiter));
            tempString = (tempString.indexOf(colorDelimiter, colorDelimiterLen) > -1) ? tempString.slice(0,tempString.indexOf(colorDelimiter, colorDelimiterLen)+colorDelimiterLen) : tempString.slice(0);
            tempArray = placeholder.split(tempString);
            tempString = (tempString.indexOf(colorDelimiter, colorDelimiterLen) > -1) ? tempString.substring(colorDelimiterLen, tempString.length-colorDelimiterLen) : tempString.substring(colorDelimiterLen);
            tempBlock += tempArray[0]+"<FONT COLOR=""+alternateColor+"">"+tempString+"</FONT>";
            placeholder = tempArray[1];
            breaker3++;
        }
        tempBlock += tempArray[1];
        holder.txtF.htmlText = tempBlock;
    }
    defaultHtmlText = holder.txtF.htmlText; // remember the "colored" state so we can revert to it onRollOut

Besides that, onRollOver and onRollOut event handlers had to be changed (for links), because the original implementation caused the whole string to revert to base color onRollOut.

In order to achieve this, change:

    holder.onRollOver = function () {
        if (hovercolor != undefined) {
            // link_color.setRGB(parseInt(hovercolor)); // old code
            fmt.color = hovercolor;                     // new code
            holder.txtF.setTextFormat(fmt);             // new code
        }
        if (underline != undefined) {
            fmt.underline=true;
            holder.txtF.setTextFormat(fmt);
        }
    }
    holder.onRollOut = function () {
        if (hovercolor != undefined) {
            // link_color.setRGB(linkcolorhex);         // old code
            holder.txtF.htmlText = defaultHtmlText;     // new code, defaultHtmlText is original "colored" state from the code above
        } 
        if (underline != undefined) {
            fmt.underline=false;
            holder.txtF.setTextFormat(fmt);
        }
    }

And you’re done!

Another benefit of this approach is that you can style (colorize) parts of the heading in the regular css so they are presented in the same fashion to non sIFR users.

I hope this helps and I’ll be happy to discuss more about it in the comments.

(Editor’s note: After hacking .as files, your old .swf files have to be reexported.)

Update

We provided demo page.

Update 2

Two Color sIFR has been rethought at Two Color sIFR Take Two article.

Marko Dugonjić is a designer specialized in user experience design, web typography and web standards. He runs a nanoscale user interface studio Creative Nights and organizes FFWD.PRO, a micro-conference and workshops for web professionals.

Interested in more content like this?