/* - - - - - - - - - - - - - - - - - - - - - - -
 JavaScript
 30 ianuarie 2010 01:19:38
 HAPedit 3.1.11.111
 - - - - - - - - - - - - - - - - - - - - - - - */

// Content:
//     AnimatorLoop
//     Animator.prototype.cloneImg
//     SmallAnimatorChain
//         JSFX.Clasor.prototype.setSpin
//         JSFX.Clasor.prototype.setDim
//         JSFX.Clasor.prototype.setMove
//         JSFX.Clasor.prototype.setSmall
//         JSFX.Clasor.prototype.setClip
//         JSFX.Clasor.prototype.setMoveH
//         JSFX.Clasor.prototype.setMove2H
//         JSFX.Clasor.prototype.setMoveX
//         JSFX.Clasor.prototype.setWave
//         JSFX.Clasor.prototype.setWaveX
//         JSFX.Clasor.prototype.setRoll
//         JSFX.Clasor.prototype.setRollX
//         JSFX.Clasor.prototype.setBorder


// loop one Animator object
function AnimatorLoop(animator, times, waitTime, options) {
    this.animator = animator;
    this.times = (times)? times - 1 : -1;
    this.waitTime = waitTime;
    this.setOptions(options);
    this.listenTo(this.animator);
    this.forwards = false;
    this.current = 0;

    this.timerId = null;
    this.stopped = null;
    this.resumed = null;
}

AnimatorLoop.prototype = {
    // apply defaults
    setOptions: function(options) {
        this.options = Animator.applyDefaults({
            // by default, each call to AnimatorChain.play() calls jumpTo(0) of each animator
            // before playing, which can cause flickering if you have multiple animators all
            // targeting the same element. Set this to false to avoid this.
            resetOnPlay: true,
            resetOnStop: false,
            onComplete: function(){},
            onStart: function(){},
            onStep: function(){}
       }, options);
    },
    // play each animator in turn
    play: function() {
        this.forwards = true;
        this.current = -1;
        if (this.options.resetOnPlay) {
           this.animator.jumpTo(0);
        }
        this.advance();
    },
    // play all animators backwards
    reverse: function() {
        this.forwards = false;
        this.current = this.times;
        if (this.options.resetOnPlay) {
           this.animator.jumpTo(1);
        }
        this.advance();
    },
    // if we have just play()'d, then call reverse(), and vice versa
    toggle: function() {
        if (this.forwards) {
            this.seekTo(0);
        } else {
            this.seekTo(1);
        }
    },
    // internal: install an event listener on an animator's onComplete option
    // to trigger the next loop after wait time
    listenTo: function(animator) {
        var oldOnComplete = animator.options.onComplete;
        var _this = this;
        animator.options.onComplete = function() {
            if (oldOnComplete) oldOnComplete.call(animator);
            if (_this.stopped) return false;
            _this.timerId = window.setTimeout(function(){_this.timerId=null;_this.advance();}, _this.waitTime);
//            _this.advance();
        }
    },
    // play the next loop
    advance: function() {
        if (this.forwards) {
            if (this.current<0)
               this.options.onStart.call(this);
            else
               this.options.onStep.call(this);
            if (this.times+1)
               if (this.current >= this.times) {
                  if (this.options.resetOnStop) this.animator.resetOnStop();
                  this.options.onComplete.call(this);
                  return;
               };
            this.current++;
            this.animator.play();
        } else {
            if (this.current>=this.times)
               this.options.onStart.call(this);
            else
               this.options.onStep.call(this);
            if (this.times+1)
               if (this.current < 0) {
                  if (this.options.resetOnStop) this.animator.resetOnStop();
                  this.options.onComplete.call(this);
                  return;
               };
            this.current--;
            this.animator.reverse();
        }
    },
    stop: function() {
        if (!this.stopped) {
           this.stopped = true;
           window.clearTimeout(this.timerId);
           this.timerId = null;
        }
    },
    resume: function() {
        if (this.stopped && !this.resumed) {
           this.resumed = true;
           this.advance();
           this.resumed = null;
           this.stopped = null;
        }
    },
    // this function is provided for drop-in compatibility with Animator objects,
    // but only accepts 0 and 1 as target values
    jumpTo: function(to) {
    },
    seekTo: function(target) {
        if (target <= 0) {
            this.forwards = false;
            this.animator.seekTo(0);
        } else {
            this.forwards = true;
            this.animator.seekTo(1);
        }
    }
}

/////////////////////////////////////////////////

// uz intern; creare duplicat imagine; intoarce coordonatele duplicatului
Animator.prototype.cloneImg = function(layer) {
        var ret = {};
        layer.el.appendChild(this.extension.newImg = layer.img.cloneNode(false));
        with (this.extension.newImg) {
             style.position = "absolute";
             style.left = 0;
             ret.left = layer.img.offsetLeft - offsetLeft;
             style.left = ret.left + "px";
             style.top  = 0;
             ret.top  = layer.img.offsetTop  - offsetTop;
             style.top  = ret.top + "px";
        }
        return ret;
}
//

// chains several Animator objects together
function SmallAnimatorChain(animators, options) {
    this.animators = animators;
    this.setOptions(options);
    for (var i=0; i<this.animators.length; i++) {
        this.listenTo(this.animators[i]);
    }
    this.current = -1;
    this.sens = 1;
}

SmallAnimatorChain.prototype = {
    // apply defaults
    setOptions: function(options) {
        this.options = Animator.applyDefaults({
            resetOnPlay: false,
            resetOnStop: false,
            onStart: function(){},
            onComplete: function(){},
            onStep: function(){}
       }, options);
    },
    // play each animator in turn
    play: function() {
        this.current = -1;
        this.sens = 1;
        this.advance();
    },
    // play all animators backwards
    reverse: function() {
        this.current = -1;
        this.sens = -1;
        this.advance();
    },
    // internal: install an event listener on an animator's onComplete option
    // to trigger the next animator
    listenTo: function(animator) {
        var oldOnComplete = animator.options.onComplete;
        var _this = this;
        animator.options.onComplete = function() {
            if (oldOnComplete) oldOnComplete.call(animator);
            _this.advance();
        }
    },
    // play the next animator
    advance: function() {
        if (this.current<0) {
            if (this.options.resetOnPlay) this.jumpTo();
            this.options.onStart.call(this);
        }
        else
            this.options.onStep.call(this);
        if (this.animators[this.current + 1] == null) {
            this.options.onComplete.call(this);
            if (this.options.resetOnStop) this.resetOnStop();
            return;
        }
        this.current++;
        this.animators[this.current].play();
    },
//    resetOnPlay: function() {
//    },
    jumpTo: function() {
    },
    resetOnStop: function() {
    },
    cloneImg: Animator.prototype.cloneImg
}

/////////////////////////////////////////////////


