Skip to content

Instantly share code, notes, and snippets.

@unruthless
Created August 2, 2010 15:35
Show Gist options
  • Save unruthless/504814 to your computer and use it in GitHub Desktop.
Save unruthless/504814 to your computer and use it in GitHub Desktop.
jQuery snippet to handle global navigation behavior
/*
* Global Navigation Behaviors
*
* @author Ruthie BenDor
* @updated 2-Aug-2010
*
* See in use on http://www.glad.org/styles/test
* How can I make this better?
*
*/
(function() {
var activeDropdown,
activeMenu,
activeMenuClass = 'droppeddown',
activeParent,
// Deactivates the current menu
deactivateMenu = function() {
if (activeDropdown) {
activeDropdown.removeClass(activeMenuClass);
activeMenu.hide();
}
},
activeExpander,
activeSubmenu,
activeSubmenuClass = 'expanded',
// Deactivates the current submenu
deactivateSubmenu = function() {
if (activeMenu) {
activeMenu.find('.expander').removeClass(activeSubmenuClass);
activeMenu.find('.submenu').hide();
}
},
// Deactivates menu and enclosed submenus when outside element is moused over
deactivateAll = function(e) {
if (typeof e !== 'object' || !activeParent) {
return;
}
var parentElement = activeParent[0];
if ( !$.contains(parentElement,e.target) || !parentElement == e.target ) {
deactivateSubmenu();
deactivateMenu();
// We don't need this function anymore, so unbind it.
$(document.body).unbind('mouseover', deactivateAll);
}
};
// Iterate through each dropdown
$('.dropdown').each(function() {
var dropdown = $(this),
menu = dropdown.next('.menu'),
parent = dropdown.parent(),
// Activates this dropdown's menu
activate = function() {
deactivateMenu();
activeDropdown = dropdown.addClass(activeMenuClass);
activeMenu = menu.show();
activeParent = parent;
// Deactivates menu when outside element is moused over
$(document.body).bind('mouseover', deactivateAll);
};
// Activate menu when mouseovered
dropdown.bind('mouseover',function(e) {
if (e) {
e.stopPropagation();
}
activate();
});
// Activate menu when focused
dropdown.bind('focus',function() {
activate();
});
});
// Iterate through each expander
$('.expander').each(function() {
var expander = $(this),
submenu = expander.next('.submenu'),
// Toggles this expander's submenu
toggle = function() {
activeExpander = expander.toggleClass(activeSubmenuClass);
activeSubmenu = submenu.slideToggle();
};
// Toggle submenu when clicked
expander.bind('click',function(e) {
if (e) {
e.stopPropagation();
e.preventDefault();
}
toggle();
});
});
})();
@kimili
Copy link

kimili commented Aug 2, 2010

Not so tricky. In that case, just bind it when you need it, and unbind it when you don't. Something like this:

(function() {

    var activeDropdown,
        activeMenu,
        activeMenuClass = 'droppeddown',
        activeParent,

        // Deactivates the current menu
        deactivateMenu = function() {
            if (activeDropdown) {
                activeDropdown.removeClass(activeMenuClass);
                activeMenu.hide();
            }
        },

        activeExpander,
        activeSubmenu,
        activeSubmenuClass = 'expanded',

        // Deactivates the current submenu
        deactivateSubmenu = function() {
            if (activeMenu) {
                activeMenu.find('.expander').removeClass(activeSubmenuClass);
                activeMenu.find('.submenu').hide();
            }
        },

        // Deactivates menu when outside element is moused over
        deactivateAll = function(e) {
            if (typeof e !== 'object' || !activeParent) {
                return;
            }
            var parentElement = activeParent[0];
            if ( !$.contains(parentElement,e.target) || !parentElement == e.target ) {
                deactivateSubmenu();
                deactivateMenu();
                // we don't need this function anymore. Unbind it.
                $(document.body).unbind('mouseover', deactivateAll);
            }
        };

    // Iterate through each dropdown
    $('.dropdown').each(function() {

        var dropdown  = $(this),
            menu      = dropdown.next('.menu'),
            parent    = dropdown.parent();

        // Activates this dropdown's menu
        var activate = function() {
            deactivateMenu();
            activeDropdown = dropdown.addClass(activeMenuClass);
            activeMenu = menu.show();
            activeParent = parent;
            // Deactivates menu when outside element is moused over
            $(document.body).bind('mouseover', deactivateAll);
        };

        // Activates menu when mouseovered
        dropdown.bind('mouseover',function(e) {
            if (e) {
                e.stopPropagation();
            }
            activate();
        });

        // Activates menu when focused
        dropdown.bind('focus',function() {
            activate();
        });

    });

    // Iterate through each expander
    $('.expander').each(function() {

        var expander  = $(this),
            submenu   = expander.next('.submenu');

        // Toggles this expander's submenu
        var toggle = function() {
          activeExpander = expander.toggleClass(activeSubmenuClass);
          activeSubmenu = submenu.slideToggle();
        }

        // Toggles submenu when clicked
        expander.bind('click',function(e) {
          if (e) {
              e.stopPropagation();
              e.preventDefault();
          }
          toggle();
        });
    });

})();

@unruthless
Copy link
Author

Michael, that's brilliant. Beers on me at the next Build Guild. Thank you so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment