/*
   PNGHandler: Object-Oriented Javascript-based PNG wrapper
   --------------------------------------------------------
   Version 1.2.20040803
   Code by Scott Schiller - www.schillmania.com
   --------------------------------------------------------
   Description:
   Provides gracefully-degrading PNG functionality where
   PNG is supported natively or via filters (Damn you, IE!)
   Should work with PNGs as images and DIV background images.
   --------------------------------------------------------
   Revision history
   --------------------------------------------------------
   1.2
   - Added refresh() for changing PNG images under IE
   - Class extension: "scale" causes PNG to scale under IE
   --------------------------------------------------------
   Known bugs
   --------------------------------------------------------
   - ie:mac doesn't support PNG background images.
   - Safari doesn't support currentStyle() - can't parse BG
     via CSS (ie. for a DIV with a PNG background by class)

*/

function PNGHandler() {
  var self = this;

  this.na = navigator.appName.toLowerCase();
  this.nv = navigator.appVersion.toLowerCase();
  this.isIE = this.na.indexOf('internet explorer')+1?1:0;
  this.isWin = this.nv.indexOf('windows')+1?1:0;
  this.isIEMac = (this.isIE&&!this.isWin);
  this.isIEWin = (this.isIE&&this.isWin);
  this.ver = this.isIE?parseFloat(this.nv.split('msie ')[1]):parseFloat(this.nv);
  this.isMac = this.nv.indexOf('mac')+1?1:0;
  this.isOpera = (navigator.userAgent.toLowerCase().indexOf('opera ')+1 || navigator.userAgent.toLowerCase().indexOf('opera/')+1);
  if (this.isOpera) this.isIE = false; // Opera filter catch (which is sneaky, pretending to be IE by default)
  this.extensions = ['.gif','.png']; // GIF to PNG by default
  this.filterID = 'DXImageTransform.Microsoft.AlphaImageLoader';
  this.PNGsupport = true;
  this.transform = self.doNothing;

  this.filterMethod = function(o) {
    // IE 5.5+ proprietary filter garbage (boo!)
    // Create new element based on old one. Doesn't seem to render properly otherwise (due to filter?)
    // use DOM "currentStyle" method, so rules inherited via CSS are picked up.
    if (o.nodeName.toLowerCase() != 'img') {
      var b = o.currentStyle.backgroundImage.toString(); // parse out background image URL
      o.style.backgroundImage = 'none';
      // Parse out background image URL from currentStyle.
      var i1 = b.indexOf('url("')+5;
      var newSrc = b.substr(i1,b.length-i1-2).replace(self.extensions[0],self.extensions[1]); // find first instance of ") after (", chop from string
      o.style.writingMode = 'lr-tb'; // Has to be applied so filter "has layout" and is displayed. Seriously. Refer to http://msdn.microsoft.com/workshop/author/filter/reference/filters/alphaimageloader.asp?frame=true
      o.style.filter = "progid:"+self.filterID+"(src='"+newSrc+"',sizingMethod='"+(o.className.indexOf('scale')+1?'scale':'crop')+"')";
    } else if (o.nodeName.toLowerCase() == 'img') {
      var newSrc = o.getAttribute('src').replace(self.extensions[0],self.extensions[1]);
      // apply filter
      o.src = 'image/none.gif'; // get rid of image
      o.style.filter = "progid:"+self.filterID+"(src='"+newSrc+"',sizingMethod="+(o.className.indexOf('scale')+1?'scale':'crop')+"')";
      o.style.writingMode = 'lr-tb'; // Has to be applied so filter "has layout" and is displayed. Seriously. Refer to http://msdn.microsoft.com/workshop/author/filter/reference/filters/alphaimageloader.asp?frame=true
    }
  }

  this.pngMethod = function(o) {
    // Native transparency support. Easy to implement. (woo!)
    bgImage = this.getBackgroundImage(o);
    if (bgImage) {
      // set background image, replacing extension
      // o.style.backgroundImage = 'url('+bgImage.replace(self.extensions[0],self.extensions[1])+')';
      o.style.backgroundImage = bgImage.replace(self.extensions[0],self.extensions[1]);
      writeDebug('PNGHandler.pngMethod(): bgImage='+o.style.backgroundImage);
    } else if (o.nodeName.toLowerCase() == 'img') {
      o.src = o.src.replace(self.extensions[0],self.extensions[1]);
    } else if (!bgImage) {
      writeDebug('PNGHandler.pngMethod('+o.nodeName+'): no bgImage');
    }
  }

  this.getBackgroundImage = function(o) {
    var b, i1; // background-related variables
    var bgUrl = null;
    if (o.nodeName.toLowerCase() != 'img' && !(this.isIE && this.isMac)) { // ie:mac PNG support broken for DIVs with PNG backgrounds
      if (document.defaultView) {
        if (document.defaultView.getComputedStyle) {
          b = document.defaultView.getComputedStyle(o,'').getPropertyValue('background-image');
          i1 = b.indexOf('url(')+4;
          bgUrl = b.substr(i1,b.length-i1-1);
        } else {
          // no computed style
          return false;
        }
      } else {
        // no default view
        var bg = (o.currentStyle?o.currentStyle:o.style).backgroundImage.toString();
        if (bg) {
          return bg;
        } else {
          writeDebug('PNGHandler.getBackgroundImage(): Could not find BG');
          return false;
        }
      }
    }
    return bgUrl;
  }

  this.refresh = function(o,src) { // ie:win32 swap/hover fix - update via current class (background), .src or provided src
    // writeDebug('PNGHandler.refresh('+o+','+(src?src:'null'));
    var newSrc = (o.currentStyle?o.currentStyle:o.style).backgroundImage.toString();
    if (src) newSrc = src; // override to be certain
    newSrc = (newSrc?newSrc:(src?src:o.src)).replace(self.extensions[0],self.extensions[1]);
    writeDebug('PNGHandler.refresh('+o+','+src+')');
    writeDebug('PNGHandler.refresh(): newSrc='+newSrc);
    if (self.PNGsupport) {
      writeDebug('PNGHandler.refresh(): using filter string '+"progid:"+self.filterID+"(src='"+newSrc+"',sizingMethod='crop')");
      o.style.filter = "progid:"+self.filterID+"(src='"+newSrc+"',sizingMethod='crop')";
      o.style.writingMode = 'lr-tb';
    } else {
      writeDebug('PNGHandler.refresh(): not using filter');
      // this seems to cause problems
      // if (newSrc) o.style.backgroundImage = newSrc;
    }
  }

  this.doNothing = function() {}
  
  this.supportTest = function() {
    // Determine method to use.
    // IE 5.5+/win32: filter

    if (this.isIE && this.isWin && this.ver >= 5.5) {
      // IE proprietary filter method (via DXFilter)
      writeDebug('PNGHandler.supportTest(): IE/win32, v5+ - supported');
      self.transform = self.filterMethod;
    } else if (!this.isIE && this.ver < 5) {
      writeDebug('PNGHandler.supportTest(): No PNG support assumed (!ie, ver<5)');
      self.PNGsupport = false;
      self.extensions = ['.png','.gif'];
      self.transform = self.pngMethod; // use typical method, but swap PNG for GIF
      // No PNG support or broken support
      // Leave existing content as-is
    } else if (!this.isIE && this.ver >= 5 || (this.isIE && this.isMac && this.ver >= 5)) { // version 5+ browser (not IE), or IE:mac 5+
      writeDebug('PNGHandler.supportTest(): ie:mac 5+ or other v5+ - supported');
      self.transform = self.pngMethod;
    } else {
      // Presumably no PNG support. GIF used instead, swapping PNG for GIF where applicable.
      writeDebug('PNGHandler.supportTest(): No PNG support assumed');
      self.PNGsupport = false;
      self.extensions = ['.png','.gif'];
      self.transform = self.pngMethod;
    }
    return true;
  }

  this.init = function() {
    if (this.transform) {
      this.elements = getElementsByClassName('png',['div','img','h2','ul']);
      writeDebug('PNGHandler.init() - start ('+this.elements.length+' elements)');
      for (var i=0; i<this.elements.length; i++) {
        this.transform(this.elements[i]);
      }
    }
    writeDebug('PNGHandler.init() - finish');
  }

}

// Instantiate and initialize PNG Handler

var pngHandler = new PNGHandler();