JSFX.Clasor.prototype.setSpin = function(alfa, options) {
    var thisObj = this;
    var spin = new Animator({duration: this.settings[this.page].frameTime});

    spin.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    spin.extension.alfa = alfa;

    spin.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        var refer = this.cloneImg(thisObj);
        with (this.extension.newImg) {
             style.height = thisObj.height;
             style.width  = thisObj.width;
        }
        thisObj.img.style.visibility = "hidden";

// defineste subiectele animatiei
        switch (alfa) {
        case "orizontal":
             this.addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "width", thisObj.width, thisObj.width))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top,  refer.top+thisObj.img.offsetHeight/2));
             break;
        case "vertical":
             this.addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, thisObj.height))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left, refer.left+thisObj.img.offsetWidth/2));
             break;
        default:
             this.addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top,  refer.top+thisObj.img.offsetHeight/2))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left, refer.left+thisObj.img.offsetWidth/2));
        }
    }

    spin.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.img.style.visibility = "";
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
    };

    spin.jumpTo = spin.resetOnPlay;

    spin.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1;
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.change = this.extension.sens;
    }

    spin.options.onComplete = function() {
        this.extension.change = this.extension.sens;
        if (this.extension.resetOnStop) this.resetOnStop();
    };

    spin.options.transition = function(pos) {
        if (2*Math.floor(2*pos)-1 == spin.extension.change) {
            if (spin.extension.change == spin.extension.sens) {
               spin.extension.change = -spin.extension.sens;
// urmatoarea imagine
               thisObj.nextFrame(spin.extension.sens);
               spin.extension.newImg.src = thisObj.img.src;
            }
        }
        if (pos<=1/2)
           return Animator.makeEaseIn(0.8)(2*pos);
        else
           return Animator.makeEaseIn(0.8)(2*(1-pos));
    }

    return spin;
}


JSFX.Clasor.prototype.setDim = function(alfa, options) {
    var thisObj = this;
    var spin = new Animator({duration: this.settings[this.page].frameTime});

    spin.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    spin.extension.alfa = alfa;

    spin.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        this.extension.refer = this.cloneImg(thisObj);
        with (this.extension.newImg) {
             style.height = thisObj.height;
             style.width  = thisObj.width;
        }
        thisObj.img.style.visibility = "hidden";

// defineste subiectele animatiei
             this.addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    this.extension.refer.top,  this.extension.refer.top+thisObj.height/2))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   this.extension.refer.left, this.extension.refer.left+thisObj.width/2));
    }

    spin.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.img.style.visibility = "";
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
    };

    spin.jumpTo = spin.resetOnPlay;

    spin.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1;
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.change = this.extension.sens;
    }

    spin.options.onComplete = function() {
        this.extension.change = this.extension.sens;
        if (this.extension.resetOnStop) this.resetOnStop();
    };

    spin.options.transition = function(pos) {
        if (2*Math.floor(2*pos)-1 == spin.extension.change) {
            if (spin.extension.change == spin.extension.sens) {
               spin.extension.change = -spin.extension.sens;
// urmatoarea imagine
               thisObj.nextFrame(spin.extension.sens);
               spin.extension.newImg.src = thisObj.img.src;
               with (spin.extension.newImg) {
                    style.left = 0;
                    spin.extension.refer.left = thisObj.img.offsetLeft - offsetLeft;
                    style.left = spin.extension.refer.left + "px";
                    style.top  = 0;
                    spin.extension.refer.top  = thisObj.img.offsetTop  - offsetTop;
                    style.top  = spin.extension.refer.top + "px";
               }
                    spin.subjects[0].from = thisObj.height;
                    spin.subjects[1].from = spin.extension.refer.top;
                    spin.subjects[1].to   = spin.extension.refer.top+thisObj.height/2;
                    spin.subjects[2].from = thisObj.width;
                    spin.subjects[3].from = spin.extension.refer.left;
                    spin.subjects[3].to   = spin.extension.refer.left+thisObj.width/2;
            }
        }
        if (pos<=1/2)
           return Animator.makeEaseIn(0.8)(2*pos);
        else
           return Animator.makeEaseIn(0.8)(2*(1-pos));
    }

    return spin;
}


JSFX.Clasor.prototype.setMove = function(alfa, options) {
    var thisObj = this;
    var move = new Animator({duration: this.settings[this.page].frameTime});

    move.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    move.extension.alfa = alfa;

    move.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        this.extension.oldOverflow = thisObj.el.style.overflow;
        thisObj.el.style.overflow = ""

        var refer = this.cloneImg(thisObj);
        this.extension.newImg.style.zIndex--;

// stabilire coordonate de miscare functie de parametrul alfa
        var newHeight = thisObj.img.offsetHeight * Math.sin(this.extension.alfa + Math.PI);
        var newWidth  = thisObj.img.offsetWidth  * Math.cos(this.extension.alfa);
        if (Math.abs(Math.tan(this.extension.alfa + Math.PI)) > thisObj.img.offsetHeight/thisObj.img.offsetWidth)
           newHeight = newHeight / Math.abs(Math.sin(this.extension.alfa + Math.PI));
        else
           newWidth  = newWidth  / Math.abs(Math.cos(this.extension.alfa));

// defineste subiectele animatiei
        this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",  refer.top,  refer.top+newHeight))
            .addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left, refer.left+newWidth));
    }

    move.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
        thisObj.el.style.overflow = this.extension.oldOverflow;
    };

    move.jumpTo = move.resetOnPlay;

    move.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.change = this.extension.sens;
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex + 1;
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
    }

    move.options.onComplete = function() {
        this.extension.newImg.src = thisObj.img.src;
        this.extension.change = this.extension.sens;
        if (this.extension.resetOnStop) this.resetOnStop();
    }

    move.options.transition = function(pos) {
        if (2*Math.floor(2*pos)-1 == move.extension.change) {
            if (move.extension.change == move.extension.sens) {
               move.extension.change = -move.extension.sens;
// trece newImg in background
               move.extension.newImg.style.zIndex = thisObj.img.style.zIndex - 1;
            }
        }
        if (pos<=1/2)
           return Animator.makeEaseIn(0.8)(2*pos);
        else
           return Animator.makeEaseIn(0.8)(2*(1-pos));
    };

    return move;
}


JSFX.Clasor.prototype.setSmall = function(alfa, options) {
    var thisObj = this;
    var small = new Animator({duration: this.settings[this.page].frameTime});

    small.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    small.extension.alfa = alfa;

    small.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        var refer = this.cloneImg(thisObj);
        with (this.extension.newImg) {
             style.height = thisObj.height;
             style.width  = thisObj.width;
             style.zIndex--;
        }

// defineste subiectele animatiei
        if (!alfa) return;
        var H = {"left": 0, "center":0.5, "right" :1.0};
        var V = {"top" : 0, "middle":0.5, "bottom":1.0};
        var alfas = alfa.split(" "); var coordH, coordV;
        if (alfas.length > 1) {
           coordH = H[alfas[0]];
           if (coordH==null) {
              coordV = V[alfas[0]];
              if (coordV==null) return;
              coordH = H[alfas[1]];
              if (coordH==null) return;
           } else {
              coordV = V[alfas[1]];
              if (coordV==null) return;
           }
           this.addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, 0))
               .addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, 0));
           if (coordH)
              this.addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left, refer.left+thisObj.width*coordH));
           if (coordV)
              this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",  refer.top, refer.top+thisObj.height*coordV));
        } else {
           coordH = H[alfas[0]];
           if (coordH==null) {
              coordV = V[alfas[0]];
              if (coordV==null) return;
              this.addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, 0))
                  .addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, thisObj.width));
              if (coordV)
                 this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top", refer.top, refer.top+thisObj.height*coordV));
           } else {
              this.addSubject(new NumericalStyleSubject(this.extension.newImg, "width",  thisObj.width, 0))
                  .addSubject(new NumericalStyleSubject(this.extension.newImg, "height", thisObj.height, thisObj.height));
              if (coordH)
                 this.addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left, refer.left+thisObj.width*coordH));

           }
        }
    }

    small.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
    };

    small.jumpTo = small.resetOnPlay;

    small.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1;
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex + 1;
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
    }

    small.options.onComplete = function() {
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex - 1;
        for (var i=0; i<this.subjects.length; i++) {
            this.subjects[i].setState(0);
        }
        this.extension.newImg.src  = thisObj.img.src;
        if (this.extension.resetOnStop) this.resetOnStop();
    };

    small.options.transition = function(pos) {// inhiva partial reverse
        return Animator.makeEaseIn(0.8)(0.5+small.extension.sens*(pos-0.5));
    }

    return small;
}


