I love BEF and the features it provides, especially the checkboxes for exposed views filters. I was wondering though, is there a way to collapse/expand according to the hierarchy?

I have a hierarchical taxonomy vocab with a depth of 3 or 4 and there are only a handful of parents and children but over a hundred grandchildren.

So it would be great if not just the root, but also all the sub-parents could be collapsible/expandable as well (like in the interface of Taxonomy Manager). Is this possible?

My clients need their website done this week so this feature request isn't really for me, but looking at drupal forums I think it would be a HUGE improvement over the views default UI (and it would have been awesome for me! :)

mikeker, thanks for all the work you've done on this. I wish I could do more to help the Drupal community and give back.

Comments

jadenoel’s picture

Posting this feature request in reference to comments 5, 6, and 7 on this thread: http://drupal.org/node/965388.

doublejosh’s picture

+1 and visiting the feature request link.

Was going to do this by pointing some simple jQuery UI scripts at the filter DOM elements, but there is no hierarchical structure to point at :(

mikeker’s picture

Status: Active » Fixed

I actually checked in the fix to this ages ago, but for whatever reason, I forgot to mark this issue as fixed. Heh... Sorry about that. This option is now available in the -dev release.

Selecting "Nested checkbox/radio buttons" puts the filter into a nested <ul>. There is currently no JavaScript added to collapse/expand the lists but that should be relatively simple now that there's an appropriate structure to work with.

Note: this ONLY works with a Taxonomy filter that has the "Show hierarchy in dropdown" option checked and relies on the "-" prefix to determine the current depth. The "-" characters are removed from the filter options.

doublejosh’s picture

Awesome. Guess this negates the other thread I wrote about this in :)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

jacobroufa’s picture

I know this is a closed issue, but I was still having some problems with what JS to use to make a collapsible list work properly so I thought I'd post my solution for the benefit of others. I went through 4-5 different variations before settling on this.

Must be using the latest -dev branch of BEF. Also requires Jquery 1.5 via jquery_update and the jquery-tree plugin. Once you have patched jquery_update and included the plugin above in your theme, create a new JS file and include it either using drupal_add_js() in your template.php or scripts[] = js/script.js in your info file. Below is the code that worked for me :

if (Drupal.jsEnabled) {

  Drupal.behaviors.bef_live_filter = function() {
      // Collapsible lists
      $('ul.bef-tree').tree();
      // Hide the apply button.
      $('.views-exposed-form input:submit').hide();

      // When the change event fires, run the submit handler
      $('.views-exposed-form input').change(function(event) {
        $(this).parents('form').submit();
      });
  }

}

Note: If you enable the context if statement found here then ajax auto-submit and the tree only work one time. Without the context statement they are persistent.

alanom’s picture

The Term Reference Tree Widget module includes a great piece of javascript designed specifically for Drupal taxonomy tree hierarchies. They've also got an open issue on more or less the same topic.

How about an option that appears if Term Reference Tree Widget module is installed to use its javascript?

Peacog’s picture

Version: 6.x-1.x-dev » 7.x-3.x-dev

I've written some very simple javascript to expand/collapse the nested lists provided by the Nested Checkboxes/Radio buttons widget. Add the following to your theme's behaviours:

Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
    attach:function (context, settings) {
      // first collapse the children
      $('ul.bef-tree-child').css('display', 'none');

      $('.form-checkboxes.bef-select-all-none-nested li').has('ul').once('bef-expand-collapse-nested', function () {
        $(this)
          .find('input.form-checkboxes:first')
          .click(function() {
            $ul = $(this).parents('li:first').find('ul');
            if($(this).attr('checked')) {
              $ul.slideDown('fast');
            }
            else {
              $ul.slideUp('fast');
            }
          })
      });
    }
  }

It should be reasonably easy to add this as an option in the filter settings. When I have some time I will make a patch.

ShaneOnABike’s picture

That code didn't work for me but this did...

/**
 * @file store_better_exposed_filters_expand.js
 *
 * Provides some client-side functionality for the Better Exposed Filters expand/collapse of taxonomy terms
 */
(function ($) {
  Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
    attach:function (context, settings) {
      // first collapse the children
      $('ul.bef-tree-child').css('display', 'none');

      $('.form-checkboxes.bef-select-all-none li').has('ul').once('bef-tree', function () {
        $(this)
          .find('input.form-checkboxes:first')
          .click(function() {
            $ul = $(this).parents('li:first').find('ul');
            if($(this).attr('checked')) {
              $ul.slideDown('fast');
            }
            else {
              $ul.slideUp('fast');
            }
          })
      });
    }
  }
}) (jQuery);
nassiesse’s picture

Hi All,
This solution is OK, but I think there is a problem.
When BEF applies the filter to the view it refreshes the page and the state of filters were lost.

How can we save the state to prevent its lost?

FaberfoX’s picture

Here's my solution, I've just started with jQuery last night so I'm sure this can be improved.

In my case, I didn't want to have to click the parents to show childs as that doesn't work for my use case, I don't want the parents checked when expanding. So, this code inserts a span with a + in front of the parents to have it be the one in charge of expanding and collapsing children. I'm using an initially undefined var to have this processed just once, because otherwise ajax refreshes were triggering the function again, adding extra expanders. Once more, I've just started with jQuery so please don't shoot me. Also, with the selectors I'm using, the select all/none is not required as it was in #9.
This will only work for 2 level trees, I hope someone that knows more than me can refactor it for any level trees.

