/*
 * jQuery.css3animate.js v.0.21 by David Aerne ( meodai.ch )
 * free to use and/or modify not protected by any kind of lisence.
 * Last modification: 2011-3-28
 *
 * Animates with CSS3 Transition if possible
 * usage: .css3animate([ css object ], speed, callback);
 *
 * Depends on: modernizer.js && jQuery
 *
 * Special thanks to backflip & Stackoverflow.
 * ToDo: use 3dAnimations to support hardoware acceleration on mobile devices
 */

(function($, undefined) {

    //global plugin variables
    var settings, browserPrefix, animation, transitionEndEvent, $fnStop, $animatedSelector;

    //default settings
    settings = {
        "speed": 500,
        "browsers": {
            "webkit": {
                "prefix": "-webkit-",
                "endEvent": "webkitTransitionEnd"
            },
            "mozilla": {
                "prefix": "-moz-",
                "endEvent": "transitionend"
            },
            "opera": {
                "prefix": "-o-",
                "endEvent": "oTransitionEnd"
            },
            "msie": {
                "prefix": "-ms-",
                "endEvent": "TransitionEnd"
            },
            "fallback": {
                "prefix": "",
                "endEvent": "transitionend"
            }
        }
    };

    //determine browser prefix and transitionEndEvent
    if ($.browser.webkit) {
        browserPrefix = settings.browsers.webkit.prefix;
        transitionEndEvent = settings.browsers.webkit.endEvent;
    } else if ($.browser.msie) {
        browserPrefix = settings.browsers.msie.prefix;
        transitionEndEvent = settings.browsers.msie.endEvent;
    } else if ($.browser.mozilla) {
        browserPrefix = settings.browsers.mozilla.prefix;
        transitionEndEvent = settings.browsers.mozilla.endEvent;
    } else if ($.browser.opera) {
        browserPrefix = settings.browsers.opera.prefix;
        transitionEndEvent = settings.browsers.opera.endEvent;
    } else {
        browserPrefix = settings.browsers.fallback.prefix;
        transitionEndEvent = settings.browsers.fallback.endEvent;
    }

    animation = function($obj, cssObject, speed, callback) {
        if (!speed) {
            var speed = settings.speed;
        }

        if (Modernizr.csstransitions) {
        
            $obj.data({
            	"css3animate": true,
            	"css3animated": true,
            	"cssObject": cssObject
            });

            $obj.css(browserPrefix + "transition", "all " + speed + "ms ease-in-out");
            $obj.css(cssObject);

            $obj.bind(transitionEndEvent, function(event) {
            	
                $obj.unbind(transitionEndEvent);
                //reset the tanstion to avoid side effects
                $obj.css(browserPrefix + "transition", "none");
                $obj.removeData("css3animated");
                
                $.isFunction(callback) && callback.call(event.target, ($(event.target), event));
            });

        } else {
            $obj.animate(cssObject, speed, function() {
                $.isFunction(callback) && callback.call($(this), (arguments));
            });
        }
    };

    //plugin methods
    methods = {
        run: function(cssObject, speed, callback) {
            myCssObject = cssObject;
            return this.each(function() {
                var $that;
                $that = $(this);
                animation($that, cssObject, speed, callback);
            });
        },
        setDefaults: function(options) {
            $.extend({}, settings, options);
        },
        stop: function(clearQueue, jumpToEnd) {
            return this.each(function() {
                var $that = $(this);

                if (!jumpToEnd) {
                    $.each($that.data("cssObject"), function(key, val) {
                        $that.css(key, $that.css(key));
                    });
                }
                   
                $that.css(browserPrefix + "transition", "none");
                
            });
        }
    };

    $.fn.css3animate = function(method) {
        if (typeof Modernizr === "undefined") {
            $.error("Please include modernizer.js to your HTML");
        } else {
            if (methods[method]) {
                return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
            } else if (typeof method === "object" || !method) {
                return methods.run.apply(this, arguments);
            } else {
                $.error("Method " + method + " does not exist on jQuery.css3animate");
            }
        }
    };
    
    if (Modernizr.csstransitions) {
    
    	$fnStop = $.fn.stop;
        $animatedSelector = jQuery.expr.filters.animated;
        
        //extend stop functionality to css3
        $.fn.stop = function( clearQueue,jumpToEnd ) {
            if (this.data("css3animate")) {
                return methods.stop.apply(this, arguments);
            } else {
                return $fnStop.call(this, arguments);
            }
        };
        
        //extend :animated selector to css3 elements
		jQuery.expr.filters.animated = function(elem) { 
    		return $animatedSelector(elem) || !!$.data(elem, 'css3animated');
		};

    }

}(jQuery));
