/*
* 
* tools.tabs
* tools.tabs.slideshow
* tools.expose
* tools.overlay
* 
*/

/**
* tools.tabs 1.0.4 - Tabs done right.
* 
* Copyright (c) 2009 Tero Piirainen
* http://flowplayer.org/tools/tabs.html
*
* Dual licensed under MIT and GPL 2+ licenses
* http://www.opensource.org/licenses
*
* Launch  : November 2008
* Date: ${date}
* Revision: ${revision} 
*/
(function ($) {

    // static constructs
    $.tools = $.tools || {};

    $.tools.tabs = {
        version: '1.0.4',

        conf: {
            tabs: 'a',
            current: 'current',
            onBeforeClick: null,
            onClick: null,
            effect: 'default',
            initialIndex: 0,
            event: 'click',
            api: false,
            rotate: 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);
        },

        // simple AJAX effect
        ajax: function (i, done) {
            this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);
        }

    };

    var w;

    // this is how you add effects
    $.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(tabs, panes, conf) {

        var self = this, $self = $(this), current;
        var userEffect = conf.effect;
        var firstCall = true;

        // bind all callbacks from configuration
        $.each(conf, function (name, fn) {
            if ($.isFunction(fn)) { $self.bind(name, fn); }
        });


        // public methods
        $.extend(this, {
            click: function (i, e) {

                var pane = self.getCurrentPane();
                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";
                $self.trigger(e, [i]);
                if (e.isDefaultPrevented()) { return; }

                //JJAG: prevents calling custom effect on page load
                (firstCall) ? conf.effect = 'default' : conf.effect = userEffect;

                // call the effect
                effects[conf.effect].call(self, i, function () {

                    // onClick callback
                    e.type = "onClick";
                    $self.trigger(e, [i]);
                    firstCall = false;
                });

                // onStart
                e.type = "onStart";
                $self.trigger(e, [i]);
                if (e.isDefaultPrevented()) { return; }

                // default behaviour
                current = i;
                tabs.each(function (index, tab) {
                    $(tab).parent().removeClass(conf.current);
                });
                tab.parent().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);
            },

            bind: function (name, fn) {
                $self.bind(name, fn);
                return self;
            },

            onBeforeClick: function (fn) {
                return this.bind("onBeforeClick", fn);
            },

            onClick: function (fn) {
                return this.bind("onClick", fn);
            },

            unbind: function (name) {
                $self.unbind(name);
                return self;
            }

        });


        // setup click actions for each tab
        tabs.each(function (i) {
            $(this).bind(conf.event, function (e) {
                self.click(i, e);
                return false;
            });
        });

        // if no pane is visible --> click on the first tab
        if (location.hash) {
            self.click(location.hash);
        } else {
            if (conf.initialIndex === 0 || conf.initialIndex > 0) {
                self.click(conf.initialIndex);
            }
        }

        // cross tab anchor link
        panes.find("a[href^=#]").click(function (e) {
            self.click($(this).attr("href"), e);
        });
    }


    // jQuery plugin implementation
    $.fn.tabs = function (query, conf) {

        // return existing instance
        var el = this.eq(typeof conf == 'number' ? conf : 0).data("tabs");
        if (el) { return el; }

        if ($.isFunction(conf)) {
            conf = { onBeforeClick: conf };
        }

        // setup options
        var globals = $.extend({}, $.tools.tabs.conf), len = this.length;
        conf = $.extend(globals, conf);


        // install tabs for each items in jQuery		
        this.each(function (i) {
            var root = $(this);

            // find tabs
            var els = root.find(conf.tabs);

            if (!els.length) {
                els = root.children();
            }

            // find panes
            var panes = query.jquery ? query : root.children(query);

            if (!panes.length) {
                panes = len == 1 ? $(query) : root.parent().find(query);
            }

            el = new Tabs(els, panes, conf);
            root.data("tabs", el);

        });

        return conf.api ? el : this;
    };

})(jQuery); 



/**
 * jQuery TOOLS plugin :: tabs.slideshow 1.0.2
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/tabs.html#slideshow
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : September 2009
 * Date: ${date}
 * Revision: ${revision} 
 */
