/*******************************************************************************
 * fauxFlash is a frame based animation framework that mimics some flash-like
 * graphic animations. 
 *
 * The only public functions contained in this package are the factory functions
 * that are used to create the stage and the animation action objects.
 *
 *
 *
 *
 *
 * Oct 20 2020 : L.Tietz
 * copyright 2020 : Laurence Tietz
 *******************************************************************************
 *******************************************************************************/
// the stage obj s a singleton - create it and pass it an array
// of frame actions to execute - we MUST create this first before creating any actions  
var gStage                                                  = null;
// constants
var WAIT_TILL_ACTION_COMPLETES_BEFORE_GOING_TO_NEXT_FRAME   = false;
var NO_WAIT_GO_TO_NEXT_FRAME                                = true;

// 1000 = 1 sec
var ONE_SECOND                                              = 1000;
var TWO_SECONDS                                             = 2000;
var THREE_SECONDS                                           = 3000;
var FOUR_SECONDS                                            = 4000;
var FIVE_SECONDS                                            = 5000;
var SIX_SECONDS                                             = 6000;
var SEVEN_SECONDS                                           = 7000;
var EIGHT_SECONDS                                           = 8000;
var NINE_SECONDS                                            = 9000;
var TEN_SECONDS                                             = 10000;

var LOOP_FRAMES                                             = true;
var DONT_LOOP_FRAMES                                        = false;


// THE FOLLOWING CODE IS GENERAL : IT REPERSENTS A FACTORY DESIGN PATTERN USED TO GENERATE
// THE AVAILABLE ACTIONS. THIS CODE WILL BE MOVED TO A UTILITY FILE
function createStage () {
        gStage = new stageClass();
}

function initStage (frames,loopFramesBoolean, loopToFrameNumber) {
    gStage.initStage(frames,loopFramesBoolean,loopToFrameNumber);    
}

function pauseStage(){
     if (gStage != null){
        gStage.pause();
     }
}

function playStage() {
     if (gStage != null) {
        gStage.play();
     }  
}

function createMoveElementAction (elementID  ,startX , stopX , startY , stopY , delay , delta,  direction ,waitForMeToComplete) {
    argObj = new argClass();
    
    argObj.elementID = elementID;
    argObj.startX = startX;
    argObj.stopX = stopX;
    argObj.startY = startY;
    argObj.stopY = stopY;

   
    //this.elementObj = document.getElementById(this.elementID);
    argObj.delay = delay;
    argObj.direction = direction;
    argObj.delta = delta;
    if (waitForMeToComplete) {
        argObj.moveCompleteF = null;
    }
    else {
        argObj.moveCompleteF = gStage.actionComplete.bind(gStage);
    }

    moveElementObj = new moveElementEffectsClass();
    var me = moveElementObj;
    var af = moveElementObj.initMoveElement.bind(me);
    _debug("af = " + af);
  
    return(new actionClass(af , waitForMeToComplete , argObj ));
}
function createSlideShowAction ( slideURLArray , elementID , delay ,waitForMeToComplete, loop  ) {
    argObj = new argClass();
    argObj.elementID = elementID;
    argObj.slideURLArray = slideURLArray;
    argObj.delay = delay;
    if (waitForMeToComplete) {
        argObj.completeF = null;
    }
    else {
        argObj.completeF = gStage.actionComplete.bind(gStage);
    }
   
    argObj.loop = loop;
    
    slideShowObj = new slideShowEffectsClass();
    var me = slideShowObj;
    var af = slideShowObj.initSlideShow.bind(me);
    _debug("af = " + af);
    
    return(new actionClass(af , waitForMeToComplete , argObj ));
}

function createShowElementObj (elementID) {
    argObj = new argClass();
    argObj.elementID = elementID;
    
    showObj = new visibityElementEffectsClass();
    var me = showObj;
    var af = showObj.show.bind(me);
    //alert("af = " + af);
    
    return(new actionClass(af , true , argObj ));
}

function createHideElementObj (elementID) {
    argObj = new argClass();
    argObj.elementID = elementID;
    
    visiblityObj = new visibityElementEffectsClass();
    var me = visiblityObj;
    var af = visiblityObj.hide.bind(me);
    //alert("af = " + af);
    
    return(new actionClass(af , true , argObj ));
}

