/**
* @license 
* jQuery Tools 1.2.4 Scrollable - New wave UI design
* 
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
* 
* http://flowplayer.org/tools/scrollable.html
*
* Since: March 2008
* Date:    Sun Aug 15 08:16:31 2010 +0000 
*/
(function ($) {

    // static constructs
    $.tools = $.tools || { version: '1.2.4' };

    $.tools.scrollable = {

        conf: {
            activeClass: 'active',
            circular: false,
            clonedClass: 'cloned',
            disabledClass: 'disabled',
            easing: 'swing',
            initialIndex: 0,
            item: null,
            items: '.items',
            keyboard: true,
            mousewheel: false,
            next: '.next',
            prev: '.prev',
            speed: 400,
            vertical: false,
            wheelSpeed: 0
        }
    };

    // get hidden element's width or height even though it's hidden
    function dim(el, key) {
        var v = parseInt(el.css(key), 10);
        if (v) { return v; }
        var s = el[0].currentStyle;
        return s && s.width && parseInt(s.width, 10);
    }

    function find(root, query) {
        var el = $(query);
        return el.length < 2 ? el : root.parent().find(query);
    }

    var current;

    // constructor
    function Scrollable(root, conf) {

        // current instance
        var self = this,
			 fire = root.add(self),
			 itemWrap = root.children(),
			 index = 0,
			 vertical = conf.vertical;

        if (!current) { current = self; }
        if (itemWrap.length > 1) { itemWrap = $(conf.items, root); }

        // methods
        $.extend(self, {

            getConf: function () {
                return conf;
            },

            getIndex: function () {
                return index;
            },

            getSize: function () {
                return self.getItems().size();
            },

            getNaviButtons: function () {
                return prev.add(next);
            },

            getRoot: function () {
                return root;
            },

            getItemWrap: function () {
                return itemWrap;
            },

            getItems: function () {
                return itemWrap.children(conf.item).not("." + conf.clonedClass);
            },

            move: function (offset, time) {
                return self.seekTo(index + offset, time);
            },

            next: function (time) {
                return self.move(1, time);
            },

            prev: function (time) {
                return self.move(-1, time);
            },

            begin: function (time) {
                return self.seekTo(0, time);
            },

            end: function (time) {
                return self.seekTo(self.getSize() - 1, time);
            },

            focus: function () {
                current = self;
                return self;
            },

            addItem: function (item) {
                item = $(item);

                if (!conf.circular) {
                    itemWrap.append(item);
                } else {
                    itemWrap.children("." + conf.clonedClass + ":last").before(item);
                    itemWrap.children("." + conf.clonedClass + ":first").replaceWith(item.clone().addClass(conf.clonedClass));
                }

                fire.trigger("onAddItem", [item]);
                return self;
            },


            /* all seeking functions depend on this */
            seekTo: function (i, time, fn) {

                // ensure numeric index
                if (!i.jquery) { i *= 1; }

                // avoid seeking from end clone to the beginning
                if (conf.circular && i === 0 && index == -1 && time !== 0) { return self; }

                // check that index is sane				
                if (!conf.circular && i < 0 || i > self.getSize() || i < -1) { return self; }

                var item = i;

                if (i.jquery) {
                    i = self.getItems().index(i);

                } else {
                    item = self.getItems().eq(i);
                }

                // onBeforeSeek
                var e = $.Event("onBeforeSeek");
                if (!fn) {
                    fire.trigger(e, [i, time]);
                    if (e.isDefaultPrevented() || !item.length) { return self; }
                }

                var props = vertical ? { top: -item.position().top} : { left: -item.position().left };

                index = i;
                current = self;
                if (time === undefined) { time = conf.speed; }

                itemWrap.animate(props, time, conf.easing, fn || function () {
                    fire.trigger("onSeek", [i]);
                });

                return self;
            }

        });

        // callbacks	
        $.each(['onBeforeSeek', 'onSeek', 'onAddItem'], function (i, name) {

            // configuration
            if ($.isFunction(conf[name])) {
                $(self).bind(name, conf[name]);
            }

            self[name] = function (fn) {
                $(self).bind(name, fn);
                return self;
            };
        });

        // circular loop
        if (conf.circular) {

            var cloned1 = self.getItems().slice(-1).clone().prependTo(itemWrap),
				 cloned2 = self.getItems().eq(1).clone().appendTo(itemWrap);

            cloned1.add(cloned2).addClass(conf.clonedClass);

            self.onBeforeSeek(function (e, i, time) {


                if (e.isDefaultPrevented()) { return; }

                /*
                1. animate to the clone without event triggering
                2. seek to correct position with 0 speed
                */
                if (i == -1) {
                    self.seekTo(cloned1, time, function () {
                        self.end(0);
                    });
                    return e.preventDefault();

                } else if (i == self.getSize()) {
                    self.seekTo(cloned2, time, function () {
                        self.begin(0);
                    });
                }

            });

            // seek over the cloned item
            self.seekTo(0, 0, function () { });
        }

        // next/prev buttons
        var prev = find(root, conf.prev).click(function () { self.prev(); }),
			 next = find(root, conf.next).click(function () { self.next(); });

        if (!conf.circular && self.getSize() > 1) {

            self.onBeforeSeek(function (e, i) {
                setTimeout(function () {
                    if (!e.isDefaultPrevented()) {
                        prev.toggleClass(conf.disabledClass, i <= 0);
                        next.toggleClass(conf.disabledClass, i >= self.getSize() - 1);
                    }
                }, 1);
            });
        }

        // mousewheel support
        if (conf.mousewheel && $.fn.mousewheel) {
            root.mousewheel(function (e, delta) {
                if (conf.mousewheel) {
                    self.move(delta < 0 ? 1 : -1, conf.wheelSpeed || 50);
                    return false;
                }
            });
        }

        if (conf.keyboard) {

            $(document).bind("keydown.scrollable", function (evt) {

                // skip certain conditions
                if (!conf.keyboard || evt.altKey || evt.ctrlKey || $(evt.target).is(":input")) { return; }

                // does this instance have focus?
                if (conf.keyboard != 'static' && current != self) { return; }

                var key = evt.keyCode;

                if (vertical && (key == 38 || key == 40)) {
                    self.move(key == 38 ? -1 : 1);
                    return evt.preventDefault();
                }

                if (!vertical && (key == 37 || key == 39)) {
                    self.move(key == 37 ? -1 : 1);
                    return evt.preventDefault();
                }

            });
        }

        // initial index
        if (conf.initialIndex) {
            self.seekTo(conf.initialIndex, 0, function () { });
        }
    }


    // jQuery plugin implementation
    $.fn.scrollable = function (conf) {

        // already constructed --> return API
        var el = this.data("scrollable");
        if (el) { return el; }

        conf = $.extend({}, $.tools.scrollable.conf, conf);

        this.each(function () {
            el = new Scrollable($(this), conf);
            $(this).data("scrollable", el);
        });

        return conf.api ? el : this;

    };


})(jQuery);

