/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate$
 * $Rev$
 *
 * Version: @VERSION
 *
 * Requires: jQuery 1.2+
 */

(function($){
    
$.dimensions = {
    version: '@VERSION'
};

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
$.each( [ 'Height', 'Width' ], function(i, name){
    
    // innerHeight and innerWidth
    $.fn[ 'inner' + name ] = function() {
        if (!this[0]) return;
        
        var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
            borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
        
        return this.is(':visible') ? this[0]['client' + name] : num( this, name.toLowerCase() ) + num(this, 'padding' + torl) + num(this, 'padding' + borr);
    };
    
    // outerHeight and outerWidth
    $.fn[ 'outer' + name ] = function(options) {
        if (!this[0]) return;
        
        var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
            borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
        
        options = $.extend({ margin: false }, options || {});
        
        var val = this.is(':visible') ? 
                this[0]['offset' + name] : 
                num( this, name.toLowerCase() )
                    + num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
                    + num(this, 'padding' + torl) + num(this, 'padding' + borr);
        
        return val + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
    };
});

// Create scrollLeft and scrollTop methods
$.each( ['Left', 'Top'], function(i, name) {
    $.fn[ 'scroll' + name ] = function(val) {
        if (!this[0]) return;
        
        return val != undefined ?
        
            // Set the scroll offset
            this.each(function() {
                this == window || this == document ?
                    window.scrollTo( 
                        name == 'Left' ? val : $(window)[ 'scrollLeft' ](),
                        name == 'Top'  ? val : $(window)[ 'scrollTop'  ]()
                    ) :
                    this[ 'scroll' + name ] = val;
            }) :
            
            // Return the scroll offset
            this[0] == window || this[0] == document ?
                self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] ||
                    $.boxModel && document.documentElement[ 'scroll' + name ] ||
                    document.body[ 'scroll' + name ] :
                this[0][ 'scroll' + name ];
    };
});

$.fn.extend({
    position: function() {
        var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;
        
        if (elem) {
            // Get *real* offsetParent
            offsetParent = this.offsetParent();
            
            // Get correct offsets
            offset       = this.offset();
            parentOffset = offsetParent.offset();
            
            // Subtract element margins
            offset.top  -= num(elem, 'marginTop');
            offset.left -= num(elem, 'marginLeft');
            
            // Add offsetParent borders
            parentOffset.top  += num(offsetParent, 'borderTopWidth');
            parentOffset.left += num(offsetParent, 'borderLeftWidth');
            
            // Subtract the two offsets
            results = {
                top:  offset.top  - parentOffset.top,
                left: offset.left - parentOffset.left
            };
        }
        
        return results;
    },
    
    offsetParent: function() {
        var offsetParent = this[0].offsetParent;
        while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
            offsetParent = offsetParent.offsetParent;
        return $(offsetParent);
    }
});

function num(el, prop) {
    return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
};

})(jQuery);
/*
 * positionBy 1.0.7 (2008-01-29)
 *
 * Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://jdsharp.us/
 *
 * Built upon jQuery 1.2.2 (http://jquery.com)
 * This also requires the jQuery dimensions plugin
 */