function createPauseState (delay ) {
    argObj = new argClass();
    argObj.delay = delay;
    argObj.pauseCompleteF = gStage.actionComplete.bind(gStage);
    
    pauseObj = new pauseFrameEffectClass();
    var me = pauseObj;
    var af = pauseObj.initPause.bind(me);
    _debug("af = " + af);
    return( new actionClass(af , false , argObj )); 
}

function createFadeOutObj (beginOpacity , endOpacity , deltaOpacity , imageId , waitForMeToComplete) {
    argObj = new argClass();
    argObj.beginOpacity = beginOpacity;
    argObj.endOpacity = endOpacity;
    argObj.deltaOpacity = deltaOpacity;
    argObj.imageId = imageId;
    if (waitForMeToComplete) {
        var fc = null;
    }
    else {
        var fc = gStage.actionComplete.bind(gStage);
    }
    
    _debug(fc);
    
    argObj.fadeCompleteF = fc;
    
    fadeOutObj = new fadeOutEffectsClass();
    var me = fadeOutObj;
    var af = fadeOutObj.initFadeOut.bind(me);
    _debug("af = " + af);
    return( new actionClass(af , waitForMeToComplete , argObj )); 
}
function createFadeInObj (beginOpacity , endOpacity , deltaOpacity , imageId , waitForMeToComplete) {
    argObj = new argClass();
    argObj.beginOpacity = beginOpacity;
    argObj.endOpacity = endOpacity;
    argObj.deltaOpacity = deltaOpacity;
    argObj.imageId = imageId;
    if (waitForMeToComplete) {
        var fc = null;
    }
    else {
        var fc = gStage.actionComplete.bind(gStage);
    }
    
    _debug(fc);
    
    argObj.fadeCompleteF = fc;
    
    fadeInObj = new fadeInEffectClass();
    var me = fadeInObj;
    var af = fadeInObj.initFadeIn.bind(me);
    _debug("af = " + af);
    return( new actionClass(af , waitForMeToComplete , argObj ));    
}

function createCrossFadeObj (deltaOpacity , inImageID , outImageID, waitForMeToComplete) {
   
    argObj = new argClass();
    argObj.inImageID = inImageID;
    argObj.outImageID = outImageID;
    argObj.opacity = 0; //opacity;
    
    
    //argObj.beginOpacity = beginOpacity;
    //argObj.endOpacity = endOpacity;
    
    argObj.deltaOpacity = deltaOpacity;
    
    if (waitForMeToComplete) {
        var fc = null;
    }
    else {
        var fc = gStage.actionComplete.bind(gStage);
    }
    
    _debug(fc);
    
    argObj.fadeCompleteF = fc;
    
    crossFadeObj = new crossFadeEffectClass();
    
    var me = crossFadeObj;
    var af = crossFadeObj.initCrossFade.bind(me);
    _debug("af = " + af);
    return( new actionClass(af , waitForMeToComplete , argObj ));
    /**/
   
}

function createBounce (leftWall, rightWall, topWall, bottomWall, deltaH, deltaV, deltaT, elementID , waitForMeToComplete , startX, startY, xDir, yDir, id) {
    argObj = new argClass();
    argObj.leftWall = leftWall;
    argObj.rightWall = rightWall;
    argObj.topWall = topWall;
    argObj.bottomWall = bottomWall;
    argObj.deltaH = deltaH;
    argObj.deltaV = deltaV;
    argObj.deltaT = deltaT;
    argObj.elementID = elementID;
    if (waitForMeToComplete) {
        var fc = null;
    }
    else {
        var fc = gStage.actionComplete.bind(gStage);
    }
    argObj.doneCallbackF = fc;
    argObj.startX = startX;
    argObj.startY = startY;
    argObj.xDir = xDir;
    argObj.yDir = yDir;
    argObj.id = id;
    
    bounceObj = new bounceElementEffectsClass ();
    var me = bounceObj;
    var af = bounceObj.init.bind(me);
    _debug("af = " + af);
    return( new actionClass(af , waitForMeToComplete , argObj ));
}
/*******************************************************************************
* The following code represents the Classes that make up the Faux Flash
* framework. This includes the following classes
* a) stageClass : manages a set of frames - each containing an action obj
* b) actionClass : general action wrapper
* c) argClass : general argument container used to buffer arguments used by actions
* d) moveElementEffectsClass : moves an element up/down/right/left
* e) slideShowEffectsClass : displays a set of images sequencially (gif animation)
* f) fadeOutEffectsClass : fade out an element
* g) fadeInEffectClass : fade in an element
* h) crossFadeEffectClass : cross fade one element with another element
* i) pauseFrameEffectClass : pause a frame for a specified period of time
* j) visibityElementEffectsClass : show or hide an element
*/
// stage class iterates through an array of "frames"
// each frame contains an action obj
function stageClass () {
    this.playStatus = false;
    
}

