/*
        Kwicks for jQuery (version 1.5.1)
        Copyright (c) 2008 Jeremy Martin
        http://www.jeremymartin.name/projects.php?project=kwicks
        
        Licensed under the MIT license:
                http://www.opensource.org/licenses/mit-license.php

        Any and all use of this script must be accompanied by this copyright/license notice in its present form.
*/

(function($){
        $.fn.kwicks = function(options) {
                var defaults = {
                        isVertical: false,
                        sticky: false,
                        defaultKwick: 0,
                        event: 'mouseover',
                        spacing: 0,
                        duration: 500
                };
                var o = $.extend(defaults, options);
                var WoH = (o.isVertical ? 'height' : 'width'); // WoH = Width or Height
                var LoT = (o.isVertical ? 'top' : 'left'); // LoT = Left or Top
                
                return this.each(function() {
                        obj = $(this);
                        var kwicks = obj.children('li');
                        var normWoH = kwicks.eq(0).css(WoH).replace(/px/,''); // normWoH = Normal Width or Height
                        if(!o.max) {
                                o.max = (normWoH * kwicks.size()) - (o.min * (kwicks.size() - 1));
                        } else {
                                o.min = ((normWoH * kwicks.size()) - o.max) / (kwicks.size() - 1);
                        }
                        // set width of obj ul
                        if(o.isVertical) {
                                obj.css({
                                        width : kwicks.eq(0).css('width'),
                                        height : (normWoH * kwicks.size()) + (o.spacing * (kwicks.size() - 1)) + 'px'
                                });                             
                        } else {
                                obj.css({
                                        width : (normWoH * kwicks.size()) + (o.spacing * (kwicks.size() - 1)) + 'px',
                                        height : kwicks.eq(0).css('height')
                                });                             
                        }

                        // pre calculate left or top values for all kwicks but the first and last
                        // i = index of currently hovered kwick, j = index of kwick we're calculating
                        var preCalcLoTs = []; // preCalcLoTs = pre-calculated Left or Top's
                        for(i = 0; i < kwicks.size(); i++) {
                                preCalcLoTs[i] = [];
                                // don't need to calculate values for first or last kwick
                                for(j = 1; j < kwicks.size() - 1; j++) {
                                        if(i == j) {
                                                preCalcLoTs[i][j] = o.isVertical ? j * o.min + (j * o.spacing) : j * o.min + (j * o.spacing);
                                        } else {
                                                preCalcLoTs[i][j] = (j <= i ? (j * o.min) : (j-1) * o.min + o.max) + (j * o.spacing);
                                        }
                                }
                        }
                        
                        // loop through all kwick elements
                        kwicks.each(function(i) {
                                var kwick = $(this);
                                // set initial width or height and left or top values
                                // set first kwick
                                if(i === 0) {
                                        kwick.css(LoT, '0px');
                                } 
                                // set last kwick
                                else if(i == kwicks.size() - 1) {
                                        kwick.css(o.isVertical ? 'bottom' : 'right', '0px');
                                }
                                // set all other kwicks
                                else {
                                        if(o.sticky) {
                                                kwick.css(LoT, preCalcLoTs[o.defaultKwick][i]);
                                        } else {
                                                kwick.css(LoT, (i * normWoH) + (i * o.spacing));
                                        }
                                }
                                // correct size in sticky mode
                                if(o.sticky) {
                                        if(o.defaultKwick == i) {
                                                kwick.css(WoH, o.max + 'px');
                                                kwick.addClass('active');
                                        } else {
                                                kwick.css(WoH, o.min + 'px');
                                        }
                                }
                                kwick.css({
                                        margin: 0,
                                        position: 'absolute'
                                });
                                
                                kwick.bind(o.event, function() {
                                        // calculate previous width or heights and left or top values
                                        var prevWoHs = []; // prevWoHs = previous Widths or Heights
                                        var prevLoTs = []; // prevLoTs = previous Left or Tops
                                        kwicks.stop().removeClass('active');
                                        for(j = 0; j < kwicks.size(); j++) {
                                                prevWoHs[j] = kwicks.eq(j).css(WoH).replace(/px/, '');
                                                prevLoTs[j] = kwicks.eq(j).css(LoT).replace(/px/, '');
                                        }
                                        var aniObj = {};
                                        aniObj[WoH] = o.max;
                                        var maxDif = o.max - prevWoHs[i];
                                        var prevWoHsMaxDifRatio = prevWoHs[i]/maxDif;
                                        kwick.addClass('active').animate(aniObj, {
                                                step: function(now) {
                                                        // calculate animation completeness as percentage
                                                        var percentage = maxDif != 0 ? now/maxDif - prevWoHsMaxDifRatio : 1;
                                                        // adjsut other elements based on percentage
                                                        kwicks.each(function(j) {
                                                                if(j != i) {
                                                                        kwicks.eq(j).css(WoH, prevWoHs[j] - ((prevWoHs[j] - o.min) * percentage) + 'px');
                                                                }
                                                                if(j > 0 && j < kwicks.size() - 1) { // if not the first or last kwick
                                                                        kwicks.eq(j).css(LoT, prevLoTs[j] - ((prevLoTs[j] - preCalcLoTs[i][j]) * percentage) + 'px');
                                                                }
                                                        });
                                                },
                                                duration: o.duration,
                                                easing: o.easing
                                        });
                                });
                        });
                        if(!o.sticky) {
                                obj.bind("mouseleave", function() {
                                        var prevWoHs = [];
                                        var prevLoTs = [];
                                        kwicks.removeClass('active').stop();
                                        for(i = 0; i < kwicks.size(); i++) {
                                                prevWoHs[i] = kwicks.eq(i).css(WoH).replace(/px/, '');
                                                prevLoTs[i] = kwicks.eq(i).css(LoT).replace(/px/, '');
                                        }
                                        var aniObj = {};
                                        aniObj[WoH] = normWoH;
                                        var normDif = normWoH - prevWoHs[0];
                                        kwicks.eq(0).animate(aniObj, {
                                                step: function(now) {
                                                        var percentage = normDif != 0 ? (now - prevWoHs[0])/normDif : 1;
                                                        for(i = 1; i < kwicks.size(); i++) {
                                                                kwicks.eq(i).css(WoH, prevWoHs[i] - ((prevWoHs[i] - normWoH) * percentage) + 'px');
                                                                if(i < kwicks.size() - 1) {
                                                                        kwicks.eq(i).css(LoT, prevLoTs[i] - ((prevLoTs[i] - ((i * normWoH) + (i * o.spacing))) * percentage) + 'px');
                                                                }
                                                        }
                                                },
                                                duration: o.duration,
                                                easing: o.easing
                                        });
                                });
                        }
                });
        };
})(jQuery);

