﻿


//author:turker@diff.com.tr
//jmenu Plug-in
(function ($) {
    $.fn.jMenu = function (options) {
        var defaults = {
    };
    var settings = $.extend({}, defaults, options);
    return this.each(function () {
        $(this).find("li:has(ul)").hover(function () {
            $(this).addClass("hover").find("ul:eq(0)").css('visibility', 'visible');
        },function () {
            $(this).removeClass("hover").find("ul:eq(0)").css('visibility', 'hidden');
        });
    });
    return this;
};
})(jQuery);

//author:turker@diff.com.tr
//livebox Plug-in
(function ($) {
    $.fn.livebox = function (options) {
        var defaults = {
        url:"",
        id:""
    };
    var settings = $.extend({}, defaults, options);
    $(this).live('click', function () {
        $(this).colorbox({open:true,onCleanup:
            function(){
                $(settings.id).html('<div class="liveboxload"><div>');
                $.get(settings.url, function (data) {
                    $(settings.id).html(data);
                });
            }
        });
        return false;
    });
    return this.each(function () {
    });
    return this;
};
})(jQuery);

//futurelist

(function ($) {
    $.fn.featureList = function (options) {
        var tabs = $(this);
        var output = $(options.output);

        new jQuery.featureList(tabs, output, options);

        return this;
    };

    $.featureList = function (tabs, output, options) {
        function slide(nr) {
            if (typeof nr == "undefined") {
                nr = visible_item + 1;
                nr = nr >= total_items ? 0 : nr;
            }

            tabs.removeClass('current').filter(":eq(" + nr + ")").addClass('current');

            output.stop(true, true).animate({marginLeft:'600px'});
            output.filter(":eq(" + nr + ")").animate({marginLeft:'0px'},function () {
                visible_item = nr;
            });
        }

        var options = options || {};
        var total_items = tabs.length;
        var visible_item = options.start_item || 0;

        options.pause_on_hover = options.pause_on_hover || true;
        options.transition_interval = options.transition_interval || 5000;

        output.eq(visible_item).css({marginLeft:'0px'});
        tabs.eq(visible_item).addClass('current');

        tabs.hover(function () {
            if ($(this).hasClass('current')) {
                return false;
            }

            slide(tabs.index(this));
            return false;
        });

        if (options.transition_interval > 0) {
            var timer = setInterval(function () {
                slide();
            }, options.transition_interval);

            if (options.pause_on_hover) {
                tabs.mouseenter(function () {
                    clearInterval(timer);

                }).mouseleave(function () {
                    clearInterval(timer);
                    timer = setInterval(function () {
                        slide();
                    }, options.transition_interval);
                });
            }
        }
    };
})(jQuery);