JSFX.Clasor.prototype.setClip = function(alfa, options) {
    var thisObj = this;
    var clip = new Animator({duration: this.settings[this.page].frameTime});

    clip.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    clip.extension.alfa = alfa;

    clip.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        var refer = this.cloneImg(thisObj);
        with (this.extension.newImg) {
             style.height = thisObj.height;
             style.width  = thisObj.width;
             style.zIndex--;
        }

// defineste subiectele animatiei
        if (!alfa) return;
        var H = {"left": 0, "center":0.5, "right" :1.0};
        var V = {"top" : 0, "middle":0.5, "bottom":1.0};
        var alfas = alfa.split(" "); var coordH, coordV;
        if (alfas.length > 1) {
           coordH = H[alfas[0]];
           if (coordH==null) {
              coordV = V[alfas[0]];
              if (coordV==null) return;
              coordH = H[alfas[1]];
              if (coordH==null) return;
           } else {
              coordV = V[alfas[1]];
              if (coordV==null) return;
           }
           this.addSubject(function(state) {
                var y = thisObj.img.offsetHeight*coordV*state;
                var x = thisObj.img.offsetWidth *coordH*state;
                clip.extension.newImg.style.clip = "rect("+ y+"px " + (x+thisObj.img.offsetWidth*(1-state))+"px "
                                                 + (y+thisObj.img.offsetHeight*(1-state))+"px " + x+"px)";});
        } else {
           coordH = H[alfas[0]];
           if (coordH==null) {
              coordV = V[alfas[0]];
              if (coordV==null) return;
              this.addSubject(function(state) {
                   var y = thisObj.img.offsetHeight*coordV*state;
                   clip.extension.newImg.style.clip = "rect("+ y+"px " + thisObj.img.offsetWidth+"px "
                                                    + (y+thisObj.img.offsetHeight*(1-state))+"px 0px)";});
           } else {
              this.addSubject(function(state) {
                   var x = thisObj.img.offsetWidth *coordH*state;
                   clip.extension.newImg.style.clip = "rect("+ "0px " + (x+thisObj.img.offsetWidth*(1-state))+"px "
                                                    + thisObj.img.offsetHeight+"px " + x+"px)";});

           }
        }
    }

    clip.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
    };

    clip.jumpTo = clip.resetOnPlay;

    clip.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1;
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex + 1;
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
    }

    clip.options.onComplete = function() {
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex - 1;
        for (var i=0; i<this.subjects.length; i++) {
            if (this.subjects[i].setState) {
                this.subjects[i].setState(0);
            } else {
                this.subjects[i](0);
            }
        }
        this.extension.newImg.src  = thisObj.img.src;
        if (this.extension.resetOnStop) this.resetOnStop();
    };

    clip.options.transition = function(pos) {// inhiva partial reverse
        return Animator.makeEaseIn(0.8)(0.5+clip.extension.sens*(pos-0.5));
    }

    return clip;
}


JSFX.Clasor.prototype.setMoveH = function(alfa, options) {
    var thisObj = this;
    var move = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.makeEaseIn(0.8)});

    move.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    move.extension.alfa = alfa;

    move.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        this.extension.oldOverflow = thisObj.el.style.overflow;
        this.extension.oldHeight   = thisObj.el.style.height;
        this.extension.oldWidth    = thisObj.el.style.width;
        thisObj.el.style.height    = thisObj.el.offsetHeight + "px";
        thisObj.el.style.width     = thisObj.el.offsetWidth + "px";
        thisObj.el.style.overflow  = "hidden";

        var refer = this.cloneImg(thisObj);
        this.extension.newImg.style.zIndex--;

// stabilire coordonate de miscare functie de parametrul alfa
        var newHeight = thisObj.img.offsetHeight * Math.sin(this.extension.alfa + Math.PI);
        var newWidth  = thisObj.img.offsetWidth  * Math.cos(this.extension.alfa);
        if (Math.abs(Math.tan(this.extension.alfa + Math.PI)) > thisObj.img.offsetHeight/thisObj.img.offsetWidth)
           newHeight = newHeight / Math.abs(Math.sin(this.extension.alfa + Math.PI));
        else
           newWidth  = newWidth  / Math.abs(Math.cos(this.extension.alfa));

// defineste subiectele animatiei
        if (state<=0) {
           this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",  refer.top, refer.top+newHeight))
               .addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left, refer.left+newWidth));
        } else {
           this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",  refer.top+newHeight, refer.top))
               .addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left+newWidth, refer.left));
        }
    }

    move.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        this.clearSubjects();
        thisObj.el.style.overflow = this.extension.oldOverflow;
        thisObj.el.style.height   = this.extension.oldHeight;
        thisObj.el.style.width    = this.extension.oldWidth;
    };

    move.jumpTo = move.resetOnPlay;

    move.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex + 1;
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
    }

    move.options.onComplete = function() {
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex - 1;
        this.subjects[0].setState((1-this.extension.sens)/2);
        this.subjects[1].setState((1-this.extension.sens)/2);
        this.extension.newImg.src  = thisObj.img.src;
        if (this.extension.resetOnStop) this.resetOnStop();
    }

    return move;
}


JSFX.Clasor.prototype.setMove2H = function(alfa, options) {
    var thisObj = this;
    var move = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.makeEaseIn(0.8)});

    move.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    move.extension.alfa = alfa;

    move.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        this.extension.oldOverflow = thisObj.el.style.overflow;
        this.extension.oldHeight   = thisObj.el.style.height;
        this.extension.oldWidth    = thisObj.el.style.width;
        thisObj.el.style.height    = thisObj.el.offsetHeight + "px";
        thisObj.el.style.width     = thisObj.el.offsetWidth + "px";
        thisObj.el.style.overflow  = "hidden";

        var refer = this.cloneImg(thisObj);
        thisObj.el.appendChild(this.extension.twoImg = this.extension.newImg.cloneNode(false));
        thisObj.img.style.visibility = "hidden";

