Sheixt
Sheixt

Reputation: 2626

Bootstrap Collapse accordion on hover

I'm using Twitter's Bootstrap 'Collapse' plug-in in a project I am working on. I have a simple accordion (setup as per the documentation), but I want to amend the default functionality from on click to the on hover event.

How can I achieve this?

Upvotes: 11

Views: 25822

Answers (7)

john Smith
john Smith

Reputation: 17936

to put it to work for bootstrap3 i made some changes

$(function() {
    $(document).on('mouseenter.collapse', '[data-toggle=collapse]', function(e) {
        var $this = $(this),
            href, 
            target = $this.attr('data-target') 
                     || e.preventDefault() 
                     || (href = $this.attr('href')) 
                     && href.replace(/.*(?=#[^\s]+$)/, ''), //strip for ie7
            option = $(target).hasClass('in') ? 'hide' : "show"

            $('.panel-collapse').not(target).collapse("hide")
            $(target).collapse(option);
    })
});

Upvotes: 4

Vishal Srinivasan
Vishal Srinivasan

Reputation: 109

This is the simplest way to make that done on mouseover. Using plain javascript in angularJs.

Script

$scope.collapsePanel = function(variable) {
    if(document.getElementById(variable).className=="collapse in") {
        document.getElementById(variable).className="collapse";
        document.getElementById(variable).setAttribute("aria-expanded","false");
        } else {
            document.getElementById(variable).className="collapse in";  
            document.getElementById(variable).setAttribute("aria-expanded","true");
        }
}

HTML code

<div ng-repeat="entity in entities">
<div class="panel-heading" ng-mouseover="collapsePanel(entity)">
     //Give your contents here
</div> 
</div>

Note: change ng-mouseover with ng-click for making it work on click instead of mouseover

Upvotes: 0

Brian Dsouza
Brian Dsouza

Reputation: 49

  1. Add the following script

    $( ".hoverExpand" ).hover(
        function() {
            if (! $(this).hasClass('collapsing') && 
                $(this).hasClass('collapsed')) {
                    $( this ).click();
            }
        }, function() {
            if  (! $(this).hasClass('collapsing') || 
                 ! $(this).hasClass('collapsed')) {
                    $( this ).click();
            }
        }
    );
    
  2. Add hoverExpand (or whatever you want to call it) to the element. See example below

    <a class="hoverExpand" data-toggle="collapse" data-parent="#accordion" 
       href="#collapseOne">A plane that flies below water</a>
    

Upvotes: 4

Blade1336
Blade1336

Reputation: 71

Based on Cliff Seal's answer I suggest queueing animations to prevent panel-collapse from staying open when mouseleave occurs before the collapse('show') animation is finished.

$('div.panel-collapse').on('shown.bs.collapse hidden.bs.collapse', function() {
  $(this).dequeue('collapse');
});
$('div.panel-heading').hover(
  function() {
    var collapse = $($(this).find('a').attr('href'));
    collapse.queue('collapse', function() {
      $(this).collapse('show');
    });
    if (!collapse.hasClass('collapsing')) {
      collapse.dequeue('collapse');
    }
  },
  function() {
    var collapse = $($(this).find('a').attr('href'));
    collapse.queue('collapse', function() {
      $(this).collapse('hide');
    });
    if (!collapse.hasClass('collapsing')) {
      collapse.dequeue('collapse');
    }
  }
}

This doesn't make use of DRY coding, but I encountered hoverevents onloadwhen using a named function. Maybe someone can advise on this?

Upvotes: 2

Jules Copeland
Jules Copeland

Reputation: 1722

I'm a bit late to the party, but for future googlers, I came up with a much simpler way of doing this.

It's coffee script I'm afraid, but you should get the idea:

$(".your-hoverable-object-class").mouseenter (e) ->
$this = $(this)
link = $this.find("a") #(assumes you only have one link)
target = link.attr('data-target') || e.preventDefault() || (href = link.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') #strip for ie7
unless $(target).hasClass('in')
  link.trigger('click') #Here's the money shot - just trigger the default functionality

The rest of the code is setting up the variables - you might need to tweak this depending how you've set it up - and the last bit checks that the panel isn't already open before triggering the click again. Again - this works for my set up, but you can remove it if doesn't work for you.

Upvotes: 2

Cliff Seal
Cliff Seal

Reputation: 101

I achieved hover functionality while maintaining 'clickability' fairly easily:

jQuery(".pointer").hover(
    function(){
        var thisdiv = jQuery(this).attr("data-target")
        jQuery(thisdiv).collapse("show");
    },
    function(){
        var thisdiv = jQuery(this).attr("data-target")
        jQuery(thisdiv).collapse("hide");
    }
);

I was already using the data-attributes, so I kept them, and used them here to trigger the right divs. "pointer" is a class on my toggle links, so you can adapt that to whatever you need.

Upvotes: 10

Andres I Perez
Andres I Perez

Reputation: 75409

You can copy the collapsible data-api straight from the plugins script and tweak it around to achieve the hover functionality. You can then place it inside your own script.js file and target the collapsible you want modified to open on hover instead of on click. Try this for example:

JS

$(function() {
    $('#accordion2').on('mouseenter.collapse.data-api', '[data-toggle=collapse]', function(e) {
        var $this = $(this),
            href, target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
            ,
            option = $(target).data('collapse') ? 'show' : $this.data()
            $(target).collapse(option)
    })
})

This is a direct copy of the data-api block found on the plugin, i just replaced the click event with mouseenter and also the collapse option, changed it to show instead.

Demo: http://jsfiddle.net/um2q2/1/

Upvotes: 9

Related Questions