diff --git a/better_exposed_filters.js b/better_exposed_filters.js index 87d606e..46a0aa9 100644 --- a/better_exposed_filters.js +++ b/better_exposed_filters.js @@ -83,7 +83,7 @@ ; // Check for and initialize datepickers - if (Drupal.settings.better_exposed_filters.bef_datepicker) { + if (Drupal.settings.better_exposed_filters.bef_datepicker && $.fn.datepicker) { // Note: JavaScript does not treat "" as null if (Drupal.settings.better_exposed_filters.bef_dateformat) { $('.bef-datepicker').datepicker({ @@ -98,6 +98,78 @@ } // attach: function() { }; // Drupal.behaviors.better_exposed_filters = { + Drupal.behaviors.better_exposed_filters_select_as_links = { + attach: function(context) { + $('.bef-select-as-links', context) + .once('bef-select-as-links') + .find('.form-type-bef-link a').click(function (event) { + event.preventDefault(); + event.stopPropagation(); + + var $link = $(this); + var $linkWrapper = $link.closest('.form-type-bef-link'); + + var $setWrapper = $linkWrapper.closest('.bef-select-as-links'); + var $hiddenElement = null; + if ($setWrapper.hasClass('bef-select-as-links-multiple')) { + // Toggle state of the individual hidden element for the clicked link. + $hiddenElement = $('#' + ($linkWrapper.attr('id')) + '-hidden'); + + if ($hiddenElement.prop('disabled')) { + $hiddenElement.prop('disabled', false); + $linkWrapper.addClass('selected'); + } + else { + $hiddenElement.prop('disabled', true); + $linkWrapper.removeClass('selected'); + } + } + else { + // Set state and value of the single hidden element for the filter. + $hiddenElement = $('#' + ($setWrapper.parent().attr('id')) + '-hidden'); + + if ($setWrapper.hasClass('bef-select-as-links-toggle')) { + if (!$linkWrapper.hasClass('selected')) { + $setWrapper.find('.form-type-bef-link').removeClass('selected'); + $linkWrapper.addClass('selected'); + } + var sort_key = $link.data('bef-select-as-links-toggle-key'); + var sort_dir = $link.data('bef-select-as-links-toggle-dir'); + $hiddenElement.attr('value', sort_key + ' ' + sort_dir); + + // Update the link's text, href, and direction data attribute. + var new_sort_dir = (sort_dir == 'ASC') ? 'DESC' : 'ASC'; + $link.html( + Drupal.settings.better_exposed_filters['select-as-links-toggle'][sort_key]['label'] + + ' ' + + Drupal.settings.better_exposed_filters['select-as-links-toggle'][sort_key][new_sort_dir] + ); + $link.attr('href', $link.attr('href').replace(sort_key + '%20' + sort_dir, sort_key + '%20' + new_sort_dir)); + $link.data('bef-select-as-links-toggle-dir', new_sort_dir); + } + else { + $setWrapper.find('.form-type-bef-link').removeClass('selected'); + if ($linkWrapper.hasClass('selected')) { + $hiddenElement.attr('value', ''); + $hiddenElement.prop('disabled', true); + } + else { + $hiddenElement.attr('value', $link.data('bef-select-as-links-value')); + $hiddenElement.prop('disabled', false); + $linkWrapper.addClass('selected'); + } + } + } + + var $form = $hiddenElement.closest('form'); + // @see ctools/js/auto-submit.js + if ($form.hasClass('ctools-auto-submit-full-form')) { + $form.find('.ctools-auto-submit-click').click(); + } + }); + } + }; + /* * Helper functions */ diff --git a/better_exposed_filters.theme b/better_exposed_filters.theme index 61b973f..4f10c04 100644 --- a/better_exposed_filters.theme +++ b/better_exposed_filters.theme @@ -445,8 +445,15 @@ function theme_select_as_links($vars) { $element['#value'] = filter_xss($element['#value']); } + $multiple = !empty($element['#multiple']); + $sort_toggle = ($element['#name'] == 'sort_bef_combine' && !empty($element['#settings']['toggle_links'])); + // Go through each filter option and build the appropriate link or plain text foreach ($element['#options'] as $option => $elem) { + if (!empty($element['#hidden_options'][$option])) { + continue; + } + // Check for Taxonomy-based filters if (is_object($elem)) { $slice = array_slice($elem->option, 0, 1, TRUE); @@ -466,24 +473,68 @@ function theme_select_as_links($vars) { } $links = array(); - $multiple = !empty($element['#multiple']); foreach ($element_set as $key => $value) { - // Custom ID for each link based on the '; - } - } - else { - $output .= ''; - } + $output_classes = array( + 'bef-select-as-links', + ); + if ($multiple) { + $output_classes[] = 'bef-select-as-links-multiple'; } + if ($sort_toggle) { + $output_classes[] = 'bef-select-as-links-toggle'; + } + $output = '
'; + $output .= theme('form_element', array('element' => $properties)); $output .= '
'; + if (!$multiple) { + $hidden_element = array( + '#type' => 'hidden', + '#name' => $name, + '#value' => $element['#value'], + '#attributes' => array( + // Hidden doesn't output #id value. + 'id' => drupal_html_id($element['#id'] . '-hidden'), + ), + ); + $output .= theme('hidden', array('element' => $hidden_element)); + } return $output; } diff --git a/better_exposed_filters_exposed_form_plugin.inc b/better_exposed_filters_exposed_form_plugin.inc index cb8ce14..f72ff2b 100644 --- a/better_exposed_filters_exposed_form_plugin.inc +++ b/better_exposed_filters_exposed_form_plugin.inc @@ -71,6 +71,7 @@ class better_exposed_filters_exposed_form_plugin extends views_plugin_exposed_fo '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.'), ); @@ -396,6 +397,10 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al '#title' => $form['sort_by']['#title'], // Already sanitized by Views ); $options = array(); + // If using the bef_toggle_links format, determine which links should + // not be shown. + $hidden_options = array(); + $toggle_js_settings = array(); // Add reset sort option at the top of the list if ($settings['sort']['advanced']['reset']) { @@ -406,8 +411,14 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al } $selected = ''; + $used_sort_keys = array(); foreach ($form['sort_by']['#options'] as $by_key => $by_val) { + $toggle_js_settings[$by_key] = array( + 'label' => $by_val, + ); foreach ($form['sort_order']['#options'] as $order_key => $order_val) { + $toggle_js_settings[$by_key][$order_key] = $order_val; + // Use a space to separate the two keys, we'll unpack them in our submit handler $options["$by_key $order_key"] = "$by_val $order_val"; @@ -416,9 +427,28 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al // will be the first one if there are multiple sort criteria. $selected = "$by_key $order_key"; } + if ($settings['sort']['bef_format'] == 'bef_toggle_links') { + if (isset($used_sort_keys[$by_key]) + || (!empty($form_state['input']['sort_bef_combine']) && $form_state['input']['sort_bef_combine'] == "$by_key $order_key") + || (empty($form_state['input']['sort_bef_combine']) && $selected == "$by_key $order_key") + ) { + $hidden_options["$by_key $order_key"] = "$by_val $order_val"; + } + else { + $used_sort_keys[$by_key] = $order_key; + } + } } } + if ($settings['sort']['bef_format'] == 'bef_toggle_links') { + drupal_add_js(array( + 'better_exposed_filters' => array( + 'select-as-links-toggle' => $toggle_js_settings + ), + ), 'setting'); + } + // Rewrite the option values if any were specified if (!empty($settings['sort']['advanced']['combine_rewrite'])) { $lines = explode("\n", $settings['sort']['advanced']['combine_rewrite']); @@ -442,6 +472,10 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al $form['sort_bef_combine'] = array( '#type' => 'radios', '#options' => $options, + '#hidden_options' => $hidden_options, + '#settings' => array( + 'toggle_links' => ($settings['sort']['bef_format'] == 'bef_toggle_links'), + ), '#default_value' => $selected, '#title' => $form['sort_by']['#title'], // Already sanitized by Views ); @@ -454,6 +488,7 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al break; case 'bef_links': + case 'bef_toggle_links': $form['sort_bef_combine']['#theme'] = 'select_as_links'; break; @@ -716,6 +751,7 @@ Title Desc|Z -> A Leave the replacement value blank to remove an option al $show_apply = TRUE; $form[$field_id]['#theme'] = 'select_as_links'; + $form['#attached']['js'][] = drupal_get_path('module', 'better_exposed_filters') . '/better_exposed_filters.js'; break; case 'bef_single':