/**
 * jQuery.pulse
 * Copyright (c) 2008 James Padolsey - jp(at)qd9(dot)co.uk | http://james.padolsey.com / http://enhance.qd-creative.co.uk
 * Dual licensed under MIT and GPL.
 * Date: 05/11/08
 *
 * @projectDescription Applies a continual pulse to any element specified
 * http://enhance.qd-creative.co.uk/demos/pulse/
 * Tested successfully with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.5 and Safari 3. on Windows XP.
 *
 * @author James Padolsey
 * @version 1.11
 * 
 * @id jQuery.pulse
 * @id jQuery.recover
 * @id jQuery.fn.pulse
 * @id jQuery.fn.recover
 */
(function($){
    $.fn.recover = function() {
        /* Empty inline styles - i.e. set element back to previous state */
        /* Note, the recovery might not work properly if you had inline styles set before pulse initiation */
        return this.each(function(){$(this).stop().css({backgroundColor:'',color:'',borderLeftColor:'',borderRightColor:'',borderTopColor:'',borderBottomColor:'',opacity:1});});
    }
    $.fn.pulse = function(options){
        var defaultOptions = {
            textColors: [],
            backgroundColors: [],
            borderColors: [],
            opacityPulse: true,
            opacityRange: [],
            speed: 1000,
            duration: false,
            runLength: false
        }, o = $.extend(defaultOptions,options);
        /* Validate custom options */
        if(o.textColors.length===1||o.backgroundColors.length===1||o.borderColors.length===1) {return false;}
        /* Begin: */
        return this.each(function(){
            var $t = $(this), pulseCount=1, pulseLimit = (o.runLength&&o.runLength>0) ? o.runLength*largestArrayLength([o.textColors.length,o.backgroundColors.length,o.borderColors.length,o.opacityRange.length]) : false;
            clearTimeout(recover);
            if(o.duration) {
                setTimeout(recover,o.duration);
            }
            function nudgePulse(textColorIndex,bgColorIndex,borderColorIndex,opacityIndex) {
                if(pulseLimit&&pulseCount===pulseLimit) {
                    return $t.recover();
                }
                pulseCount++;
                /* Initiate color change - on callback continue */
                return $t.animate(getColorsAtIndex(textColorIndex,bgColorIndex,borderColorIndex,opacityIndex),o.speed,function(){
                    /* Callback of each step */
                    nudgePulse(
                        getNextIndex(o.textColors,textColorIndex),
                        getNextIndex(o.backgroundColors,bgColorIndex),
                        getNextIndex(o.borderColors,borderColorIndex),
                        getNextIndex(o.opacityRange,opacityIndex)
                    );
                });
            }
            /* Set CSS to first step (no animation) */
            $t.css(getColorsAtIndex(0,0,0,0));
            /* Then animate to second step */
            nudgePulse(1,1,1,1);
            function getColorsAtIndex(textColorIndex,bgColorIndex,borderColorIndex,opacityIndex) {
                /* Prepare animation object - get's all property names/values from passed indexes */
                var params = {};
                if(o.backgroundColors.length) {
                    params['backgroundColor'] = o.backgroundColors[bgColorIndex];
                }
                if(o.textColors.length) {
                    params['color'] = o.textColors[textColorIndex];
                }
                if(o.borderColors.length) {
                    params['borderLeftColor'] = o.borderColors[borderColorIndex];
                    params['borderRightColor'] = o.borderColors[borderColorIndex];
                    params['borderTopColor'] = o.borderColors[borderColorIndex];
                    params['borderBottomColor'] = o.borderColors[borderColorIndex];
                }
                if(o.opacityPulse&&o.opacityRange.length) {
                    params['opacity'] = o.opacityRange[opacityIndex];
                }
                return params;
            }
            function getNextIndex(property,currentIndex) {
                if (property.length>currentIndex+1) {return currentIndex+1;}
                else {return 0;}
            }
            function largestArrayLength(arrayOfArrays) {
                return Math.max.apply( Math, arrayOfArrays ); 
            }
            function recover() {
                $t.recover();
            }
        });
    }
})(jQuery);
/* The below code extends the animate function so that it works with color animations */
/* By John Resig */