// stabilire coordonate de miscare functie de parametrul alfa
        var newHeight = thisObj.img.offsetHeight * Math.sin(this.extension.alfa + Math.PI);
        var newWidth  = thisObj.img.offsetWidth  * Math.cos(this.extension.alfa);
        if (Math.abs(Math.tan(this.extension.alfa + Math.PI)) > thisObj.img.offsetHeight/thisObj.img.offsetWidth)
           newHeight = newHeight / Math.abs(Math.sin(this.extension.alfa + Math.PI));
        else
           newWidth  = newWidth  / Math.abs(Math.cos(this.extension.alfa));

// defineste subiectele animatiei
        this.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",  refer.top,  refer.top+newHeight))
            .addSubject(new NumericalStyleSubject(this.extension.newImg, "left", refer.left, refer.left+newWidth))
            .addSubject(new NumericalStyleSubject(this.extension.twoImg, "top",  refer.top-newHeight, refer.top))
            .addSubject(new NumericalStyleSubject(this.extension.twoImg, "left", refer.left-newWidth, refer.left));
        if (state>0) {
           var temp;
           for (var i=0; i<4; i++) {
               temp = this.subjects[i].from;
               this.subjects[i].from = this.subjects[i].to;
               this.subjects[i].to   = temp;
           }
        }
    }

    move.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.img.style.visibility = "";
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        thisObj.el.removeChild(this.extension.twoImg);
        this.extension.twoImg = null;
        this.clearSubjects();
        thisObj.el.style.overflow = this.extension.oldOverflow;
        thisObj.el.style.height   = this.extension.oldHeight;
        thisObj.el.style.width    = this.extension.oldWidth;
    };

    move.jumpTo = move.resetOnPlay;

    move.options.onStart = function() {
        this.extension.sens   = this.state < this.target? 1 : -1
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.subjects[2].setState((1-this.extension.sens)/2);
        this.subjects[3].setState((1-this.extension.sens)/2);
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
        this.extension.twoImg.src  = thisObj.img.src;
    }

    move.options.onComplete = function() {
        this.subjects[0].setState((1-this.extension.sens)/2);
        this.subjects[1].setState((1-this.extension.sens)/2);
        this.extension.newImg.src  = thisObj.img.src;
        if (this.extension.resetOnStop) this.resetOnStop();
    }

    return move;
}


JDS = new Object();

/* Flip Beta 1a ©2007 John Davenport Scheuer
 * This credit Must remain for legal use */
 
JDS.flipinit = function(im) {
    JDS.flip[im.id] = null;
}

JDS.flip = function(im, sens) {// sens = 0 -> horizontal, sens = 2 -> vertical
   var flip = arguments.callee;
   if (document.documentElement.filters)
      if (typeof flip[im.id] != 'number'){
         flip[im.id] = im.filters.length;
         im.style.filter += 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+sens+', mirror=1)';
      } else {
         im.filters[flip[im.id]].rotation = im.filters[flip[im.id]].rotation==sens? 0 : sens;
         im.filters[flip[im.id]].mirror   = im.filters[flip[im.id]].mirror==1? 0 : 1;
      }
}


JSFX.Clasor.prototype.setMoveX = function(alfa, options) {
    var thisObj = this;

    var move1 = new Animator({duration: this.settings[this.page].frameTime/2, transition: Animator.makeEaseOut(0.8)});

    var spin  = new Animator({duration: this.settings[this.page].frameTime/2});
    spin.options.transition = function(pos) {
        if (2*Math.floor(2*pos)-1 == chain.extension.change) {
            if (chain.extension.change == chain.extension.sens) {
               chain.extension.change = -chain.extension.sens;
// trece newImg in background
               chain.extension.newImg.style.zIndex = thisObj.img.style.zIndex - 1;
               switch (chain.extension.alfa) {
               case Math.PI/2:
               case Math.PI*3/2:
                    JDS.flip(chain.extension.newImg, 2);
                    break;
               default:
                    JDS.flip(chain.extension.newImg, 0);
                    break;
               }
            }
        }
        if (pos<=1/2)
           return Animator.makeEaseIn(0.8)(2*pos);
        else
           return Animator.makeEaseIn(0.8)(2*(1-pos));
    }

    var move2 = new Animator({duration: this.settings[this.page].frameTime/2, transition: Animator.makeEaseOut(0.8)});
    move2.options.onComplete = function() {
               switch (chain.extension.alfa) {
               case Math.PI/2:
               case Math.PI*3/2:
                    JDS.flip(chain.extension.newImg, 2);
                    break;
               default:
                    JDS.flip(chain.extension.newImg, 0);
                    break;
               }
    }

    var chain = new AnimatorChain([move1, spin, move2], {resetOnPlay: false})

    chain.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    chain.extension.alfa = alfa;

    chain.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

// creare duplicat imagine
        thisObj.el.appendChild(this.extension.newImg = thisObj.img.cloneNode(false));
        var refer = {};
        with (this.extension.newImg) {
             style.position = "absolute";
             style.left = 0;
             refer.left = thisObj.img.offsetLeft - offsetLeft;
             style.left = refer.left + "px";
             style.top  = 0;
             refer.top  = thisObj.img.offsetTop  - offsetTop;
             style.top  = refer.top + "px";
             style.width  = thisObj.img.width;
             style.height = thisObj.img.height;
             style.zIndex--;
        }
        JDS.flipinit(chain.extension.newImg);

// defineste subiectele animatiei si coordonate de miscare functie de parametrul alfa

        switch (alfa) {
        case Math.PI/2:
             move1.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top, refer.top-thisObj.img.offsetHeight/2));
             spin.addSubject(new NumericalStyleSubject(this.extension.newImg,  "height", thisObj.height, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "width", thisObj.width, thisObj.width))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "top",    refer.top-thisObj.img.offsetHeight/2, refer.top));
             move2.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top-thisObj.img.offsetHeight/2, refer.top));
             break;
        case Math.PI:
             move1.addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left, refer.left-thisObj.img.offsetWidth/2));
             spin.addSubject(new NumericalStyleSubject(this.extension.newImg,  "width",  thisObj.width, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "height", thisObj.height, thisObj.height))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "left",   refer.left-thisObj.img.offsetWidth/2, refer.left));
             move2.addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left-thisObj.img.offsetWidth/2, refer.left));
           break;
        case Math.PI*3/2:
             move1.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top, refer.top+thisObj.img.offsetHeight/2));
             spin.addSubject(new NumericalStyleSubject(this.extension.newImg,  "height", thisObj.height, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "width", thisObj.width, thisObj.width))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "top",    refer.top+thisObj.img.offsetHeight/2, refer.top+thisObj.img.offsetHeight));
             move2.addSubject(new NumericalStyleSubject(this.extension.newImg, "top",    refer.top+thisObj.img.offsetHeight/2, refer.top));
             break;
        default:
             move1.addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left, refer.left+thisObj.img.offsetWidth/2));
             spin.addSubject(new NumericalStyleSubject(this.extension.newImg,  "width",  thisObj.width, 0))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "height", thisObj.height, thisObj.height))
                 .addSubject(new NumericalStyleSubject(this.extension.newImg,  "left",   refer.left+thisObj.img.offsetWidth/2, refer.left+thisObj.img.offsetWidth));
             move2.addSubject(new NumericalStyleSubject(this.extension.newImg, "left",   refer.left+thisObj.img.offsetWidth/2, refer.left));
           break;
        }
    }

    chain.resetOnStop = function() {
        if (!this.extension.newImg) return;
        thisObj.el.removeChild(this.extension.newImg);
        this.extension.newImg = null;
        move1.clearSubjects();
        spin.clearSubjects();
        move2.clearSubjects();
    };

    chain.jumpTo = chain.resetOnPlay;

    chain.options.onStart = function() {
        this.extension.sens   = this.forwards? 1 : -1;
        if (this.extension.resetOnPlay) this.resetOnPlay((1-this.extension.sens)/2);
        this.extension.change = this.extension.sens;
        this.extension.newImg.style.zIndex = thisObj.img.style.zIndex + 1;
// urmatoarea imagine
        thisObj.nextFrame(this.extension.sens);
    }

    chain.options.onComplete = function() {
        this.extension.newImg.src = thisObj.img.src;
        this.extension.change = this.extension.sens;
        if (this.extension.resetOnStop) this.resetOnStop();
    }

    return chain;
}


