When creating a datetime field in other areas of drupal DateAPI allows you to order a select list of year values in the reverse of the default (with the largest date at the top instead of at the bottom). This is done by indicating a range of "+3:-3" instead of the default "-3:+3". But when I try to do something similar with the date filter (as my employer is very particular about the order of the date-select list), views tells me that I'm not following the right format. Would it be possible to remove this limitation, since dateAPI doesn't seem to actually have a problem with handling ranges in this format?

I can reverse the absolute date range, but the restriction exists for relative.

Thanks!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

KarenS’s picture

Title: Date filter prevents reversal of select list order » Reverse select list order
Category: bug » feature

I'm confused. I can't actually see any place in the Date API where this would work. Where are you able to do this and get a reverse order? And if you want things to work differently, can you provide a patch to do what you are trying to do?

Making it work would be a fine feature request, but it wasn't designed that way and I can't see any place that it will work that way now.

patcon’s picture

Sorry, I update my post later with that final line, but it was a little vague: I can't reverse the order wih relative dates anywhere, but I can with absolute dates in the filter date range input (with the "select" option) so that the filter can list either forwards or backwards.

okokokok’s picture

Version: 6.x-2.1 » 6.x-2.4
Assigned: Unassigned » okokokok

Merely taking out the check in date_api_filter_handler.inc::extra_options_validate() is not enough.

donquixote’s picture

Here is what you can do:

in date_api.module,
function date_range_years(),
line 2460 ff (EDIT: line number applies to an older version of date module)

<?php
  if (!empty($value_year)) {
    if ($min_year > $max_year) {
      // reverse order of years in the select item.
      $min_year = max($value_year, $min_year);
      $max_year = min($value_year, $max_year);
    } else {
      $min_year = min($value_year, $min_year);
      $max_year = max($value_year, $max_year);
    }
  }
?>

(ok, yes, i will make this a patch soon)

And probably you should change the validation in
date_api_filter_handler.inc::extra_options_validate()
maybe reusing the date_range_years() function.

donquixote’s picture

FileSize
1.89 KB

I was on the wrong version, resulting in wrong line numbers.
The following patch is against HEAD, but I have no idea if it works.

okokokok’s picture

Assigned: okokokok » Unassigned
Status: Active » Needs review

Works well for me!

aidanlis’s picture

Doesn't work for me ... the input is accepted but the list of years is not shown, only the selected year is shown in the drop down.

donquixote’s picture

Are you using the patch #5 on the lates dev version?
And are you talking about views filters or about node creation?
(on my test install it works well in both)
What exactly did you type in the configuration?

benkewell’s picture

currently running into the same issue on my view list
want to order the exposed date filter options in reverse order

although i believe it should be the date filter to handle reverse year range values,
the code below is what i used to solve the issue without hacking into date.module code

/**
 * Implementation of hook_form_alter().
 */
function ssms_members_views_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form') {
    $view = $form['#parameters'][1]['view'];
    if ($view->name == 'ssms_members' && $view->current_display == 'person_list') {
      $form['birthday']['#after_build'][] = 'ssms_members_views_views_exposed_form_birthday_after_build';
    }
  }
}

/**
 * After build handler for birthday element on views exposed form of view ssms_members
 */
function ssms_members_views_views_exposed_form_birthday_after_build($element, &$form_state) {
  $options =& $element['value']['year']['#options'];
  $year_label = array_shift($options);
  $options = array_reverse($options);
  array_unshift($options, $year_label);
  return $element;
}

put the code in a new module and enable it
of course the code has to be modified to suite your site
the idea is to use hook_form_alter to hook into views exposed form
if it's the exposed form that need to be modified,
use #after_build to rewrite select options order before rendering

deviantintegral’s picture

Version: 6.x-2.4 » 6.x-2.x-dev
FileSize
1.81 KB
24.51 KB

I don't think the patch in #5 is needed anymore since #977002: #date_year_range breaks when #default_value is set on a date_select field got committed. Either way, I think a much cleaner method is to have a flag to indicate that the years should be reversed. The attached patch adds a #date_year_range_reverse flag, that when TRUE reverses the order of the years.

patcon’s picture

@deviantintegral, I appreciate the effort in making the patch, but my vote is still for simply switching the order of the text field components. I think that makes sense, as long as it's prominently and concisely explained in the help.

Actually... if this could be granular for months and dates as well, then maybe a checkbox wooouuuld make more sense...

deviantintegral’s picture