(function($){
    /**
     * This function centers an absolutely positioned element
     */
    /*
    $.fn.positionCenter = function(offsetLeft, offsetTop) {
        var offsetLeft  = offsetLeft || 1;
        var offsetTop   = offsetTop || 1;

        var ww = $(window).width();
        var wh = $(window).height();
        var sl = $(window).scrollLeft();
        var st = $(window).scrollTop();

        return this.each(function() {
            var $t = $(this);
            
            // If we are not visible we have to display our element (with a negative position offscreen)

            var left = Math.round( ( ww - $t.outerWidth() ) / 2 );
            if ( left < 0 ) {
                left = 0;
            } else {
                left *= offsetLeft;
            }
            left += sl;
            var top  = Math.round( ( wh - $t.outerHeight() ) / 2 );
            if ( top < 0 ) {
                top = 0;
            } else {
                top *= offsetTop;
            }
            top += st;

            $(this).parents().each(function() {
                var $this = $(this);
                if ( $this.css('position') != 'static' ) {
                    var o = $this.offset();
                    left += -o.left;
                    top  += -o.top;
                    return false;
                }
            });

            $t.css({left: left, top: top});
        });
    };
    */
    
    // Our range object is used in calculating positions
    var Range = function(x1, y1, x2, y2) {
        this.x1 = x1;   this.x2 = x2;
        this.y1 = y1;   this.y2 = y2;
    };
    Range.prototype.contains = function(range) {
        return  (this.x1 <= range.x1 && range.x2 <= this.x2) 
                && 
                (this.y1 <= range.y1 && range.y2 <= this.y2);
    };
    Range.prototype.transform = function(x, y) {
        return new Range(this.x1 + x, this.y1 + y, this.x2 + x, this.y2 + y);
    };

    $.fn.positionBy = function(args) {
        var date1 = new Date();
        if ( this.length == 0 ) {
            return this;
        }
        
        var args = $.extend({   // The target element to position us relative to
                                target:     null,
                                // The target's corner, possible values 0-3
                                targetPos:  null,
                                // The element's corner, possible values 0-3
                                elementPos: null,
                                
                                // A raw x,y coordinate
                                x:          null,
                                y:          null,

                                // Pass in an array of positions that are valid 0-15
                                positions:  null,

                                // Add the final position class to the element (eg. positionBy0 through positionBy3, positionBy15)
                                addClass:   false,
                                
                                // Force our element to be at the location we specified (don't try to auto position it)
                                force:      false,
                                
                                // The element that we will make sure our element doesn't go outside of
                                container:  window,

                                // Should the element be hidden after positioning?
                                hideAfterPosition: false
                            }, args);

        if ( args.x != null ) {
            var tLeft   = args.x;
            var tTop    = args.y;
            var tWidth  = 0;
            var tHeight = 0;
            
        // Position in relation to an element
        } else {
            var $target = $( $( args.target )[0] );
            var tWidth  = $target.outerWidth();
            var tHeight = $target.outerHeight();
            var tOffset = $target.offset();
            var tLeft   = tOffset.left;
            var tTop    = tOffset.top;
        }

        // Our target right, bottom coord
        var tRight  = tLeft + tWidth;
        var tBottom = tTop + tHeight;

        return this.each(function() {
            var $element = $( this );

            // Position our element in the top left so we can grab its width without triggering scrollbars
            if ( !$element.is(':visible') ) {
                $element.css({  left:       -3000, 
                                top:        -3000
                                })
                                .show();
            }

            var eWidth  = $element.outerWidth();
            var eHeight = $element.outerHeight();
    
            // Holds x1,y1,x2,y2 coordinates for a position in relation to our target element
            var position = [];
            // Holds a list of alternate positions to try if this one is not in the browser viewport
            var next     = [];
    
            // Our Positions via ASCII ART
            /*
             8   9       10   11
               +------------+
             7 | 15      12 | 0
               |            |
             6 | 14      13 | 1
               +------------+ 
             5   4        3   2
    
             */

            position[0] = new Range(tRight,             tTop,               tRight + eWidth,    tTop + eHeight);
            next[0]     = [1,7,4];
        
            position[1] = new Range(tRight,             tBottom - eHeight,  tRight + eWidth,    tBottom);
            next[1]     = [0,6,4];
        
            position[2] = new Range(tRight,             tBottom,            tRight + eWidth,    tBottom + eHeight);
            next[2]     = [1,3,10];
        
            position[3] = new Range(tRight - eWidth,    tBottom,            tRight,             tBottom + eHeight);
            next[3]     = [1,6,10];
            
            position[4] = new Range(tLeft,              tBottom,            tLeft + eWidth,     tBottom + eHeight);
            next[4]     = [1,6,9];
        
            position[5] = new Range(tLeft - eWidth,     tBottom,            tLeft,              tBottom + eHeight);
            next[5]     = [6,4,9];
        
            position[6] = new Range(tLeft - eWidth,     tBottom - eHeight,  tLeft,              tBottom);
            next[6]     = [7,1,4];
            
            position[7] = new Range(tLeft - eWidth,     tTop,               tLeft,              tTop + eHeight);
            next[7]     = [6,0,4];
            
            position[8] = new Range(tLeft - eWidth,     tTop - eHeight,     tLeft,              tTop);
            next[8]     = [7,9,4];
            
            position[9] = new Range(tLeft,              tTop - eHeight,     tLeft + eWidth,     tTop);
            next[9]     = [0,7,4];
            
            position[10]= new Range(tRight - eWidth,    tTop - eHeight,     tRight,             tTop);
            next[10]    = [0,7,3];
        
            position[11]= new Range(tRight,             tTop - eHeight,     tRight + eWidth,    tTop);
            next[11]    = [0,10,3];
            
            position[12]= new Range(tRight - eWidth,    tTop,               tRight,             tTop + eHeight);
            next[12]    = [13,7,10];
            
            position[13]= new Range(tRight - eWidth,    tBottom - eHeight,  tRight,             tBottom);
            next[13]    = [12,6,3];
            
            position[14]= new Range(tLeft,              tBottom - eHeight,  tLeft + eWidth,     tBottom);
            next[14]    = [15,1,4];
            
            position[15]= new Range(tLeft,              tTop,               tLeft + eWidth,     tTop + eHeight);
            next[15]    = [14,0,9];
    
            if ( args.positions !== null ) {
                var pos = args.positions[0];
            } else if ( args.targetPos != null && args.elementPos != null ) {
                var pos = [];
                pos[0] = [];
                pos[0][0] = 15;
                pos[0][1] = 7;
                pos[0][2] = 8;
                pos[0][3] = 9;
                pos[1] = [];
                pos[1][0] = 0;
                pos[1][1] = 12;
                pos[1][2] = 10;
                pos[1][3] = 11;
                pos[2] = [];
                pos[2][0] = 2;
                pos[2][1] = 3;
                pos[2][2] = 13;
                pos[2][3] = 1;
                pos[3] = [];
                pos[3][0] = 4;
                pos[3][1] = 5;
                pos[3][2] = 6;
                pos[3][3] = 14;

                var pos = pos[args.targetPos][args.elementPos];
            }
            var ePos = position[pos];
            var fPos = pos;

            if ( !args.force ) {
                // TODO: Do the args.container
                // window width & scroll offset
                $window = $( window );
                var sx = $window.scrollLeft();
                var sy = $window.scrollTop();
                
                // TODO: Look at innerWidth & innerHeight
                var container = new Range( sx, sy, sx + $window.width(), sy + $window.height() );
    
                // If we are outside of our viewport, see if we are outside vertically or horizontally and push onto the stack
                var stack;
                if ( args.positions ) {
                    stack = args.positions;
                } else {
                    stack = [pos];
                }
                var test = [];      // Keeps track of our positions we already tried
                
                while ( stack.length > 0 ) {
                    var p = stack.shift();
                    if ( test[p] ) {
                        continue;
                    }
                    test[p] = true;
    
                    // If our current position is not within the viewport (eg. window) 
                    // add the next suggested position
                    if ( !container.contains(position[p]) ) {
                        if ( args.positions === null ) {
                            stack = jQuery.merge( stack, next[p] );
                        }
                    } else {
                        ePos = position[p];
                        break;
                    }
                }
            }

            // + TODO: Determine if we are going to use absolute left, top, bottom, right 
            // positions relative to our target
        
            // Take into account any absolute or fixed positioning
            // to 'normalize' our coordinates
            $element.parents().each(function() {
                var $this = $(this);
                if ( $this.css('position') != 'static' ) {
                    var abs = $this.offset();
                    ePos = ePos.transform( -abs.left, -abs.top );
                    return false;
                }
            });
        
            // Finally position our element
            var css = { left: ePos.x1, top: ePos.y1 };
            if ( args.hideAfterPosition ) {
                css['display'] = 'none';
            }
            $element.css( css );

            if ( args.addClass ) {
                $element.removeClass( 'positionBy0 positionBy1 positionBy2 positionBy3 positionBy4 positionBy5 '
                                    + 'positionBy6 positionBy7 positionBy8 positionBy9 positionBy10 positionBy11 '
                                    + 'positionBy12 positionBy13 positionBy14 positionBy15')
                        .addClass('positionBy' + p);
            }
        });
    };
})(jQuery);
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate$
 * $Rev$
 *
 * Version 2.1.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE6 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 *      by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 *      is used here, pixels will be assumed. Otherwise, be sure
 *      to specify a unit. An expression could also be used. 
 *      By default the value is "auto" which will use an expression 
 *      to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 *      by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 *      is used here, pixels will be assumed. Otherwise, be sure
 *      to specify a unit. An expression could also be used. 
 *      By default the value is "auto" which will use an expression 
 *      to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *      a number is used here, pixels will be assume. Otherwise, be sure
 *      to specify a unit. An experssion could also be used.
 *      By default the value is "auto" which will use an experssion
 *      to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *      a number is used here, pixels will be assume. Otherwise, be sure
 *      to specify a unit. An experssion could also be used.
 *      By default the value is "auto" which will use an experssion
 *      to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 *      to use opacity. If set to true, the opacity of 0 is applied. If
 *      set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *      the src of the iframe to whatever they need.
 *      Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
    // This is only for IE6
    if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
        s = $.extend({
            top     : 'auto', // auto == .currentStyle.borderTopWidth
            left    : 'auto', // auto == .currentStyle.borderLeftWidth
            width   : 'auto', // auto == offsetWidth
            height  : 'auto', // auto == offsetHeight
            opacity : true,
            src     : 'javascript:false;'
        }, s || {});
        var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
            html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
                       'style="display:block;position:absolute;z-index:-1;'+
                           (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
                           'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
                           'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
                           'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
                           'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
                    '"/>';
        return this.each(function() {
            if ( $('> iframe.bgiframe', this).length == 0 )
                this.insertBefore( document.createElement(html), this.firstChild );
        });
    }
    return this;
};

})(jQuery);
/*
 * jdMenu 1.4.1 (2008-03-31)
 *
 * Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://jdsharp.us/
 *
 * Built upon jQuery 1.2.1 (http://jquery.com)
 * This also requires the jQuery dimensions >= 1.2 plugin
 */

