Sunday, August 5, 2007

Fix the PNGs

While developing a recent website I ran into the all classic PNG transparency problem, where IE before version 7 needs th AlphaImageLoader to correctly handle transparent PNG images. While this doesn't work properly for CSS background images, it makes it possible to use PNGs to a certain degree of satisfactory.

There's a bunch of scripts out there to "automagically" handle loading of PNG images, but the most elegant I found somewhere was the pngbehaviour.htc file, which adds a behaviour to the img tag in IE using a css "trick":


img {
behavior: url("../css/pngbehavior.htc");
}


I did have to make some changes to the script, firstly because not all PNG images used had a suffix of ".png", and second because it detected compability with IE 7,8 and 9, where PNG transparency works, and only added extra overhead to IE users with a working version.

The modified pngbehaviour script follows:


<public:component>
<public:attach event="onpropertychange" onevent="propertyChanged()" />
<script>

var supported = /MSIE (5\.5)|[6]/.test(navigator.userAgent) && navigator.platform == "Win32";
var realSrc = "";
var blankSrc = "/img/web/trans.gif";

if (supported) fixImage();

function propertyChanged() {
if (!supported) return;

var pName = event.propertyName;
if (pName != "src") return;
// if not set to blank
if ( ! new RegExp(blankSrc).test(src))
fixImage();
};

function fixImage() {
// get src
var src = element.src;
var fixme = element.fixme;

// check for real change
if (src == realSrc) {
element.src = blankSrc;
return;
}

if ( ! new RegExp(blankSrc).test(src)) {
// backup old src
realSrc = src;
}

// test for png
if ( /\.png$/.test( realSrc.toLowerCase() ) ||
(fixme && fixme == 1)) {
// set blank image
element.src = blankSrc;
// set filter
element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='image')";
}
else {
// remove filter
element.runtimeStyle.filter = "";
}
}

</script>
</public:component>


I have introduced a new attribute (which breaks xhtml, yes), named "fixme", to "force" the script above to "fix" images that do not have a suffix of .png (automatically generated images). Example:
<a href="/generateImage1" fixme="1"/>

Enjoy