JSFX.Clasor.prototype.setWave = function(parameters, options) {
    var thisObj = this;

    var wave = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.makeEaseOut(0.8)});

    var calm = new Animator({duration: this.settings[this.page].frameTime/2, transition: Animator.makeEaseOut(0.8)});

    var chain = new SmallAnimatorChain([wave, calm], options);

    chain.extension = Animator.applyDefaults({
         waveCycle : 1,       // nr. cercuri
         waveSize  : 0.2,     // procent din thisObj.height
         lineSize  : 1,       // rastru
         alfa      : "down",  // alfa="down", "right", "up", "left"
         beta      : "under", // beta="under", "over"
         overflow  : "hidden"
    }, parameters);

    chain.jumpTo = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        thisObj.img.style.visibility = "hidden";
        this.extension.oldOverflow   = thisObj.el.style.overflow;
        thisObj.el.style.overflow    = this.extension.overflow;

        this.extension.height   = thisObj.img.offsetHeight;
        this.extension.width    = thisObj.img.offsetWidth;
        this.extension.sinTable = [];
        this.extension.lineBuff = [];
        this.extension.ref      = {};

        with (this.extension) {
             if (alfa=="down" || alfa=="up") {
                var lines = Math.floor(height / lineSize);
             } else {
                var lines = Math.floor(width / lineSize);
             }
             for (var i=0; i<lines; i++)
                 sinTable[i] = Math.sin(2 * Math.PI * i / lines);

             if (beta=="under")
                var zOrder = function(x) {return x}
             else
                var zOrder = function(x) {return lines-x}

             switch (alfa) {
             case "down":
                  for (var j=lines; j>=0; j--) {
                      ref = this.cloneImg(thisObj); // creaza this.extension.newImg; intoarce coordonatele sale
                      newImg.style.top  = ref.top - height;
                      i = zOrder(j);
                      lineBuff[i] = newImg;
                      newImg.style.clip = "rect(" + (i*lineSize)+"px "
                                          + (width)+"px " + ((i+1)*lineSize)+"px 0px)";
                  }
                  break;
             case "up":
                  for (var j=lines; j>=0; j--) {
                      ref = this.cloneImg(thisObj);
                      newImg.style.top  = ref.top + height;
                      i = zOrder(lines-j);
                      lineBuff[i] = newImg;
                      newImg.style.clip = "rect(" + (i*lineSize)+"px "
                                          + (width)+"px " + ((i+1)*lineSize)+"px 0px)";
                  }
                  break;
             case "right":
                  for (var j=lines; j>=0; j--) {
                      ref = this.cloneImg(thisObj);
                      newImg.style.left = ref.left - width;
                      i = zOrder(j);
                      lineBuff[i] = newImg;
                      newImg.style.clip = "rect(0px " + ((i+1)*lineSize)+"px "
                                          + (height)+"px " + (i*lineSize)+"px)";
                  }
                  break;
             case "left":
                  for (var j=lines; j>=0; j--) {
                      ref = this.cloneImg(thisObj);
                      newImg.style.left = ref.left + width;
                      i = zOrder(lines-j);
                      lineBuff[i] = newImg;
                      newImg.style.clip = "rect(0px " + ((i+1)*lineSize)+"px "
                                          + (height)+"px " + (i*lineSize)+"px)";
                  }
                  break;
             }
        }

// defineste subiectele animatiei
        wave.addSubject(function(pos){
            with (chain.extension) {
                 var lines = sinTable.length;
                 switch (alfa) {
                 case "down":
                      var top   = Math.floor(lines * (1 - pos));
                      var ypx   = ref.top - lineSize * top + "px";
                      var wavy  = height * waveSize;
                      for (var i=top; i<=lines; i++) {
                          lineBuff[i].src = thisObj.img.src;
                          lineBuff[i].style.left = ref.left +
                                 Math.floor(wavy * sinTable[Math.floor((i-top)*waveCycle) % lines]) + "px";
                          lineBuff[i].style.top  = ypx;
                          lineBuff[i].style.visibility = "";
                      }
                      break;
                 case "up":
                      var top   = Math.floor(lines * pos);
                      var ypx   = ref.top + height - lineSize * top + "px";
                      var wavy  = height * waveSize;
                      for (var i=0; i<=top; i++) {
                          lineBuff[i].src = thisObj.img.src;
                          lineBuff[i].style.left = ref.left +
                                 Math.floor(wavy * sinTable[Math.floor((top-i)*waveCycle) % lines]) + "px";
                          lineBuff[i].style.top  = ypx;
                          lineBuff[i].style.visibility = "";
                      }
                      break;
                 case "right":
                      var top   = Math.floor(lines * (1-pos));
                      var xpx   = ref.left - lineSize * top + "px";
                      var wavy  = width * waveSize;
                      for (var i=top; i<=lines; i++) {
                          lineBuff[i].src = thisObj.img.src;
                          lineBuff[i].style.top = ref.top +
                                 Math.floor(wavy * sinTable[Math.floor((i-top)*waveCycle) % lines]) + "px";
                          lineBuff[i].style.left = xpx;
                          lineBuff[i].style.visibility = "";
                      }
                      break;
                 case "left":
                      var top   = Math.floor(lines * pos);
                      var xpx   = ref.left + width - lineSize * top + "px";
                      var wavy  = width * waveSize;
                      for (var i=0; i<=top; i++) {
                          lineBuff[i].src = thisObj.img.src;
                          lineBuff[i].style.top = ref.top +
                                 Math.floor(wavy * sinTable[Math.floor((top-i)*waveCycle) % lines]) + "px";
                          lineBuff[i].style.left = xpx;
                          lineBuff[i].style.visibility = "";
                      }
                      break;
                 }
            }
        })

        calm.addSubject(function(pos) {
            with (chain.extension) {
                 var lines = sinTable.length;
                 switch (alfa) {
                 case "down":
                    var wavy  = (1 - pos) * height * waveSize;
                    for (var i=0; i<=lines; i++) {
                        lineBuff[i].style.left = ref.left +
                                Math.floor(wavy * sinTable[Math.floor(i*waveCycle) % lines]) + "px";
                    }
                    break;
                 case "up":
                    var wavy  = (1-pos) * height * waveSize;
                    for (var i=0; i<=lines; i++) {
                        lineBuff[i].style.left = ref.left +
                                Math.floor(wavy * sinTable[Math.floor((lines-i)*waveCycle) % lines]) + "px";
                    }
                    break;
                 case "right":
                    var wavy  = (1 - pos) * width * waveSize;
                    for (var i=0; i<=lines; i++) {
                        lineBuff[i].style.top = ref.top +
                                Math.floor(wavy * sinTable[Math.floor(i*waveCycle) % lines]) + "px";
                    }
                    break;
                 case "left":
                    var wavy  = (1 - pos) * width * waveSize;
                    for (var i=0; i<=lines; i++) {
                        lineBuff[i].style.top = ref.top +
                                Math.floor(wavy * sinTable[Math.floor((lines-i)*waveCycle) % lines]) + "px";
                    }
                    break;
                 }
            }
        })

    }

    chain.resetOnStop = function() {
        with (this.extension) {
             if (!newImg) return;

             for (var i=0; i<=sinTable.length; i++)
                 thisObj.el.removeChild(lineBuff[i]);
             newImg = null;
             sinTable = null;
             lineBuff = null;
        }

        wave.clearSubjects();
        calm.clearSubjects();

        thisObj.img.style.visibility = "";
        thisObj.el.style.overflow = this.extension.oldOverflow;
    };

    chain.options.onStart = function() {
        if (this.extension.changeImage) {
           thisObj.nextFrame(this.sens);
           this.extension.changeImage = false;
        }
    }

    chain.options.onComplete = function() {
        this.extension.changeImage = true;
    }

    return chain;
}