(function ($) {
  Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
    attach:function (context, settings) {

      if (!('$befSetupDone' in window)) {
        $('ul.bef-tree-child').css('display', 'none');

        var $expander = $('<span class="expander">+</span>');

        $('ul.bef-tree > li > div.form-item').prepend($expander);

        $('.expander')
          .click(function() {
            $ul = $(this).parents('li:first').find('ul');
            $ul.toggle('fast');
         })

        $befSetupDone = 1;
      }
    }
  }
}) (jQuery);

I'm using Code per Views dev to insert the JS and so far it's working great.

knigh7’s picture

Any luck with this?

nassiesse’s picture

I solved this problem using the jquery.cookie plugin (http://archive.plugins.jquery.com/project/Cookie) that is already included in Drupal 7 distribution.

I modified the script on post #9 to save in a cookie the opened accordion id, so I can set it as open on the next post.

I hope this is usefull.

forpost’s picture

Try Simple hierarchical select
"The widget is available in node forms and as Views exposed filter."
http://drupal.org/project/shs

ah_ma81’s picture

Issue summary: View changes

I am using this module (Code per Views Display) to add this codes and none of them is working ... can any one please tell me what i have to do

m-si’s picture

Issue tags: +possible solution for rembering the status of expanded lists.

Hi I have been codeing arround to have a working solution for folding taxonomy hirarchies in a views filter that ist renewing itself via ajax. It is ugly coded, maybe some of you guys do have an Idea to shorten it. It overcomes the double binding of function of #11. It works for all levels nested. I included it in the .info file via

scripts[] = scripts/expcol-bef-tax.js

//set up a static varibale to remeber the status of the non collapsed
var $lastOpen = [];
(function ($) {
Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
attach:function (context, settings) {
    var $expander = $('<span class="expander">+</span>');
    //collapse all
    $('ul.bef-tree-child > li:has(ul) .form-item').addClass('collapsed');
    //but don't collapse the previous opened
    if ($lastOpen != 0) {
    	$('ul.bef-tree-child > li:has(ul) > div.form-item').each(function(index) {
    	    $checklist = $(this).attr("class");
    		for (var k = 0; k < $lastOpen.length; k++) {
    			if ($checklist.indexOf($lastOpen[k]) != -1) {
    			    if ($checklist.indexOf('collapsed') != -1) {
    				$(this).removeClass('collapsed'); }
    			} 
    		}
    	});
    }
    //give every list parent an expander and change the cursor *of course
    $('ul.bef-tree-child > li:has(ul) > div.form-item:not(:has(span))').prepend($expander);
    $('.expander').css('cursor', 'pointer');
    //collapse all on the first pageview
    $('div.collapsed').next('ul').css('display', 'none');
    //make it expand on click (only once)
    $('.expander').once($(this), function() {
      $(this).click(function() {
        $(this).parent().toggleClass('collapsed');
        //remember the unfolded for the next ajax call (tid is used for identification)
        var $list = $(this).parent().attr("class");
        var classList = $list.split(' ');
        for (var i = 0; i < classList.length; i++) {
   			if (classList[i].indexOf('tid') != -1) {
   			    if ($lastOpen != null) {
   			    	if ($list.indexOf('collapsed') != -1) {
   			    		var j = $.inArray(classList[i],$lastOpen)
							if (j >= 0){
    						$lastOpen.splice(j, 1);
							}
   			    	} else {
   			    	$lastOpen.push(classList[i]);
   			    	}
     			} else {
     			$lastOpen.push(classList[i]);
     			}
   			}
		}
        $(this).parents('li:first').children('ul').slideToggle('fast');
        });
     });
 } 
 }
 }) (jQuery);
golddragon007’s picture

Here is an actual version of #16 with some cleaning and optimalization.

// Set up a static varibale to remeber the status of the non collapsed.
var lastOpen = [];
(function ($) {
	Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
		attach:function (context, settings) {
			var expander = $('<span class="expander">+</span>');
			var mainTreeSelector = "ul.bef-tree > li:has(ul) > div.form-item";
			var childTreeSelector = "ul.bef-tree-child > li:has(ul) > div.form-item";

			// Collapse all.
			$(mainTreeSelector + ', ' + childTreeSelector).addClass('collapsed');
			// But don't collapse the previous opened.
			if (lastOpen.length != 0) {
				$(mainTreeSelector + ' input.form-radio, ' + childTreeSelector + ' input.form-radio').each(function(index) {
					checklist = $(this).attr("id");
					if (lastOpen.indexOf(checklist) != -1) {
						$(this).parent().removeClass('collapsed');
					}
				});
			}
			// Give every list parent an expander and change the cursor *of course.
			$(mainTreeSelector + ':not(:has(span.expander)), ' + childTreeSelector + ':not(:has(span.expander))').prepend(expander);
			// Collapse all on the first pageview.
			$('div.collapsed').next('ul').css('display', 'none');
			// Make it expand on click (only once).
			$('.expander').css('cursor', 'pointer').once($(this), function() {
				$(this).click(function() {
					var thisParent = $(this).parent();
					thisParent.toggleClass('collapsed');
					// Remember the unfolded for the next ajax call (tid is used for identification).
					var id = thisParent.find('input').attr("id");
					if (lastOpen != null && thisParent.hasClass('collapsed')) {
						var j = $.inArray(id,lastOpen);
						if (j >= 0){
							lastOpen.splice(j, 1);
						}
					} else {
						lastOpen.push(id);
					}
					$(this).parents('li:first').children('ul').slideToggle('fast');
				});
			});
		}
	}
}) (jQuery);
bib_boy’s picture

If you are using an admin theme (e.g. Seven) then remember to add the script there and not your main theme!

hockey2112’s picture

Was this feature ever implemented into the BEF module? If not, is there a modern/current code implementation that would work for Drupal 10?