﻿/* jQuery Hoverintent script */
/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
* 
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* hoverIntent is currently available for use in all personal or commercial 
* projects under both MIT and GPL licenses. This means that you can choose 
* the license that best suits your project, and use it accordingly.
* 
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
* 
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
*    sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
*    interval: 100,   // number = milliseconds of polling interval
*    over: showNav,  // function = onMouseOver callback (required)
*    timeout: 0,   // number = milliseconds delay before onMouseOut function call
*    out: hideNav    // function = onMouseOut callback (required)
* });
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($) {
    $.fn.hoverIntent = function(f,g) {
        // default configuration options
        var cfg = {
            sensitivity: 7,
            interval: 100,
            timeout: 0
        };
        // override configuration options with user supplied object
        cfg = $.extend(cfg, g ? { over: f, out: g } : f );
        // instantiate variables
        // cX, cY = current X and Y position of mouse, updated by mousemove event
        // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
        var cX, cY, pX, pY;
        // A private function for getting mouse position
        var track = function(ev) {
            cX = ev.pageX;
            cY = ev.pageY;
        };
        // A private function for comparing current and previous mouse position
        var compare = function(ev,ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            // compare mouse positions to see if they've crossed the threshold
            if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
                $(ob).unbind("mousemove",track);
                // set hoverIntent state to true (so mouseOut can be called)
                ob.hoverIntent_s = 1;
                return cfg.over.apply(ob,[ev]);
            } else {
                // set previous coordinates for next time
                pX = cX; pY = cY;
                // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
                ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
            }
        };
        // A private function for delaying the mouseOut function
        var delay = function(ev,ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            ob.hoverIntent_s = 0;
            return cfg.out.apply(ob,[ev]);
        };
        // A private function for handling mouse 'hovering'
        var handleHover = function(e) {
            // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
            var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
            while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
            if ( p == this ) { return false; }
            // copy objects to be passed into t (required for event object to be passed in IE)
            var ev = jQuery.extend({},e);
            var ob = this;
            // cancel hoverIntent timer if it exists
            if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
            // else e.type == "onmouseover"
            if (e.type == "mouseover") {
                // set "previous" X and Y position based on initial entry point
                pX = ev.pageX; pY = ev.pageY;
                // update "current" X and Y position based on mousemove
                $(ob).bind("mousemove",track);
                // start polling interval (self-calling timeout) to compare mouse coordinates over time
                if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
            // else e.type == "onmouseout"
            } else {
                // unbind expensive mousemove event
                $(ob).unbind("mousemove",track);
                // if hoverIntent state is true, then call the mouseOut function after the specified delay
                if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
            }
        };
        // bind the function to the two event listeners
        return this.mouseover(handleHover).mouseout(handleHover);
    };
})(jQuery);


