// ie5.5+ png alpha fix v2.0 alpha: background tiling support // (c) 2008-2009 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 = math.max(0, xpos + pngw > elmw ? elmw - xpos : pngw), clipb = math.max(0, ypos + pngh > elmh ? elmh - ypos : pngh); d = tiles.cache[count]; s = d.style; s.behavior = 'none'; s.left = (xpos - parseint(elm.currentstyle.paddingleft)) + '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); }); }