(function($) {
	
	var t = $.tools.tabs; 
	t.plugins = t.plugins || {}; 
	t.plugins.slideshow = { 
		version: '1.0.2',
		
		// CALLBACKS: onBeforePlay, onPlay, onBeforePause, onPause,  
		conf: {
			next: '.forward',
			prev: '.backward',
			disabledClass: 'disabled',
			autoplay: false,
			autopause: true,
			interval: 3000, 
			clickable: true,
			api: false
		}
	};


	// jQuery plugin implementation
	$.prototype.slideshow = function(conf) {
	
		var globals = $.extend({}, t.plugins.slideshow.conf),
			 len = this.length, 
			 ret;
			 
		conf = $.extend(globals, conf);	 
		
		this.each(function() {
			
			var tabs = $(this), api = tabs.tabs(), $api = $(api), ret = api; 
			
			// bind all callbacks from configuration
			$.each(conf, function(name, fn) {
				if ($.isFunction(fn)) { api.bind(name, fn); }
			});
		
			
			function find(query) {
				return len == 1 ? $(query) : tabs.parent().find(query);	
			}	
			
			var nextButton = find(conf.next).click(function() {
				api.next();		
			});
			
			var prevButton = find(conf.prev).click(function() {
				api.prev();		
			});
			
			// interval stuff
			var timer, hoverTimer, startTimer, stopped = false;
	

			// extend the Tabs API with slideshow methods			
			$.extend(api, {
					
				play: function() {
		
					// do not start additional timer if already exists
					if (timer) { return; }
					
					// onBeforePlay
					var e = $.Event("onBeforePlay");
					$api.trigger(e);
					
					if (e.isDefaultPrevented()) { return api; }				
					
					stopped = false;
					
					// construct new timer
					timer = setInterval(api.next, conf.interval);
	
					// onPlay
					$api.trigger("onPlay");				
					
					api.next();
				},
			
				pause: function() {
					
					if (!timer) { return api; }
					
					// onBeforePause
					var e = $.Event("onBeforePause");
					$api.trigger(e);					
					if (e.isDefaultPrevented()) { return api; }		
					
					timer = clearInterval(timer);
					startTimer = clearInterval(startTimer);
					
					// onPause
					$api.trigger("onPause");		
				},
				
				// when stopped - mouseover won't restart 
				stop: function() {					
					api.pause();
					stopped = true;	
				},
				
				onBeforePlay: function(fn) {
					return api.bind("onBeforePlay", fn);
				},
				
				onPlay: function(fn) {
					return api.bind("onPlay", fn);
				},

				onBeforePause: function(fn) {
					return api.bind("onBeforePause", fn);
				},
				
				onPause: function(fn) {
					return api.bind("onPause", fn);
				}
				
			});
	
			
		
			/* when mouse enters, slideshow stops */
			if (conf.autopause) {
				var els = api.getTabs().add(nextButton).add(prevButton).add(api.getPanes());
				
				els.hover(function() {					
					api.pause();					
					hoverTimer = clearInterval(hoverTimer);
					
				}, function() {
					if (!stopped) {						
						hoverTimer = setTimeout(api.play, conf.interval);						
					}
				});
			} 
			
			if (conf.autoplay) {
				startTimer = setTimeout(api.play, conf.interval);				
			} else {
				api.stop();	
			}
			
			if (conf.clickable) {
				api.getPanes().click(function()  {
					api.next();
				});
			} 
			
			// manage disabling of next/prev buttons
			if (!api.getConf().rotate) {
				
				var cls = conf.disabledClass;
				
				if (!api.getIndex()) {
					prevButton.addClass(cls);
				}
				api.onBeforeClick(function(e, i)  {
					if (!i) {
						prevButton.addClass(cls);
					} else {
						prevButton.removeClass(cls);	
					
						if (i == api.getTabs().length -1) {
							nextButton.addClass(cls);
						} else {
							nextButton.removeClass(cls);	
						}
					}
				});
			}
			
		});
		
		return conf.api ? ret : this;
	};
	
})(jQuery); 