stageClass.prototype.initStage = function (stageFrames , loopFrames , loopToFrameNumber) {
    this.loopFrames = loopFrames;
    this.stageFrames = stageFrames;
    this.frameIndex = 0;
    this.goToNextFrame = true;
    this.loopToFrameNumber = loopToFrameNumber;
    var me = this;
    _debug("stageClass :: initStage :: me " + me);
    var f =   this.update.bind(me);
    _debug("stageClass :: initStage :: this.continueStatus " + this.continueStatus);
    _debug("stageClass :: initStage :: f " + f);
    
    window.setInterval (f, 10);
}

stageClass.prototype.update=function(){
    //_debug(" update scope = " + this);

    if (this.goToNextFrame && this.playStatus) {
        //console.log("go to next frame");
        if (this.frameIndex < this.stageFrames.length) {
            _debug("frame index = " + this.frameIndex + " of " + this.stageFrames.length);
            actionObj = this.stageFrames[this.frameIndex++];
            _debug("actionObj " + actionObj);
            this.goToNextFrame = actionObj.getContinueStatus();
            _debug("this.goToNextFrame immediately after starting this action?  "+this.goToNextFrame);
            _debug("update " + actionObj.actionFunction);
            argObj = actionObj.argObj;         
            actionObj.actionFunction(argObj);
        }
        else {
            if (this.loopFrames) {this.frameIndex =  this.loopToFrameNumber - 1;}
        }
    }
    else {_debug("wait");}
}

stageClass.prototype.actionComplete=function () {
    //_debug("action complete " + (this.frameIndex - 1));
    this.goToNextFrame = true;
}

stageClass.prototype.pause = function () {
    this.playStatus = false;
    // remove any timers
   /* for (i=0;i<this.stageFrames.length;i++) {
        actionObj = this.stageFrames[i];
        actionObj.removeTimer();
    } */
}


stageClass.prototype.play = function () {
   
    this.playStatus = true;    
}
//------------------------------------------------------------------------------
// container class to hold an action function and the arguments that will
// be passed to it as well as whether or not the stage obj should wait
// for the completion of the action before issuing the next action on the stack
function actionClass(actionFunction , conditionalReturn , argObj) {
    this.actionFunction = actionFunction;
    this.nextFrame      = conditionalReturn;
    this.argObj         = argObj;
}
//
actionClass.prototype.getContinueStatus = function () {
    return (this.nextFrame);
}

actionClass.prototype.getActionFunction = function (){
    return(this.actionFunction);
}

actionClass.prototype.setContinueStatus = function (s){
    _debug("wtf");
    this.nextFrame = s;
}

actionClass.prototype.getArgObj = function () {
    return(this.argObj);
}

actionClass.prototype.removeTimer = function () {        
        this.actionFunction.removeTimer();
}

//------------------------------------------------------------------------------
function argClass () {
    obj = new Object(); 
    return(obj);
}
//------------------------------------------------------------------------------
function xfadeSlideShow() {
        
}

xfadeSlideShow.prototype.init = function(element1 , element2 , imageLst ) {
   this.element1 = element1;
   this.element2 = element2;
   this.imageList = imageLst;
   this.index = 0;
   this.toggle = false;
   this.clearTimer = null;
}

xfadeSlideShow.prototype.play = function() {
   
   if (   this.toggle ) {
        this.toggle = false;
        document.getElementById(this.element1).innerHtml = "";
   }
   else {
          this.toggle = true;
   }
}

xfadeSlideShow.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}

//------------------------------------------------------------------------------
function moveElementEffectsClass () {
 
}

