﻿/*
 * HoverMenu - jQuery plugin for context menus on hover.
 *
 * Author: Jeff Dietrich, Shaun Humphries
 * Contributors: Chris Domigan, Dan G. Switzer, II (jquery.contextmenu - http://www.trendskitchens.co.nz/jquery/contextmenu/)
 * Parts of this plugin are borrowed from Chris Domigan's ContextMenu plugin, which is in turn inspired by
 * Joern Zaefferer's Tooltip plugin.
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Version: 0.1
 * Date: 17 April 2009
 *
 */
 
(function($) {

    var menu;
    // MSIE 6 detection requires extra crapness due to http://dev.jquery.com/ticket/3169:
    var isCrapBrowser = $.browser.msie && /MSIE 6\.0/i.test(window.navigator.userAgent) && !/MSIE 7\.0/i.test(window.navigator.userAgent);
    var isOverMenu = false;
    var isOverControl = false;
    var trigger, currentTarget, shadow;
    // private vars / defaults
    var defaults = {
        contentId: "contextMenuContentDiv",
        itemNormalStyle: {
            border: '1px solid #fff',
            backgroundColor: 'transparent',
            cursor: 'default'
        },
        itemHoverStyle: {
            border: '1px solid #0a246a',
            backgroundColor: '#b6bdd2',
            cursor: 'pointer'
        },
        eventPosX: 'pageX',
        eventPosY: 'pageY',
        bindings: {},
        onShow: null,
        onHide: null,
        shadow: true
    };
    var opts = null;

    // actual plugin method
    var hm =
        $.hovermenu = function(selector, options) {
            opts = $.extend({}, defaults, options);
            if (!menu) {                                      // Create singleton menu
                //console.log("** creating singleton menu");
                menu = $('<div id="jqHoverMenu"></div>')
                   .hide()
                   .css({ position: 'absolute', zIndex: '500' })
                   .appendTo('body')
                   .hoverIntent({ 
                        sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)    
                        interval: 0, // number = milliseconds for onMouseOver polling interval  
                        timeout: 500, // number = milliseconds delay before onMouseOut 
                        over: function(e) {
                               //console.log("Menu in" + dbgState());
                               isOverMenu = true;
                               //console.log("  set isOverMenu true");
                            },
                        out: function(e) {
                               //console.log("Menu out" + dbgState());
                               isOverMenu = false;
                               //console.log("  set isOverMenu false");
                               if (!isOverControl) {
                                   //console.log("  hiding (because not overControl)");
                                   hide();
                               }
                            } 
                    });

                content = $('#' + opts.contentId).find('ul:first').clone(true);
                content.find('img').css({ verticalAlign: 'middle', paddingRight: '2px' });

                menu.html(content);
                // attach bindings
                $.each(opts.bindings, function(id, func) {
                    $('li#' + id, menu).bind('click', function(e) {
                        hide();
                        func(trigger, currentTarget);
                    });
                    if (isCrapBrowser) {
                        //alert("Attach crap hover handling");
                        //$('li#' + id, menu).css(itemHoverStyle);
                        $('li#' + id, menu).hover(function(e) {
                            $(this).css(opts.itemHoverStyle);
                        },
                        function(e) {
                            $(this).css(opts.itemNormalStyle);
                        });
                    };
                });

                if (opts.shadow) menu.append('<div class="shadow"></div>');

            };

            //console.log("* hovermenu main body (non singleton)");

            $(selector).hoverIntent({ 
                sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)    
                interval: 100, // number = milliseconds for onMouseOver polling interval  
                timeout: 500, // number = milliseconds delay before onMouseOut 
                over: function(e) {
                        //console.log("control mouseover: " + dbgState());
                        isOverControl = true;
                        //console.log("  set isOverControl true");
                        //console.log("     -- showing menu -- ");
                        trigger = this;
                        if(opts.onShow != null) opts.onShow(e);
                        menu.css({ 'left': e[opts.eventPosX], 'top': e[opts.eventPosY] }).show();
                    },
                out: function(e) {
                        //console.log("control mouseout: " + dbgState());
                        isOverControl = false;
                        //console.log("  set isOverControl false");
                        if (!isOverMenu) {
                            //console.log("  hiding (because not overMenu)");
                            hide();
                        }
                    } 
            });
        };

    hm.debugShow = function() {
        menu.css({ 'left': 0, 'top': 0 }).unbind('mouseenter mouseleave').show();
    }

    function hide() {
        isOverMenu = false;
        isOverControl = false;
        //console.log("Hiding: " + dbgState());
        if(opts.onHide != null) opts.onHide();
        menu.hide();
    }

    function dbgState() {
        return "[isOverMenu:" + isOverMenu + "] [isOverControl:" + isOverControl + "]";
    }

})(jQuery);