/**
* tools.expose 1.0.5 - Make HTML elements stand out
* 
* Copyright (c) 2009 Tero Piirainen
* http://flowplayer.org/tools/expose.html
*
* Dual licensed under MIT and GPL 2+ licenses
* http://www.opensource.org/licenses
*
* Launch  : June 2008
* Date: ${date}
* Revision: ${revision} 
*/
(function ($) {

    // static constructs
    $.tools = $.tools || {};

    $.tools.expose = {
        version: '1.0.5',
        conf: {

            // mask settings
            maskId: null,
            loadSpeed: 'slow',
            closeSpeed: 'fast',
            closeOnClick: true,
            closeOnEsc: true,

            // css settings
            zIndex: 9998,
            opacity: 0.8,
            color: '#456',
            api: false
        }
    };

    /* one of the greatest headaches in the tool. finally made it */
    function viewport() {

        // the horror case
        if ($.browser.msie) {

            // if there are no scrollbars then use window.height
            var d = $(document).height(), w = $(window).height();

            return [
				window.innerWidth || 							// ie7+
				document.documentElement.clientWidth || 	// ie6  
				document.body.clientWidth, 					// ie6 quirks mode
				d - w < 20 ? w : d
			];
        }

        // other well behaving browsers
        return [$(window).width(), $(document).height()];

    }

    function Expose(els, conf) {

        // private variables
        var self = this, $self = $(this), mask = null, loaded = false, origIndex = 0;

        // bind all callbacks from configuration
        $.each(conf, function (name, fn) {
            if ($.isFunction(fn)) { $self.bind(name, fn); }
        });

        // adjust mask size when window is resized (or firebug is toggled)
        $(window).resize(function () {
            self.fit();
        });


        // public methods
        $.extend(this, {

            getMask: function () {
                return mask;
            },

            getExposed: function () {
                return els;
            },

            getConf: function () {
                return conf;
            },

            isLoaded: function () {
                return loaded;
            },

            load: function (e) {

                // already loaded ?
                if (loaded) { return self; }

                origIndex = els.eq(0).css("zIndex");

                // find existing mask
                if (conf.maskId) { mask = $("#" + conf.maskId); }

                if (!mask || !mask.length) {

                    var size = viewport();

                    mask = $('<div/>').css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        width: size[0],
                        height: size[1],
                        display: 'none',
                        opacity: 0,
                        zIndex: conf.zIndex
                    });

                    // id
                    if (conf.maskId) { mask.attr("id", conf.maskId); }

                    $("body").append(mask);


                    // background color 
                    var bg = mask.css("backgroundColor");

                    if (!bg || bg == 'transparent' || bg == 'rgba(0, 0, 0, 0)') {
                        mask.css("backgroundColor", conf.color);
                    }

                    // esc button
                    if (conf.closeOnEsc) {
                        $(document).bind("keydown.unexpose", function (evt) {
                            if (evt.keyCode == 27) {
                                self.close();
                            }
                        });
                    }

                    // mask click closes
                    if (conf.closeOnClick) {
                        mask.bind("click.unexpose", function (e) {
                            self.close(e);
                        });
                    }
                }

                // possibility to cancel click action
                e = e || $.Event();
                e.type = "onBeforeLoad";
                $self.trigger(e);

                if (e.isDefaultPrevented()) { return self; }

                // make sure element is positioned absolutely or relatively
                $.each(els, function () {
                    var el = $(this);
                    if (!/relative|absolute|fixed/i.test(el.css("position"))) {
                        el.css("position", "relative");
                    }
                });

                // make elements sit on top of the mask				
                els.css({ zIndex: Math.max(conf.zIndex + 1, origIndex == 'auto' ? 0 : origIndex) });


                // reveal mask
                var h = mask.height();

                if (!this.isLoaded()) {

                    mask.css({ opacity: 0, display: 'block' }).fadeTo(conf.loadSpeed, conf.opacity, function () {

                        // sometimes IE6 misses the height property on fadeTo method
                        if (mask.height() != h) { mask.css("height", h); }
                        e.type = "onLoad";
                        $self.trigger(e);

                    });
                }

                loaded = true;

                return self;
            },


            close: function (e) {

                if (!loaded) { return self; }

                e = e || $.Event();
                e.type = "onBeforeClose";
                $self.trigger(e);
                if (e.isDefaultPrevented()) { return self; }

                mask.fadeOut(conf.closeSpeed, function () {
                    e.type = "onClose";
                    $self.trigger(e);
                    els.css({ zIndex: $.browser.msie ? origIndex : null });
                });

                loaded = false;
                return self;
            },

            fit: function () {
                if (mask) {
                    var size = viewport();
                    mask.css({ width: size[0], height: size[1] });
                }
            },

            bind: function (name, fn) {
                $self.bind(name, fn);
                return self;
            },

            unbind: function (name) {
                $self.unbind(name);
                return self;
            }

        });

        // callbacks	
        $.each("onBeforeLoad,onLoad,onBeforeClose,onClose".split(","), function (i, ev) {
            self[ev] = function (fn) {
                return self.bind(ev, fn);
            };
        });

    }


    // jQuery plugin implementation
    $.fn.expose = function (conf) {

        var el = this.eq(typeof conf == 'number' ? conf : 0).data("expose");
        if (el) { return el; }

        if (typeof conf == 'string') {
            conf = { color: conf };
        }

        var globals = $.extend({}, $.tools.expose.conf);
        conf = $.extend(globals, conf);

        // construct exposes
        this.each(function () {
            el = new Expose($(this), conf);
            $(this).data("expose", el);
        });

        return conf.api ? el : this;
    };


})(jQuery);