moveElementEffectsClass.prototype.initMoveElement = function (argObj) {

    this.elementID = argObj.elementID;
    this.startX = argObj.startX;
    this.stopX = argObj.stopX;
    this.startY = argObj.startY;
    this.stopY = argObj.stopY;
    this.y = this.startY;
    
    this.elementObj = document.getElementById(this.elementID);
    this.delay = argObj.delay;
    this.direction = argObj.direction;
    this.delta = argObj.delta;
    this.moveCompleteF = argObj.moveCompleteF;
    this.clearTimer = null;
    this.moveElement();
}

moveElementEffectsClass.prototype.moveElement = function () {
    //y = this.elementObj.top;
    switch (this.direction) {
        case "up":
            this.moveUp();
            break;
        case "down":
            this.moveDown();
            break;
    }
}

moveElementEffectsClass.prototype.moveUp = function () {
        if (this.y > this.stopY) {
        //_debug(" what is y " + this.y);
        this.elementObj.style.top = this.y+"px";
        this.y-= this.delta;
        f = this.moveElement.bind(this);    
	this.clearTimer = window.setTimeout(f, this.delay);
    }
    else {
         if (this.moveCompleteF) {this.moveCompleteF();};
    }
}


moveElementEffectsClass.prototype.moveDown = function () {
        if (this.y < this.stopY) {
        _debug(" what is y " + this.y);
        this.elementObj.style.top = this.y+"px";
        this.y+= this.delta;
        f = this.moveElement.bind(this);    
	this.clearTimer = window.setTimeout(f, this.delay);
    }
    else {
         if (this.moveCompleteF) {this.moveCompleteF();};
    }
}

moveElementEffectsClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
function slideShowEffectsClass () {
    
}

slideShowEffectsClass.prototype.initSlideShow = function(argObj) {
    this.slideIndex = 0;
    this.slideURLArray = argObj.slideURLArray;
    this.completeF = argObj.completeF;
   //alert("argObj.elementID "+argObj.elementID);
    this.elementID = argObj.elementID;
    this.elementObj = document.getElementById(this.elementID);
    this.delay = argObj.delay;
    this.loop = argObj.loop;
    this.clearTimer = null;
    this.nextSlide();
}

slideShowEffectsClass.prototype.nextSlide = function () {
    _debug("slide index = " + this.slideIndex + " : " + this.slideURLArray.length);
    if (this.slideIndex < this.slideURLArray.length) {
        image = this.slideURLArray[this.slideIndex];
        this.nextIndex();
        //console.log("slide url = " + image);
        //console.log("this.elementID "+this.elementID);
       
       // if (this.elementObj == null) {
                this.elementObj = document.getElementById(this.elementID);
        // }
        //console.log("this.elementObj "+this.elementObj);
        if (this.elementObj!=null) {
                this.elementObj.innerHTML = "<img src="+image+">";
        }
       
        f = this.nextSlide.bind(this);    
	this.clearTimer = window.setTimeout(f, this.delay);
    }
    else {
        if (this.completeF) {this.completeF();};
    }
}

slideShowEffectsClass.prototype.nextIndex = function () {
    if (this.slideIndex < this.slideURLArray.length - 1) {
        this.slideIndex++;
    }
    else {
        if (this.loop) {
            this.slideIndex = 0;
        }
        else {
            this.slideIndex++;
        }
    }
}

slideShowEffectsClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
function fadeOutEffectsClass () {
    
}

fadeOutEffectsClass.prototype.initFadeOut = function(argObj) {
    this.imageId = argObj.imageId;
    this.beginOpacity = argObj.beginOpacity;
    this.opacity = this.beginOpacity;
    this.endOpacity = argObj.endOpacity;
    this.deltaOpacity = argObj.deltaOpacity;
    this.fadeCompleteF = argObj.fadeCompleteF;
    this.clearTimer = null;
    this.fadeOut();
}

fadeOutEffectsClass.prototype.fadeOut = function (objId,opacity){
    _debug("opacity = " + opacity);
    if (document.getElementById) {
	obj = document.getElementById(this.imageId);
	if (this.opacity > this.endOpacity) {
	    setOpacity(obj, this.opacity);
	    this.opacity -= this.deltaOpacity;
	    _debug("opacity = " + this.opacity);
	    f = this.fadeOut.bind(this);
            _debug("fade in set timer call back = " + f);
            
	    this.clearTimer = window.setTimeout(f, 100);
	}
	else {
	   // done fade out - hide the element
	    obj.style.display = 'none';
            if (this.fadeCompleteF) {this.fadeCompleteF();};
	}
    }  
}

fadeOutEffectsClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
// fade in action class
// function to fade an element / image
function fadeInEffectClass () {
    
}

fadeInEffectClass.prototype.initFadeIn = function (argObj) {
    this.imageId = argObj.imageId;
    this.beginOpacity = argObj.beginOpacity;
    this.opacity = this.beginOpacity;
    this.endOpacity = argObj.endOpacity;
    this.deltaOpacity = argObj.deltaOpacity;
    this.fadeCompleteF = argObj.fadeCompleteF;
    _debug("WTF is this = " + this.fadeCompleteF);
    //argObj.doneCallbackF
    _debug("initFadeIn::imageId " + this.imageId);
    image = document.getElementById(this.imageId);
    setOpacity(image, this.beginOpacity);
    image.style.visibility = "visible";
    image.style.display = '';
    this.clearTimer = null;
    this.fadeIn();
}

// PRIVATE should only be called from initFadeIn
fadeInEffectClass.prototype.fadeIn = function () {
    //imageId = argObj.imageId;
    //this.opacity = argObj.opacity;
    //fadeCompleteF = argObj.fadeCompleteF;
    _debug("imageId = " + this.imageId);
    _debug("opacity = " + this.opacity);
    if (document.getElementById) {
	obj = document.getElementById(this.imageId);
        _debug(" obj = " + obj);
	if (this.opacity <= this.endOpacity) {
            _debug("fadeIn::setOpacity = " + this.opacity + ": " + obj);
	    setOpacity(obj, this.opacity);
            _debug("fadeIn :: did set opacity ok " );
	    this.opacity += this.deltaOpacity;
	    
            f = this.fadeIn.bind(this);
            _debug("fade in set timer call back = " + f);
            
	    this.clearTimer = window.setTimeout(f, 100);
	}
        else {
            _debug("about to call fadeCompleteF " + this.fadeCompleteF)
            if (this.fadeCompleteF) {this.fadeCompleteF();};
        }
    }
}


fadeInEffectClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}

//------------------------------------------------------------------------------

function crossFadeEffectClass () {
    
}

crossFadeEffectClass.prototype.initCrossFade = function(argObj) {
    _debug("imageId " + argObj.inImageID);
    this.inElementID = argObj.inImageID;
    this.outElementID = argObj.outImageID;
    this.opacity = argObj.opacity;
    this.deltaOpacity = argObj.deltaOpacity;
    this.fadeCompleteF = argObj.fadeCompleteF;
    
    this.imageIn = document.getElementById(argObj.inImageID);
    this.imageOut = document.getElementById(argObj.outImageID);
    //console.log("argObj.inImageID "+argObj.inImageID);
    //console.log("this.imageIn  "+this.imageIn );
    document.getElementById(argObj.inImageID).style.display = '';
    document.getElementById(argObj.outImageID).style.display = '';
    this.clearTimer = null;
    setOpacity(this.imageIn , 0);

	
    this.crossFade();
}

crossFadeEffectClass.prototype.crossFade= function() {
    // check to see if this js feature is supported - if not we are toast since we don't have alternative coding
    //_debug("cross fade " + this.inElementID + " " +  this.outElementID + " " + this.opacity);
    if (document.getElementById) {
	if (this.opacity <= 100) {
	    setOpacity(this.imageIn,this.opacity);
	    setOpacity(this.imageOut,100 - this.opacity);
	    _debug("and now ? " + this.opacity);
	    this.opacity += this.deltaOpacity;
	    _debug("opacity = "+ this.opacity);
	    //gCrossFadeObj = window.setTimeout("crossFade()", 100);
            f = this.crossFade.bind(this);
            _debug("fade in set timer call back = " + f);
            this.clearTimer = window.setTimeout(f, 100);
	}
	else {
	    // done fade out - hide the element
	    document.getElementById(argObj.outImageID).style.display = 'none';
            //_debug("about to call fadeCompleteF " + this.fadeCompleteF)
            if (this.fadeCompleteF) {this.fadeCompleteF();};
	}
    }
}



crossFadeEffectClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
function pauseFrameEffectClass () {
    
}

pauseFrameEffectClass.prototype.initPause = function (argObj) {
    //_debug("init pause " + argObj.delay)
    //this.pauseTimeOut = argObj.delay;
    this.pauseCompleteF = argObj.pauseCompleteF;
    this.clearTimer = null;
    f = this.clearPause.bind(this);
    window.setTimeout(f, argObj.delay);
}

pauseFrameEffectClass.prototype.clearPause = function () {
    //_debug("clear pause");
    if (this.pauseCompleteF) {this.pauseCompleteF();}
}

pauseFrameEffectClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
function visibityElementEffectsClass () {
    this.clearTimer = null;
}

visibityElementEffectsClass.prototype.show = function (argObj) {
    //_debug("show "+argObj.elementID);
    document.getElementById(argObj.elementID).style.display = '';
    setOpacity(document.getElementById(argObj.elementID), 100);
}

visibityElementEffectsClass.prototype.hide = function (argObj) {
    document.getElementById(argObj.elementID).style.display = 'none';
}


visibityElementEffectsClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
//------------------------------------------------------------------------------
function bounceElementEffectsClass () {
    this.active = false;
}

bounceElementEffectsClass.prototype.init = function (argObj) {
    if (this.active  == false) {
        //alert("init the bounce");
        this.leftWall = argObj.leftWall;
        this.rightWall = argObj.rightWall;
        this.topWall = argObj.topWall;
        this.bottomWall = argObj.bottomWall;
        this.deltaH = argObj.deltaH;
        this.deltaV = argObj.deltaV;
        this.deltaT = argObj.deltaT;
        this.elementID = argObj.elementID;
        this.doneCallbackF = argObj.doneCallbackF;
        this.imageID = document.getElementById(argObj.elementID);
        this.x = argObj.startX;
        this.y = argObj.startY;
        this.xDir = argObj.xDir;
        this.yDir = argObj.yDir;
        this.imageID.style.left = this.x + "px";
        this.imageID.style.top = this.y + "px";
        this.active = true;
        this.id = argObj.id;
        
        this.move();       
    }
}

bounceElementEffectsClass.prototype.move = function () {
    //alert("id = " + this.id);
    this.moveH();
    this.moveV();
    f = this.move.bind(this);
    _debug("fade in set timer call back = " + f);
    this.clearTimer = window.setTimeout(f, this.deltaT);
    
}
bounceElementEffectsClass.prototype.moveH = function () {  
    if (this.xDir) {
        if (this.x < this.rightWall) {
            this.x += this.deltaH;
        }
        else {
            this.xDir = false;
            this.x -= this.deltaH;
        }
   }
   else {
        if (this.x > this.leftWall) {
            this.x -= this.deltaH;
        }
        else {
            this.xDir = true;
        }
   }
   this.imageID.style.left = this.x + "px";
}

bounceElementEffectsClass.prototype.moveV = function () {
    if (this.yDir) {
        if (this.y < this.bottomWall) {
            this.y += this.deltaV;
        }
        else {
            this.yDir = false;
            this.y += this.deltaV;
        }
   }
   else {
        if (this.y > this.topWall) {
            this.y -= this.deltaV;
        }
        else {
            this.yDir = true;
        }
   }
   this.imageID.style.top = this.y + "px";
}

bounceElementEffectsClass.prototype.removeTimer = function () {
        if (this.clearTimer != null) {
           clearInterval(this.clearTimer);
           this.clearTimer = null;
        }
}
/**/
//------------------------------------------------------------------------------
Function.prototype.bind = function(scope) {
    _debug("bind scope = " + scope);
    var _function = this;
  
    return function() {
        return _function.apply(scope, arguments);
  }
}

function setOpacity(obj, opacity) {
    opacity = (opacity == 100)?99.999:opacity;
    // IE/Win
	obj.style.filter = "alpha(opacity:"+opacity+")";
    // Safari<1.2, Konqueror
    obj.style.KHTMLOpacity = opacity/100;
    // Older Mozilla and Firefox
    obj.style.MozOpacity = opacity/100;
    // Safari 1.2, newer Firefox and Mozilla, CSS3
    obj.style.opacity = opacity/100;
}


function _debug(msg) {
    //_debug(msg);    
}