// This initializes the menu
$(function() {
    $('ul.jd_menu').jdMenu();
});

(function($){
    function addEvents(ul) {
        var settings = $.data( $(ul).parents().andSelf().filter('ul.jd_menu')[0], 'jdMenuSettings' );
        $('> li', ul)
            .bind('mouseenter.jdmenu mouseleave.jdmenu', function(evt) {
                $(this).toggleClass('jdm_hover');
                var ul = $('> ul', this);
                if ( ul.length == 1 ) {
                    clearTimeout( this.$jdTimer );
                    var enter = ( evt.type == 'mouseenter' );
                    var fn = ( enter ? showMenu : hideMenu );
                    this.$jdTimer = setTimeout(function() {
                        fn( ul[0], settings.onAnimate, settings.isVertical );
                    }, enter ? settings.showDelay : settings.hideDelay );
                }
            })
            .bind('click.jdmenu', function(evt) {
                var ul = $('> ul', this);
                if ( ul.length == 1 && 
                    ( settings.disableLinks == true || $(this).hasClass('accessible') ) ) {
                    showMenu( ul, settings.onAnimate, settings.isVertical );
                    return false;
                }
                
                // The user clicked the li and we need to trigger a click for the a
                if ( evt.target == this ) {
                    var link = $('> a', evt.target).not('.accessible');
                    if ( link.length > 0 ) {
                        var a = link[0];
                        if ( !a.onclick ) {
                            window.open( a.href, a.target || '_self' );
                        } else {
                            $(a).trigger('click');
                        }
                    }
                }
                if ( settings.disableLinks || 
                    ( !settings.disableLinks && !$(this).parent().hasClass('jd_menu') ) ) {
                    $(this).parent().jdMenuHide();
                    evt.stopPropagation();
                }
            })
            .find('> a')
                .bind('focus.jdmenu blur.jdmenu', function(evt) {
                    var p = $(this).parents('li:eq(0)');
                    if ( evt.type == 'focus' ) {
                        p.addClass('jdm_hover');
                    } else { 
                        p.removeClass('jdm_hover');
                    }
                })
                .filter('.accessible')
                    .bind('click.jdmenu', function(evt) {
                        evt.preventDefault();
                    });
    }

    function showMenu(ul, animate, vertical) {
        var ul = $(ul);
        if ( ul.is(':visible') ) {
            return;
        }
        ul.bgiframe();
        var li = ul.parent();
        ul  .trigger('jdMenuShow')
            .positionBy({   target:     li[0], 
                            targetPos:  ( vertical === true || !li.parent().hasClass('jd_menu') ? 1 : 3 ), 
                            elementPos: 0,
                            hideAfterPosition: true
                            });
        if ( !ul.hasClass('jdm_events') ) {
            ul.addClass('jdm_events');
            addEvents(ul);
        }
        li  .addClass('jdm_active')
            // Hide any adjacent menus
            .siblings('li').find('> ul:eq(0):visible')
                .each(function(){
                    hideMenu( this ); 
                });
        if ( animate === undefined ) {
            ul.show();
        } else {
            animate.apply( ul[0], [true] );
        }
    }
    
    function hideMenu(ul, animate) {
        var ul = $(ul);
        $('.bgiframe', ul).remove();
        ul  .filter(':not(.jd_menu)')
            .find('> li > ul:eq(0):visible')
                .each(function() {
                    hideMenu( this );
                })
            .end();
        if ( animate === undefined ) {
            ul.hide()
        } else {
            animate.apply( ul[0], [false] );
        }

        ul  .trigger('jdMenuHide')
            .parents('li:eq(0)')
                .removeClass('jdm_active jdm_hover')
            .end()
                .find('> li')
                .removeClass('jdm_active jdm_hover');
    }
    
    // Public methods
    $.fn.jdMenu = function(settings) {
        // Future settings: activateDelay
        var settings = $.extend({   // Time in ms before menu shows
                                    showDelay:      200,
                                    // Time in ms before menu hides
                                    hideDelay:      500,
                                    // Should items that contain submenus not 
                                    // respond to clicks
                                    disableLinks:   false
                                    // This callback allows for you to animate menus
                                    //onAnimate:    null
                                    }, settings);
        if ( !$.isFunction( settings.onAnimate ) ) {
            settings.onAnimate = undefined;
        }
        return this.filter('ul.jd_menu').each(function() {
            $.data( this, 
                    'jdMenuSettings', 
                    $.extend({ isVertical: $(this).hasClass('jd_menu_vertical') }, settings) 
                    );
            addEvents(this);
        });
    };
    
    $.fn.jdMenuUnbind = function() {
        $('ul.jdm_events', this)
            .unbind('.jdmenu')
            .find('> a').unbind('.jdmenu');
    };
    $.fn.jdMenuHide = function() {
        return this.filter('ul').each(function(){ 
            hideMenu( this );
        });
    };

    // Private methods and logic
    $(window)
        // Bind a click event to hide all visible menus when the document is clicked
        .bind('click.jdmenu', function(){
            $('ul.jd_menu ul:visible').jdMenuHide();
        });
})(jQuery);