/* jQuery Mega Menu v1.02
* Last updated: June 29th, 2009. This notice must stay intact for usage 
* Author: JavaScript Kit at http://www.javascriptkit.com/
* Visit http://www.javascriptkit.com/script/script2/jScale/ for full source code
* 
* Modifications for Pershing.com and Hoverintent integration by DH, Dec 2009
*/
//jQuery.noConflict();
var jkmegamenu={
effectduration: 100, //duration of animation, in milliseconds
delaytimer: 100, //delay after mouseout before menu should be hidden, in milliseconds
megamenulabels: [],
megamenus: [], //array to contain each block menu instances
zIndexVal: 1000, //starting z-index value for drop down menu
$shimobj: null,
addshim:function($){
    $(document.body).append('<IFRAME id="outlineiframeshim" src="'+(location.protocol=="https:"? 'blank.htm' : 'about:blank')+'" style="display:none; left:0; top:0; z-index:999; position:absolute; filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)" frameBorder="0" scrolling="no"></IFRAME>')
    this.$shimobj=$("#outlineiframeshim")
},
alignmenu:function($, e, megamenu_pos){
    var megamenu=this.megamenus[megamenu_pos]
    var $anchor=megamenu.$anchorobj
    var $menu=megamenu.$menuobj
    var menuleft=($(window).width()-(megamenu.offsetx-$(document).scrollLeft())>megamenu.actualwidth)? megamenu.offsetx : megamenu.offsetx-megamenu.actualwidth+megamenu.anchorwidth //get x coord of menu
    //var menutop=($(window).height()-(megamenu.offsety-$(document).scrollTop()+megamenu.anchorheight)>megamenu.actualheight)? megamenu.offsety+megamenu.anchorheight : megamenu.offsety-megamenu.actualheight
    var menutop=megamenu.offsety+megamenu.anchorheight  //get y coord of menu
    $menu.css({left:menuleft+"px", top:menutop+"px"})
    this.$shimobj.css({width:megamenu.actualwidth+"px", height:megamenu.actualheight+"px", left:menuleft+"px", top:menutop+"px", display:"block"})
},
showmenu:function(e, megamenu_pos){
    var megamenu=this.megamenus[megamenu_pos]
    var $menu=megamenu.$menuobj
    var $menuinner=megamenu.$menuinner
    if ($menu.css("display")=="none"){
        this.alignmenu(jQuery, e, megamenu_pos)
        $menu.css("z-index", ++this.zIndexVal)
        //$menu.show(this.effectduration, function(){
        //original uses 'show' which scales and fades, we changed to 'fadein' which affects only opacity -DH
        $menu.fadeIn(this.effectduration, function(){
        $menuinner.css('visibility', 'visible')
        }
        )
    }
    else if ($menu.css("display")=="block" && e.type=="click"){ //if menu is hidden and this is a "click" event (versus "mouseout")
        this.hidemenu(e, megamenu_pos)
    }
    return false
},
hidemenu:function(e, megamenu_pos){
    var megamenu=this.megamenus[megamenu_pos]
    var $menu=megamenu.$menuobj
    var $menuinner=megamenu.$menuinner
    $menuinner.css('visibility', 'hidden')
    this.$shimobj.css({display:"none", left:0, top:0})
    //$menu.hide(this.effectduration)
    //original uses 'hide' which scales and fades, we changed to 'fadeout' which affects only opacity -DH
      $menu.fadeOut(this.effectduration)
},
definemenu:function(anchorid, menuid, revealtype){
    this.megamenulabels.push([anchorid, menuid, revealtype])
},
render:function($){
    for (var i=0, labels=this.megamenulabels[i]; i<this.megamenulabels.length; i++, labels=this.megamenulabels[i]){
        if ($('#'+labels[0]).length!=1 || $('#'+labels[1]).length!=1) //if one of the two elements are NOT defined, exist
            return
        this.megamenus.push({$anchorobj:$("#"+labels[0]), $menuobj:$("#"+labels[1]), $menuinner:$("#"+labels[1]).children('ul:first-child'), revealtype:labels[2], hidetimer:null})
        var megamenu=this.megamenus[i]    
        megamenu.$anchorobj.add(megamenu.$menuobj).attr("_megamenupos", i+"pos") //remember index of this drop down menu
        megamenu.actualwidth=megamenu.$menuobj.outerWidth()
        megamenu.actualheight=megamenu.$menuobj.outerHeight()
        megamenu.offsetx=megamenu.$anchorobj.offset().left
        megamenu.offsety=megamenu.$anchorobj.offset().top
        megamenu.anchorwidth=megamenu.$anchorobj.outerWidth()
        megamenu.anchorheight=megamenu.$anchorobj.outerHeight()
        $(document.body).append(megamenu.$menuobj) //move drop down menu to end of document
        megamenu.$menuobj.css("z-index", ++this.zIndexVal).hide()
        megamenu.$menuinner.css("visibility", "hidden")
        
        
        
        
//    original code:
//
//        megamenu.$anchorobj.bind(megamenu.revealtype=="click"? "click" : "mouseenter", function(e){
//            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
//            clearTimeout(menuinfo.hidetimer) //cancel hide menu timer
                    
//            return jkmegamenu.showmenu(e, parseInt(this.getAttribute("_megamenupos")))
//        })
    
        
// original mouseleave code:
//
//        megamenu.$anchorobj.bind("mouseleave", function(e){
//            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
//            if (e.relatedTarget!=menuinfo.$menuobj.get(0) && $(e.relatedTarget).parents("#"+menuinfo.$menuobj.get(0).id).length==0){ //check that mouse hasn't moved into menu object
//                menuinfo.hidetimer=setTimeout(function(){ //add delay before hiding menu
//                    jkmegamenu.hidemenu(e, parseInt(menuinfo.$menuobj.get(0).getAttribute("_megamenupos")))
//                }, jkmegamenu.delaytimer)
//            }
            
//        })
        
        /* Explanation of Modifications:
           
           To incorporate the use of Brian Cherne's Hoverintent functionality, I removed the 'bind' to mouse event code chunks and liberated the show and hide pieces into standalone functions called by the configuration variable of the hoverintent call. The mouse enter and leave events are then handled by hoverintent. -DH
        
        */
        
        function expand(e){
            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
            clearTimeout(menuinfo.hidetimer) //cancel hide menu timer
            
            /* on mouse ON of ANCHOR -DH */
        
            return jkmegamenu.showmenu(e, parseInt(this.getAttribute("_megamenupos")))
        }
        
            
        function contract(e){
            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
            if (e.relatedTarget!=menuinfo.$menuobj.get(0) && $(e.relatedTarget).parents("#"+menuinfo.$menuobj.get(0).id).length==0){ //check that mouse hasn't moved into menu object
                menuinfo.hidetimer=setTimeout(function(){ //add delay before hiding menu
                    jkmegamenu.hidemenu(e, parseInt(menuinfo.$menuobj.get(0).getAttribute("_megamenupos")))
                }, jkmegamenu.delaytimer)
            }            
            /* on mouse OUT of ANCHOR -DH */
        }
        var config = {    
            sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)    
            interval: 100, // number = milliseconds for onMouseOver polling interval    
            over: expand, // function = onMouseOver callback (REQUIRED)    
            timeout: 100, // number = milliseconds delay before onMouseOut    
            out: contract // function = onMouseOut callback (REQUIRED)    
        };
        /* IMPORTANT: this initializes the use of hoverintent */
        $(megamenu.$anchorobj).hoverIntent(config)
// end of hoverintent integration
            
        megamenu.$menuobj.bind("mouseenter", function(e){
            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
            clearTimeout(menuinfo.hidetimer) //cancel hide menu timer
                    
            /* on mouse ENTER of menu -DH */
            var $currentId = $(this).attr('id')
            var $targetId = ($currentId + '-link')
            //testing: alert ("the element id is: " + $currentId + " and the target id is: " + $targetId)
            $("a#"+$targetId).addClass('active-item')
        })
        
        
        megamenu.$menuobj.bind("click mouseleave", function(e){
            var menuinfo=jkmegamenu.megamenus[parseInt(this.getAttribute("_megamenupos"))]
            menuinfo.hidetimer=setTimeout(function(){ //add delay before hiding menu
                jkmegamenu.hidemenu(e, parseInt(menuinfo.$menuobj.get(0).getAttribute("_megamenupos")))
            }, jkmegamenu.delaytimer)
                
            /* on mouse EXIT of menu -DH */
            //$('a').removeClass('active-item')
            function cleanup() { $('a').removeClass('active-item'); }
            setTimeout(cleanup,200)
        })
        
        
    } //end for loop
    
    
    if(/Safari/i.test(navigator.userAgent)){ //if Safari
        $(window).bind("resize load", function(){
            for (var i=0; i<jkmegamenu.megamenus.length; i++){
                var megamenu=jkmegamenu.megamenus[i]
                var $anchorisimg=(megamenu.$anchorobj.children().length==1 && megamenu.$anchorobj.children().eq(0).is('img'))? megamenu.$anchorobj.children().eq(0) : null
                if ($anchorisimg){ //if anchor is an image link, get offsets and dimensions of image itself, instead of parent A
                    megamenu.offsetx=$anchorisimg.offset().left
                    megamenu.offsety=$anchorisimg.offset().top
                    megamenu.anchorwidth=$anchorisimg.width()
                    megamenu.anchorheight=$anchorisimg.height()
                }
            }
        })
    }
    else{
        $(window).bind("resize", function(){
            for (var i=0; i<jkmegamenu.megamenus.length; i++){
                var megamenu=jkmegamenu.megamenus[i]    
                megamenu.offsetx=megamenu.$anchorobj.offset().left
                megamenu.offsety=megamenu.$anchorobj.offset().top
            }
        })
    }
    jkmegamenu.addshim($)
}
}
jQuery(document).ready(function($){
    jkmegamenu.render($)
    
})