// IE5.5+ PNG Alpha Fix v2.0 Alpha: Background Tiling Support
// (c) 2008 Angus Turnbull http://www.twinhelix.com

// This is licensed under the GNU LGPL, version 2.1 or later.
// For details, see: http://creativecommons.org/licenses/LGPL/2.1/
var IEPNGFix = window.IEPNGFix || {};

IEPNGFix.tileBG = function(elm, pngSrc, ready) {
    // Params: A reference to a DOM element, the PNG src file pathname, and a
    // hidden "ready-to-run" passed when called back after image preloading.

    var data = this.data[elm.uniqueID], elmW = Math.max(elm.clientWidth, elm.scrollWidth), elmH = Math.max(
	    elm.clientHeight, elm.scrollHeight), bgX = elm.currentStyle.backgroundPositionX, bgY = elm.currentStyle.backgroundPositionY, bgR = elm.currentStyle.backgroundRepeat;

    // Cache of DIVs created per element, and image preloader/data.
    if (!data.tiles) {
	data.tiles = {
	    elm :elm,
	    src :'',
	    cache : [],
	    img :new Image(),
	    old : {}
	};
    }
    var tiles = data.tiles, pngW = tiles.img.width, pngH = tiles.img.height;

    if (pngSrc) {
	if (!ready && pngSrc != tiles.src) {
	    // New image? Preload it with a callback to detect dimensions.
	    tiles.img.onload = function() {
		this.onload = null;
		IEPNGFix.tileBG(elm, pngSrc, 1);
	    };
	    return tiles.img.src = pngSrc;
	}
    } else {
	// No image?
	if (tiles.src)
	    ready = 1;
	pngW = pngH = 0;
    }
    tiles.src = pngSrc;

    if (!ready && elmW == tiles.old.w && elmH == tiles.old.h && bgX == tiles.old.x && bgY == tiles.old.y
	    && bgR == tiles.old.r) {
	return;
    }

    // Convert English and percentage positions to pixels.
    var pos = {
	top :'0%',
	left :'0%',
	center :'50%',
	bottom :'100%',
	right :'100%'
    }, x, y, pc;
    x = pos[bgX] || bgX;
    y = pos[bgY] || bgY;
    if (pc = x.match(/(\d+)%/)) {
	x = Math.round((elmW - pngW) * (parseInt(pc[1]) / 100));
    }
    if (pc = y.match(/(\d+)%/)) {
	y = Math.round((elmH - pngH) * (parseInt(pc[1]) / 100));
    }
    x = parseInt(x);
    y = parseInt(y);

    // Handle backgroundRepeat.
    var repeatX = {
	'repeat' :1,
	'repeat-x' :1
    }[bgR], repeatY = {
	'repeat' :1,
	'repeat-y' :1
    }[bgR];
    if (repeatX) {
	x %= pngW;
	if (x > 0)
	    x -= pngW;
    }
    if (repeatY) {
	y %= pngH;
	if (y > 0)
	    y -= pngH;
    }

    // Go!
    this.hook.enabled = 0;
    if (!( {
	relative :1,
	absolute :1
    }[elm.currentStyle.position])) {
	elm.style.position = 'relative';
    }
    var count = 0, xPos, maxX = repeatX ? elmW : x + 0.1, yPos, maxY = repeatY ? elmH : y + 0.1, d, s, isNew;
    if (pngW && pngH) {
	for (xPos = x; xPos < maxX; xPos += pngW) {
	    for (yPos = y; yPos < maxY; yPos += pngH) {
		isNew = 0;
		if (!tiles.cache[count]) {
		    tiles.cache[count] = document.createElement('div');
		    isNew = 1;
		}
		var clipR = (xPos + pngW > elmW ? elmW - xPos : pngW), clipB = (yPos + pngH > elmH ? elmH - yPos : pngH);
		d = tiles.cache[count];
		s = d.style;
		s.behavior = 'none';
		s.left = xPos + 'px';
		s.top = yPos + 'px';
		s.width = clipR + 'px';
		s.height = clipB + 'px';
		s.clip = 'rect(' + (yPos < 0 ? 0 - yPos : 0) + 'px,' + clipR + 'px,' + clipB + 'px,'
			+ (xPos < 0 ? 0 - xPos : 0) + 'px)';
		s.display = 'block';
		if (isNew) {
		    s.position = 'absolute';
		    s.zIndex = -999;
		    if (elm.firstChild) {
			elm.insertBefore(d, elm.firstChild);
		    } else {
			elm.appendChild(d);
		    }
		}
		this.fix(d, pngSrc, 0);
		count++;
	    }
	}
    }
    while (count < tiles.cache.length) {
	this.fix(tiles.cache[count], '', 0);
	tiles.cache[count++].style.display = 'none';
    }

    this.hook.enabled = 1;

    // Cache so updates are infrequent.
    tiles.old = {
	w :elmW,
	h :elmH,
	x :bgX,
	y :bgY,
	r :bgR
    };
};

IEPNGFix.update = function() {
    // Update all PNG backgrounds.
    for ( var i in IEPNGFix.data) {
	var t = IEPNGFix.data[i].tiles;
	if (t && t.elm && t.src) {
	    IEPNGFix.tileBG(t.elm, t.src);
	}
    }
};
IEPNGFix.update.timer = 0;

if (window.attachEvent && !window.opera) {
    window.attachEvent('onresize', function() {
	clearTimeout(IEPNGFix.update.timer);
	IEPNGFix.update.timer = setTimeout(IEPNGFix.update, 100);
    });
}
