I've created a sample module that creates a new block which allows you to filter by Taxonomy term. The code is very clearly documented, to make it easier for you to adapt it to your needs.

The block is defined by a hook_block() implementation:

/**
 * Implementation of hook_block().
 */
function hs_taxonomy_filter_block_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks['hs-taxonomy-filter'] = array(
      'info'   => t('Hierarchical Select term filter'),
      'weight' => 0,
      'region' => 'left',
      'cache'  => BLOCK_NO_CACHE, // Drupal Forms may never be cached.
    );
    return $blocks;
  }
  else if ($op == 'view') {
    switch($delta) {
      case 'hs-taxonomy-filter':
        $block['subject'] = t('Filter by term');
        $block['content'] = drupal_get_form('hs_taxonomy_filter_block_form');
        return $block;
    }
  }
}

Besides that, there are a form definition function and a form submit callback:

/**
 * Form definition function; Hierarchical Select Taxonomy Filter Block form.
 */
function hs_taxonomy_filter_block_form($form_state) {
  $form['filter'] = array(
    '#type' => 'hierarchical_select',
    '#title' => t('Filter by term'),
    '#description' => t('This is a pointless description.'),
    // Consult API.txt for an explanation of all these settings.
    '#config' => array(
      'module' => 'hs_taxonomy',
      'params' => array(
        'vid' => 1, // Enter your vocabulary ID here.
        'root_term' => NULL, // Enter a term ID here if you want to display only terms below the term with that ID.
      ),
      'save_lineage'    => 0,
      'enforce_deepest' => 1,
      'entity_count'    => 0,
      'require_entity'  => 0,
      'resizable'       => 1,
      'level_labels' => array(
        'status' => 1,
        'labels' => array(
          0 => t('Continent'),
          1 => t('Country'),
          2 => t('State or province'),
          2 => t('City'),
        ),
      ),
      'dropbox' => array(
        // Only allow for a single term or single lineage to be selected.
        'status' => 0,
      ),
      'editability' => array(
        // Creating new terms from within a form to filter by existing terms
        // doesn't make sense, hence it is disabled.
        'status' => 0,
      ),
    ),
    '#default_value' => array(), // To set a default value, fill this with one or more term IDs.
  );

  $form['apply'] = array(
    '#type' => 'submit', 
    '#value' => t('Apply'),
  );

  return $form;
}

/**
 * Form submit callback; Hierarchical Select Taxonomy Filter Block form.
 */
function hs_taxonomy_filter_block_form_submit($form_id, &$form_state) {
  $value = $form_state['values']['filter'];

  // Create an array containing all the term names that have been selected.
  // Even when only a single term has been submitted (i.e. when the dropbox is
  // disabled).
  $terms = array();
  if (is_array($value)) {
    foreach ($value as $term_id) {
      $term = taxonomy_get_term($term_id);
      $terms[] = $term->name;
    }
  }
  else {
    $term = taxonomy_get_term($value);
    $terms[] = $term->name;
  }

  // Maybe you want to display a message?
  $output = t('The following term(s) have been selected: !terms.', array('!terms' => implode(', ', $terms)));
  drupal_set_message($output);

  // Or redirect the user?
  $tid = (is_array($value)) ? reset($value) : $value; // If multiple values are selected, use the first.
  drupal_goto("taxonomy/term/$tid");
}

That's it :)

The sample submit callback does two things:

  1. It displays a message mentioning the selected term(s).
  2. It redirects the user to the term page

These are just examples of what you can do in the submit callback, of course. You can do anything you want.

A .zip file containing this module is attached. Happy Hierarchical Selecting!

AttachmentSize
hs_taxonomy_filter_block.zip3.01 KB

Comments

elpy’s picture

When modifying the last lines to the following code, users are redirected to the term's page at its correct path alias.
This is working fine even with pathauto and taxonomy_redirect.

  // Or redirect the user?
  $tid = (is_array($value)) ? reset($value) : $value; // If multiple values are selected, use the first.
  $term_path_alias = drupal_get_path_alias( taxonomy_term_path( taxonomy_get_term($tid) ) );
  drupal_goto($term_path_alias);

Thanks a lot for the module and this filter block code!

smitty’s picture

The above code - written for D6 - can also be used with Hierarchical Select 5.x-3.7.

All yo have to do is to change two lines:

function hs_taxonomy_filter_block_form($form_state) {

should become

function hs_taxonomy_filter_block_form() {

And

function hs_taxonomy_filter_block_form_submit($form_id, &$form_state) {
  $value = $form_state['values']['filter'];

mut be changed to

function hs_taxonomy_filter_block_form_submit($form_id, $form_values) {
  $value = $form_values['filter'];
faridjame’s picture

Is there any way to combine this with CCK fields? More specifically, I'd like to accomplish the following:

I have a product (ubercart product), that has three fields.

1) First one is using Hierarchical Select to select manufacturer/category/subcategory (all defined in taxonomy)
2) Second field is the series number
3) Third field is the part number

Using the above sample, I'm able to accomplish the first part, which deals with taxonomies. Is it possible to modify this sample module to include the cck fields in the drop downs too?

Thanks for any help

venusrising’s picture

Is there any way to alter the vid to vids so it can pull multiple vocabularies? I have been playing with it but have not gotten the syntax to work right.

Thanks for anyone that may reply.

venusrising

drupalinside’s picture

Very usefull!
But after submission select became empty.
How hs can remember lineage selected?

thanks

adityamenon’s picture

Yet again, you seem to know exactly what I'm looking for! Amazing stuff, thanks a lot!

I've implemented a Jump menu using this, and a little custom jquery - I was so lucky to have stumbled across this, while trying to write my own module which does exactly what this little module does!

Like I said, amazing.

calculus’s picture

Thank you for your script, but i want to get terms only that are associated with nodes.

I use this script, with options below enabled:

      'entity_count'    => 1,
      'require_entity'  => 1,

but nothing happens. What do i do wrong?

ps. I have modify this script for D7.

haysuess’s picture

I'm having trouble setting a root term. I have a vocabulary like the following:

Parent 1
--Child 1
Parent 2
--Child 2
----Grandchild 2
------GGrandchild 2
----Grandchild 2-2
Parent 3
--Child 3

I want the dropdown only to show Parent 2 and its subcategories, so I figured I could change this from NULL to 35 since Parent 2 is term 35, but it doesn't change anything:

'root_term' => 35, // Enter a term ID here if you want to display only terms below the term with that ID.

Any ideas?

yuseferi’s picture

my idea was

function mymodule_alter_form_alter(&$form, &$form_state, $form_id) {
	
	if($form_id == 'myform_node_form')
	{	
	$form['field_myfield']['und']['#config']['params']['root_term']=53;
}

but not worked for me , any body have another idea about this?

I have be born to be mankind

rudins’s picture

Did you managed to work it out?

adrianalbisser’s picture

Has anyone successfully ported this to D7?

Buliwyfa’s picture

+1 to D7 port ^^

Luke Harrison’s picture

//----------------------------------------------------------------------------
// Drupal core hooks.

/* =============================================================================
   Blocks
   ========================================================================== */

/**
 * Implements hook_block_info().
 */
function hs_taxonomy_filter_block_block_info() {
	$blocks['hs-taxonomy-filter'] = array(
      'info'   => t('Hierarchical Select term filter'),
      'weight' => 0,
      'region' => 'left',
    );
	return $blocks;
}

/**
 * Implements hook_block_view().
 */
function hs_taxonomy_filter_block_block_view($delta = '') {
	$block = array();
	switch($delta) {
		case 'hs-taxonomy-filter':
			$block['subject'] = t('Filter by term');
			$block['content'] = drupal_get_form('hs_taxonomy_filter_block_form');
		break;
	}
	return $block;
}


//----------------------------------------------------------------------------
// Forms API callbacks.


/**
 * Form definition function; Hierarchical Select Taxonomy Filter Block form.
 */
function hs_taxonomy_filter_block_form($form_state) {
  $vid = 1;
  $form['filter'] = array(
    '#type' => 'hierarchical_select',
    '#title' => t('Select the tag you wish to use.'),
    '#size' => 1,
    '#config' => array(
      'module' => 'hs_taxonomy',
      'params' => array(
        'vid' => $vid,
      ),
      'save_lineage'    => 0,
      'enforce_deepest' => 0,
      'entity_count'    => 0,
      'require_entity'  => 0,
      'resizable'       => 0,
      'level_labels' => array(
        'status' => 0,
        'labels' => array(
          0 => t('Main category'),
          1 => t('Subcategory'),
          2 => t('Third level category'),
        ),
      ),
      'dropbox' => array(
        'status'   => 0,
        'title'    => t('All selections'),
        'limit'    => 0,
        'reset_hs' => 1,
      ),
      'editability' => array(
        'status'           => 0,
        'item_types'       => array(),
        'allowed_levels'   => array(
          0 => 0,
          1 => 0,
          2 => 1,
        ),
        'allow_new_levels' => 0,
        'max_levels'       => 3,
      ),
      // These settings cannot be configured through the UI: they can only be
      // overridden through code.
      'animation_delay'    => 400,
      'special_items'      => array(),
      'render_flat_select' => 0,
    ),
  );

  $form['apply'] = array(
    '#type' => 'submit', 
    '#value' => t('Apply'),
  );

  return $form;
}

/**
 * Form submit callback; Hierarchical Select Taxonomy Filter Block form.
 */
function hs_taxonomy_filter_block_form_submit($form_id, &$form_state) {
  $value = $form_state['values']['filter'];

  // Create an array containing all the term names that have been selected.
  // Even when only a single term has been submitted (i.e. when the dropbox is
  // disabled).
  $terms = array();
  if (is_array($value)) {
    foreach ($value as $term_id) {
      $term = taxonomy_term_load($term_id);
      $terms[] = $term->name;
    }
  }
  else {
    $term = taxonomy_term_load($value);
    $terms[] = $term->name;
  }
  // Maybe you want to display a message?
  $output = t('The following term(s) have been selected: !terms.', array('!terms' => implode(', ', $terms)));
  drupal_set_message($output);

  // Or redirect the user?
  $tid = (is_array($value)) ? reset($value) : $value; // If multiple values are selected, use the first.
  drupal_goto("taxonomy/term/$tid");
}

dalegrebey’s picture

How to remove the initial and blank options from the select list?

dalegrebey’s picture

In template.php:

/**
 * Override Hierarchical Select Options for None
 */
function mytheme_hierarchical_select_special_option($option) {
  $option = 'Select State';
  return $option;
}

...may be good to add an if statement

If ($option == 'none') {
  // Do Something
}
dalegrebey’s picture

I also noticed that this causes a conflict with the module itself when you use it for content editing which does not seem to allow the second drop down to work.

dalegrebey’s picture

This function, hs_taxonomy_filter_block_form($form_state), that sets up the block configuration for Hierarchical Select, conflicts with Hierarchical Select as a field type widget when editing content. This should probably be reworked so that instead of re-defining settings here, it pulls the actual configuration settings and uses those. Perhaps I will look at that when I have a bit of spare time. I didn't specifically see what with this function was causing the conflict.

To resolve this issue, to insure that Hierarchical Select as a Block does not conflict with Hierarchical Select as a Field Widget, I simply wrapped that function with:

if (!strpos($_SERVER['REQUEST_URI'], 'node/add/')) {
  function hs_taxonomy_filter_block_form($form_state) {  
    // Function code as listed above
  }
}

I may look at making HS block functionality part of the module itself if possible, but for the time being. ...deadlines.

thummel’s picture

I tried to implement the module above but I'm getting:

Fatal error: Unsupported operand types in /home/ab51319/public_html/devel/sites/all/modules/hierarchical_select/hierarchical_select.module on line 1683

The only change I made was to rename the module name so it does not conflict with the hs_taxonomy module.

Please help.

Thanks,
Tracey

Daniele Belitrandi’s picture

I've ported this script in D7 and work perfectly. I would like to modify it but my knowledge is limited. ?

I would like to use this script to create a custom link code which can be copied to other website to link back.

I've disabled the last 3 lines:

// Or redirect the user?
$tid = (is_array($value)) ? reset($value) : $value; // If multiple values are selected, use the first.
drupal_goto("taxonomy/term/$tid");

I've changed the line

'save_lineage' => 0,

into

'save_lineage' => 1,

From the taxonomy term I select Italy > Florence > hotel
After I submit the button I get the message: "The following term(s) have been selected: Italy, Florence, Hotels.".

I would like to grab the term individually (not all 3 term together in a row) in order to construct my code.

The result should be something like this:

<a href="example.com/italy/florence/hotels">Hotels reservation in Florence, Italy</a> - Find the best hotels for your holiday in Florence, Italy

can someone help me with this ?

Thanks in advance