Skip to content

Instantly share code, notes, and snippets.

@frugan-dev
Created December 17, 2017 10:05
Show Gist options
  • Save frugan-dev/fd3021f9f81a0e89fca82fc5a819f886 to your computer and use it in GitHub Desktop.
Save frugan-dev/fd3021f9f81a0e89fca82fc5a819f886 to your computer and use it in GitHub Desktop.

Revisions

  1. @ewake ewake created this gist Dec 17, 2017.
    134 changes: 134 additions & 0 deletions bootstrap-hover-dropdown.custom.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    /**
    * @preserve
    * Project: Bootstrap Hover Dropdown
    * Author: Cameron Spear
    * Version: v2.2.1
    * Contributors: Mattia Larentis
    * Dependencies: Bootstrap's Dropdown plugin, jQuery
    * Description: A simple plugin to enable Bootstrap dropdowns to active on hover and provide a nice user experience.
    * License: MIT
    * Homepage: http://cameronspear.com/blog/bootstrap-dropdown-on-hover-plugin/
    */
    ;(function ($, window, undefined) {
    // outside the scope of the jQuery plugin to
    // keep track of all dropdowns
    var $allDropdowns = $();

    // if instantlyCloseOthers is true, then it will instantly
    // shut other nav items when a new one is hovered over
    $.fn.dropdownHover = function (options) {
    // don't do anything if touch is supported
    // (plugin causes some issues on mobile)
    //----------------------------------- start add
    //if('ontouchstart' in document) return this; // don't want to affect chaining
    //----------------------------------- end add

    // the element we really care about
    // is the dropdown-toggle's parent
    $allDropdowns = $allDropdowns.add(this.parent());

    return this.each(function () {
    var $this = $(this),
    $parent = $this.parent(),
    defaults = {
    delay: 500,
    hoverDelay: 0,
    instantlyCloseOthers: true
    },
    data = {
    delay: $(this).data('delay'),
    hoverDelay: $(this).data('hover-delay'),
    instantlyCloseOthers: $(this).data('close-others')
    },
    showEvent = 'show.bs.dropdown',
    hideEvent = 'hide.bs.dropdown',
    // shownEvent = 'shown.bs.dropdown',
    // hiddenEvent = 'hidden.bs.dropdown',
    settings = $.extend(true, {}, defaults, options, data),
    timeout, timeoutHover;

    $parent.hover(function (event) {
    // so a neighbor can't open the dropdown
    if(!$parent.hasClass('open') && !$this.is(event.target)) {
    // stop this event, stop executing any code
    // in this callback but continue to propagate
    return true;
    }

    openDropdown(event);
    }, function () {
    // clear timer for hover event
    window.clearTimeout(timeoutHover)
    timeout = window.setTimeout(function () {
    $this.attr('aria-expanded', 'false');
    $parent.removeClass('open');
    $this.trigger(hideEvent);
    }, settings.delay);
    });

    // this helps with button groups!
    $this.hover(function (event) {
    // this helps prevent a double event from firing.
    // see https://github.com/CWSpear/bootstrap-hover-dropdown/issues/55
    if(!$parent.hasClass('open') && !$parent.is(event.target)) {
    // stop this event, stop executing any code
    // in this callback but continue to propagate
    return true;
    }

    openDropdown(event);
    });

    // handle submenus
    $parent.find('.dropdown-submenu').each(function (){
    var $this = $(this);
    var subTimeout;
    $this.hover(function () {
    window.clearTimeout(subTimeout);
    $this.children('.dropdown-menu').show();
    // always close submenu siblings instantly
    $this.siblings().children('.dropdown-menu').hide();
    }, function () {
    var $submenu = $this.children('.dropdown-menu');
    subTimeout = window.setTimeout(function () {
    $submenu.hide();
    }, settings.delay);
    });
    });

    function openDropdown(event) {
    //----------------------------------- start add
    /*if($this.parents(".navbar").find(".navbar-toggle").is(":visible")) {
    // If we're inside a navbar, don't do anything when the
    // navbar is collapsed, as it makes the navbar pretty unusable.
    return;
    }*/
    //----------------------------------- end add

    // clear dropdown timeout here so it doesnt close before it should
    window.clearTimeout(timeout);
    // restart hover timer
    window.clearTimeout(timeoutHover);

    // delay for hover event.
    timeoutHover = window.setTimeout(function () {
    $allDropdowns.find(':focus').blur();

    if(settings.instantlyCloseOthers === true)
    $allDropdowns.removeClass('open');

    // clear timer for hover event
    window.clearTimeout(timeoutHover);
    $this.attr('aria-expanded', 'true');
    $parent.addClass('open');
    $this.trigger(showEvent);
    }, settings.hoverDelay);
    }
    });
    };

    $(document).ready(function () {
    // apply dropdownHover to all elements with the data-hover="dropdown" attribute
    $('[data-hover="dropdown"]').dropdownHover();
    });
    })(jQuery, window);