/*
 * jQuery Dropdown plugin v1.0
 * File Date: 9/24/2009
 *
 * Copyright (c) 2009 Jim Salyer
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 */
 
jQuery.fn.extend({
  dropdown: function(locals)
  {
    // create the global properties off of defaults and the provided parameters
    var globals = {
      animation: null,    // animation properties (e.g. { opacity: 1 })
      easing: "swing",    // easing for animation (linear and swing built in, plugin required for others)
      hideDelay: 500,     // delay before hiding menus (in milliseconds)
      load: function(){}, // function to run after menu has loaded
      showDelay: 0,       // delay before showing menus (in milliseconds)
      speed: "normal"     // speed of the animation (slow, normal, fast or a number of milliseconds)
    };
    jQuery.extend(globals, locals);
    
    // loop through the given elements and keep the jQuery chain alive
    return jQuery(this).each(function()
    {
      // set up the current system and initialize its timers
      var dd = jQuery(this);
      if (dd.data("dropdown_showTimer")) return true; // don't set up a system twice
      dd.data("dropdown_showTimer", null);
      dd.data("dropdown_hideTimer", null);
      
      // create the mouseout functionality for the menus
      dd.add(jQuery("ul ul", dd).hide()).mouseout(function(event)
      {
        // make sure the timer's are cleared out and get a reference to the current menu
        clearTimeout(dd.data("dropdown_showTimer"));
        clearTimeout(dd.data("dropdown_hideTimer"));
        var el = jQuery(this);
        
        // start the hide timer
        dd.data("dropdown_hideTimer", setTimeout(function()
        {
          // make sure the timers are cleared and get a reference to the current menu system
          clearTimeout(dd.data("dropdown_showTimer"));
          clearTimeout(dd.data("dropdown_hideTimer"));
          if (el.get(0) != dd.get(0)) el = el.parents("ul.dropdown");
          
          // for every item that shows a menu, unhighlight it and hide the menu it opens
          jQuery("li:has(ul)", el).find("a:first").andSelf().removeClass("dropdown-hover").end().end().find("> ul").hide().css("visibility", "hidden");
        }, globals.hideDelay));
      });
      
      // create the mouseover functionality for the menu items
      $("li", dd).addClass("dropdown-scripted").mouseover(function(event)
      {
        // make sure the timer's are cleared out and get a reference to the current item
        clearTimeout(dd.data("dropdown_showTimer"));
        clearTimeout(dd.data("dropdown_hideTimer"));
        var el = jQuery(this);
        
        // start the show timer
        dd.data("dropdown_showTimer", setTimeout(function()
        {
          // make sure the timers are cleared
          clearTimeout(dd.data("dropdown_showTimer"));
          clearTimeout(dd.data("dropdown_hideTimer"));
          
          // for every item in this item's menu and down (hierarchy), unhighlight the item and hide its menu (if applicable)
          el.siblings(":has(ul)").find("li.dropdown-hover").andSelf().find("a:first").andSelf().removeClass("dropdown-hover").end().end().find("> ul").hide().css("visibility", "hidden");
          
          // if this item shows a submenu, highlight the item and show its menu
          if (el.is(":has(ul)"))
          {
            var menu = jQuery("> ul", el);
            if (menu.css("visibility") == "hidden")
            {
              el.addClass("dropdown-hover").find("a:first").addClass("dropdown-hover");
              menu.css("visibility", "visible");
              
              // if an animation is defined, set up the initial values and run it
              if (globals.animation)
              {
                // get the default CSS properties corresponding to the animation
                var defaults = menu.data("dropdown_animation");
                if (!defaults)
                {
                  // if the default CSS properties haven't been compiled yet, do so now
                  defaults = {};
                  for (var prop in globals.animation)
                    defaults[prop] = menu.css(prop);
                  menu.data("dropdown_animation", defaults);
                }
                
                // run the animation
                menu.css(defaults).animate(globals.animation, {
                  duration: globals.speed,
                  easing: globals.easing,
                  queue: false
                });
              }
              else
                menu.show();
            }
          }
        }, globals.showDelay));
        event.stopPropagation(); // make sure the above functinality doesn't bubble upward
      });
      globals.load.call(dd); // run any post load actions for the current menu system
    });
  }
});