JSFX.Clasor.prototype.setWaveX = function(parameters, options) {
    var thisObj = this;

    var excit = new Animator({duration: this.settings[this.page].frameTime/4, transition: Animator.tx.linear});

    var wave = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.makeEaseOut(0.8)});

    var calm = new Animator({duration: this.settings[this.page].frameTime/2, transition: Animator.makeEaseIn(0.8)});
    var tmp = calm.play;
    calm.play = calm.reverse;
    calm.reverse = tmp;

    var chain = new SmallAnimatorChain([excit, wave, calm], options);

    chain.extension = Animator.applyDefaults({
         waveCycle : 1,       // nr. cercuri
         waveCota  : 0.2,     // procent din thisObj.width pt. alfa="down" sau "up", thisObj.height pt. alfa="right" sau "left"
         lineSize  : 1,       // rastru
         alfa      : "down",  // alfa="down", "right", "up", "left"
         beta      : "under", // beta="under", "over"
         overflow  : "hidden"
    }, parameters);

    chain.sliceImg = {// pregatire animatie
    "down": function() {
        with (this.extension) {
             for (var j=lines; j>=0; j--) {
                 ref = this.cloneImg(thisObj); // creaza this.extension.newImg; intoarce coordonatele sale
                 newImg.style[moveAxis]  = ref[moveAxis] - imgMoveSize;
                 var i = zOrder(j);
                 lineBuff[i] = newImg;
                 newImg.style.clip = "rect(" + i*lineSize+"px "
                                   + imgWaveSize+"px " + (i+1)*lineSize+"px 0px)";
             }
        }
    },
    "right": function() {
        with (this.extension) {
             for (var j=lines; j>=0; j--) {
                 ref = this.cloneImg(thisObj);
                 newImg.style[moveAxis] = ref[moveAxis] - imgMoveSize;
                 var i = zOrder(j);
                 lineBuff[i] = newImg;
                 newImg.style.clip = "rect(0px " + (i+1)*lineSize+"px "
                                   + imgWaveSize+"px " + i*lineSize+"px)";
             }
        }
    },
    "up": function() {
        with (this.extension) {
             for (var j=lines; j>=0; j--) {
                 ref = this.cloneImg(thisObj);
                 newImg.style[moveAxis]  = ref[moveAxis] + imgMoveSize;
                 var i = zOrder(lines-j);
                 lineBuff[i] = newImg;
                 newImg.style.clip = "rect(" + i*lineSize+"px "
                                   + imgWaveSize+"px " + (i+1)*lineSize+"px 0px)";
             }
        }
    },
    "left": function() {
        with (this.extension) {
             for (var j=lines; j>=0; j--) {
                 ref = this.cloneImg(thisObj);
                 newImg.style[moveAxis] = ref[moveAxis] + imgMoveSize;
                 var i = zOrder(lines-j);
                 lineBuff[i] = newImg;
                 newImg.style.clip = "rect(0px " + (i+1)*lineSize+"px "
                                   + imgWaveSize+"px " + i*lineSize+"px)";
             }
        }
    }}


// subiecte animatie "wave"
    chain.move = function(pos) {
        with (chain.extension) {
             var topLine = Math.floor(lines * (1 - pos));
             var movepx  = ref[moveAxis] - lineSize * topLine + "px";
             for (var i=topLine; i<=lines; i++) {
                 lineBuff[i].src = thisObj.img.src;
                 lineBuff[i].style[moveAxis] = movepx;
                 lineBuff[i].style.visibility = "";
                 lineBuff[i].style[waveAxis] = ref[waveAxis] +
                                 Math.floor(waveSize * sinTable[Math.floor((i-topLine)*waveCycle) % lines]) + "px";
             }
        }
    }
    chain.mirrorMove = function(pos) {
        with (chain.extension) {
             var topLine = Math.floor(lines * pos);
             var movepx  = ref[moveAxis] + imgMoveSize - lineSize * topLine + "px";
             for (var i=0; i<=topLine; i++) {
                 lineBuff[i].src = thisObj.img.src;
                 lineBuff[i].style[moveAxis] = movepx;
                 lineBuff[i].style.visibility = "";
                 lineBuff[i].style[waveAxis] = ref[waveAxis] +
                                 Math.floor(waveSize * sinTable[Math.floor((topLine-i)*waveCycle) % lines]) + "px";
             }
        }
    }


