//Browser independant fade transition from a source image object to a target image  
function swapFadeImageTransition(inMidTransitionCallback, inEndTransitionCallback) {
  
  //restrict max opacity to prevent a visual popping effect in some browsers
  var itsMaxOpacity=0.999999;                                
  //browser independant swap fader object
  var itsGenericSwapFader = { 'clock' : null, 'fade' : true, 'opacity' : itsMaxOpacity};     
  var self = this;
  var itsMidTransitionCallback=inMidTransitionCallback;
  var itsEndTransitionCallback=inEndTransitionCallback;


  function setBrowserType() {
    //use for generic browser support
    if(typeof itsGenericSwapFader.obj.style.opacity != 'undefined') {
      itsGenericSwapFader.type = 'w3c'; }
    else if(typeof itsGenericSwapFader.obj.style.MozOpacity != 'undefined')
      itsGenericSwapFader.type = 'moz';
    else if(typeof itsGenericSwapFader.obj.style.KhtmlOpacity != 'undefined')
      itsGenericSwapFader.type = 'khtml';
    //no opacity support in IE5 on win and mac, check for signatures.
    else if(typeof itsGenericSwapFader.obj.style.filter != 'undefined')  
    	  itsGenericSwapFader.type ='ie';
    else
      itsGenericSwapFader.type = 'none';
};


  function setOpacity() {

   switch(itsGenericSwapFader.type)  {
    case 'ie' :
      itsGenericSwapFader.obj.style.filter = "alpha(opacity="+itsGenericSwapFader.opacity * 100+")";
      break;			
    case 'khtml' :
      itsGenericSwapFader.obj.style.KhtmlOpacity = itsGenericSwapFader.opacity;
      break;
    case 'moz' : 
      itsGenericSwapFader.obj.style.MozOpacity = itsGenericSwapFader.opacity;
      break;
    case 'w3c' : 
      itsGenericSwapFader.obj.style.opacity = itsGenericSwapFader.opacity;
    }
  };


  this.stop = function(inImageFname, inImageObject) {    

    if(typeof inImageObject != 'undefined')
      itsGenericSwapFader.obj = inImageObject;  
    
    if(typeof inImageFname != 'undefined')
    itsGenericSwapFader.obj.src = inImageFname;
    
    setBrowserType();
    if(itsGenericSwapFader.type != 'none') { 
      clearInterval(itsGenericSwapFader.clock);
      itsGenericSwapFader.clock = null;
      itsGenericSwapFader.fade = true;
      itsGenericSwapFader.opacity = itsMaxOpacity;
      setOpacity();
    }
  };


  //Incremental fade
  this.swapfade = function() {
    
    //fade on an exponential rate (either fade-out or fade-in)
    //itsGenericSwapFader.opacity = (itsGenericSwapFader.fade) ? itsGenericSwapFader.opacity * 0.9 : (itsGenericSwapFader.opacity * (1/0.9)); 
    
    //fade on a linear scale
    itsGenericSwapFader.opacity = (itsGenericSwapFader.fade)? itsGenericSwapFader.opacity-(itsMaxOpacity / itsGenericSwapFader.res) : itsGenericSwapFader.opacity+ (itsMaxOpacity / itsGenericSwapFader.res);		
    
    //if fade-out complete, reverse fade direction (fade in to next image)
    if(itsGenericSwapFader.opacity < (itsMaxOpacity / itsGenericSwapFader.res)){
      clearInterval(itsGenericSwapFader.clock);
      itsGenericSwapFader.clock = null;
      itsGenericSwapFader.obj.src = itsGenericSwapFader.src;
      itsGenericSwapFader.fade = false;
      itsGenericSwapFader.clock = setInterval(self.swapfade, itsGenericSwapFader.length/itsGenericSwapFader.res);
      //call the mid-transition callback function
       if(typeof itsMidTransitionCallback == 'function')
            itsMidTransitionCallback();
    }
    //if fade-in complete
    if(itsGenericSwapFader.opacity > (itsMaxOpacity - (itsMaxOpacity / itsGenericSwapFader.res))) {
       self.stop();
        //call the end-transition callback function
       if(typeof itsEndTransitionCallback == 'function')
            itsEndTransitionCallback();
    }

    setOpacity();
  };
  
  this.start = function(inImageFname, inImageObject, inDuration, inAltText, inMidTransitionCallback, inEndTransitionCallback) {

   //This should preload next image to cache
    var theImageBuff = new Image();
    theImageBuff.src=inImageFname;
    
    //start only if a transition is not already taking place
    if(itsGenericSwapFader.clock == null ){
      //param: image object 
      itsGenericSwapFader.obj = inImageObject
      //param: target image src
      itsGenericSwapFader.src = inImageFname;

      //param: total transition duration length (in seconds, for both images), convert to ms and devide by 2 
      itsGenericSwapFader.length=parseFloat(inDuration, 10) * 500;
      //sampling resolution (20 per transition steps, 10 per image)
      itsGenericSwapFader.res = parseFloat(inDuration, 10) * 20;
      //param: image alt text (optional)
      if(typeof inAltText != 'undefined' && inAltText != '')
         //itsGenericSwapFader.obj.alt = inAltText;
      setBrowserType();
      //set the callbacks
       if(typeof inMidTransitionCallback == 'function')
            itsMidTransitionCallback=inMidTransitionCallback;
     if(typeof inEndTransitionCallback == 'function')
            itsEndTransitionCallback=inEndTransitionCallback;
      //Do the transition
      if(itsGenericSwapFader.type != 'none')  
         itsGenericSwapFader.clock = setInterval(self.swapfade, itsGenericSwapFader.length/itsGenericSwapFader.res);
      else
        itsGenericSwapFader.obj.src = itsGenericSwapFader.src;
    }
  };

    this.setCallbacks = function(inMidTransitionCallback, inEndTransitionCallback) {
         if(typeof inMidTransitionCallback == 'function')
            itsMidTransitionCallback=inMidTransitionCallback;
     if(typeof inEndTransitionCallback == 'function')
            itsEndTransitionCallback=inEndTransitionCallback;
   };

};




  