// tipsy, facebook style tooltips for jquery
// version 1.0.0a
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
// releated under the MIT license
(function ($) {
    function fixTitle($ele) {
        if ($ele.attr('title') || typeof ($ele.attr('original-title')) != 'string') {
            $ele.attr('original-title', $ele.attr('title') || '').removeAttr('title');
        }
    }
    function Tipsy(element, options) {
        this.$element = $(element);
        this.options = options;
        this.enabled = true;
        fixTitle(this.$element);
    }
    Tipsy.prototype = {
        show: function () {
            var title = this.getTitle();
            if (title && this.enabled) {
                var $tip = this.tip();
                $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
                $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
                $tip.remove().css({ top: 0, left: 0, visibility: 'hidden', display: 'block' }).appendTo(document.body);
                var pos = $.extend({}, this.$element.offset(), {
                    width: this.$element[0].offsetWidth,
                    height: this.$element[0].offsetHeight
                });
                var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
                var gravity = (typeof this.options.gravity == 'function') ? this.options.gravity.call(this.$element[0]) : this.options.gravity;
                var tp;
                switch (gravity.charAt(0)) {
                    case 'n':
                        tp = { top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2 };
                        break;
                    case 's':
                        tp = { top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2 };
                        break;
                    case 'e':
                        tp = { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset };
                        break;
                    case 'w':
                        tp = { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset };
                        break;
                }
                if (gravity.length == 2) {
                    if (gravity.charAt(1) == 'w') {
                        tp.left = pos.left + pos.width / 2 - 15;
                    } else {
                        tp.left = pos.left + pos.width / 2 - actualWidth + 15;
                    }
                }
                $tip.css(tp).addClass('tipsy-' + gravity);
                if (this.options.fade) {
                    $tip.stop().css({ opacity: 0, display: 'block', visibility: 'visible' }).animate({ opacity: this.options.opacity });
                } else {
                    $tip.css({ visibility: 'visible', opacity: this.options.opacity });
                }
            }
        },
        hide: function () {
            if (this.options.fade) {
                this.tip().stop().fadeOut(function () { $(this).remove(); });
            } else {
                this.tip().remove();
            }
        },
        getTitle: function () {
            var title, $e = this.$element, o = this.options;
            fixTitle($e);
            var title, o = this.options;
            if (typeof o.title == 'string') {
                title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
            } else if (typeof o.title == 'function') {
                title = o.title.call($e[0]);
            }
            title = ('' + title).replace(/(^\s*|\s*$)/, "");
            return title || o.fallback;
        },
        tip: function () {
            if (!this.$tip) {
                this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"/></div>');
            }
            return this.$tip;
        },
        validate: function () {
            if (!this.$element[0].parentNode) this.hide();
        },
        enable: function () { this.enabled = true; },
        disable: function () { this.enabled = false; },
        toggleEnabled: function () { this.enabled = !this.enabled; }
    };
    $.fn.tipsy = function (options) {
        if (options === true) {
            return this.data('tipsy');
        } else if (typeof options == 'string') {
            if (this.data('tipsy'))
                return this.data('tipsy')[options]();
            else
                return this;
        }
        options = $.extend({}, $.fn.tipsy.defaults, options);
        function get(ele) {
            var tipsy = $.data(ele, 'tipsy');
            if (!tipsy) {
                tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
                $.data(ele, 'tipsy', tipsy);
            }
            return tipsy;
        }
        function enter() {
            var tipsy = get(this);
            tipsy.hoverState = 'in';
            if (options.delayIn == 0) {
                tipsy.show();
            } else {
                setTimeout(function () { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
            }
        };
        function leave() {
            var tipsy = get(this);
            tipsy.hoverState = 'out';
            if (options.delayOut == 0) {
                tipsy.hide();
            } else {
                setTimeout(function () { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
            }
        };
        if (!options.live) this.each(function () { get(this); });
        if (options.trigger != 'manual') {
            var binder = options.live ? 'live' : 'bind';
            trigs = options.trigger.split(',');
            tip = this;
            $(trigs).each(function (i, item) {
                eventIn = item == 'hover' ? 'mouseenter' : 'focus',eventOut = item == 'hover' ? 'mouseleave' : 'blur';
                tip[binder](eventIn, enter)[binder](eventOut, leave);
            });
        }
        return this;
    };
    $.fn.tipsy.defaults = {
        delayIn: 0,
        delayOut: 0,
        fade: false,
        fallback: '',
        gravity: 'n',
        html: false,
        live: false,
        offset: 0,
        opacity: 0.8,
        title: 'title',
        trigger: 'hover'
    };
    // Overwrite this method to provide options on a per-element basis.
    // For example, you could store the gravity in a 'tipsy-gravity' attribute:
    // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
    // (remember - do not modify 'options' in place!)
    $.fn.tipsy.elementOptions = function (ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };
    $.fn.tipsy.autoNS = function () {
        return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
    };
    $.fn.tipsy.autoWE = function () {
        return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
    };
})(jQuery);
//author:turker@diff.com.tr
//jValidate Plug-in
(function ($) {
    $.fn.jValidate = function (options) {
        var defaults = {
            vUrl: null,
            pass: false,
            onValid: function (frm, mdl) {
                   $(frm).prepend("<fieldset class='msg'><legend>Kayıt Oluşturuldu</legend></fieldset>");
                   $.colorbox.close(); 
            },
            beforeValidate: function OnBeginValidate(frm) {
                $('.tipsy').remove();
                frm.find('fieldset>fieldset.error').removeClass('error').find('legend').remove();
                frm.find('.tipped').untipsy().removeClass('tipped');
            }
        };
        var settings = $.extend({}, defaults, options);
        function OnValidationError(frm, elem, msg) {
            frm.find('#' + elem).parent('fieldset').addClass('error').append('<legend>' + msg + '</legend>');
            $("#" + elem).addClass('tipped').tipsy({ trigger: 'focus,hover', gravity: 'w', title: function () { return $(this).next('legend').html(); } });
            $("#" + elem).tipsy("show");
        };
        return this.each(function () {
            if (settings.vUrl == null) {
                settings.vUrl = $(this).attr('action');
                settings.pass = true;
            }
            $(this).unbind('submit').bind('submit', function (e) {
                e.preventDefault();
                sbmt = $(this).find('input:submit');
                var valid = false;
                var form = $(this);
                sbmt.loader();
                $.post(settings.vUrl, $(this).serialize(), function (data) {

                    var json=null;
                    try {
                            json=jQuery.parseJSON(data);
                    } catch (e) {
                        $.fn.colorbox({html:$(data).html(),open:true});
                        return false;
                     }
                    settings.beforeValidate(form);
                    if (!json.IsValid) {
                        $.each(json.Errors, function (i, err) {
                            OnValidationError(form, err.Key, err.Value);
                        });
                    }
                    else {
                        form.unbind('submit');
                        settings.onValid(form, json.Model);
                        valid = false;
                    }
                    sbmt.loader(true);
                },'html');
                return valid;
            });
        });
        return this;
    };
    $.fn.untipsy = function () {
        return this.each(function () {
            var t = $(this).tipsy(true);
            if (t.options.trigger != 'manual') {
                trigs = t.options.trigger.split(',');
                var binder = t.options.live ? 'die' : 'unbind';
                tip = $(this);
                $(trigs).each(function (i, item) {
                    eventIn = item == 'hover' ? 'mouseenter' : 'focus',eventOut = item == 'hover' ? 'mouseleave' : 'blur';
                    tip[binder](eventIn)[binder](eventOut);
                });
            }
            $.removeData(this, "tipsy");
        });
        return this;
    };
    $.fn.loader = function (remove) {
        return this.each(function () {
            if (remove) {
                $(this).next('.loader').remove();
                $(this).show().tipsy('show');
            }
            else {
                $("<div class='loader'/>").insertAfter($(this));
                h = $(this).outerHeight();
                w = $(this).outerWidth();
                $(this).next('.loader').width(w).height(h);
                $(this).hide();
            }
        });
        return this;
    };
})(jQuery);
//end of jValidate
// dateInput
DateInput = (function ($) {

    function DateInput(el, opts) {
        if (typeof (opts) != "object") opts = {};
        $.extend(this, DateInput.DEFAULT_OPTS, opts);

        this.input = $(el);
        this.bindMethodsToObj("show", "hide", "hideIfClickOutside", "keydownHandler", "selectDate");

        this.build();
        this.selectDate();
        this.hide();
    };
    DateInput.DEFAULT_OPTS = {
        month_names: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
        short_month_names: ["Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık"],
        short_day_names: ["Pzr", "Pzrts", "Sal", "Çar", "Per", "Cum", "Cets"],
        start_of_week: 1
    };
    DateInput.prototype = {
        build: function () {
            var monthNav = $('<p class="month_nav">' +
      '<span class="button prev" title="[Page-Up]">&#171;</span>' +
      ' <span class="month_name"></span> ' +
      '<span class="button next" title="[Page-Down]">&#187;</span>' +
      '</p>');
            this.monthNameSpan = $(".month_name", monthNav);
            $(".prev", monthNav).click(this.bindToObj(function () { this.moveMonthBy(-1); }));
            $(".next", monthNav).click(this.bindToObj(function () { this.moveMonthBy(1); }));

            var yearNav = $('<p class="year_nav">' +
      '<span class="button prev" title="[Ctrl+Page-Up]">&#171;</span>' +
      ' <span class="year_name"></span> ' +
      '<span class="button next" title="[Ctrl+Page-Down]">&#187;</span>' +
      '</p>');
            this.yearNameSpan = $(".year_name", yearNav);
            $(".prev", yearNav).click(this.bindToObj(function () { this.moveMonthBy(-12); }));
            $(".next", yearNav).click(this.bindToObj(function () { this.moveMonthBy(12); }));

            var nav = $('<div class="nav"></div>').append(monthNav, yearNav);

            var tableShell = "<table><thead><tr>";
            $(this.adjustDays(this.short_day_names)).each(function () {
                tableShell += "<th>" + this + "</th>";
            });
            tableShell += "</tr></thead><tbody></tbody></table>";

            this.dateSelector = this.rootLayers = $('<div class="date_selector"></div>').append(nav, tableShell).insertAfter(this.input);

            if ($.browser.msie && $.browser.version < 7) {

                this.ieframe = $('<iframe class="date_selector_ieframe" frameborder="0" src="#"></iframe>').insertBefore(this.dateSelector);
                this.rootLayers = this.rootLayers.add(this.ieframe);

                $(".button", nav).mouseover(function () { $(this).addClass("hover") });
                $(".button", nav).mouseout(function () { $(this).removeClass("hover") });
            };

            this.tbody = $("tbody", this.dateSelector);

            this.input.change(this.bindToObj(function () { this.selectDate(); }));
            this.selectDate();
        },

        selectMonth: function (date) {
            var newMonth = new Date(date.getFullYear(), date.getMonth(), 1);

            if (!this.currentMonth || !(this.currentMonth.getFullYear() == newMonth.getFullYear() &&
                                this.currentMonth.getMonth() == newMonth.getMonth())) {

                this.currentMonth = newMonth;

                var rangeStart = this.rangeStart(date), rangeEnd = this.rangeEnd(date);
                var numDays = this.daysBetween(rangeStart, rangeEnd);
                var dayCells = "";

                for (var i = 0; i <= numDays; i++) {
                    var currentDay = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate() + i, 12, 00);

                    if (this.isFirstDayOfWeek(currentDay)) dayCells += "<tr>";

                    if (currentDay.getMonth() == date.getMonth()) {
                        dayCells += '<td class="selectable_day" date="' + this.dateToString(currentDay) + '">' + currentDay.getDate() + '</td>';
                    } else {
                        dayCells += '<td class="unselected_month" date="' + this.dateToString(currentDay) + '">' + currentDay.getDate() + '</td>';
                    };

                    if (this.isLastDayOfWeek(currentDay)) dayCells += "</tr>";
                };

                this.tbody.empty().append(dayCells);

                this.monthNameSpan.empty().append(this.monthName(date));
                this.yearNameSpan.empty().append(this.currentMonth.getFullYear());

                $(".selectable_day", this.tbody).click(this.bindToObj(function (event) {
                    this.changeInput($(event.target).attr("date"));
                }));

                $('td[date="' + this.dateToString(new Date()) + '"]', this.tbody).addClass("today");

                $("td.selectable_day", this.tbody).mouseover(function () { $(this).addClass("hover") });
                $("td.selectable_day", this.tbody).mouseout(function () { $(this).removeClass("hover") });

            };

            $('.selected', this.tbody).removeClass("selected");
            $('td[date="' + this.selectedDateString + '"]', this.tbody).addClass("selected");
        },

        selectDate: function (date) {
            if (typeof (date) == "undefined") {

                date = this.stringToDate(this.input.val());

            };
            if (!date) date = new Date();

            this.selectedDate = date;
            this.selectedDateString = this.dateToString(this.selectedDate);

            this.selectMonth(this.selectedDate);

        },

        changeInput: function (dateString) {
            this.input.val(dateString).change();
            this.hide();
        },

        show: function () {
            this.rootLayers.css("display", "block");
            $([window, document.body]).click(this.hideIfClickOutside);
            this.input.unbind("focus", this.show);
            $(document.body).keydown(this.keydownHandler);
            this.setPosition();
        },

        hide: function () {
            this.rootLayers.css("display", "none");
            $([window, document.body]).unbind("click", this.hideIfClickOutside);
            this.input.focus(this.show);
            $(document.body).unbind("keydown", this.keydownHandler);
        },

        hideIfClickOutside: function (event) {
            if (event.target != this.input[0] && !this.insideSelector(event)) {
                this.hide();
            };
        },

        insideSelector: function (event) {
            var offset = this.dateSelector.offset();
            offset.right = offset.left + this.dateSelector.outerWidth();
            offset.bottom = offset.top + this.dateSelector.outerHeight();

            return event.pageY < offset.bottom &&
           event.pageY > offset.top &&
           event.pageX < offset.right &&
           event.pageX > offset.left;
        },

        keydownHandler: function (event) {
            switch (event.keyCode) {
                case 9:
                case 27:
                    this.hide();
                    return;
                    break;
                case 13:
                    this.changeInput(this.selectedDateString);
                    break;
                case 33:
                    this.moveDateMonthBy(event.ctrlKey ? -12 : -1);
                    break;
                case 34:
                    this.moveDateMonthBy(event.ctrlKey ? 12 : 1);
                    break;
                case 38:
                    this.moveDateBy(-7);
                    break;
                case 40:
                    this.moveDateBy(7);
                    break;
                case 37:
                    this.moveDateBy(-1);
                    break;
                case 39:
                    this.moveDateBy(1);
                    break;
                default:
                    return;
            }
            event.preventDefault();
        },

        stringToDate: function (string) {
            var matches;
            if (matches = string.match(/^(\d{1,2}) ([^\s]+) (\d{4,4})$/)) {
                var myDate = new Date();
                myDate.setFullYear(matches[3], this.shortMonthNum(matches[2]), matches[1]);
                return myDate;
            } else {

                return null;
            };
        },

        dateToString: function (date) {

            return date.getDate() + " " + this.short_month_names[date.getMonth()] + " " + date.getFullYear();
        },

        setPosition: function () {
            var offset = this.input.position();
            this.rootLayers.css({
                top: offset.top + this.input.outerHeight(),
                left: offset.left
            });

            if (this.ieframe) {
                this.ieframe.css({
                    width: this.dateSelector.outerWidth(),
                    height: this.dateSelector.outerHeight()
                });
            };
        },

        moveDateBy: function (amount) {
            var newDate = new Date(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate() + amount);
            this.selectDate(newDate);
        },

        moveDateMonthBy: function (amount) {
            var newDate = new Date(this.selectedDate.getFullYear(), this.selectedDate.getMonth() + amount, this.selectedDate.getDate());
            if (newDate.getMonth() == this.selectedDate.getMonth() + amount + 1) {

                newDate.setDate(0);
            };
            this.selectDate(newDate);
        },

        moveMonthBy: function (amount) {
            var newMonth = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() + amount, this.currentMonth.getDate());
            this.selectMonth(newMonth);
        },

        monthName: function (date) {
            return this.month_names[date.getMonth()];
        },

        bindToObj: function (fn) {
            var self = this;
            return function () { return fn.apply(self, arguments) };
        },

        bindMethodsToObj: function () {
            for (var i = 0; i < arguments.length; i++) {
                this[arguments[i]] = this.bindToObj(this[arguments[i]]);
            };
        },

        indexFor: function (array, value) {
            for (var i = 0; i < array.length; i++) {
                if (value == array[i]) return i;
            };
        },

        monthNum: function (month_name) {
            return this.indexFor(this.month_names, month_name);
        },

        shortMonthNum: function (month_name) {
            return this.indexFor(this.short_month_names, month_name);
        },

        shortDayNum: function (day_name) {
            return this.indexFor(this.short_day_names, day_name);
        },

        daysBetween: function (start, end) {
            start = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
            end = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());
            return (end - start) / 86400000;
        },

        changeDayTo: function (dayOfWeek, date, direction) {
            var difference = direction * (Math.abs(date.getDay() - dayOfWeek - (direction * 7)) % 7);
            return new Date(date.getFullYear(), date.getMonth(), date.getDate() + difference);
        },

        rangeStart: function (date) {
            return this.changeDayTo(this.start_of_week, new Date(date.getFullYear(), date.getMonth()), -1);
        },

        rangeEnd: function (date) {
            return this.changeDayTo((this.start_of_week - 1) % 7, new Date(date.getFullYear(), date.getMonth() + 1, 0), 1);
        },

        isFirstDayOfWeek: function (date) {
            return date.getDay() == this.start_of_week;
        },

        isLastDayOfWeek: function (date) {
            return date.getDay() == (this.start_of_week - 1) % 7;
        },

        adjustDays: function (days) {
            var newDays = [];
            for (var i = 0; i < days.length; i++) {
                newDays[i] = days[(i + this.start_of_week) % 7];
            };
            return newDays;
        }
    };

    $.fn.dateInput = function (opts) {
        return this.each(function () { new DateInput(this, opts); });
    };
    $.dateInput = { initialize: function (opts) {
        $("input.date_input").date_input(opts);
    }
    };

    return DateInput;
})(jQuery);


/**
* @license 
* jQuery Tools 1.2.5 Tabs- The basics of UI design.
* 
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
* 
* http://flowplayer.org/tools/tabs/
*
* Since: November 2008
* Date:    Wed Sep 22 06:02:10 2010 +0000 
*/
(function ($) {
    // static constructs
    $.tools = $.tools || { version: '1.2.5' };
    $.tools.tabs = {
        conf: {
            tabs: 'a',
            current: 'current',
            onBeforeClick: null,
            onClick: null,
            effect: 'default',
            initialIndex: 0,
            event: 'click',
            rotate: false,
            // 1.2
            history: false
        },
        addEffect: function (name, fn) {
            effects[name] = fn;
        }
    };
    var effects = {
        // simple "toggle" effect
        'default': function (i, done) {
            this.getPanes().hide().eq(i).show();
            done.call();
        },
        /*
        configuration:
        - fadeOutSpeed (positive value does "crossfading")
        - fadeInSpeed
        */
        fade: function (i, done) {
            var conf = this.getConf(),speed = conf.fadeOutSpeed,panes = this.getPanes();
            if (speed) {
                panes.fadeOut(speed);
            } else {
                panes.hide();
            }
            panes.eq(i).fadeIn(conf.fadeInSpeed, done);
        },
        // for basic accordions
        slide: function (i, done) {
            this.getPanes().slideUp(200);
            this.getPanes().eq(i).slideDown(400, done);
        },
        /**
        * AJAX effect
        */
        ajax: function (i, done) {
            this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);
        }
    };
    var w;
    /**
    * Horizontal accordion
    * 
    * @deprecated will be replaced with a more robust implementation
    */
    $.tools.tabs.addEffect("horizontal", function (i, done) {
        // store original width of a pane into memory
        if (!w) { w = this.getPanes().eq(0).width(); }
        // set current pane's width to zero
        this.getCurrentPane().animate({ width: 0 }, function () { $(this).hide(); });
        // grow opened pane to it's original width
        this.getPanes().eq(i).animate({ width: w }, function () {
            $(this).show();
            done.call();
        });
    });
    function Tabs(root, paneSelector, conf) {
        var self = this,trigger = root.add(this),tabs = root.find(conf.tabs),panes = paneSelector.jquery ? paneSelector : root.children(paneSelector),current;
        // make sure tabs and panes are found
        if (!tabs.length) { tabs = root.children(); }
        if (!panes.length) { panes = root.parent().find(paneSelector); }
        if (!panes.length) { panes = $(paneSelector); }
        // public methods
        $.extend(this, {
            click: function (i, e) {
                var tab = tabs.eq(i);
                if (typeof i == 'string' && i.replace("#", "")) {
                    tab = tabs.filter("[href*=" + i.replace("#", "") + "]");
                    i = Math.max(tabs.index(tab), 0);
                }
                if (conf.rotate) {
                    var last = tabs.length - 1;
                    if (i < 0) { return self.click(last, e); }
                    if (i > last) { return self.click(0, e); }
                }
                if (!tab.length) {
                    if (current >= 0) { return self; }
                    i = conf.initialIndex;
                    tab = tabs.eq(i);
                }
                // current tab is being clicked
                if (i === current) { return self; }
                // possibility to cancel click action				
                e = e || $.Event();
                e.type = "onBeforeClick";
                trigger.trigger(e, [i]);
                if (e.isDefaultPrevented()) { return; }
                // call the effect
                effects[conf.effect].call(self, i, function () {
                    // onClick callback
                    e.type = "onClick";
                    trigger.trigger(e, [i]);
                });
                // default behaviour
                current = i;
                tabs.removeClass(conf.current);
                tab.addClass(conf.current);
                return self;
            },
            getConf: function () {
                return conf;
            },
            getTabs: function () {
                return tabs;
            },
            getPanes: function () {
                return panes;
            },
            getCurrentPane: function () {
                return panes.eq(current);
            },
            getCurrentTab: function () {
                return tabs.eq(current);
            },
            getIndex: function () {
                return current;
            },
            next: function () {
                return self.click(current + 1);
            },
            prev: function () {
                return self.click(current - 1);
            },
            destroy: function () {
                tabs.unbind(conf.event).removeClass(conf.current);
                panes.find("a[href^=#]").unbind("click.T");
                return self;
            }
        });
        // callbacks	
        $.each("onBeforeClick,onClick".split(","), function (i, name) {
            // configuration
            if ($.isFunction(conf[name])) {
                $(self).bind(name, conf[name]);
            }
            // API
            self[name] = function (fn) {
                if (fn) { $(self).bind(name, fn); }
                return self;
            };
        });
        if (conf.history && $.fn.history) {
            $.tools.history.init(tabs);
            conf.event = 'history';
        }
        // setup click actions for each tab
        tabs.each(function (i) {
            $(this).bind(conf.event, function (e) {
                self.click(i, e);
                return e.preventDefault();
            });
        });
        // cross tab anchor link
        panes.find("a[href^=#]").bind("click.T", function (e) {
            self.click($(this).attr("href"), e);
        });
        // open initial tab
        if (location.hash && conf.tabs == "a" && root.find("[href=" + location.hash + "]").length) {
            self.click(location.hash);
        } else {
            if (conf.initialIndex === 0 || conf.initialIndex > 0) {
                self.click(conf.initialIndex);
            }
        }
    }
    // jQuery plugin implementation
    $.fn.tabs = function (paneSelector, conf) {
        // return existing instance
        var el = this.data("tabs");
        if (el) {
            el.destroy();
            this.removeData("tabs");
        }
        if ($.isFunction(conf)) {
            conf = { onBeforeClick: conf };
        }
        // setup conf
        conf = $.extend({}, $.tools.tabs.conf, conf);
        this.each(function () {
            el = new Tabs($(this), paneSelector, conf);
            $(this).data("tabs", el);
        });
        return conf.api ? el : this;
    };
})(jQuery); 


