﻿// list of effects already run to be reused
var effects = {};
// latest effect ran
var prevEffect = false;
// CSS initial properties for the elements on which we apply the effects
var initialElements = [];
// list of style properties to be monitored
var saveStyle = ['position', 'width', 'height', 'opacity', 'filter', 'top', 'left', 'backgroundColor', 'visibility', 'display'];

Spry.Effect.FadeBlind = function(element, options) {
    Spry.Effect.Cluster.call(this, options);

    this.name = 'FadeBlind';
    var duration = 1000;
    var doToggle = false;
    var from = 100;
    var to = 0;

    if (options) {
        if (options.duration) duration = options.duration;
        if (options.toggle) doToggle = options.toggle;
        if (options.from) from = options.from;
        if (options.to) to = options.to;
    }

    var options = { duration: duration, from: from, to: to, toggle: doToggle };
    var blind = new Spry.Effect.Blind(element, options);
    this.addParallelEffect(blind);

    var options = { duration: duration, from: from, to: to, toggle: doToggle };
    var fade = new Spry.Effect.Fade(element, options);
    this.addParallelEffect(fade);
};

Spry.Effect.FadeBlind.prototype = new Spry.Effect.Cluster();
Spry.Effect.FadeBlind.prototype.constructor = Spry.Effect.FadeBlind;

/* 
* FadeSlide 
* 		Custom Cluster effect that fade in/out and slide simultaneous an element
* 		by running in parallel the Fade() and Slide() predefined clusters
*/

Spry.Effect.FadeSlide = function(element, options) {
    Spry.Effect.Cluster.call(this, options);

    this.name = 'FadeSlide';
    var duration = 1000;
    var doToggle = false;
    var from = 100;
    var to = 0;

    if (options) {
        if (options.duration) duration = options.duration;
        if (options.toggle) doToggle = options.toggle;
        if (options.from) from = options.from;
        if (options.to) to = options.to;
    }

    var options = { duration: duration, from: from, to: to, toggle: doToggle };
    var slide = new Spry.Effect.Slide(element, options);
    this.addParallelEffect(slide);

    var options = { duration: duration, from: from, to: to, toggle: doToggle };
    var fade = new Spry.Effect.Fade(element, options);
    this.addParallelEffect(fade);
};

Spry.Effect.FadeSlide.prototype = new Spry.Effect.Cluster();
Spry.Effect.FadeSlide.prototype.constructor = Spry.Effect.FadeSlide;

var Observer = {};

/*
* 	Observer.onPreEffect(obj)
* 		Before running an effect forward the initial CSS values are saved.
*    We will use later these when the animation will finish or is canceled 
* 		to restore the animated element to be ready for the next effect.
*    This function is automatically called by the effect.
*  Parameters:
* 		obj - the running effect that calls this function
*/
Observer.onPreEffect = function(obj) {
    if (obj.direction && obj.direction == Spry.forwards)
        saveElement(obj.element);
    else
        restoreElement(obj.element);
};

/*
* 	Observer.onCancel(obj)
* 		When an effect is canceled this function will restore the element CSS.
* 		Also we toggle the effect so the next time will run to go forward again.
*    This function is automatically called by the effect.
*  Parameters:
* 		obj - the running effect that calls this function
*/
Observer.onCancel = function(obj) {
    if (obj.direction == Spry.forwards)
        obj.doToggle();
    restoreElement(obj.element);
};

/*
* 	Observer.onPostEffect(obj)
*    This function is automatically called by the effect.
*  Parameters:
* 		obj - the running effect that calls this function
*/
Observer.onPostEffect = function(obj) {
    //if (obj.direction == Spry.forwards)
    //	setTimeout(function(){obj.start()}, 150);
    //else
    //	restoreElement(obj.element);
    if (obj.direction == Spry.forwards)
        obj.element.style.display = 'none';
    //else
    //	obj.element.style.visibility = 'hidden';
};

/* 
* saveElement(el)
* 		Save into the global array of 'initialElements' some CSS properties 
* 		of the given element that where altered by the animation running.
* Parameters:
*		el - the DOM element for which to save the CSS properties
*/
var saveElement = function(el) {
    if (!initialElements[el.id]) {
        initialElements[el.id] = {};
        for (var i = 0; i < saveStyle.length; i++) {
            initialElements[el.id][saveStyle[i]] = Spry.Effect.getStyleProp(el, saveStyle[i]);
        }
    }
};

/* 
* restoreElement(el)
* 		Restore from the global array 'initialElements' some CSS properties 
* 		of the given element to prepare it for the next effect to run.
* Parameters:
*		el - the DOM element for which to restore the CSS properties
*/
var restoreElement = function(el) {
    for (var i = 0; i < saveStyle.length; i++)
        el.style[saveStyle[i]] = initialElements[el.id][saveStyle[i]];
};

var runEffect = function(element, options, imgobj, closeimg, openimg, noeffect) {
    if (noeffect) {
        var obj = document.getElementById(element);
        if (obj.style.display == 'none') {
            imgobj.src = closeimg;
            obj.style.display = 'block';
        }
        else {
            obj.style.display = 'none';
            imgobj.src = openimg;
        }
        return;
    }

    var effect = 'Squish';
    if (prevEffect && effects[prevEffect + '_' + element] && effects[prevEffect + '_' + element].isRunning) {
        effects[prevEffect + '_' + element].cancel();
        setTimeout(function() { runEffect(effect, element, options) }, 150);
        return false;
    }

    if (!effects[effect + '_' + element]) {
        effects[effect + '_' + element] = new Spry.Effect[effect](element, options);
        if (effect != 'Highlight' && effect != 'Shake' && effect != 'Pulsate')
            effects[effect + '_' + element].addObserver(Observer);
    }

    if (effects[effect + '_' + element].direction == Spry.forwards)
        imgobj.src = closeimg;
    else
        imgobj.src = openimg;

    effects[effect + '_' + element].start();
    prevEffect = effect;
    return false;
};


