Hello,

I've been doing a lot of research on this topic, and there seems to be nothing out there that really does this much needed feature. I have a fairly standard scenario: posts that can be tagged with Country/State/City. Country is a distant parent of State, which is a distant parent of City. The input works wonderful, but there is no real way to display the output. I don't want to go with embedding a view inside a category, which works alright, but I need extended Views functionality.

What I'm looking for is to create simple dependent exposed views filters based on distant parent/child relationship. So when I come to a view and select a country, a list of states populates, etc.

I'm thinking of just using template.php, as it's the easiest way to have access to the filters.

Here's the basic idea:

function phptemplate_views_display_filters_VIEW_NAME($view) {
  $form = drupal_retrieve_form('views_filters', $view);

  if ($form['filter0']['#default_value'] == 'event') {
    unset($form['filter1']);
  }

  drupal_process_form('views_filters', $form);
  return drupal_render_form('views_filters', $form);
}

In the above example, I do a simple conditional check, that if in the first filter "Event Calendar" is selected, take off the second filter, which is not related to events is taken out.

Using the same principle I want to do this:

First, create three filters:
[country]
[state]
[city]

hide [state]
hide [city]

if (filter[country] == selected) {
  show [state]
  remove all options that don't have distant parent of selected country
}

if (filter[state] == selected)
  show [city]
  remove all options that don't have distant parent of selected state
}

Pretty simple, right?

First I want to create this without AJAX, just based on simple "Submit", getting the selected value from $form['filter0']['#default_value'], and then apply the AJAX jQuery to the process.

Questions I have so far:
* How can I check for a distant parent of a particular node?
* How can I do a onSelect jQuery call?
* How do I dynamically populate a select box using AJAX?

Help, feedback and ideas are very much appreciated!

Andrey.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mr.andrey’s picture

OK, the principle here seems to work, and can be easily applied to the Cities.

  // COUNTRY
  $selected_country = $form['filter2']['#default_value']; // get the selected country cid
  // END COUNTRY

  // STATE/PROVINCE
  $options = $form['filter3']['#options']; // array of states/provinces

  // ... code to remove options you don't want ...
  foreach ($options as $option => $text) {
    $parents = category_get_parents($option, 'cid', true);
    $parent = $parents[0]->cid;
    if ($parent != $selected_country) { // state/province parent doesn't match the selected country
      unset($options[$option]); // remove it from the list
    }
  }
  $form['filter3']['#options'] = $options;

  // don't display the states/provinces filter if there are no results
  if (empty($form['filter3']['#options'])) {
  	drupal_set_message('unset filster3');
  	unset($form['filter3']);
  }
  // END STATE/PROVINCE

Can anyone help me with jQuery to make this all dynamic, so when I select a country, the state/province box appears and gets populated?

mr.andrey’s picture

OK, got all of this working with Ajax. It's too complex to try to explain, so I will just attach a screenshot to this post and instructions on how to set it up to the next.

What this does (see screenshot):
* Use Active Select and to create Dependent Drop-downs from Views' Exposed Filters based on Distant Parent relationships, so when someone clicks on a country, the list of states/provinces in populated, etc.
* Counts how many nodes there are in each category and put the number there.
* Counts dependent of the classified type (left column), so when someone selects "For sale", the country/state/city lists only count the nodes for that type.

This is truly an amazing feature to have, as it integrates the wonderful ajax Category's distant-parent dependent drop-downs on the input of a node and (the all-powerful) Views for output. IMO this should be integrated into the category module, as it will open up amazing possibilities for output listing, but I see that it will be quite complicated to do that. All the pieces are there, so if the developers are interested, this is a good starting point.

Best,
Andrey.

mr.andrey’s picture

Attached are all the instructions on how to get this going. It includes:
* small patch for category.module
* styles.css additions for general UI
* template.php functions
* custom filter template that is called from template.php - views_classifieds.tpl.php
* view setup instructions

note: I'm using Vim and have folds set up that get triggered by //{ and //}, so if you too are using Vim, adding those fold triggers will make it much more readable and organized, otherwise just ignore them.

This is solid and works great, it also degrades gracefully to a non-javascript/activeselect version. I'm planning to port this to an Event Calendar view as well for local events, as there isn't really anything now that supports nice browsing through local events. Eventually I will add Group functionality to the Event view interface.

Good luck!
Andrey.

mr.andrey’s picture

FileSize
16.54 KB

Updated template.php functions, fixes.

rvarkonyi’s picture

Wow!

This looks great, just what I'm looking for! Is there any way you could create a drupal module of these codes?

I'm sure there would be a lot of interest in that!

Thanks!

cr

mr.andrey’s picture

I have too many projects going on at the moment, so I don't think I'll be making a module of this anytime soon.

Sorry.

It is stable, however, and we've used this on a production community site (transformationteam.net).

Andrey.

frdesign’s picture

Do you think this code would work in D6? I'm want to create a travel site so most of my content would be tagged by location.

As a side note, how did you geotag your content? I tried Calais for auto tagging but it's not very consistent with locations. I'm looking into geonames but there isn't much info for newbies like me.

mr.andrey’s picture

It might need a bit of tweaking to get Drupal 6 to work, try it out. It's been a while since I wrote this thing, and right now I'm not planning on any further development.

In our case, we are using it as an events/classified setup, and the site is closed membership, so we know the user's location before they join. We then create the appropriate city/state/country categories for them before we approve their application. People can then tag posts with the proper categories using the default category interface.

Hope this helps,
Andrey.

inforeto’s picture

Subscribing.

Good ideas here, it'd be worth to take a look at making it generic as there are plenty of use cases like brand/model, etc.

inforeto’s picture

Both category_activeselect_filter() and the original category_activeselect() do load the whole tree of categories for the value of 'all'.
Performance can be improved by printing drupal_to_js with preselected values for the initial page load.

Something like this:

  if (isset($array['**ALL**'])) {
    $options = array();
    $multiple = FALSE;

    $key = '**ALL**';
    $value = '<All>';
    $options[$key]['value'] = $value;
    $output['filter1'] = array('options' => $options, 'multiple' => $multiple);

    $value = ' - - - - - - - - ';
    $options[$key]['value'] = $value;
    $output['filter2'] = array('options' => $options, 'multiple' => $multiple);

    activeselect_set_header_nocache();
    print drupal_to_js($output);
    return;
  }

This would only affect /category/activeselect/filter1/filter2/**ALL**%7C%All%3E/3%2CArray%2Ccontent_type
Any further calls to /category/activeselect with other values would work as normal.

druplicate’s picture

Isn't this effort a duplicate of the Hierarchical Select module that appears to be almost ready for release to support content taxonomy and Views filters?

http://drupal.org/node/342991
http://drupal.org/node/342992

I need a dependent filter selection process that doesn't use taxonomy however, and posted that feature request here: http://drupal.org/node/526956

I need a filter selection process that just displays a different column in a DB table based on the drop down selection. At the moment it seems the only way to solve that problem is to use some conditional logic in the template.php file, or in the tpl.php file.

inforeto’s picture

Hierarchical Select isn't compatible with Category in 5.x, not sure which filter is used in 6.x
Activeselect was developed to work with distant parents, which only belong to Category.