You are here

function theme_select_as_tree in Better Exposed Filters 7.3

Same name and namespace in other branches
  1. 8.3 better_exposed_filters.theme \theme_select_as_tree()
  2. 6.3 better_exposed_filters.theme \theme_select_as_tree()
  3. 6 better_exposed_filters.theme \theme_select_as_tree()
  4. 6.2 better_exposed_filters.theme \theme_select_as_tree()
  5. 7 better_exposed_filters.theme \theme_select_as_tree()

Themes a taxonomy-based exposed filter as a nested unordered list.

Note: this routine depends on the '-' char prefixed on the term names by Views to determine depth.

Parameters

array $vars: An array of arrays, the 'element' item holds the properties of the element.

Return value

string Nested, unordered list of filter options

1 string reference to 'theme_select_as_tree'
better_exposed_filters_theme in ./better_exposed_filters.module
Implements hook_theme().
2 theme calls to theme_select_as_tree()
theme_select_as_checkboxes in ./better_exposed_filters.theme
Themes a select element as a set of checkboxes.
theme_select_as_radios in ./better_exposed_filters.theme
Themes a select drop-down as a collection of radio buttons.

File

./better_exposed_filters.theme, line 321
Provides theming functions to display exposed forms using different interfaces.

Code

function theme_select_as_tree($vars) {
  $element = $vars['element'];

  // The selected keys from #options.
  $selected_options = empty($element['#value']) ? $element['#default_value'] : $element['#value'];

  // Build a bunch of nested unordered lists to represent the hierarchy based
  // on the '-' prefix added by Views or optgroup structure.
  $output = '<ul class="bef-tree">';
  $curr_depth = 0;
  foreach ($element['#options'] as $option_value => $option_label) {

    // Check for Taxonomy-based filters.
    if (is_object($option_label)) {
      $slice = array_slice($option_label->option, 0, 1, TRUE);
      $option_value = key($slice);
      $option_label = current($slice);
    }

    // Check for optgroups -- which is basically a two-level deep tree.
    if (is_array($option_label)) {

      // TODO:
    }
    else {

      // Build hierarchy based on prefixed '-' on the element label.
      if (t('- Any -') == $option_label) {
        $depth = 0;
      }
      else {
        preg_match('/^(-*).*$/', $option_label, $matches);
        $depth = strlen($matches[1]);
        $option_label = ltrim($option_label, '-');
      }

      // Build either checkboxes or radio buttons, depending on Views' settings.
      $html = '';
      if (!empty($element['#multiple'])) {
        if (isset($element['#bef_term_descriptions'][$option_value])) {
          $element[$option_value]['#description'] = $element['#bef_term_descriptions'][$option_value];
        }
        $html = theme('bef_checkbox', array(
          'element' => $element,
          'value' => $option_value,
          'label' => $option_label,
          'selected' => array_search($option_value, $selected_options) !== FALSE,
        ));
      }
      else {
        if (isset($element['#bef_term_descriptions'][$option_value])) {
          $element[$option_value]['#description'] = $element['#bef_term_descriptions'][$option_value];
        }
        $element[$option_value]['#title'] = $option_label;
        $element[$option_value]['#children'] = theme('radio', array(
          'element' => $element[$option_value],
        ));
        $html .= theme('form_element', array(
          'element' => $element[$option_value],
        ));
      }
      if ($depth > $curr_depth) {

        // We've moved down a level: create a new nested <ul>.
        // TODO: Is there is a way to jump more than one level deeper at a time?
        // I don't think so...
        $output .= "<ul class='bef-tree-child bef-tree-depth-{$depth}'><li>{$html}";
        $curr_depth = $depth;
      }
      elseif ($depth < $curr_depth) {

        // We've moved up a level: finish previous <ul> and <li> tags, once for
        // each level, since we can jump multiple levels up at a time.
        while ($depth < $curr_depth) {
          $output .= '</li></ul>';
          $curr_depth--;
        }
        $output .= "</li><li>{$html}";
      }
      else {
        if (-1 == $curr_depth) {

          // No </li> needed -- this is the first element.
          $output .= "<li>{$html}";
          $curr_depth = 0;
        }
        else {

          // Remain at same level as previous entry.
          $output .= "</li><li>{$html}";
        }
      }
    }
  }

  // foreach ($element['#options'] as $option_value => $option_label)
  if (!$curr_depth) {

    // Close last <li> tag.
    $output .= '</li>';
  }
  else {

    // Finish closing <ul> and <li> tags.
    while ($curr_depth) {
      $curr_depth--;
      $output .= '</li></ul></li>';
    }
  }

  // Close the opening <ul class="bef-tree"> tag.
  $output .= '</ul>';

  // Add exposed filter description.
  $description = '';
  if (!empty($element['#bef_description'])) {
    $description = '<div class="description">' . $element['#bef_description'] . '</div>';
  }

  // Add the select all/none option, if needed.
  if (!empty($element['#bef_select_all_none'])) {
    if (empty($element['#attributes']['class'])) {
      $element['#attributes']['class'] = array();
    }
    $element['#attributes']['class'][] = 'bef-select-all-none';
  }

  // Add the select all/none nested option, if needed.
  if (!empty($element['#bef_select_all_none_nested'])) {
    if (empty($element['#attributes']['class'])) {
      $element['#attributes']['class'] = array();
    }
    $element['#attributes']['class'][] = 'bef-select-all-none-nested';
  }

  // Name and multiple attributes are not valid for <div>'s.
  if (isset($element['#attributes']['name'])) {
    unset($element['#attributes']['name']);
  }
  if (isset($element['#attributes']['multiple'])) {
    unset($element['#attributes']['multiple']);
  }
  return '<div' . drupal_attributes($element['#attributes']) . ">{$description}{$output}</div>";
}