You are here

function better_exposed_filters_exposed_form_plugin::options_form in Better Exposed Filters 7.3

Same name and namespace in other branches
  1. 6.3 better_exposed_filters_exposed_form_plugin.inc \better_exposed_filters_exposed_form_plugin::options_form()
  2. 6 better_exposed_filters_exposed_form_plugin.inc \better_exposed_filters_exposed_form_plugin::options_form()
  3. 7 better_exposed_filters_exposed_form_plugin.inc \better_exposed_filters_exposed_form_plugin::options_form()

Provide a form to edit options for this plugin.

Overrides views_plugin_exposed_form::options_form

File

./better_exposed_filters_exposed_form_plugin.inc, line 40
Provides an Better Exposed Filters exposed form plugin for View 3.x.

Class

better_exposed_filters_exposed_form_plugin
Better exposed filter form plugin class.

Code

function options_form(&$form, &$form_state) {
  parent::options_form($form, $form_state);
  $bef_options = array();

  // Get current settings and default values for new filters.
  $existing = $this
    ->_bef_get_settings();

  /*
   * Add general options for exposed form items.
   */
  $bef_options['general']['input_required'] = array(
    '#type' => 'checkbox',
    '#default_value' => $existing['general']['input_required'],
    '#title' => t('Require input before results are shown'),
    '#description' => t("Emulates the built in <em>Input Required</em> exposed filter handler"),
  );
  $bef_options['general']['text_input_required'] = array(
    '#type' => 'container',
    // Indent dependent options.
    '#prefix' => '<div class="dependent-options">',
    '#suffix' => '</div>',
    '#states' => array(
      // Hide this field when the input_required checkbox is disabled.
      'invisible' => array(
        ':input[name="exposed_form_options[bef][general][input_required]"]' => array(
          'checked' => FALSE,
        ),
      ),
    ),
  );
  $bef_options['general']['text_input_required']['text_input_required'] = array(
    '#type' => 'text_format',
    '#title' => t('Text on demand'),
    '#description' => t('Text to display instead of results until the user selects and applies an exposed filter.'),
    '#default_value' => $existing['general']['text_input_required']['text_input_required']['value'],
    '#format' => $existing['general']['text_input_required']['text_input_required']['format'],
    '#wysiwyg' => FALSE,
  );
  $bef_options['general']['allow_secondary'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable secondary exposed form options'),
    '#default_value' => $existing['general']['allow_secondary'],
    '#description' => t('Allows you to specify some exposed form elements as being secondary options and places those elements in a collapsible fieldset. Use this option to place some exposed filters in an "Advanced Search" area of the form, for example.'),
  );
  $bef_options['general']['secondary_label'] = array(
    '#type' => 'textfield',
    '#default_value' => $existing['general']['secondary_label'],
    '#title' => t('Secondary options label'),
    '#description' => t('The name of the fieldset to hold secondary options. This cannot be left blank or there will be no way to show/hide these options.'),
    // Indent dependent options.
    '#prefix' => '<div class="dependent-options">',
    '#suffix' => '</div>',
    '#states' => array(
      'required' => array(
        ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
          'checked' => TRUE,
        ),
      ),
      'visible' => array(
        ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $bef_options['general']['secondary_collapse_override'] = array(
    '#type' => 'select',
    '#title' => t('Override secondary options fieldset'),
    '#default_value' => $existing['general']['secondary_collapse_override'],
    '#description' => t('This setting overrides the secondary options fieldset collapsed value. By default the fieldset renders opened if a value within is selected and closed otherwise.'),
    '#options' => array(
      0 => t('Default'),
      1 => t('Always open'),
      2 => t('Always closed'),
    ),
    // Indent dependent options.
    '#prefix' => '<div class="dependent-options">',
    '#suffix' => '</div>',
    '#states' => array(
      'visible' => array(
        ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );

  /*
   * Add options for exposed sorts.
   */
  $exposed = FALSE;
  foreach ($this->display->handler
    ->get_handlers('sort') as $label => $sort) {
    if ($sort->options['exposed']) {
      $exposed = TRUE;
      break;
    }
  }
  if ($exposed) {
    $bef_options['sort']['bef_format'] = array(
      '#type' => 'select',
      '#title' => t('Display exposed sort options as'),
      '#default_value' => $existing['sort']['bef_format'],
      '#options' => array(
        'default' => t('Default select list'),
        'bef' => t('Radio Buttons'),
        'bef_links' => t('Links'),
        'bef_toggle_links' => t('Toggle Links'),
      ),
      '#description' => t('Select a format for the exposed sort options. Note: the "toggle links" option will only work correctly if "Combine sort order with sort by" is checked in the "Advanced Sort Options" section.'),
    );
    $bef_options['sort']['advanced'] = array(
      '#type' => 'fieldset',
      '#title' => t('Advanced sort options'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $bef_options['sort']['advanced']['collapsible'] = array(
      '#type' => 'checkbox',
      '#title' => t('Make sort options collapsible'),
      '#default_value' => $existing['sort']['advanced']['collapsible'],
      '#description' => t('Puts the sort options in a collapsible fieldset'),
    );
    $bef_options['sort']['advanced']['collapsible_label'] = array(
      '#type' => 'textfield',
      '#title' => t('Collapsible fieldset title'),
      '#default_value' => empty($existing['sort']['advanced']['collapsible_label']) ? t('Sort options') : $existing['sort']['advanced']['collapsible_label'],
      '#description' => t('This cannot be left blank or there will be no way to show/hide sort options.'),
      // Indent dependent options.
      '#prefix' => '<div class="dependent-options">',
      '#suffix' => '</div>',
      '#states' => array(
        'visible' => array(
          'input[name="exposed_form_options[bef][sort][advanced][collapsible]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $bef_options['sort']['advanced']['combine'] = array(
      '#type' => 'checkbox',
      '#title' => t('Combine sort order with sort by'),
      '#default_value' => $existing['sort']['advanced']['combine'],
      '#description' => t('Combines the sort by options and order (ascending or decending) into a single list.  Use this to display "Option1 Desc", "Option1 Asc", "Option2 Desc", "Option2 Asc" in a single form element. "Expose sort order" must be checked to enable this option.'),
      '#states' => array(
        'disabled' => array(
          'input[name="exposed_form_options[expose_sort_order]"]' => array(
            'checked' => FALSE,
          ),
        ),
      ),
    );
    $bef_options['sort']['advanced']['combine_param'] = array(
      '#type' => 'textfield',
      '#title' => t('Enter a query parameter to use for combined sorts'),
      '#default_value' => $existing['sort']['advanced']['combine_param'],
      '#description' => t('This will be the $_GET parameter used in query strings. Useful for preventing collisions between exposed filters when there are multiple instances of BEF on the page. Use only UTF-8 letters, numbers, and the dash (-), underscore (_), asterisk (*), and period(.) characters.'),
      '#default_value' => empty($existing['sort']['advanced']['combine_param']) ? 'sort_bef_combine' : $existing['sort']['advanced']['combine_param'],
      '#required' => TRUE,
      // Indent dependent options -- closing </div> is in combine_rewrite.
      '#prefix' => '<div class="dependent-options">',
      '#states' => array(
        'visible' => array(
          'input[name="exposed_form_options[bef][sort][advanced][combine]"]' => array(
            'checked' => TRUE,
          ),
          'input[name="exposed_form_options[expose_sort_order]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $bef_options['sort']['advanced']['combine_rewrite'] = array(
      '#type' => 'textarea',
      '#title' => t('Rewrite the text displayed'),
      '#default_value' => $existing['sort']['advanced']['combine_rewrite'],
      '#description' => t('Use this field to rewrite the text displayed for combined sort options and sort order. Use the format of current_text|replacement_text, one replacement per line. For example: <pre>
Post date Asc|Oldest first
Post date Desc|Newest first
Title Asc|A -> Z
Title Desc|Z -> A</pre> Leave the replacement text blank to remove an option altogether.'),
      '#suffix' => '</div>',
      '#states' => array(
        'visible' => array(
          'input[name="exposed_form_options[bef][sort][advanced][combine]"]' => array(
            'checked' => TRUE,
          ),
          'input[name="exposed_form_options[expose_sort_order]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $bef_options['sort']['advanced']['reset'] = array(
      '#type' => 'checkbox',
      '#title' => t('Include a "Reset sort" option'),
      '#default_value' => $existing['sort']['advanced']['reset'],
      '#description' => t('Adds a "Reset sort" option which will use Views\' default sort order.'),
    );
    $bef_options['sort']['advanced']['reset_label'] = array(
      '#type' => 'textfield',
      '#title' => t('"Reset sort" label'),
      '#default_value' => $existing['sort']['advanced']['reset_label'],
      '#description' => t('This cannot be left blank if the above option is checked'),
      // Indent dependent options.
      '#prefix' => '<div class="dependent-options">',
      '#suffix' => '</div>',
      '#states' => array(
        'required' => array(
          'input[name="exposed_form_options[bef][sort][advanced][reset]"]' => array(
            'checked' => TRUE,
          ),
        ),
        'visible' => array(
          'input[name="exposed_form_options[bef][sort][advanced][reset]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
    );
    $bef_options['sort']['advanced']['is_secondary'] = array(
      '#type' => 'checkbox',
      '#title' => t('This is a secondary option'),
      '#default_value' => $existing['sort']['advanced']['is_secondary'],
      '#states' => array(
        'visible' => array(
          ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
      '#description' => t('Places this element in the secondary options portion of the exposed form.'),
    );
    $bef_options['sort']['advanced']['autosubmit'] = array(
      '#type' => 'checkbox',
      '#title' => t('Autosubmit'),
      '#default_value' => $existing['sort']['advanced']['autosubmit'],
      '#states' => array(
        'disabled' => array(
          ':input[name="exposed_form_options[autosubmit]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
      '#description' => t('Automatically submit the form once a sort element is changed. This option is not available if you enabled autosubmit option for the whole form.'),
    );
  }

  /*
   * Add options for exposed pager.
   */
  $pager_exposed = FALSE;
  $current_display = $this->display->handler->view->display[$this->display->handler->view->current_display];
  $default_display = $this->display->handler->view->display['default'];
  if (!empty($current_display->handler->options['defaults']["pager"])) {
    $pager_exposed = isset($default_display->handler->options['pager']) && !empty($default_display->handler->options['pager']['options']['expose']['items_per_page']);
  }
  else {
    $pager_exposed = isset($current_display->handler->options['pager']) && !empty($current_display->handler->options['pager']['options']['expose']['items_per_page']);
  }
  if ($pager_exposed) {
    $bef_options['pager']['bef_format'] = array(
      '#type' => 'select',
      '#title' => t('Display exposed pager options as'),
      '#default_value' => $existing['pager']['bef_format'],
      '#options' => array(
        'default' => t('Default select list'),
        'bef' => t('Radio Buttons'),
        'bef_links' => t('Links'),
      ),
      '#description' => t('Select a format for the exposed pager options.'),
    );
    $bef_options['pager']['is_secondary'] = array(
      '#type' => 'checkbox',
      '#title' => t('This is a secondary option'),
      '#default_value' => $existing['pager']['is_secondary'],
      '#states' => array(
        'visible' => array(
          ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
      '#description' => t('Places this element in the secondary options portion of the exposed form.'),
    );
  }

  // Only add the description text once -- it was getting a little long to be
  // added to each filter.
  $bef_filter_intro = FALSE;

  // Go through each filter and add BEF options.
  foreach ($this->display->handler
    ->get_handlers('filter') as $label => $filter) {
    if (!$filter->options['exposed']) {
      continue;
    }

    // If we're adding BEF filter options, add an intro to explain what's
    // going on.
    if (!$bef_filter_intro) {
      $link = l(t('BEF settings documentation'), 'http://drupal.org/node/1701012');
      $bef_options['bef_intro'] = array(
        '#markup' => '<h3>' . t('Exposed Filter Settings') . '</h3><p>' . t('This section lets you select additional options for exposed filters. Some options are only available in certain situations. If you do not see the options you expect, please see the !link page for more details.', array(
          '!link' => $link,
        )) . '</p>',
      );
      $bef_filter_intro = TRUE;
    }

    // These filter operators get our standard options: radio or checkboxes.
    $bef_standard = FALSE;

    // Allows a filter to be rendered as a hidden <input> element. Useful when
    // building multi-step filter "wizards," for example.
    $bef_hidden = FALSE;

    // Renders the filter as a link.
    // @TODO: expand to include toggle links for all bef_links filters, not
    // just exposed sorts.
    $bef_links = FALSE;

    // These filters get a single on/off checkbox option for boolean
    // operators.
    $bef_single = FALSE;

    // Used for taxonomy filters with hierarchy.
    $bef_nested = FALSE;

    // Allows the term description to be added to rendered output.
    $bef_term_description = FALSE;

    // Used for date-based filters.
    $bef_datepicker = FALSE;

    // Used for numeric, non-date filters.
    $bef_slider = FALSE;

    // Check various filter types and determine what options are available.
    if ($filter instanceof views_handler_filter_string || $filter instanceof views_handler_filter_in_operator) {
      if (in_array($filter->operator, array(
        'in',
        'or',
        'and',
        'not',
      ))) {
        $bef_standard = TRUE;
        $bef_links = TRUE;
        $bef_hidden = TRUE;
      }
      if (in_array($filter->operator, array(
        'empty',
        'not empty',
      ))) {
        $bef_standard = TRUE;
        $bef_links = TRUE;
        $bef_hidden = TRUE;
        if (!$filter->options['expose']['multiple']) {
          $bef_single = TRUE;
        }
      }
    }
    if ($filter instanceof views_handler_filter_boolean_operator) {
      $bef_standard = TRUE;
      $bef_links = TRUE;
      $bef_hidden = TRUE;
      if (!$filter->options['expose']['multiple']) {
        $bef_single = TRUE;
      }
    }

    // Grouped filters will have a limited number of filter options available
    // so we can offer basic BEF options.
    if ($filter->options['is_grouped']) {
      $bef_standard = TRUE;
      $bef_links = TRUE;
      $bef_hidden = TRUE;
    }
    if ($filter instanceof views_handler_filter_term_node_tid) {

      // Autocomplete and dropdown taxonomy filter are both instances of
      // view_handler_filter_term_node_tid, but we can't show BEF options for
      // the autocomplete widget.
      if ('textfield' == $filter->options['type']) {
        $bef_standard = FALSE;
        $bef_links = FALSE;
        $bef_hidden = FALSE;
      }
      else {
        $bef_term_description = TRUE;
        if (!empty($filter->options['hierarchy'])) {
          $bef_nested = TRUE;
        }
      }
    }
    if ($filter instanceof views_handler_filter_date || !empty($filter->date_handler)) {
      $bef_datepicker = TRUE;
      $bef_hidden = TRUE;
    }

    // The date filter handler extends the numeric filter handler so we have
    // to exclude it specifically.
    if ($filter instanceof views_handler_filter_numeric && !$filter instanceof views_handler_filter_date) {
      $bef_slider = TRUE;
      $bef_hidden = TRUE;
    }

    // Search API extends the more general views_handler_filter rather than
    // operator-specific classes such as views_handler_filter_in_operator.
    // Handle those options here.
    if ($filter instanceof SearchApiViewsHandlerFilterOptions) {
      $bef_standard = TRUE;
      $bef_links = TRUE;
      $bef_hidden = TRUE;
    }
    elseif ($filter instanceof SearchApiViewsHandlerFilterDate) {
      $bef_datepicker = TRUE;
      if ($filter->options['is_grouped']) {
        $bef_standard = TRUE;
        $bef_links = TRUE;
        $bef_hidden = TRUE;
      }
    }
    elseif ($filter instanceof SearchApiViewsHandlerFilter && !$filter instanceof SearchApiViewsHandlerFilterFulltext) {
      $bef_slider = TRUE;
    }
    elseif ($filter instanceof SearchApiViewsHandlerFilterBoolean) {
      $bef_single = TRUE;
    }

    // All filters can use the default filter exposed by Views.
    $display_options = array(
      'default' => t('Default select list'),
    );
    if ($bef_standard) {

      // Main BEF option: radios/checkboxes.
      $display_options['bef'] = t('Checkboxes/Radio Buttons');
    }
    if ($bef_nested) {
      $display_options['bef_ul'] = t('Nested Checkboxes/Radio Buttons');
    }
    if ($bef_single) {
      $display_options['bef_single'] = t('Single on/off checkbox');
    }
    if ($bef_datepicker) {
      $display_options['bef_datepicker'] = t('jQuery UI Datepicker');
    }
    if ($bef_slider) {
      $display_options['bef_slider'] = t('jQuery UI slider');
    }
    if ($bef_links) {
      $display_options['bef_links'] = t('Links');
    }
    if ($bef_hidden) {
      $display_options['bef_hidden'] = t('Hidden');
    }

    // Alter the list of available display options for this filter.
    drupal_alter('better_exposed_filters_display_options', $display_options, $filter);
    $filter_key = $filter->options['is_grouped'] ? 'group_info' : 'expose';
    $identifier = '"' . $filter->options[$filter_key]['identifier'] . '"';
    if (!empty($filter->options[$filter_key]['label'])) {
      $identifier .= ' ' . t('(Filter label: "@fl")', array(
        '@fl' => $filter->options[$filter_key]['label'],
      ));
    }
    $bef_options[$label]['bef_format'] = array(
      '#type' => 'select',
      '#title' => t('Display @identifier exposed filter as', array(
        '@identifier' => $identifier,
      )),
      '#default_value' => $existing[$label]['bef_format'],
      '#options' => $display_options,
    );
    if ($bef_slider) {

      // Fieldset for jQuery slider options.
      $bef_options[$label]['slider_options'] = array(
        '#type' => 'fieldset',
        '#title' => t('Slider options for @identifier', array(
          '@identifier' => $identifier,
        )),
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
        '#states' => array(
          'visible' => array(
            ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
              'value' => 'bef_slider',
            ),
          ),
        ),
      );
      $bef_options[$label]['slider_options']['bef_slider_min'] = array(
        '#type' => 'textfield',
        '#title' => t('Range minimum'),
        '#default_value' => $existing[$label]['slider_options']['bef_slider_min'],
        '#bef_filter_id' => $label,
        '#states' => array(
          'required' => array(
            ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
              'value' => 'bef_slider',
            ),
          ),
        ),
        '#description' => t('The minimum allowed value for the jQuery range slider. It can be positive, negative, or zero and have up to 11 decimal places.'),
        '#element_validate' => array(
          'element_validate_number',
          'better_exposed_filters_element_validate_slider_required',
          'better_exposed_filters_element_validate_slider_min_max',
        ),
      );
      $bef_options[$label]['slider_options']['bef_slider_max'] = array(
        '#type' => 'textfield',
        '#title' => t('Range maximum'),
        '#default_value' => $existing[$label]['slider_options']['bef_slider_max'],
        '#bef_filter_id' => $label,
        '#states' => array(
          'required' => array(
            ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
              'value' => 'bef_slider',
            ),
          ),
        ),
        '#description' => t('The maximum allowed value for the jQuery range slider. It can be positive, negative, or zero and have up to 11 decimal places.'),
        '#element_validate' => array(
          'element_validate_number',
          'better_exposed_filters_element_validate_slider_required',
          'better_exposed_filters_element_validate_slider_min_max',
        ),
      );
      $bef_options[$label]['slider_options']['bef_slider_step'] = array(
        '#type' => 'textfield',
        '#title' => t('Step'),
        '#default_value' => empty($existing[$label]['slider_options']['bef_slider_step']) ? 1 : $existing[$label]['slider_options']['bef_slider_step'],
        '#bef_filter_id' => $label,
        '#states' => array(
          'required' => array(
            ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
              'value' => 'bef_slider',
            ),
          ),
        ),
        '#description' => t('Determines the size or amount of each interval or step the slider takes between the min and max.') . '<br />' . t('The full specified value range of the slider (Range maximum - Range minimum) must be evenly divisible by the step.') . '<br />' . t('The step must be a positive number of up to 5 decimal places.'),
        '#element_validate' => array(
          'element_validate_number',
          'better_exposed_filters_element_validate_slider_required',
          'better_exposed_filters_element_validate_slider_step',
        ),
      );
      $bef_options[$label]['slider_options']['bef_slider_animate'] = array(
        '#type' => 'textfield',
        '#title' => t('Animate'),
        '#default_value' => $existing[$label]['slider_options']['bef_slider_animate'],
        '#bef_filter_id' => $label,
        '#description' => t('Whether to slide handle smoothly when user click outside handle on the bar. Allowed values are "slow", "normal", "fast" or the number of milliseconds to run the animation (e.g. 1000). If left blank, there will be no animation, the slider will just jump to the new value instantly.'),
        '#element_validate' => array(
          'better_exposed_filters_element_validate_slider_animate',
        ),
      );
      $bef_options[$label]['slider_options']['bef_slider_orientation'] = array(
        '#type' => 'select',
        '#title' => t('Orientation'),
        '#options' => array(
          'horizontal' => t('Horizontal'),
          'vertical' => t('Vertical'),
        ),
        '#default_value' => $existing[$label]['slider_options']['bef_slider_orientation'],
        '#bef_filter_id' => $label,
        '#states' => array(
          'required' => array(
            ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
              'value' => 'bef_slider',
            ),
          ),
        ),
        '#description' => t('The orientation of the jQuery range slider.'),
      );
    }

    // Fieldset to keep the UI from getting out of hand.
    $bef_options[$label]['more_options'] = array(
      '#type' => 'fieldset',
      '#title' => t('More options for @identifier', array(
        '@identifier' => $identifier,
      )),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );

    // Select all checkbox.
    if ($bef_standard) {
      $bef_options[$label]['more_options']['bef_select_all_none'] = array(
        '#type' => 'checkbox',
        '#title' => t('Add select all/none links'),
        '#default_value' => $existing[$label]['more_options']['bef_select_all_none'],
        '#disabled' => !$filter->options['expose']['multiple'],
        '#description' => t('Add a "Select All/None" link when rendering the exposed filter using
              checkboxes. If this option is disabled, edit the filter and check the
              "Allow multiple selections".'),
      );
      if ($bef_nested) {
        $bef_options[$label]['more_options']['bef_select_all_none_nested'] = array(
          '#type' => 'checkbox',
          '#title' => t('Add nested all/none selection'),
          '#default_value' => $existing[$label]['more_options']['bef_select_all_none_nested'],
          '#disabled' => !$filter->options['expose']['multiple'] || !$filter->options['hierarchy'],
          '#description' => t('When a parent checkbox is checked, check all its children. If this option
                is disabled, edit the filter and check "Allow multiple selections" and
                edit the filter settings and check "Show hierarchy in dropdown".'),
        );
      }
      if ($bef_term_description) {
        $bef_options[$label]['more_options']['bef_term_description'] = array(
          '#type' => 'checkbox',
          '#title' => t('Include the term description'),
          '#default_value' => $existing[$label]['more_options']['bef_term_description'],
          '#description' => t('For taxonomy term filters, includes the term description for each filter option.'),
          '#states' => array(
            'visible' => array(
              ':input[name="exposed_form_options[bef][' . $label . '][bef_format]"]' => array(
                array(
                  'value' => 'bef',
                ),
                array(
                  'value' => 'bef_ul',
                ),
              ),
            ),
          ),
        );
      }

      // Put filter in collapsible fieldset option.
      // TODO: expand to all exposed filters.
      $bef_options[$label]['more_options']['bef_collapsible'] = array(
        '#type' => 'checkbox',
        '#title' => t('Make this filter collapsible'),
        '#default_value' => $existing[$label]['more_options']['bef_collapsible'],
        '#description' => t('Puts this filter in a collapsible fieldset'),
      );
    }

    // Individual element autosubmit option.
    $bef_options[$label]['more_options']['autosubmit'] = array(
      '#type' => 'checkbox',
      '#title' => t('Autosubmit'),
      '#default_value' => $existing[$label]['more_options']['autosubmit'],
      '#states' => array(
        'disabled' => array(
          ':input[name="exposed_form_options[autosubmit]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
      '#description' => t('Automatically submit the form once a filter element is changed. This option is not available if you enabled autosubmit option for the whole form.'),
    );

    // Allow any filter to be moved into the secondary options fieldset.
    $bef_options[$label]['more_options']['is_secondary'] = array(
      '#type' => 'checkbox',
      '#title' => t('This is a secondary option'),
      '#default_value' => $existing[$label]['more_options']['is_secondary'],
      '#states' => array(
        'visible' => array(
          ':input[name="exposed_form_options[bef][general][allow_secondary]"]' => array(
            'checked' => TRUE,
          ),
        ),
      ),
      '#description' => t('Places this element in the secondary options portion of the exposed form.'),
    );

    // Allow "Any" label to be overridden.
    $bef_options[$label]['more_options']['any_label'] = array(
      '#type' => 'textfield',
      '#title' => t('Override "Any" option label'),
      '#default_value' => $existing[$label]['more_options']['any_label'],
      '#description' => t('Leave blank to use Views default value.'),
    );

    // Build a description option form element -- available to all exposed
    // filters.
    $bef_options[$label]['more_options']['bef_filter_description'] = array(
      '#type' => 'textarea',
      '#title' => t('Description'),
      '#default_value' => $existing[$label]['more_options']['bef_filter_description'],
      '#description' => t('Adds descriptive text to the exposed filter.  This is usually rendered in smaller print under the label or the options. You may use tokens as specified below and in the "Global replacements values" section at the bottom of this page.'),
    );

    // Add token support to the description field.
    $bef_options[$label]['more_options']['tokens'] = array(
      '#title' => t('Replacement patterns'),
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    if (!module_exists('token')) {
      $bef_options[$label]['more_options']['tokens']['no_tokens'] = array(
        '#markup' => '<p>' . t('Enable the !token module to use replacement values.', array(
          '!token' => l(t('Token'), 'http://drupal.org/project/token'),
        )) . '</p>',
      );
    }
    else {

      // Collect a list of token types that make sense for this filter.
      $available = array(
        'global_types',
      );
      if (!empty($filter->options['vocabulary'])) {
        $available[] = 'vocabulary';
      }

      /* @TODO: Other token types? */
      $filter_specific = array_diff($available, array(
        'global_types',
      ));
      if (empty($filter_specific)) {
        $bef_options[$label]['more_options']['tokens']['nothing_specific'] = array(
          '#markup' => '<p>' . t('There are no filter-specific tokens for this filter. See the "Global replacement tokens" at the bottom of this dialog for additional token replacement options.') . '<p>',
        );
      }
      else {
        $bef_options[$label]['more_options']['tokens']['list'] = array(
          '#theme' => 'token_tree',
          '#token_types' => $filter_specific,
          '#global_types' => FALSE,
        );
      }
      $bef_options[$label]['more_options']['tokens']['available'] = array(
        // Save us from parsing available tokens again.
        '#type' => 'value',
        '#value' => $available,
      );
    }

    // Allow rewriting of filter options for any filter.
    $bef_options[$label]['more_options']['rewrite'] = array(
      '#title' => t('Rewrite filter options'),
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $bef_options[$label]['more_options']['rewrite']['filter_rewrite_values'] = array(
      '#type' => 'textarea',
      '#title' => t('Rewrite the text displayed'),
      '#default_value' => $existing[$label]['more_options']['rewrite']['filter_rewrite_values'],
      '#description' => t('
          Use this field to rewrite the filter options displayed. Use the format
          of current_text|replacement_text, one replacement per line. For
          example: <pre>
Current|Replacement
On|Yes
Off|No
</pre> Leave the replacement text blank to remove an option altogether. If using hierarchical taxonomy filters, do not including leading hyphens in the current value.
        '),
    );

    // Add an option to override defaults for the jQuery UI Datepicker.
    if ($bef_datepicker) {
      $bef_options[$label]['more_options']['datepicker_options'] = array(
        '#type' => 'textarea',
        '#title' => t('jQuery UI Datepicker option'),
        '#default_value' => $existing[$label]['more_options']['datepicker_options'],
        '#description' => t('Use this field to override the default options for the Datepicker widget. Options should be in the form of <code>option_name: option_value</code>, one setting per line. For example, to set the days of the week and date format to French: <pre>
dayNamesMin: [ "Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa" ]
dateFormat: "dd-mm-yy"
</pre>More information about datepicker options can be found on the <a href="!link">jQuery UI website</a>. This field is translatable so you can specify different options for different languages. See the <a href="!docs_link">BEF localization documentation</a> for more details.', array(
          '!link' => 'http://api.jqueryui.com/datepicker/',
          '!docs_link' => 'https://www.drupal.org/node/2460797',
        )),
      );
    }
  }

  /* Ends: foreach ($filters as $filter) { */

  // Add global token replacements, if available.
  if (module_exists('token')) {
    $bef_options['global_replacement_tokens'] = array(
      '#title' => t('Global replacement patterns'),
      '#type' => 'fieldset',
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $bef_options['global_replacement_tokens']['list'] = array(
      '#theme' => 'token_tree',
      '#token_types' => array(
        'global_types',
      ),
    );
  }

  // Add BEF form elements to the exposed form options form.
  $form['bef'] = $bef_options;
}