2

How to collapse and expand items under their parent using better exposed filter and Nested Checkboxes .. What i mean ...that all the child items to be collapsed and they expand when the user click on (+ e.g) for the parent or check the parent box. I am making a car dealer website and i need that to make an advanced search. Any help will be appreciated.

  • Update: any help please – Ahmed Hassan Feb 24 '14 at 11:57
1

I fixed this issue and here is the solution for any one want to do the same, based on this conversion Collapse and Expand according to Hierarchy

add this code to your theme and you can use this module to add Javascript or CSS through the views page or block Code per Views Display

This code will add a + button beside the every parent, which will expand the checkboxes when clicked

(function ($) {
Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
attach:function (context, settings) {
  if (!('$befSetupDone' in window)) {
    $('ul.bef-tree-child.bef-tree-depth-1').css('display', 'none');
    var $expander = $('<span class="expander">+</span>');
    $('ul.bef-tree-child > li:has(ul) > div.form-item').prepend($expander);
    $('.expander')
      .click(function() {
        $ul = $(this).parents('li:first').find('ul');
        $ul.toggle('fast');
     })
    $befSetupDone = 1;
  }
 }
 }
 }) (jQuery);

and another code which will expand when the parent checkbox checked

(function ($) {
Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
attach:function (context, settings) {
  // first collapse the children
  $('ul.bef-tree-child.bef-tree-depth-1').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);

Note: You will have to choose (Nested Checkboxex/Radio Buttons) and check this option in better exposed filter

Add select all/none links


0

You will need to write some custom JavaScript to get the nested lists to expand/contract. There are several jQuery plugins that will do this as well as come custom code as shown here.

0

Based on the code from Ahmed Hassan, I added functionality:

  1. keyboard navigation
  2. checkbox hidden on parent nodes
  3. aria, labels and other accessibility functionality

    /**
     * @file store_better_exposed_filters_expand.js
     *
     * Provides some client-side functionality for the Better Exposed Filters expand/collapse of taxonomy terms
     *
     * Kevin Finkenbinder
     * Added keyboard interface, aria labels and functionality, removed checkbox in front of parent nodes
     * Based on the work of Ahmed Hassan (https://drupal.stackexchange.com/a/109214/19071)
     */
    (function ($)
    {
      Drupal.behaviors.betterExposedFiltersExpandCollapseNested = {
        attach: function (context, settings)
        {
          if (!('$befSetupDone' in window))
          {
            $('bef-tree').attr('role', 'tree');
            $('bef-tree-child').attr('role', 'treeitem');
            $('bef-tree-child ul').attr('role', 'group');
            $('bef-tree-child li').attr('role,treeitem');
            $('ul.bef-tree-child.bef-tree-depth-1').css('display', 'none');
            $('.bef-tree-child input').attr('tabindex', -1);
            var $expander = $('<span tabindex=-1 class="expander">+</span>');
            $('ul.bef-tree > li:has(ul) > div.form-item').prepend($expander);
            $('ul.bef-tree-child > li:has(ul) > div.form-item').prepend($expander);
            $('.expander').each(function (index)
            {
              $(this).attr('id', $(this).next().attr('id'));
            });
            $('ul.bef-tree > li:has(ul) > div.form-item > input ').remove();
            $('ul.bef-tree-child > li:has(ul) > div.form-item > input').remove();
            $('.expander').first().attr('tabindex', 0); /* tab to control but not individual elements - see accesssibleculture.org/articles/2013/02/not-so-simple-aria-tree-views-and-screen-readers/ */
            $('ul.bef-tree-child.bef-tree-depth-1').css('display', 'none');
            $('ul.bef-tree-child').css('list-style-type', 'none');
            $('ul.bef-tree').css('list-style-type', 'none');
            $('.expander').css('cursor', 'pointer');
            $('.expander').on('click keydown', function (event)
            {
              if (event.which == 32 || event.which == 13 || event.which==1) /*spacebar,enter or mouse click*/
              {
                $ul = $(this).parents('li:first').find('ul');
                $ul.toggle('fast');
                event.preventDefault();
                return false;
              }
              else if (event.which == 37) /*left arrow */
              {
                if ($(this).parents('li:first').find('ul').is(":visible"))
                {
                  $(this).parents('li:first').find('ul').hide();
                  event.preventDefault();
                  return false;
                }
              }
              else if (event.which == 38) /*up arrow */
              {
                if (!$(this).closest("li").is(':first-of-type'))
                {
                  if ($(this).closest("li").prev().find('ul').is(':visible'))
                  {
                    $(this).closest("li").prev().find("ul li:last div input:checkbox").focus();
                  }
                  else
                  {
                    $(this).closest("li").prev().find(".expander").focus();
                  }
                  event.preventDefault();
                  return false;
                }
              }
              else if (event.which == 39) /*right arrow */
              {
                if ($(this).parents('li:first').find('ul').is(":visible"))
                {
                  $(this).parents('li:first').find('ul input').first().focus();
                  event.preventDefault();
                  return false;
                }
                else
                {
                  $(this).parents('li:first').find('ul').show();
                  event.preventDefault();
                  return false;
                }
              }
              else if (event.which == 40) /*down arrow */
              {
                if ($(this).closest('li').find('ul').is(':visible'))
                {
                  $(this).closest('li').find('ul li:first div input:checkbox').focus();
                }
                else if (!$(this).closest("li").is(':last-of-type'))
                {
                  $(this).closest("li").next().find(".expander").focus();
                  event.preventDefault();
                  return false;
                }
              }
            });
            $('.bef-tree input:checkbox').on('keydown', function (event)
            {
              if (event.which == 37) /*left arrow */
              {
                $(this).parents('li:eq(1)').find('.expander').first().focus();
                event.preventDefault();
                return false;
              }
              else if (event.which == 38) /*up arrow */
              {
                if ($(this).closest('li').is(":first-child"))
                {
                  $(this).parents('li:eq(1)').find('.expander').first().focus();
                }
                else
                {
                  $(this).closest('li').prev('li').find(':checkbox').focus();
                }
                event.preventDefault();
                return false;
              }
              else if (event.which == 40) /*down arrow */
              {
                if ($(this).closest('li').is(":last-child") && !$.isEmptyObject($(this).parents('li:eq(1)').next().find('.expander')))
                {
                  $(this).parents('li:eq(1)').next().find('.expander').focus();
                }
                else
                {
                  $(this).closest('li').next().find(':checkbox').focus();
                }
                event.preventDefault();
                return false;
              }
            });
            $befSetupDone = 1;
          }
        }
      }
    })(jQuery);
    
0

Here is what I used to output the field in a hierarchy. Note, I include this using Display Suite Code Fields, but it could easily be placed in a module.

<?php

function map_leaves($term_parents, &$term_tree, $depth = 0) {
  if (!isset($term_tree[$term_parents[$depth]->name])) {
    $term_tree[$term_parents[$depth]->name] = NULL;
  }
  if ($depth < count($term_parents) - 1) {
    map_leaves($term_parents, $term_tree[$term_parents[$depth]->name],$depth + 1);
  }
}

function output_term_tree($term_tree) {
  $return = '<ul class=msul_3';
  $return .= 'style="column-count:3;-webkit-column-count:3;-moz-column-count: 3;"';
  $return .= '>' . PHP_EOL;
  foreach ($term_tree as $term_name => $children) {
    $return .= '<li class="field-items">' . PHP_EOL . $term_name . PHP_EOL;
    if (!empty($children)) {
      $return .= output_term_tree($children);
    }
    $return .= '</li>' . PHP_EOL;
  }
  $return .= '</ul>' . PHP_EOL;
  return $return;
}

$node = node_load(explode('/', $_GET['q'])[1]);

$terms = $node->field_library_space_equipment['und'];
$term_tree = [];
if (!empty($terms)) {
  foreach ($terms as $term) {
    $term_parents = array_reverse(taxonomy_get_parents_all($term['tid']));
    map_leaves($term_parents, $term_tree);
  }
}
unset($term_tree['Space Location'], $term_tree['Space Types']);
$return = output_term_tree($term_tree);
echo $return;
?>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.