// subiecte animatie "excit" si "calm"
    chain.mirrorDance = function(pos) {
        with (chain.extension) {
             var waveCrt = pos * waveSize;
             for (var i=0; i<=lines; i++) {
                 lineBuff[i].style[waveAxis] = ref[waveAxis] +
                                Math.floor(waveCrt * sinTable[Math.floor(i*waveCycle) % lines]) + "px";
             }
        }
    }
    chain.dance = function(pos) {
        with (chain.extension) {
             var waveCrt = pos * waveSize;
             for (var i=0; i<=lines; i++) {
                 lineBuff[i].style[waveAxis] = ref[waveAxis] +
                                Math.floor(waveCrt * sinTable[Math.floor((lines-i)*waveCycle) % lines]) + "px";
             }
        }
    }


    chain.jumpTo = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        thisObj.img.style.visibility = "hidden";
        this.extension.oldOverflow   = thisObj.el.style.overflow;
        thisObj.el.style.overflow    = this.extension.overflow;

        with (this.extension) {
             if (alfa=="down" || alfa=="up") {
                imgMoveSize = thisObj.img.offsetHeight;
                imgWaveSize = thisObj.img.offsetWidth;
                waveAxis = "left";
                moveAxis = "top";
             } else {
                imgMoveSize = thisObj.img.offsetWidth;
                imgWaveSize = thisObj.img.offsetHeight;
                waveAxis = "top";
                moveAxis = "left";
             }
             lines    = Math.floor(imgMoveSize / lineSize);
             waveSize = imgWaveSize * waveCota;

             if (beta=="under")
                zOrder = function(x) {return x}
             else
                zOrder = function(x) {return lines-x}

             // pregatire animatie
             sinTable = [];
             for (var i=0; i<lines; i++)
                 sinTable[i] = Math.sin(Math.PI+(2 * Math.PI * i) / lines);

             lineBuff = [];
             this.sliceImg[alfa].call(this);

             // defineste subiectele animatiei
             if (alfa=="down" || alfa=="right") {
                excit.addSubject(this.dance);
                wave.addSubject(this.move);
                calm.addSubject(this.mirrorDance);
             } else {
                calm.addSubject(this.dance);
                wave.addSubject(this.mirrorMove);
                excit.addSubject(this.mirrorDance);
             }
        }
    }

    chain.resetOnStop = function() {
        with (this.extension) {
             if (!newImg) return;

             for (var i=0; i<=sinTable.length; i++)
                 thisObj.el.removeChild(lineBuff[i]);
             newImg = null;
             sinTable = null;
             lineBuff = null;
        }

        excit.clearSubjects();
        wave.clearSubjects();
        calm.clearSubjects();

        thisObj.img.style.visibility = "";
        thisObj.el.style.overflow = this.extension.oldOverflow;
    };

    chain.options.onStart = function() {
        if (this.extension.changeImage) {
           thisObj.nextFrame(this.sens);
           this.extension.changeImage = false;
        }
    }

    chain.options.onComplete = function() {
        this.extension.changeImage = true;
    }

    return chain;
}


JSFX.Clasor.prototype.setRoll = function(rollSize, alfa, options) {
    var thisObj = this;

    var move = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.tx.easeInOut});

    move.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false
    }, options);
    move.extension.rollSize = rollSize; // procent din thisObj.height pt. alfa="down" sau "up", thisObj.width pt. alfa="right" sau "left"
    move.extension.alfa     = alfa;     // alfa="down", "up", "right", "left"

// defineste subiectele animatiei
    move.downOrRight = function(pos) {// roll down, right
             with (move.extension) {
                  if (sens == -1) // reverse -> play
                     pos = 1 - pos;
                  var baza = Math.floor(pos * imgRollSize);
                  var rest = imgRollSize-baza;

                  newImg.clip[rollFrom] = baza;
                  JSN.setClip(newImg);

                  twoImg.clip[rollFrom] = rest;
                  if (baza < scroll) {
                     twoImg.clip[rollTo] = imgRollSize;
                  } else if (rest > scroll) {
                            twoImg.clip[rollTo] = twoImg.clip[rollFrom]+scroll;
                         } else {
                            twoImg.clip[rollTo] = twoImg.clip[rollFrom]+rest;
                         }
                  JSN.setClip(twoImg);
                  twoImg.style[moveAxis] = refer[moveAxis]+baza-rest + "px";
             }
    }

    move.upOrLeft = function(pos) {// roll up, left
             with (move.extension) {
                  if (sens == -1) // reverse -> play
                     pos = 1 - pos;
                  var baza = Math.floor(pos * imgRollSize);
                  var rest = imgRollSize-baza;

                  newImg.clip[rollTo] = rest;
                  JSN.setClip(newImg);

                  twoImg.clip[rollTo] = baza;
                  if (baza < scroll) {
                     twoImg.clip[rollFrom] = 0;
                  } else if (rest > scroll) {
                            twoImg.clip[rollFrom] = twoImg.clip[rollTo]-scroll;
                         } else {
                            twoImg.clip[rollFrom] = twoImg.clip[rollTo]-rest;
                         }
                  JSN.setClip(twoImg);
                  twoImg.style[moveAxis] = refer[moveAxis]-baza+rest + "px";
             }
    }

    move.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        this.extension.overflow = thisObj.el.style.overflow;
        thisObj.el.style.overflow = "hidden";

        this.extension.refer = this.cloneImg(thisObj);
        thisObj.el.appendChild(this.extension.twoImg = this.extension.newImg.cloneNode(false));
        this.extension.newImg.clip = {"top":0, "right":thisObj.img.offsetWidth, "bottom":thisObj.img.offsetHeight, "left":0};
        this.extension.twoImg.clip = {"top":0, "right":thisObj.img.offsetWidth, "bottom":thisObj.img.offsetHeight, "left":0};

        with (this.extension) {
             if (alfa == "up" || alfa == "down") {// parametrii pt. animatie
                this.extension.imgRollSize = thisObj.img.offsetHeight;
                this.extension.imgMoveClip = thisObj.img.offsetWidth;
                this.extension.rollFrom = "top";
                this.extension.rollTo   = "bottom";
                this.extension.moveAxis = "top";
                twoImg.style.filter = "flipV alpha(opacity=75)";
             } else {
                this.extension.imgRollSize = thisObj.img.offsetWidth;
                this.extension.imgMoveClip = thisObj.img.offsetHeight;
                this.extension.rollFrom = "left";
                this.extension.rollTo   = "right";
                this.extension.moveAxis = "left";
                twoImg.style.filter = "flipH alpha(opacity=75)";
             }
             this.extension.scroll = Math.floor(imgRollSize * rollSize);
             if (alfa == "right" || alfa == "down") // animatie
                this.addSubject(this.downOrRight);
             else
                this.addSubject(this.upOrLeft);
        }
    }

/*
roll over
             with (move.extension) {
                  if (sens == 1) // play
                     pos = 1 - pos; // else reverse
                  var baza = pos * height;
                  newImg.style.clip = "rect("+(height-baza)+"px "+width+"px "+height+"px 0px)";
                  if (pos < rollSize) {
                     twoImg.style.clip = "rect("+baza+"px "+width+"px "+(baza+baza)+"px 0px)";
                  } else if (pos < 1-rollSize) {
                            twoImg.style.clip = "rect("+baza+"px "+width+"px "+(scroll+baza)+"px 0px)";
                         } else {
                            twoImg.style.clip = "rect("+baza+"px "+width+"px "+height+"px 0px)";
                         }
                  twoImg.style.top  = refer.top-baza+height-baza + "px";
             }
*/

    move.resetOnStop = function() {
        with (this.extension) {
             if (!newImg) return;

             thisObj.el.removeChild(newImg);
             newImg = null;
             thisObj.el.removeChild(twoImg);
             twoImg = null;
             thisObj.el.style.overflow = overflow;
        }

        this.clearSubjects();
    };

    move.jumpTo = move.resetOnPlay;

    move.options.onStart = function() {
        this.extension.sens = this.state < this.target? 1 : -1
        with (this.extension) {
             if (resetOnPlay) this.resetOnPlay((1-sens)/2);

             thisObj.nextFrame(sens);
//           twoImg.src  = thisObj.img.src;
//           twoImg.style.filter = "flipV alpha(opacity=75)";

             this.subjects[0]((1-sens)/2);
        }
    }

    move.options.onComplete = function() {
        with (this.extension) {
             newImg.src  = thisObj.img.src;
             twoImg.src  = thisObj.img.src;
             if (alfa == "up" || alfa == "down")
                twoImg.style.filter = "flipV alpha(opacity=75)";
             else
                twoImg.style.filter = "flipH alpha(opacity=75)";

             if (resetOnStop) this.resetOnStop();
        }
    }

    return move;
}