/**
* tools.overlay 1.1.2 - Overlay HTML with eye candy.
* 
* Copyright (c) 2009 Tero Piirainen
* http://flowplayer.org/tools/overlay.html
*
* Dual licensed under MIT and GPL 2+ licenses
* http://www.opensource.org/licenses
*
* Launch  : March 2008
* Date: ${date}
* Revision: ${revision} 
*/
(function ($) {

    // static constructs
    $.tools = $.tools || {};

    $.tools.overlay = {

        version: '1.1.2',

        addEffect: function (name, loadFn, closeFn) {
            effects[name] = [loadFn, closeFn];
        },

        conf: {
            top: '10%',
            left: 'center',
            absolute: false,

            speed: 'normal',
            closeSpeed: 'fast',
            effect: 'default',

            close: null,
            oneInstance: true,
            closeOnClick: true,
            closeOnEsc: true,
            api: false,
            expose: null,

            // target element to be overlayed. by default taken from [rel]
            target: null
        }
    };


    var effects = {};

    // the default effect. nice and easy!
    $.tools.overlay.addEffect('default',

    /* 
    onLoad/onClose functions must be called otherwise none of the 
    user supplied callback methods won't be called
    */
		function (onLoad) {
		    this.getOverlay().fadeIn(this.getConf().speed, onLoad);

		}, function (onClose) {
		    this.getOverlay().fadeOut(this.getConf().closeSpeed, onClose);
		}
	);


    var instances = [];


    function Overlay(trigger, conf) {

        // private variables
        var self = this,
			 $self = $(this),
			 w = $(window),
			 closers,
			 overlay,
			 opened,
			 expose = conf.expose && $.tools.expose.version;

        // get overlay and triggerr
        var jq = conf.target || trigger.attr("rel");
        overlay = jq ? $(jq) : null || trigger;

        // overlay not found. cannot continue
        if (!overlay.length) { throw "Could not find Overlay: " + jq; }

        // if trigger is given - assign it's click event
        if (trigger && trigger.index(overlay) == -1) {
            trigger.click(function (e) {
                self.load(e);
                return e.preventDefault();
            });
        }

        // bind all callbacks from configuration
        $.each(conf, function (name, fn) {
            if ($.isFunction(fn)) { $self.bind(name, fn); }
        });


        // API methods  
        $.extend(self, {

            load: function (e) {

                // can be opened only once
                if (self.isOpened()) { return self; }


                // find the effect
                var eff = effects[conf.effect];
                if (!eff) { throw "Overlay: cannot find effect : \"" + conf.effect + "\""; }

                // close other instances?
                if (conf.oneInstance) {
                    $.each(instances, function () {
                        this.close(e);
                    });
                }

                // onBeforeLoad
                e = e || $.Event();
                e.type = "onBeforeLoad";
                $self.trigger(e);
                if (e.isDefaultPrevented()) { return self; }

                // opened
                opened = true;

                // possible expose effect
                if (expose) { overlay.expose().load(e); }

                // calculate end position 
                var top = conf.top;
                var left = conf.left;

                // get overlay dimensions
                var oWidth = overlay.outerWidth({ margin: true });
                var oHeight = overlay.outerHeight({ margin: true });

                if (typeof top == 'string') {
                    top = top == 'center' ? Math.max((w.height() - oHeight) / 2, 0) :
						parseInt(top, 10) / 100 * w.height();
                }

                if (left == 'center') { left = Math.max((w.width() - oWidth) / 2, 0); }

                if (!conf.absolute) {
                    top += w.scrollTop();
                    left += w.scrollLeft();
                }

                // position overlay
                overlay.css({ top: top, left: left, position: 'absolute' });

                // onStart
                e.type = "onStart";
                $self.trigger(e);

                // load effect  		 		
                eff[0].call(self, function () {
                    if (opened) {
                        e.type = "onLoad";
                        $self.trigger(e);
                    }
                });

                // when window is clicked outside overlay, we close
                if (conf.closeOnClick) {
                    $(document).bind("click.overlay", function (e) {
                        if (!self.isOpened()) { return; }
                        var et = $(e.target);
                        if (et.parents(overlay).length > 1) { return; }
                        $.each(instances, function () {
                            this.close(e);
                        });
                    });
                }

                // keyboard::escape
                if (conf.closeOnEsc) {

                    // one callback is enough if multiple instances are loaded simultaneously
                    $(document).unbind("keydown.overlay").bind("keydown.overlay", function (e) {
                        if (e.keyCode == 27) {
                            $.each(instances, function () {
                                this.close(e);
                            });
                        }
                    });
                }

                return self;
            },

            close: function (e) {

                if (!self.isOpened()) { return self; }

                e = e || $.Event();
                e.type = "onBeforeClose";
                $self.trigger(e);
                if (e.isDefaultPrevented()) { return; }

                opened = false;

                // close effect
                effects[conf.effect][1].call(self, function () {
                    e.type = "onClose";
                    $self.trigger(e);
                });

                // if all instances are closed then we unbind the keyboard / clicking actions
                var allClosed = true;
                $.each(instances, function () {
                    if (this.isOpened()) { allClosed = false; }
                });

                if (allClosed) {
                    $(document).unbind("click.overlay").unbind("keydown.overlay");
                }


                return self;
            },

            // @deprecated
            getContent: function () {
                return overlay;
            },

            getOverlay: function () {
                return overlay;
            },

            getTrigger: function () {
                return trigger;
            },

            getClosers: function () {
                return closers;
            },

            isOpened: function () {
                return opened;
            },

            // manipulate start, finish and speeds
            getConf: function () {
                return conf;
            },

            // bind
            bind: function (name, fn) {
                $self.bind(name, fn);
                return self;
            },

            // unbind
            unbind: function (name) {
                $self.unbind(name);
                return self;
            }

        });

        // callbacks	
        $.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","), function (i, ev) {
            self[ev] = function (fn) {
                return self.bind(ev, fn);
            };
        });


        // exposing effect
        if (expose) {

            // expose configuration
            if (typeof conf.expose == 'string') { conf.expose = { color: conf.expose }; }

            $.extend(conf.expose, {
                api: true,
                closeOnClick: conf.closeOnClick,

                // only overlay control's the esc button
                closeOnEsc: false
            });

            // initialize expose api
            var ex = overlay.expose(conf.expose);

            ex.onBeforeClose(function (e) {
                self.close(e);
            });

            self.onClose(function (e) {
                ex.close(e);
            });
        }

        // close button
        closers = overlay.find(conf.close || ".close");

        if (!closers.length && !conf.close) {
            closers = $('<div class="close"></div>');
            overlay.prepend(closers);
        }

        closers.click(function (e) {
            self.close(e);
        });
    }

    // jQuery plugin initialization
    $.fn.overlay = function (conf) {

        // already constructed --> return API
        var el = this.eq(typeof conf == 'number' ? conf : 0).data("overlay");
        if (el) { return el; }

        if ($.isFunction(conf)) {
            conf = { onBeforeLoad: conf };
        }

        var globals = $.extend({}, $.tools.overlay.conf);
        conf = $.extend(true, globals, conf);

        this.each(function () {
            el = new Overlay($(this), conf);
            instances.push(el);
            $(this).data("overlay", el);
        });

        return conf.api ? el : this;
    };

})(jQuery);


/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

(function($){
	$.fn.superfish = function(op){
		
		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); };
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}
	};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);