I agree; that would be better DX. However, I don't think date_popup supports that, so unless we do a patch upstream to support that in the JS for the popup calendar. I did think about reversing days and months as well, I just couldn't think of a situation where that was needed. But if we did go that route, I'd suggest renaming the property to #date_display_reverse, containing an array with possible values 'days', 'months', and 'years'.

LGLC’s picture

Thanks deviantintegral. I used your patch but added in a couple of extra lines to ensure the default element stays as the first choice (which is a blank year in my case):

// Retain the default element in the first position of the array
$default_element = array_shift($sub_element[$field]['#options']);
krsort($sub_element[$field]['#options']);
array_unshift($sub_element[$field]['#options'], $default_element);

I have a lovely Date of Birth field now. Thanks!

rvilar’s picture

Subscribe

alit’s picture

@BenKewell, thanks for the snippet! #9 needs one small correction - must call array_reverse with the second parameter to preserve array keys:

$options = array_reverse($options, TRUE);

The same solution for D7:

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  // Birth date: years in reverse order.
  $form['field_birthday']['und']['#after_build'][] = '_reverse_years';
}

function _reverse_years($element, &$form_state) {
  $options = &$element[0]['value']['year']['#options'];
  $year_label = array_shift($options);
  $options = array_reverse($options, TRUE);
  array_unshift($options, $year_label);
  return $element;
}
alit’s picture

UPD: #15 doesn't work properly. Here is the correct code:

function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  // Birth date: years in reverse order.
  $form['field_birthday']['und']['#after_build'][] = '_reverse_years';
}

function _reverse_years($element, &$form_state) {
  $options = &$element[0]['value']['year']['#options'];
  $label = array_slice($options, 0, 1, TRUE);
  $reverse_years = array_reverse(array_slice($options, 1, NULL, TRUE), TRUE);
  $options = $label + $reverse_years;
  return $element;
}
Stephen Ollman’s picture

This finally worked for me in D7.

Custom module called 'date_reverse'.

Replace 'media' with your view name. or remove the view validation if you don't want to limit it to a view.

*********************
<?php

/**
* Implementation of hook_form_alter().
*/

function date_reverse_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'views_exposed_form') {
$view = $form_state['view'];
if ($view->name == 'media') {
$form['date_filter']['#after_build'][] = 'date_reverse_views_exposed_form_date_order';
}
}
}

function date_reverse_views_exposed_form_date_order($element, &$form_state) {
$options = &$element['value']['year']['#options'];
$label = array_slice($options, 0, 1, TRUE);
$reverse_years = array_reverse(array_slice($options, 1, NULL, TRUE), TRUE);
$options = $label + $reverse_years;
return $element;
}

deviantintegral’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev

Amazingly, the patch in #10 applies directly to 7.x-2.x and is working fine for me. No matter what direction this issue goes, it should be for 7.x anyways.

podarok’s picture

Issue summary: View changes
Status: Needs review » Active

bot restart

podarok’s picture

Status: Active » Needs review
pedrosp’s picture

Using Date 7.x-2.8, and dealing with a birthdate field with form API, default date should be NULL, and year select list as descendant.

Here's my recipe:
As @devianintegral said in #18, patch #10 against date/date_api/date_api_elements.inc still applies.
There is 4 parts on the patch, but the last one failed:
- Update of info text about #date_year_range_reverse
- Declaration of a new option/flag: #date_year_range_reverse and set it as FALSE as default
- Update of the function that create the select list and reverse if flag is true
- FAILED function date convert update? // no such function present, seems not to affect desired output.

Manual modification of date_api_elements after patch:

      case 'year':
        $range = date_range_years($element['#date_year_range'], $date);
        $min_year = $range[0];
        $max_year = $range[1];

        $sub_element[$field]['#default_value'] = is_object($date) ? $date->format('Y') : '';
        if ($part_type == 'select') {
        
          $sub_element[$field]['#options'] = drupal_map_assoc(date_years($min_year, $max_year, $part_required));
//start of patched code modified 
          if ($element['#date_year_range_reverse']) {
            krsort($sub_element[$field]['#options']);           
          }
//end of patched code modified
        }
        break;

Sorry not to provide an updated patch, still no such skills yet.

UPDATE/EDIT 12 oct 2014
Simpler code, and I removed the array pop/unshift logic because keys were reseted.

podarok’s picture

Status: Needs review » Patch (to be ported)
nerdcore’s picture

Status: Patch (to be ported) » Closed (duplicate)
Related issues: +#206127: Add ability to sort Views exposed filters SELECT lists in reverse

I believe this has been resolved in #206127