JSFX.Clasor.prototype.setRollX = function(parameters, options) {
    var thisObj = this;

    var anim = new Animator({duration: this.settings[this.page].frameTime, transition: Animator.tx.easeInOut});

    anim.extension = Animator.applyDefaults({
         resetOnPlay: false,
         resetOnStop: false,
         waveCota   : 0.1,    // procent din thisObj.width pt. alfa="down" sau "up", thisObj.height pt. alfa="right" sau "left"
         rollSize   : 0.5,    // procent din thisObj.height pt. alfa="down" sau "up", thisObj.width pt. alfa="right" sau "left"
         alfa       : "down"  // alfa="down", "right", "up", "left"
    }, parameters || options);

    anim.sliceImg = function() {
        with (this.extension) {
             for (var i=imgRollSize; i>=0; i--) {
                 this.extension.refer = this.cloneImg(thisObj);
                 newImg.clip = {"top":0, "right":thisObj.img.offsetWidth, "bottom":thisObj.img.offsetHeight, "left":0};
                 newImg.clip[rollFrom] = i;
                 newImg.clip[rollTo] = i+1;
                 JSN.setClip(newImg);
                 slices[i] = newImg;
             }
        }
    }

    anim.sliceMirrorImg = function() {
        with (this.extension) {
             for (var i=0; i<=imgRollSize; i++) {
                 this.extension.refer = this.cloneImg(thisObj);
                 newImg.clip = {"top":0, "right":thisObj.img.offsetWidth, "bottom":thisObj.img.offsetHeight, "left":0};
                 newImg.clip[rollFrom] = i;
                 newImg.clip[rollTo] = i+1;
                 JSN.setClip(newImg);
                 slices[i] = newImg;
             }
        }
    }

// defineste subiectele animatiei
    anim.rule = function(pos) {// roll down, right
        with (anim.extension) {
             if (sens == -1) pos = 1 - pos; // reverse -> play
             var road = Math.floor(pos * (imgRollSize + raza));

             for (var i=Math.min(road, imgRollSize); i>=0; i--){
                 var t = (road - i) / raza;
                 var offset = road - Math.floor(raza * Math.sin(t));
                 if (offset >= imgRollSize) {
                    slices[i].style.visibility = "hidden";
                    slices[i].style[moveAxis] = refer[moveAxis];
                    slices[i].style[waveAxis] = refer[waveAxis];
                    slices[i].style.zIndex    = thisObj.img.style.zIndex;
                 } else {
                    slices[i].style[moveAxis] = refer[moveAxis] - i + offset + "px";
                    slices[i].style[waveAxis] = refer[waveAxis] + Math.floor(waveSize * (1 - Math.cos(t))) + "px";
                    if (t > Math.PI*3/2 || t < Math.PI*1/2)
                       slices[i].style.zIndex = thisObj.img.style.zIndex + 1;
                    else
                       slices[i].style.zIndex = thisObj.img.style.zIndex + 2;
                    slices[i].style.visibility = "";
                 }
             }
        }
    }

    anim.mirrorRule = function(pos) {// roll up, left
        with (anim.extension) {
             if (sens == -1) pos = 1 - pos; // reverse -> play
             var road = Math.floor(pos * (imgRollSize + raza));

             for (var i=Math.min(road, imgRollSize); i>=0; i--){
                 var t = (road - i) / raza;
                 var offset = road - Math.floor(raza * Math.sin(t));
                 var j = imgRollSize-i;
                 if (offset >= imgRollSize) {
                    slices[j].style.visibility = "hidden";
                    slices[j].style[moveAxis] = refer[moveAxis];
                    slices[j].style[waveAxis] = refer[waveAxis];
                    slices[j].style.zIndex    = thisObj.img.style.zIndex;
                 } else {
                    slices[j].style[moveAxis] = refer[moveAxis] + i - offset + "px";
                    slices[j].style[waveAxis] = refer[waveAxis] + Math.floor(waveSize * (1 - Math.cos(t))) + "px";
                    if (t > Math.PI*3/2 || t < Math.PI*1/2)
                       slices[j].style.zIndex = thisObj.img.style.zIndex + 1;
                    else
                       slices[j].style.zIndex = thisObj.img.style.zIndex + 2;
                    slices[j].style.visibility = "";
                 }
             }
        }
    }

    anim.resetOnPlay = function(state) {
        if (this.extension.newImg) return;

        if (!thisObj.height)
           thisObj.setState(state);

        with (this.extension) {
             if (alfa == "up" || alfa == "down") {// parametrii pt. animatie
                this.extension.imgRollSize = thisObj.img.offsetHeight;
                this.extension.imgWaveSize = thisObj.img.offsetWidth;
                this.extension.rollFrom = "top";
                this.extension.rollTo   = "bottom";
                this.extension.moveAxis = "top";
                this.extension.waveAxis = "left";
             } else {
                this.extension.imgRollSize = thisObj.img.offsetWidth;
                this.extension.imgWaveSize = thisObj.img.offsetHeight;
                this.extension.rollFrom = "left";
                this.extension.rollTo   = "right";
                this.extension.moveAxis = "left";
                this.extension.waveAxis = "top";
             }

             this.extension.scroll   = Math.floor(imgRollSize * rollSize);
             this.extension.waveSize = imgWaveSize * waveCota;
             this.extension.teta     = Math.PI * 3 / 2;
             this.extension.raza     = scroll / teta;

             this.extension.slices = [];

             if (alfa == "right" || alfa == "down") {// pregatire si adaugare subiecte animatie
                this.sliceImg();
                this.addSubject(this.rule);
             } else {
                this.sliceMirrorImg();
                this.addSubject(this.mirrorRule);
             }
        }

    }

    anim.resetOnStop = function() {
        with (this.extension) {
             if (!newImg) return;

             for (var i=0; i<=imgRollSize; i++)
                 thisObj.el.removeChild(slices[i]);
             slices = null;
             newImg = null;
        }

        this.clearSubjects();
    };

    anim.jumpTo = anim.resetOnPlay;

    anim.options.onStart = function() {
        this.extension.sens = this.state < this.target? 1 : -1
        with (this.extension) {
             if (resetOnPlay) this.resetOnPlay((1-sens)/2);

             for (var i=0; i<=imgRollSize; i++) {
                 slices[i].src = thisObj.img.src;
                 slices[i].style.visibility = "";
             }

             thisObj.nextFrame(sens);
        }
    }

    anim.options.onComplete = function() {
        with (this.extension) {
             if (resetOnStop) this.resetOnStop();
        }
    }

    return anim;
}