/**
* @license 
* jQuery Tools 1.2.4 / Scrollable Navigator
* 
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/scrollable/navigator.html
*
* Since: September 2009
* Date:    Sun Aug 15 08:16:31 2010 +0000 
*/
(function ($) {

    var t = $.tools.scrollable;

    t.navigator = {

        conf: {
            navi: '.navi',
            naviItem: null,
            activeClass: 'active',
            indexed: false,
            idPrefix: null,

            // 1.2
            history: false
        }
    };

    function find(root, query) {
        var el = $(query);
        return el.length < 2 ? el : root.parent().find(query);
    }

    // jQuery plugin implementation
    $.fn.navigator = function (conf) {

        // configuration
        if (typeof conf == 'string') { conf = { navi: conf }; }
        conf = $.extend({}, t.navigator.conf, conf);

        var ret;

        this.each(function () {

            var api = $(this).data("scrollable"),
				 navi = conf.navi.jquery ? conf.navi : find(api.getRoot(), conf.navi),
				 buttons = api.getNaviButtons(),
				 cls = conf.activeClass,
				 history = conf.history && $.fn.history;

            // @deprecated stuff
            if (api) { ret = api; }

            api.getNaviButtons = function () {
                return buttons.add(navi);
            };


            function doClick(el, i, e) {
                api.seekTo(i);
                if (history) {
                    if (location.hash) {
                        location.hash = el.attr("href").replace("#", "");
                    }
                } else {
                    return e.preventDefault();
                }
            }

            function els() {
                return navi.find(conf.naviItem || '> *');
            }

            function addItem(i) {

                var item = $("<" + (conf.naviItem || 'a') + "/>").click(function (e) {
                    doClick($(this), i, e);

                }).attr("href", "#" + i);

                // index number / id attribute
                if (i === 0) { item.addClass(cls); }
                if (conf.indexed) { item.text(i + 1); }
                if (conf.idPrefix) { item.attr("id", conf.idPrefix + i); }

                return item.appendTo(navi);
            }


            // generate navigator
            if (els().length) {
                els().each(function (i) {
                    $(this).click(function (e) {
                        doClick($(this), i, e);
                    });
                });

            } else {
                $.each(api.getItems(), function (i) {
                    addItem(i);
                });
            }

            // activate correct entry
            api.onBeforeSeek(function (e, index) {
                setTimeout(function () {
                    if (!e.isDefaultPrevented()) {
                        var el = els().eq(index);
                        if (!e.isDefaultPrevented() && el.length) {
                            els().removeClass(cls).eq(index).addClass(cls);
                        }
                    }
                }, 1);
            });

            function doHistory(evt, hash) {
                var el = els().eq(hash.replace("#", ""));
                if (!el.length) {
                    el = els().filter("[href=" + hash + "]");
                }
                el.click();
            }

            // new item being added
            api.onAddItem(function (e, item) {
                item = addItem(api.getItems().index(item));
                if (history) { item.history(doHistory); }
            });

            if (history) { els().history(doHistory); }

        });

        return conf.api ? ret : this;

    };

})(jQuery);

/**
* @license 
* jQuery Tools 1.2.4 Tabs- The basics of UI design.
* 
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
* 
* http://flowplayer.org/tools/tabs/
*
* Since: November 2008
* Date:    Sun Aug 15 08:16:31 2010 +0000 
*/
(function ($) {

    // static constructs
    $.tools = $.tools || { version: '1.2.4' };

    $.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(conf.tabs + 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); 

