Index: API.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/API.txt,v
retrieving revision 1.57
diff -u -F^f -r1.57 API.txt
--- API.txt	25 Jul 2009 10:27:59 -0000	1.57
+++ API.txt	12 Aug 2009 16:13:38 -0000
@@ -78,8 +78,9 @@
       // These settings cannot be configured through the UI: they can only be
       // overridden through code.
       'animation_delay'    => 400,
-      'exclusive_lineages' => array(),
+      'special_items'      => array(),
       'render_flat_select' => 0,
+      'path'               => 'hierarchical_select_json',
     ),
     '#default_value' => '83',
   ); 
@@ -116,7 +117,10 @@
  - require_entity (optional, defaults to 0)
    Whether an item should only be displayed if it has at least one associated
    entity.
- 
+
+ - resizable (optional, defaults to 1)
+   Makes the hierarchical select resizable.
+
  - level_labels['status'] (optional, defaults to 0)
    Whether level labels should be enabled or not. When save_lineage is
    enabled, this will result in *empty* level labels.
@@ -180,10 +184,35 @@
  - animation_delay (optional, defaults to 400)
    The delay of each animation (the drop in left and right animations), in ms.
 
- - exclusive_lineages (optional, defaults to the empty array)
-   Sometimes, it's desirable to have exclusive lineages. When one of these
-   lineages is selected, the user should not be able to select anything else.
-   e.g. the **ALL** option in Views exposed filters.
+ - special_items (optional, defaults to the empty array)
+   Through this setting, you can mark each item with special properties it
+   possesses. There currently are two special properties: 'exclusive' and
+   'none'.
+   Note: you should include these items in the hierarchy as if it were a
+   normal item and then you can mark them as special through this property.
+   * 'exclusive': Sometimes it's desirable to have exclusive lineages. When
+                  such an option is selected, the user should not be able to
+                  select anything else. This also means that  nothing else in
+                  the dropbox can be selected: if the dropbox contains
+                  anything, it will be reset.
+                  Can be applied to multiple items.
+                  e.g. an 'entire_tree' item:
+                    'special_items' => array(
+                      'entire_tree' => array('exclusive'),
+                    )
+   * 'none': Sometimes you want to replace the default '<none>' option by
+             something else. This replacement should of course also exist in
+             the root level.
+             Can be applied to only one item.
+             e.g. an 'any' item (used in hs_taxonomy_views):
+               'special_items' => array(
+                 'any' => array('none', 'exclusive'),
+               )
+   And a final example for a better overview:
+    'special_items' => array(
+      'entire_tree' => array('exclusive'),
+      'any'         => array('none', 'exclusive'),
+    )
 
  - render_flat_select (optional, defaults to 0)
    Because the hierarchical_select form element consists of multiple form
@@ -194,8 +223,12 @@
    see the JavaScript events section for details) and you have a work-around
    (which, admittedly, only works when JS is enabled).
 
- - resizable (optional, defaults to 1)
-   Makes the hierarchical select resizable.
+ - path (optional, defaults to 'hierarchical_select_json')
+   The Drupal path at which a JSON object with Hierarchical Select update
+   information is available. In 99% of the cases, this will remain unchanged,
+   but for advanced use cases, e.g. Views, where an object is referenced by
+   the form in which Hierarchical Select is present and must this exist before
+   the form is rendered, this can be a work-around.
 3) We *don't* specify a list of options: Hierarchical Select automatically
 generates the options for us, thanks to the 'module' and 'params' settings.
 
@@ -391,7 +424,8 @@ for the HS_DEVELOPER_MODE constant to TR
 
   // Add the the submit handler for the Hierarchical Select config form.
   $parents = array('foobar_hierarchical_select_config');
-  $form['#submit']['hierarchical_select_common_config_form_submit'] = array($parents);
+  $form['#submit'][] = 'hierarchical_select_common_config_form_submit';
+  $form['#hs_common_config_form_parents'] = $parents;
 
 
 Configuration management
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/README.txt,v
retrieving revision 1.38
diff -u -F^f -r1.38 README.txt
--- README.txt	4 Aug 2009 22:34:18 -0000	1.38
+++ README.txt	12 Aug 2009 16:13:38 -0000
@@ -21,7 +21,7 @@
 * Menu (Drupal core)
 * Taxonomy (Drupal core)
 * Content Taxonomy (http://drupal.org/project/content_taxonomy) – NOT YET PORTED TO DRUPAL 6
-* Views – NOT YET PORTED TO DRUPAL 6
+* Views
 
 
 Installation
@@ -163,46 +163,6 @@ function.
 theme, create e.g. garland_hierarchical_select_selection_as_lineages().
 
 
-Addressing Views exposed filters display issues
------------------------------------------------
-When using Hierarchical Select to alter an exposed Views filter (i.e. an 
-exposed taxonomy filter), you may run into display issues due to the Views
-method theme_views_filters(), which renders filters as columns within a table.
-This results in behavior where the select boxes within the Hierarchical Select
-widget may split onto multiple lines or be too cramped together. The following
-theme override sample, written for the Zen theme, renders the filters as rows 
-within a table, leaving much more room for the Hierarchical Select widget. To
-use, follow the instructions for overriding theme functions described at 
-http://drupal.org/node/55126.
-
-<?php
-function zen_views_filters($form) {
-  $view = $form['view']['#value'];
-  $rows = array();
-  $form['submit']['#value'] = t('Search');
-  if (isset($view->exposed_filter)) {
-    foreach ($view->exposed_filter as $count => $expose) {
-      $rows[] = array(
-        array('data' => $expose['label'], 'header' => TRUE),
-        drupal_render($form["op$count"]) . drupal_render($form["filter$count"]),
-      );
-    }
-  }
-  $rows[] = array(
-    array('data' => '', 'header' => TRUE),
-    drupal_render($form['submit'])
-  );
-  if (count($rows) > 1) {
-    $output = drupal_render($form['q']) . theme('table', array(), $rows) . drupal_render($form);
-  }
-  else {
-    $output = drupal_render($form);
-  }
-  return $output;
-}
-?>
-
-
 Setting a fixed size
 --------------------
 When you don't want users to be able to resize a hierarchical select
@@ -231,6 +191,8 @@ function zen_views_filters($form) {
    The Worx Company, http://www.worxco.com.
 * Ability to only show items that are associated with at least one entity:
    Merge, http://merge.nl.
+* Views 2 support:
+   Merge, http://merge.nl.
 
 
 Author
Index: hierarchical_select.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/hierarchical_select.js,v
retrieving revision 1.94
diff -u -F^f -r1.94 hierarchical_select.js
--- hierarchical_select.js	27 Jul 2009 11:29:16 -0000	1.94
+++ hierarchical_select.js	12 Aug 2009 16:13:39 -0000
@@ -19,6 +19,11 @@
 };
 
 Drupal.HierarchicalSelect.initialize = function(hsid) {
+  // Prevent JS errors when Hierarchical Select is loaded dynamically.
+  if (undefined == Drupal.settings.HierarchicalSelect || undefined == Drupal.settings.HierarchicalSelect.settings[hsid]) {
+    return false;
+  }
+
   // If you set Drupal.settings.HierarchicalSelect.pretendNoJS to *anything*,
   // and as such, Hierarchical Select won't initialize its Javascript! It
   // will seem as if your browser had Javascript disabled.
@@ -500,7 +505,7 @@
   // server. If a client-side cache is found however, it's possible that this
   // won't be used.
   var ajaxOptions = {
-    url:        Drupal.settings.HierarchicalSelect.url,
+    url:        Drupal.settings.HierarchicalSelect.basePath + Drupal.settings.HierarchicalSelect.settings[hsid]['path'],
     type:       'POST',
     dataType:   'json',
     data:       post,
Index: hierarchical_select.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/hierarchical_select.module,v
retrieving revision 1.167
diff -u -F^f -r1.167 hierarchical_select.module
--- hierarchical_select.module	4 Aug 2009 22:34:18 -0000	1.167
+++ hierarchical_select.module	12 Aug 2009 16:13:41 -0000
@@ -119,8 +119,9 @@ function hierarchical_select_elements() 
         'max_levels'       => 3,
       ),
       'animation_delay'    => variable_get('hierarchical_select_animation_delay', 400),
-      'exclusive_lineages' => array(),
+      'special_items'      => array(),
       'render_flat_select' => 0,
+      'path'               => 'hierarchical_select_json',
     ),
     '#default_value' => -1,
   );
@@ -360,7 +361,7 @@ function hierarchical_select_json() {
 /**
  * Hierarchical select form element type #process callback.
  */
-function hierarchical_select_process($element, $edit, $form_state, $form) {
+function hierarchical_select_process($element, $edit, &$form_state, $form) {
   // The HSID is stored in the session, to allow for multiple Hierarchical
   // Select form items on the same page of which at least one is added through
   // AHAH. A normal static variable won't do in this case, because then at
@@ -392,27 +393,35 @@ function hierarchical_select_process($el
   // necessary to find this form item back in an AJAX callback.
   _hierarchical_select_store_name($element, $hsid);
 
+  // Get the config and convert the 'special_items' setting to a more easily
+  // accessible format.
+  $config = $element['#config'];
+  if (isset($config['special_items'])) {
+    $special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
+    $special_items['none']      = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
+  }
+
   // Set up Javascript and add settings specifically for the current
   // hierarchical select.
   $config = _hierarchical_select_inherit_default_config($element['#config']);
   _hierarchical_select_setup_js();
-  drupal_add_js(
-    array(
-      'HierarchicalSelect' => array(
-        'settings' => array(
-          $hsid => array(
-            'animationDelay'   => ($config['animation_delay'] == 0) ? (int) variable_get('hierarchical_select_animation_delay', 400) : $config['animation_delay'],
-            'cacheId'          => $config['module'] .'_'. implode('_', (is_array($config['params'])) ? $config['params'] : array()),
-            'renderFlatSelect' => (isset($config['render_flat_select'])) ? (int) $config['render_flat_select'] : 0,
-            'createNewItems'   => (isset($config['editability']['status'])) ? (int) $config['editability']['status'] : 0,
-            'createNewLevels'  => (isset($config['editability']['allow_new_levels'])) ? (int) $config['editability']['allow_new_levels'] : 0,
-            'resizable'        => (isset($config['resizable'])) ? (int) $config['resizable'] : 0,
-          ),
+   _hierarchical_select_setup_js($form_state);
+   $settings =  array(
+     'HierarchicalSelect' => array(
+       'settings' => array(
+         $hsid => array(
+           'animationDelay'   => ($config['animation_delay'] == 0) ? (int) variable_get('hierarchical_select_animation_delay', 400) : $config['animation_delay'],
+           'cacheId'          => $config['module'] .'_'. implode('_', (is_array($config['params'])) ? $config['params'] : array()),
+           'renderFlatSelect' => (isset($config['render_flat_select'])) ? (int) $config['render_flat_select'] : 0,
+           'createNewItems'   => (isset($config['editability']['status'])) ? (int) $config['editability']['status'] : 0,
+           'createNewLevels'  => (isset($config['editability']['allow_new_levels'])) ? (int) $config['editability']['allow_new_levels'] : 0,
+           'resizable'        => (isset($config['resizable'])) ? (int) $config['resizable'] : 0,
+           'path'             => $config['path'],
         ),
-      )
-    ),
-    'setting'
+       ),
+     )
   );
+  _hierarchical_select_add_js_settings($settings, $form_state);
 
   // Basic config validation and diagnostics.
   if (HS_DEVELOPER_MODE) {
@@ -458,10 +467,12 @@ function hierarchical_select_process($el
     }
   }
 
-  // If the exclusive_lineages setting has been configured, and the dropbox
-  // is enabled, then do the necessary processing to make exclusive lineages
-  // possible.
-  if (count($config['exclusive_lineages']) && $config['dropbox']['status']) {
+  // If:
+  // - the special_items setting has been configured
+  // - at least one special item has the 'exclusive' property
+  // - the dropbox is enabled
+  // then do the necessary processing to make exclusive lineages possible.
+  if (isset($config['special_items']) && count($special_items['exclusive']) && $config['dropbox']['status']) {
     // When the form is first loaded, $db_selection will contain the selection
     // that we should check, but in updates, $hs_selection will.
     $selection = (!empty($hs_selection)) ? $hs_selection : $db_selection;
@@ -469,23 +480,18 @@ function hierarchical_select_process($el
     // If the current selection of the hierarchical select matches one of the
     // configured exclusive items, then disable the dropbox (to ensure an
     // exclusive selection).
-    if (in_array($selection, $config['exclusive_lineages']) // A lineage.
-        || (count($selection) == 1 && in_array($selection[0], $config['exclusive_lineages']))) { // An item at the root level.
+    $exclusive_item = array_intersect($selection, $special_items['exclusive']);
+    if (count($exclusive_item)) {
       // By also updating the configuration stored in $element, we ensure that
       // the validation step, which extracts the configuration again, also gets
       // the updated config.
       $element['#config']['dropbox']['status'] = 0;
-
       $config = _hierarchical_select_inherit_default_config($element['#config']);
 
-      // When the form is first loaded, $db_selection contained the selection
-      // selection that we checked for. Since we've now disabled the dropbox,
-      // we should overwrite $hs_selection with the value of $db_selection and
-      // reset $db_selection.
-      if (empty($hs_selection)) {
-        $hs_selection = $db_selection;
-        $db_selection = array();
-      }
+      // Set the hierarchical select to the exclusive item and make the
+      // dropbox empty.
+      $hs_selection = array(0 => reset($exclusive_item));
+      $db_selection = array();
     }
   }
 
@@ -660,16 +666,14 @@ function hierarchical_select_process($el
 
   if (HS_DEVELOPER_MODE) {
     $element['log'] = array('#type' => 'value', '#value' => _hierarchical_select_log(NULL, TRUE));
-    drupal_add_js(
-      array(
-        'HierarchicalSelect' => array(
-          'initialLog' => array(
-            $hsid => $element['log']['#value'],
-          ),
+    $settings = array(
+      'HierarchicalSelect' => array(
+        'initialLog' => array(
+          $hsid => $element['log']['#value'],
         ),
       ),
-      'setting'
     );
+    _hierarchical_select_add_js_settings($settings, $form_state);
   }
 
   // If the form item is marked as disabled, disable all child form items as
@@ -790,15 +794,13 @@ function _hierarchical_select_validate(&
   if ($element['#disabled']) {
     $element['#return_value'] = $element['#default_value'];
   }
-  // If the array is empty, set 0 as the value, which the Forms API
-  // detects as an empty form value.
-  $value = (empty($element['#return_value'])) ? 0 : $element['#return_value'];
-  $element['#value'] = $value;
-  form_set_value($element, $value, $form_state);
+
+  $element['#value'] = $element['#return_value'];
+  form_set_value($element, $element['#value'], $form_state);
 
   // We have to check again for errors. This line is taken litterally from
   // form.inc, so it works in an identical way.
-  if ($element['#required'] && empty($element['#value']) && $element['#value'] !== '0') {
+  if ($element['#required'] && (!count($element['#value']) || (is_string($element['#value']) && strlen(trim($element['#value'])) == 0))) {
     form_error($element, t('!name field is required.', array('!name' => $element['#title'])));
   }
 }
@@ -808,7 +810,16 @@ function _hierarchical_select_validate(&
  */
 function _hierarchical_select_submit($form, &$form_state) {
   // Delete the stored form information when the form is submitted.
-  cache_clear_all($form_state['hs_form_build_id'], 'cache');
+  // [VIEWS] TRICKY: when using Views, which uses its own Forms API workflow
+  // instead of core's, this #submit callback is called even when there is
+  // nothing really there to submit. So to prevent our cache to be cleared,
+  // which would result in failing AHAH callbacks, we just prevent it from
+  // clearing the cache. This results in cache entries that aren't cleared
+  // immediately upon finishing use of the form, but that's acceptable in the
+  // end because the cache will be cleared anyway at some point.
+  if (isset($form_state['hs_form_build_id']) && !isset($form_state['view'])) {
+    cache_clear_all($form_state['hs_form_build_id'], 'cache');
+  }
 }
 
 
@@ -936,7 +947,12 @@ function _hierarchical_select_process_ca
   $dropbox = (bool) $config['dropbox']['status'];
   $op = $element['#post']['op'];
 
-  if (empty($element['#post'])) {
+  // When:
+  // - no data was POSTed,
+  // - or #value is set directly and not by a Hierarchical Select POST (and
+  //   therefor set either manually or by another module),
+  // then use the value of #default_value, or when available, of #value.
+  if (empty($element['#post']) || !isset($element['#value']['hierarchical_select'])) {
     $value = (isset($element['#value'])) ? $element['#value'] : $element['#default_value'];
     $value = (is_array($value)) ? $value : array($value);
     if ($dropbox) {
@@ -1178,7 +1194,7 @@ function _hierarchical_select_process_re
     '#type' => 'select',
     '#multiple' => ($config['save_lineage'] || $config['dropbox']['status']),
     '#options' => $options,
-    '#default_value' => array_keys($options),
+    '#value' => array_keys($options),
     // Use a #theme callback to prevent the select from being wrapped in a
     // div. This simplifies the CSS and JS code.
     '#theme' => 'hierarchical_select_select',
@@ -1239,6 +1255,7 @@ function _hierarchical_select_process_ca
     }
     $return_value = array_unique($return_value);
   }
+
   return $return_value;
 }
 
@@ -1278,21 +1295,29 @@ function _hierarchical_select_inherit_de
 
 /**
  * Helper function to add the required Javascript files and settings.
+ *
+ * @param $form_state
+ *   A form state array. Necessary to set the callback URL for Hierarchical
+ *   Select through _hierarchical_select_add_js_settings().
  */
-function _hierarchical_select_setup_js() {
+function _hierarchical_select_setup_js(&$form_state = NULL) {
   static $ran_once;
+  static $js_settings_added;
 
   $jquery_ui_components = array(
     'effects.core',
     'effects.drop',
   );
 
-  if (!$ran_once) {
-    $ran_once = TRUE;
-
+  if (!$js_settings_added && isset($form_state)) {
     $url = base_path();
     $url .= variable_get('clean_url', 0) ? '' : 'index.php?q=';
-    $url .= 'hierarchical_select_json';
+    _hierarchical_select_add_js_settings(array('HierarchicalSelect' => array('basePath' => $url)), $form_state);
+    $js_settings_added = TRUE;
+  }
+
+  if (!$ran_once) {
+    $ran_once = TRUE;
 
     // Add the CSS and JS, set the URL that should be used by all hierarchical
     // selects.
@@ -1315,7 +1340,6 @@ function _hierarchical_select_setup_js()
     else {
       jquery_ui_add($jquery_ui_components);
     }
-    drupal_add_js(array('HierarchicalSelect' => array('url' => $url)), 'setting');
   }
 }
 
@@ -1564,6 +1588,12 @@ function _hierarchical_select_log($item,
 function _hierarchical_select_hierarchy_generate($config, $selection, $required, $dropbox = FALSE) {
   $hierarchy = new stdClass();
 
+  // Convert the 'special_items' setting to a more easily accessible format.
+  if (isset($config['special_items'])) {
+    $special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
+    $special_items['none']      = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
+  }
+
 
   //
   // Build the lineage.
@@ -1603,7 +1633,7 @@ function _hierarchical_select_hierarchy_
   $selection = _hierarchical_select_hierarchy_validate($selection, $config['module'], $config['params']);
 
   // When nothing is currently selected, set the root level to:
-  // - "<none>" when:
+  // - "<none>" (or its equivalent special item) when:
   //    - enforce_deepest is enabled *and* level labels are enabled *and*
   //      no root level label is set (1), or
   //    - the dropbox is enabled *and* at least one selection has been added
@@ -1611,10 +1641,17 @@ function _hierarchical_select_hierarchy_
   // - "label_0" (the root level label) in all other cases.
   if ($selection == -1) {
     $root_level = module_invoke($config['module'], 'hierarchical_select_root_level', $config['params']);
-
     $first_case  = $config['enforce_deepest'] && $config['level_labels']['status'] && !isset($config['level_labels']['labels'][0]);
     $second_case = $dropbox && count($dropbox->lineages) > 0;
-    $hierarchy->lineage[0] = ($first_case || $second_case) ? 'none' : 'label_0';
+
+    // If
+    // - the special_items setting has been configured, and
+    // - one special item has the 'none' property
+    // then we'll use the special item instead of the normal "<none>" option.
+    $none_option = (count($special_items['none'])) ? $special_items['none'][0] : 'none';
+
+    // Set "<none>" option (or its equivalent special item), or "label_0".
+    $hierarchy->lineage[0] = ($first_case || $second_case) ? $none_option : 'label_0';
   }
   else {
     // If save_lineage setting is enabled, then the selection *is* a lineage.
@@ -1677,10 +1714,13 @@ function _hierarchical_select_hierarchy_
   // - enforce_deepest is enabled (2), or
   // - the dropbox is enabled *and* at least one selection has been added to
   //   the dropbox (3)
+  // except when:
+  // - the special_items setting has been configured, and
+  // - one special item has the 'none' property
   $first_case  = !$required;
   $second_case = $config['enforce_deepest'];
   $third_case  = $dropbox && count($dropbox->lineages) > 0;
-  if ($first_case || $second_case || $third_case) {
+  if (($first_case || $second_case || $third_case) && !count($special_items['none'])) {
     $option = theme('hierarchical_select_special_option', t('none'));
     $hierarchy->levels[0] = array('none' => $option) + $hierarchy->levels[0];
   }
@@ -1848,14 +1888,23 @@ function _hierarchical_select_hierarchy_
  *   The updated level
  */
 function _hierarchical_select_apply_entity_settings($level, $config) {
+  if (isset($config['special_items'])) {
+    $special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
+    $special_items['none']      = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
+  }
+
   // Only do something when the entity_count or the require_entity (or both)
   // settings are enabled.
   // NOTE: this uses the optional "hierarchical_selectentity_count" hook, so
   // we also check if it's implemented.
   if (($config['entity_count'] || $config['require_entity']) && module_hook($config['module'], 'hierarchical_select_entity_count')) {
     foreach ($level as $item => $label) {
-      // We don't want to alter special items.
-      if (!preg_match('/(none|label_\d+|create_new_item)/', $item)) {
+      // We don't want to alter internal or special items.
+      if (!preg_match('/(none|label_\d+|create_new_item)/', $item)
+          && !in_array($item, $special_items['exclusive'])
+          && !in_array($item, $special_items['none'])
+         )
+      {
         $entity_count = module_invoke($config['module'], 'hierarchical_select_entity_count', $item, $config['params']);
 
         // When the require_entity setting is enabled and the entity count is
@@ -2182,3 +2231,50 @@ function array_smart_merge($array, $over
   }
   return $array;
 }
+
+/**
+ * Helper function needed for the array_filter() call to filter the items
+ * marked with the 'exclusive' property
+ *
+ * @param $item
+ *   An item in the 'special_items' setting.
+ * @return
+ *   TRUE if it's marked with the 'exclusive' property, FALSE otherwise.
+ */
+function _hierarchical_select_special_item_exclusive($item) {
+  return in_array('exclusive', $item);
+}
+
+/**
+ * Helper function needed for the array_filter() call to filter the items
+ * marked with the 'none' property
+ *
+ * @param $item
+ *   An item in the 'special_items' setting.
+ * @return
+ *   TRUE if it's marked with the 'none' property, FALSE otherwise.
+ */
+function _hierarchical_select_special_item_none($item) {
+  return in_array('none', $item);
+}
+
+
+/**
+ * Abstraction around drupal_add_js() and Views' $form_state['js settings'].
+ *
+ * @param $settings
+ *   The JS settings you'd like to add.
+ * @param $form_state
+ *   A form state array.
+ */
+function _hierarchical_select_add_js_settings($settings, &$form_state) {
+  // If we're on a Views-powered form, we must use $form_state['js settings'].
+  if (isset($form_state['view']) && !empty($form_state['ajax'])) {
+    $form_state['js settings'] = (!is_array($form_state['js settings'])) ? array() : $form_state['js settings'];
+    $form_state['js settings'] = array_merge_recursive($form_state['js settings'], $settings);
+  }
+  // Otherwise, use drupal_add_js().
+  else {
+    drupal_add_js($settings, 'setting');
+  }
+}
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/includes/common.inc,v
retrieving revision 1.26
diff -u -F^f -r1.26 common.inc
--- includes/common.inc	4 Aug 2009 14:35:02 -0000	1.26
+++ includes/common.inc	12 Aug 2009 16:13:41 -0000
@@ -43,7 +43,6 @@ function hierarchical_select_common_conf
   variable_del('hs_config_'. $config_id);
 }
 
-
 /**
  * Apply a config to a form item.
  *
@@ -184,6 +183,8 @@ function hierarchical_select_common_conf
       '#attributes' => array('class' => 'require-entity'),
     );
   }
+  $form['level_labels']['#theme'] = 'hierarchical_select_common_config_form_level_labels';
+  $form['level_labels']['#strings'] = $strings;
 
   $form['resizable'] = array(
     '#type' => 'radios',
@@ -369,10 +370,10 @@ function hierarchical_select_common_conf
 }
 
 /**
- * Helper function that adds the JS to reposition the exposed filters of a
- * View just once.
+ * Helper function that adds the JS to make Hierarchical Select work when used
+ * as a Views exposed filter.
  */
-function hierarchical_select_common_views_exposed_filters_reposition() {
+function hierarchical_select_common_add_views_js() {
   static $js_added;
 
   if (!isset($js_added)) {
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/includes/theme.inc,v
retrieving revision 1.5
diff -u -F^f -r1.5 theme.inc
--- includes/theme.inc	4 Aug 2009 22:34:18 -0000	1.5
+++ includes/theme.inc	12 Aug 2009 16:13:41 -0000
@@ -344,7 +344,6 @@ function theme_hierarchical_select_selec
  * allow for level label styles.
  * TODO: rename to _hierarchical_select_select_options().
  */
-// TODO: check if this has changed in D6.
 function _hierarchical_select_options($element) {
   if (!isset($choices)) {
     $choices = $element['#options'];
Index: includes/views.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/includes/views.js,v
retrieving revision 1.7
diff -u -F^f -r1.7 views.js
--- includes/views.js	5 Aug 2008 21:55:59 -0000	1.7
+++ includes/views.js	12 Aug 2009 16:13:41 -0000
@@ -15,14 +15,14 @@
 
 if (Drupal.jsEnabled) {
   $(document).ready(function(){
-    $('form#views-filters, form#views-filterblock').submit(function() {
+    $('.view-filters form').submit(function() {
       // Remove the Hierarchical Select form build id and the form id, to
       // prevent them from ending up in the GET URL.
-      $('#edit-hs-form-build-id, #edit-views-filters, #edit-views-filterblock').remove();
+      $('#edit-hs-form-build-id').remove();
 
       // Prepare the hierarchical select form elements that are used as
       // exposed filters for a GET submit.
-      $('form#views-filters, form#views-filterblock')
+      $('.view-filters form')
       .find('.hierarchical-select-wrapper')
       .trigger('prepare-GET-submit');
     });
Index: modules/hs_taxonomy_views.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/modules/hs_taxonomy_views.info,v
retrieving revision 1.2
diff -u -F^f -r1.2 hs_taxonomy_views.info
--- modules/hs_taxonomy_views.info	28 Jun 2008 18:25:28 -0000	1.2
+++ modules/hs_taxonomy_views.info	12 Aug 2009 16:13:42 -0000
@@ -1,5 +1,8 @@
 ; $Id: hs_taxonomy_views.info,v 1.2 2008/06/28 18:25:28 wimleers Exp $
 name = Hierarchical Select Taxonomy Views
 description = Use Hierarchical Select for Taxonomy exposed filters in Views.
-dependencies = hierarchical_select hs_taxonomy views
+dependencies[] = hierarchical_select
+dependencies[] = hs_taxonomy 
+dependencies[] = views
 package = Form Elements
+core = 6.x
\ No newline at end of file
Index: modules/hs_taxonomy_views.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/modules/hs_taxonomy_views.module,v
retrieving revision 1.16
diff -u -F^f -r1.16 hs_taxonomy_views.module
--- modules/hs_taxonomy_views.module	20 Nov 2008 01:04:51 -0000	1.16
+++ modules/hs_taxonomy_views.module	12 Aug 2009 16:13:43 -0000
@@ -8,171 +8,236 @@
  */
 
 
+define('HS_TAXONOMY_VIEWS_ALL_OPTION', 'All');
+
+
 //----------------------------------------------------------------------------
 // Core hooks.
 
 /**
  * Implementation of hook_menu().
  */
-function hs_taxonomy_views_menu($may_cache) {
+function hs_taxonomy_views_menu() {
   $items = array();
 
-  if (!$may_cache && arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'views' && is_string(arg(3)) && arg(4) == 'hs_config' && is_numeric(arg(5))) {
-    $view_name = arg(3);
-    $vid = arg(5); // Vocabulary ID, not View ID!
-
-    $items[] = array(
-      'path' => "admin/build/views/$view_name/hs_config/$vid",
-      'title' => t('Hierarchical Select configuration for !view', array('!view' => $view_name)),
-      'callback' => 'drupal_get_form',
-      'callback arguments' => array('hs_taxonomy_views_config_form', $view_name, $vid),
-      'access' => user_access('administer views'),
-      'type' => MENU_NORMAL_ITEM,
-    );
-  }
+  $items["admin/build/views/hs_config/%views_ui_cache/%/%"] = array(
+    'title'            => 'Hierarchical Select configuration',
+    'title callback'   => 'hs_taxonomy_views_config_title',
+    'title arguments'  => array(4, 5, 6),
+    'page callback'    => 'hs_taxonomy_views_config',
+    'page arguments'   => array(4, 5, 6),
+    'access arguments' => array('administer views'),
+    'type'             => MENU_NORMAL_ITEM,
+  );
+
+  $items['hs_taxonomy_views_json/%/%'] = array(
+    'page callback'   => 'hs_taxonomy_views_json',
+    'page arguments'   => array(1, 2),
+    'type'            => MENU_CALLBACK,
+    // TODO: Needs improvements. Ideally, this would inherit the permissions
+    // of the form the Hierarchical Select was in.
+    'access callback' => TRUE,
+  );
+
   return $items;
 }
 
 /**
  * Implementation of hook_form_alter().
  */
-function hs_taxonomy_views_form_alter($form_id, &$form) {
-  // Change the exposed filters of Views. Only affects hierarchical vocabulary
-  // filters.
-  if (in_array($form_id, array('views_filters', 'views_filterblock'))) {
-    $hs_exposed_filters_found = 0;
-
-    // Find the ids and vocabulary ids of the exposed filters.
-    foreach ($form['view']['#value']->exposed_filter as $id => $filter) {
-      if (preg_match("/term_node_(\d+)\.tid/", $filter['field'], $matches)) {
-        $vid = $matches[1];
-
-        // Only apply Hierarchical Select if it's enabled for this vocabulary.
-        if (variable_get("taxonomy_hierarchical_select_$vid", 0)) {
-          $hs_exposed_filters_found++;
-          $vocabulary = taxonomy_get_vocabulary($vid);
-          $view = $form['view']['#value'];
-
-          // Make it use a hierarchical select.
-          require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc');
-
-          unset($form["filter$id"]['#options']);
-          unset($form["filter$id"]['#theme']);
-          unset($form["filter$id"]['#size']);
-
-          $form["filter$id"]['#type'] = 'hierarchical_select';
-          $defaults_override = array(
-            'module' => 'hs_taxonomy_views',
-            'params' => array(
-              'optional'    => (bool) $view->exposed_filter[$id]['optional'],
-              'vid'         => $vid,
-              'exclude_tid' => NULL,
-              'root_term'   => NULL,
-            ),
-            // When the **ALL** option is selected, nothing else should be.
-            'exclusive_lineages' => array('**ALL**'),
-            // This is a GET form, so also render the flat select.
-            'render_flat_select' => 1,
-          );
-          hierarchical_select_common_config_apply($form["filter$id"], "taxonomy-views-$view->name-$vid", $defaults_override);
+function hs_taxonomy_views_form_alter(&$form, $form_state, $form_id) {
+  // 
+  if ($form_id == 'views_ui_edit_view_form') {
+    // Add JS and CSS required for Hierarchical Select to work.
+    _hierarchical_select_setup_js();
+
+    // Ensure that Drupal.HierarchicalSelect.prepareGETSubmit() gets called.
+    require_once(drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc');
+    hierarchical_select_common_add_views_js();
+  }
+
+  if ($form_id == 'views_ui_config_item_form'
+      && $form_state['type'] == 'filter'
+      && $form_state['handler']->table == 'term_node'
+      && $form_state['handler']->field == 'tid')
+  {
+    require_once(drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc');
+
+    $view_name  = $form_state['view']->name;
+    $filter_id  = $form_state['id'];
+    $display_id = _hs_taxonomy_views_get_display_id_for_filter($form_state['view'], $filter_id);
+    
 
-          // Inherit #required from the exposed filter settings.
-          $form["filter$id"]['#required'] = !((bool) $view->exposed_filter[$id]['optional']);
+    $config_id = "taxonomy-views-$view_name-$display_id-$filter_id";
+    $config    = hierarchical_select_common_config_get($config_id);
 
-          // Put the altered exposed filters in a separate table row.
-          hierarchical_select_common_views_exposed_filters_reposition();
-        }
-      }
+    if ($config['save_lineage']) {
+      $description = t("Managed by Hierarchical Select because the 'Save lineage' setting is enabled.");
+      // "Operator"
+      $form['options']['operator']['#disabled'] = TRUE;
+      $form['options']['operator']['#description'] = $description;
+      // "Unlock operator"
+      $form['options']['expose']['use_operator']['#disabled'] = TRUE;
+      $form['options']['expose']['use_operator']['#description'] = $description;
+      // "Operator identifier"
+      $form['options']['expose']['operator']['#disabled'] = TRUE;
+      $form['options']['expose']['operator']['#description'] = $description;
     }
+  }
+}
 
-    if ($hs_exposed_filters_found > 0) {
-      // Views will remove the form_id in views_filters_process(), but we need
-      // it for Hierarchical Select to work, so put it back.
-      $form['copy_of_form_id'] = $form['form_id'] + array('#parents' => array('form_id'));
-    }
+//----------------------------------------------------------------------------
+// Menu system callbacks.
+
+/**
+ * Title callback; Hierarchical Select configuration form page.
+ *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
+ */
+function hs_taxonomy_views_config_title($view, $display_id, $filter_id) {
+  $filter_label = _hs_taxonomy_views_get_filter_label($view, $display_id, $filter_id);
+  return t('Hierarchical Select configuration for the "!filter-id" filter in
+            the "!view-name" view\'s "!display-id" display',
+            array(
+              '!view-name'  => $view->name,
+              '!display-id' => $display_id,
+              '!filter-id'  => $filter_id,
+            )
+          );
+}
+
+/**
+ * Menu callback; Hierarchical Select configuration form page.
+ *
+ * When the given filter id doesn't exist, a 404 page is displayed.
+ *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
+ */
+function hs_taxonomy_views_config($view, $display_id, $filter_id) {
+  $filter = _hs_taxonomy_views_get_filter($view, $display_id, $filter_id);
+  if ($filter == FALSE) {
+    drupal_not_found();
   }
+  else {
+    views_set_current_view($view);
+    return drupal_get_form('hs_taxonomy_views_config_form', $view, $display_id, $filter_id);
+  }
+}
 
-  // Alter the edit view form: add a link to the Hierarchical Select
-  // configuration when appropriate and to mark which settings are now managed
-  // by the Hierarchical Select configuration.
-  if ($form_id == 'views_edit_view') {
-    foreach ($form['exposed_filter'] as $filter_id => $filter) {
-      if (is_numeric($filter_id)) {
-        $id = $form['exposed_filter'][$filter_id]['id']['#default_value'];
-        if (preg_match("/term_node_(\d+)\.tid/", $id, $matches)) {
-          $vid  = $matches[1];
-          if (variable_get("taxonomy_hierarchical_select_$vid", 0)) {
-            $view = $form['#parameters'][1];
-
-            $link = l(t('Configure Hierarchical Select'), "admin/build/views/$view->name/hs_config/$vid");
-            $form['exposed_filter'][$filter_id]['name']['#value'] .= '<br />'. $link;
-
-            // Alter the form to support the current Hierarchical Select
-            // config.
-            require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc');
-            $config_id = "taxonomy-views-$view->name-$vid";
-            $config = hierarchical_select_common_config_get($config_id);
-
-            $text = t('This setting is now managed by the<br />Hierarchical Select configuration!');
-            
-            // Exposed filter's "Force single" setting.
-            $form['exposed_filter'][$filter_id]['single']['#description'] = $text;
-
-            // Additional settings when save_lineage is enabled.
-            if ($config['save_lineage']) {
-              // Filter's "Operator" setting.
-              $form['filter'][$filter_id]['operator']['#description'] = $text;
-
-              // Exposed filter's "Lock Operator" setting.
-              $form['exposed_filter'][$filter_id]['operator']['#description'] = $text;
-            }
-          }
-        }
-      }
-    }
+
+/**
+ * Menu callback; wrapper around hierarchical_select_json, with support for
+ * preloading the view thats is referenced from within the form.
+ *
+ * @param $view_name
+ *   The name of the view to load.
+ * @param $display_id
+ *   The ID of a display to execute.
+ */
+function hs_taxonomy_views_json($view_name, $display_id) {
+  $view = views_get_view($view_name);
+
+  if ($view != NULL) {
+    $view->execute_display($display_id);
+    views_set_current_view($view);
   }
+
+  return hierarchical_select_json();
 }
 
+
+//----------------------------------------------------------------------------
+// Views hooks.
+
 /**
- * Implementation of hook_requirements().
+ * Implementation of hook_views_api().
  */
-function hs_taxonomy_views_requirements($phase) {
-  $requirements = array();
+function hs_taxonomy_views_api() {
+  return array(
+    'api' => 2,
+    'path' => drupal_get_path('module', 'hierarchical_select') . '/modules',
+  );
+}
 
-  if ($phase == 'runtime') {
-    $pattern = <<<EOT
-function _views_build_filters_form(\$view) {
-  // When the form is retrieved through an AJAX callback, the cache hasn't
-  // been loaded yet. The cache is necesssary for _views_get_filters().
-  views_load_cache();
-EOT;
-    $views_with_patch_257004 = preg_match('#'. preg_quote($pattern) .'#m', file_get_contents(drupal_get_path('module', 'views') .'/views.module'));
-
-    if ($views_with_patch_257004) {
-      $value = t('The Views module is new enough.');
-      $description = '';
-      $severity = REQUIREMENT_OK;
-    }
-    else {
-      $value = t('The Views module is outdated.');
-      $description = t("The version of Views that you have installed is either
-        older than May 11, 2008, or doesn't have the obligatory patch applied.
-        Please apply the <a href=\"!patch_url\">patch</a> or update to a newer
-        version of the Views module!",
-        array('!patch_url' => 'http://drupal.org/files/issues/hs_compatibility.patch')
-      );
-      $severity = REQUIREMENT_ERROR;
-    }
+/**
+ * Implementation of hook_views_handlers().
+ */
+function hs_taxonomy_views_handlers() {
+  return array(
+    'handlers' => array(
+      // Provide a subclass of the term filter handler, to make it possible to
+      // use Hierarchical Select in Views.
+      'hs_taxonomy_views_handler_filter_term_node_tid' => array(
+        'parent' => 'views_handler_filter_term_node_tid',
+      ),
+    )
+  );
+}
 
-    $requirements['hs_taxonomy_views'] = array(
-      'title'       => t('Hierarchical Select Views Taxonomy'),
-      'value'       => $value,
-      'description' => $description,
-      'severity'    => $severity,
-    );
-  }
+/**
+ * Implementation of hook_views_data_alter().
+ */
+function hs_taxonomy_views_data_alter(&$data) {
+  // Term view type, tid field.
+  $data['term_data']['tid'] = array(
+   'title' => t('Term ID'),
+   'help'  => t('The taxonomy term ID.'),
+   'field' => array(
+     'handler'   => 'views_handler_field_numeric',
+     'skip base' => array('node', 'node_revision'),
+   ),
+   'argument' => array(
+     'handler'   => 'views_handler_argument_numeric',
+     'skip base' => array('node', 'node_revision'),
+   ),
+   // Override the views_handler_filter_term_node_tid filter handler: use our
+   // hs_taxonomy_views_handler_filter_term_node_tid subclass instead.
+   'filter' => array(
+     'handler'         => 'hs_taxonomy_views_handler_filter_term_node_tid',
+     'hierarchy table' => 'term_hierarchy',
+     'numeric'         => TRUE,
+     'skip base'       => array('node', 'node_revision'),
+   ),
+  );
 
-  return $requirements;
+  // Node view type, tid field.
+  $data['term_node']['tid'] = array(
+    'title' => t('Term ID'),
+    'help'  => t('The taxonomy term ID.'),
+    'field' => array(
+      'title'     => t('All terms'),
+      'help'      => t('Display all taxonomy terms associated with a node from specified vocabularies.'),
+      'handler'   => 'views_handler_field_term_node_tid',
+      'skip base' => 'term_data',
+    ),
+    'argument' => array(
+      'handler'          => 'views_handler_argument_term_node_tid',
+      'name table'       => 'term_data',
+      'name field'       => 'name',
+      'empty name field' => t('Uncategorized'),
+      'numeric'          => TRUE,
+      'skip base'        => 'term_data',
+    ),
+    // Override the views_handler_filter_term_node_tid filter handler: use our
+    // hs_taxonomy_views_handler_filter_term_node_tid subclass instead.
+    'filter' => array(
+      'title'           => t('Term'),
+      'handler'         => 'hs_taxonomy_views_handler_filter_term_node_tid',
+      'hierarchy table' => 'term_hierarchy',
+      'numeric'         => TRUE,
+      'skip base'       => 'term_data',
+    ),
+  );
 }
 
 
@@ -181,47 +246,45 @@ function _views_build_filters_form(\$vie
 
 /**
  * Form definition; configuration form for Hierarchical Select as the widget
- * for a Taxonomy exposed filter.
+ * for a Taxonomy filter.
  *
- * @param $view_name
- *   Name of a view. Provides necessary context.
- * @param $vid
- *   A vocabulary id. Provides necessary context.
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
  */
-function hs_taxonomy_views_config_form($view_name, $vid) {
-  require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc');
+function hs_taxonomy_views_config_form($form_state, $view, $display_id, $filter_id) {
+  require_once(drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc');
 
-  // Find the exposed filter, we need this to set the default value of
-  // $config['dropbox']['status'].
-  $view = views_get_view($view_name);
-  foreach ($view->exposed_filter as $filter) {
-    if ($filter['id'] == "term_node_$vid.tid") {
-      $exposed_filter = $filter;
-      break;
-    }
-  }
+  $filter = _hs_taxonomy_views_get_filter($view, $display_id, $filter_id);
+
+  // Build the config ID.
+  $config_id = "taxonomy-views-$view->name-$display_id-$filter_id";
 
   // Add the Hierarchical Select config form.
   $module = 'hs_taxonomy_views';
   $params = array(
-    'optional'    => (bool) $view->exposed_filter[$id]['optional'],
-    'vid'         => $vid,
+    'optional'    => (bool) $filter['expose']['optional'],
+    'filter_id'   => $filter_id,
+    'vid'         => $filter['vid'],
     'exclude_tid' => NULL,
     'root_term'   => NULL,
   );
-    
-  
-  $config_id = "taxonomy-views-$view_name-$vid";
-  $vocabulary = taxonomy_get_vocabulary($vid);
   $defaults = array(
     // Enable the save_lineage setting by default if the multiple parents
     // vocabulary option is enabled.
     'save_lineage' => (int) ($vocabulary->hierarchy == 2),
-    'dropbox' => array(
-      'status' => !$exposed_filter['single'],
-    ),
     'editability' => array(
-      'max_levels' => _hs_taxonomy_hierarchical_select_get_depth($vid),
+      'max_levels' => _hs_taxonomy_hierarchical_select_get_depth($filter['vid']),
+    ),
+    // Use our custom callback.
+    'path' => "hs_taxonomy_views_json/$view->name/$display_id",
+    // When the 'All' option is selected, nothing else should be and it
+    // should replace the '<none>' option.
+    'special_items' => array(
+      HS_TAXONOMY_VIEWS_ALL_OPTION => array('none', 'exclusive'),
     ),
   );
   $strings = array(
@@ -233,17 +296,12 @@ function hs_taxonomy_views_config_form($
     'entity'      => t('node'),
     'entities'    => t('nodes'),
   );
-  $max_hierarchy_depth = _hs_taxonomy_hierarchical_select_get_depth($vid);
-  $preview_is_required = !(bool)$exposed_filter['optional'];
+  $max_hierarchy_depth = _hs_taxonomy_hierarchical_select_get_depth($vocabulary->vid);
+  $preview_is_required = !(bool)$exposed_filter['expose']['optional'];
   $form['hierarchical_select_config'] = hierarchical_select_common_config_form($module, $params, $config_id, $defaults, $strings, $max_hierarchy_depth, $preview_is_required);
-  $form['hierarchical_select_config']['save_lineage']['#description'] .= '<br />'. t(
-    'When you enable the %save_lineage setting, you will have to resave the
-    "Edit view" form as well!',
-    array('%save_lineage' => $form['hierarchical_select_config']['save_lineage']['#options'][1])
-  );
 
   $form['link'] = array(
-    '#value' => l('Back to the view configuration', "admin/build/views/$view_name/edit"),
+    '#value' => l("Back to the View's display configuration", "admin/build/views/edit/$view->name", array('fragment' => 'views-tab-' . $display_id)),
     '#prefix' => '<div class="hierarchical-select-config-back-link">',
     '#suffix' => '</div>',
     '#weight' => -5,
@@ -254,62 +312,46 @@ function hs_taxonomy_views_config_form($
     '#value' => t('Save'),
   );
 
-  // Add the the submit handler for the Hierarchical Select config form.
-  $parents = array('hierarchical_select_config');
-  $form['#submit']['hierarchical_select_common_config_form_submit'] = array($parents);
+  // Add the custom submit handler for the Hierarchical Select config form
+  // that will update the View object when necessary.
+  $form['#submit'][] = 'hs_taxonomy_views_common_config_form_submit';
+  $form['#custom_submit_data'] = array(
+    'view_name'  => $view->name,
+    'display_id' => $display_id,
+    'filter_id'  => $filter_id,
+  );
 
-  $form['#submit']['hs_taxonomy_views_common_config_form_submit'] = array($view_name, $vid);
+  // Add the submit handler for the Hierarchical Select config form.
+  $parents = array('hierarchical_select_config');
+  $form['#submit'][] = 'hierarchical_select_common_config_form_submit';
+  $form['#hs_common_config_form_parents'] = $parents;
 
   return $form;
 }
 
 /**
  * Additional submit callback to redirect the user to the "Edit view" form.
- *
- * @param $form_id
- * @param $form_values
- * @param $view_name
- *   Name of a view. Provides necessary context.
- * @param $vid
- *   A vocabulary id. Provides necessary context.
- */
-function hs_taxonomy_views_common_config_form_submit($form_id, $form_values, $view_name, $vid) {
-  $view_id = db_result(db_query("SELECT vid FROM {view_view} WHERE name = '%s'", $view_name));
-  $field = 'term_node_'. $vid .'.tid';
-
-  $filter = db_fetch_object(db_query("SELECT operator FROM {view_filter} WHERE vid = %d AND field = '%s'", $view_id, $field));
-  $exposed_filter = db_fetch_object(db_query("SELECT operator, single FROM {view_exposed_filter} WHERE vid = %d AND field = '%s'", $view_id, $field));
-
-  // Overrides when save_lineage is enabled.
-  if ($form_values['hierarchical_select_config']['save_lineage']) {
-    // "Operator" must always be 'AND'.
-    $filter->operator = 'AND';
+ */
+function hs_taxonomy_views_common_config_form_submit($form, &$form_state) {
+  require_once(drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc');
 
-    // The exposed filter must be locked to 'AND'.
-    $exposed_filter->operator = 1;
+  $view_name  = $form['#custom_submit_data']['view_name'];
+  $display_id = $form['#custom_submit_data']['display_id'];
+  $filter_id  = $form['#custom_submit_data']['filter_id'];
+  $view       = views_get_view($view_name);
 
-    // "Force single" must be disabled.
-    $exposed_filter->single = 0;
-  }
-  else {
-    // "Force single" must be enabled.
-    $exposed_filter->single = 1;      
-  }
+  $config_id = $form_state['values']['hierarchical_select_config']['config_id'];
+  $config    = hierarchical_select_common_config_get($config_id);
 
-  // Overrides when the dropbox is enabled.
-  if ($form_values['hierarchical_select_config']['dropbox']['status']) {
-    // "Force single" must be disabled.
-    $exposed_filter->single = 0;
-  }
+  // Overrides when save_lineage is enabled.
+  $new_config = $form_state['values']['hierarchical_select_config'];
+  if ($new_config['save_lineage'] == 1 && $config['save_lineage'] != $new_config['save_lineage']) {
+    $view->display[$display_id]->display_options['filters'][$filter_id]['operator'] = 'and';
+    $view->display[$display_id]->display_options['filters'][$filter_id]['expose']['use_operator'] = 0;
+    $view->save();
 
-  if ($view_id === FALSE) {
-    drupal_set_message(t("Could not update the view because it doesn't live in the database."), 'error');
-  }
-  else {
-    db_query("UPDATE {view_filter} SET operator = '%s' WHERE vid = %d AND field = '%s'", $filter->operator, $view_id, $field);
-    db_query("UPDATE {view_exposed_filter} SET operator = %d, single = %d WHERE vid = %d AND field = '%s'", $exposed_filter->operator, $exposed_filter->single, $view_id, $field);
-    cache_clear_all('views_urls', 'cache_views');
-    drupal_set_message(t("Updated the View's exposed filter according to the settings you made."));
+    views_object_cache_clear('view', $view_name);
+    drupal_set_message(t("Because you've enabled the 'Save Lineage' setting, the operator has been set to 'AND' and cannot be changed by the end user."));
   }
 }
 
@@ -321,14 +363,21 @@ function hs_taxonomy_views_common_config
  * Implementation of hook_hierarchical_select_params().
  */
 function hs_taxonomy_views_hierarchical_select_params() {
-  return array('optional') + hs_taxonomy_hierarchical_select_params();
+  $params = array(
+    'vid',
+    'optional',    // Do we display an "All" option?
+    'filter_id',   // The ID of the filter. Necessary for entity count support.
+    'exclude_tid', // Allows a term to be excluded (necessary for the taxonomy_form_term form).
+    'root_term',   // Displays a fake "<root>" term in the root level (necessary for the taxonomy_form-term form).
+  );
+  return $params;
 }
 
 /**
  * Implementation of hook_hierarchical_select_root_level().
  */
 function hs_taxonomy_views_hierarchical_select_root_level($params) {
-  $root_level =  ($params['optional']) ? array('**ALL**' => '<'. t('all') .'>') : array();
+  $root_level =  ($params['optional']) ? array(HS_TAXONOMY_VIEWS_ALL_OPTION => '<'. t('Any') .'>') : array();
   $root_level += hs_taxonomy_hierarchical_select_root_level($params);
   return $root_level;
 }
@@ -337,28 +386,28 @@ function hs_taxonomy_views_hierarchical_
  * Implementation of hook_hierarchical_select_children().
  */
 function hs_taxonomy_views_hierarchical_select_children($parent, $params) {
-  return ($parent == '**ALL**') ? array() : hs_taxonomy_hierarchical_select_children($parent, $params);
+  return ($parent == HS_TAXONOMY_VIEWS_ALL_OPTION) ? array() : hs_taxonomy_hierarchical_select_children($parent, $params);
 }
 
 /**
  * Implementation of hook_hierarchical_select_lineage().
  */
 function hs_taxonomy_views_hierarchical_select_lineage($item, $params) {
-  return ($item == '**ALL**') ? array($item) : hs_taxonomy_hierarchical_select_lineage($item, $params);
+  return ($item == HS_TAXONOMY_VIEWS_ALL_OPTION) ? array($item) : hs_taxonomy_hierarchical_select_lineage($item, $params);
 }
 
 /**
  * Implementation of hook_hierarchical_select_valid_item().
  */
 function hs_taxonomy_views_hierarchical_select_valid_item($item, $params) {
-  return ($item == '**ALL**' || hs_taxonomy_hierarchical_select_valid_item($item, $params));
+  return ($item == HS_TAXONOMY_VIEWS_ALL_OPTION || hs_taxonomy_hierarchical_select_valid_item($item, $params));
 }
 
 /**
  * Implementation of hook_hierarchical_select_item_get_label().
  */
 function hs_taxonomy_views_hierarchical_select_item_get_label($item, $params) {
-  return ($item == '**ALL**') ? '<'. t('all') .'>' : hs_taxonomy_hierarchical_select_item_get_label($item, $params);
+  return ($item == HS_TAXONOMY_VIEWS_ALL_OPTION) ? '<'. t('Any') .'>' : hs_taxonomy_hierarchical_select_item_get_label($item, $params);
 }
 
 /**
@@ -372,12 +421,95 @@ function hs_taxonomy_views_hierarchical_
  * Implementation of hook_hierarchical_select_entity_count().
  */
 function hs_taxonomy_views_hierarchical_select_entity_count($item, $params) {
-  if ($item == '**ALL**') {
-    return db_result(db_query('SELECT COUNT(DISTINCT(t.nid)) FROM {term_node} t INNER JOIN {node} n ON t.nid = n.nid WHERE n.status = 1'));
-  }
-  else {
-    return hs_taxonomy_hierarchical_select_entity_count($item, $params);
+  static $count;
+
+  $current_view = views_get_current_view();
+
+  if (!isset($count[$current_view->name][$item])) {
+    $temp_view = $current_view->clone_view();
+    $display_id = (isset($current_view->current_display)) ? $current_view->current_display : 'default';
+    $temp_view->set_display($display_id);
+
+    // Disable the pager to get *all* results.
+    $temp_view->set_use_pager(FALSE);
+
+    // Pretend nothing is exposed, otherwise an exposed filters form will also
+    // be rendered and thereby cause endless recursion.
+    $temp_view->display_handler->has_exposed = 0;
+
+    // Dynamically add an additional filter when
+    if ($item != HS_TAXONOMY_VIEWS_ALL_OPTION) {
+      // Get an array with all tids: the tid of the currently selected term and
+      // all child terms.
+      $term = taxonomy_get_term($item);
+      $tree = _hs_taxonomy_hierarchical_select_get_tree($term->vid, $term->tid);
+      $tids = array($term->tid => $term->tid);
+      foreach ($tree as $descendant) {
+        $tids[$descendant->tid] = $descendant->tid;
+      }
+
+      $id = 'tid_' . implode('-', $tids);
+      $temp_view->display[$display_id]->handler->override_option('filters', array(
+        $id => array(
+          'operator' => 'or',
+          'value' => $tids,
+          'group' => '0',
+          'exposed' => FALSE,
+          'expose' => array(
+            'operator' => FALSE,
+            'label' => '',
+          ),
+          'type' => 'select',
+          'limit' => TRUE,
+          'vid' => $params['vid'],
+          'id' => $id,
+          'table' => 'term_node',
+          'field' => 'tid',
+          'hierarchy' => 0,
+          'override' => array(
+            'button' => 'Override',
+          ),
+          'relationship' => 'none',
+          'reduce_duplicates' => 0,
+        ),
+      ));
+    }
+    else {
+      // Disable the default value, otherwise the <Any> option will actually
+      // filter by the default value.
+      $filter_id = $params['filter_id'];
+      $temp_view->display[$display_id]->display_options['filters'][$filter_id]['value'] = array();
+      $temp_view->display[$display_id]->handler->options['filters'][$filter_id]['value'] = array();
+      $temp_view->display['default']->display_options['filters'][$filter_id]['value'] = array();
+      $temp_view->display['default']->handler->options['filters'][$filter_id]['value'] = array();
+    }
+
+    // Build the queries and collect the arguments.
+    $temp_view->build($display_id);
+
+    // We only need the count query. We don't care about the actual fields or
+    // order of the View.
+    $count_query = $temp_view->build_info['count_query'];
+    $args        = $temp_view->build_info['query_args'];
+
+    // Regenerate the query after we set the distinct flag for the nid field.
+    // This unfortunately doesn't work, because Views doesn't create an
+    // optimized count query when any of the fields have the distinct flag set.
+    //$temp_view->query->fields['nid']['distinct'] = TRUE;
+    //$count_query = $temp_view->query->query(TRUE);
+
+    // Due to the above: sneak DISTINCT() in through a string replace ...
+    $count_query = str_replace("SELECT node.nid AS nid", "SELECT DISTINCT(node.nid) AS nid", $count_query);
+
+    // Apply the same query transformations as view::execute() does.
+    $count_query = db_rewrite_sql($count_query, $temp_view->base_table, $temp_view->base_field, array('view' => &$temp_view));
+    $count_query = 'SELECT COUNT(*) FROM (' . $count_query . ') count_alias';
+
+    // Execute the count query.
+    $count[$current_view->name][$item] = db_result(db_query($count_query, $args));
   }
+
+  return $count[$current_view->name][$item];
 }
 
 /**
@@ -394,32 +526,34 @@ function hs_taxonomy_views_hierarchical_
  * Implementation of hook_hierarchical_select_config_info().
  */
 function hs_taxonomy_views_hierarchical_select_config_info() {
-  static $config_info;
+  $views = views_get_all_views();
 
-  if (!isset($config_info)) {
-    $config_info = array();
-
-    views_load_cache();
-    $result = db_query("SELECT vid, name FROM {view_view} ORDER BY name");
-    while ($view = db_fetch_object($result)) {
-      $view = views_get_view($view->name);
-
-      foreach ($view->exposed_filter as $filter_id => $filter) {
-        $vid = _hs_taxonomy_views_parse_vocabulary_id_from_id($filter['id']);
-        if ($vid) {
-          $vocabulary = taxonomy_get_vocabulary($vid);
-
-          $config_id = "taxonomy-views-$view->name-$vid";
-          $config_info[$config_id] = array(
-            'config_id'      => $config_id,
-            'hierarchy type' => t('Taxonomy'),
-            'hierarchy'      => t($vocabulary->name),
-            'entity type'    => t('Node'),
-            'entity'         => '',
-            'context type'   => t('Views exposed filter'),
-            'context'        => t($view->name),
-            'edit link'      => "admin/build/views/$view->name/hs_config/$vid",
-          );
+  foreach ($views as $view) {
+    foreach (array_keys($view->display) as $display_id) {
+      if (count($view->display[$display_id]->display_options['filters'])) {
+        foreach ($view->display[$display_id]->display_options['filters'] as $filter) {
+          if ($filter['type'] == 'hierarchical_select' && $filter['table'] == 'term_node' && $filter['field'] == 'tid') {
+            $vocabulary = taxonomy_vocabulary_load($filter['vid']);
+            $filter_label = (!empty($filter['expose']['label'])) ? $filter['expose']['label'] : t('Taxonomy: Term');
+
+            $config_id = "taxonomy-views-$view->name-$vocabulary->vid";
+            $config_info[$config_id] = array(
+              'config_id'      => $config_id,
+              'hierarchy type' => t('Taxonomy'),
+              'hierarchy'      => t($vocabulary->name),
+              'entity type'    => t('Node'),
+              'entity'         => '',
+              'context type'   => t('Views (exposed) filter'),
+              'context'        => t('"!view-name" view, "!display-name" display, "!filter-label" filter',
+                                    array(
+                                      '!view-name'    => $view->name,
+                                      '!display-name' => $display_id,
+                                      '!filter-label' => $filter_label,
+                                    )
+                                   ),
+              'edit link'      => _hs_taxonomy_views_config_path($view->name, $display_id, $filter['id']),
+            );
+          }
         }
       }
     }
@@ -428,17 +562,79 @@ function hs_taxonomy_views_hierarchical_
   return  $config_info;
 }
 
+
+//----------------------------------------------------------------------------
+// Private functions.
+
 /**
- * Given an id of the form "term_node_1.tid", with 1 the vid, get the vid.
+ * Get a filter from a view object.
  *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
  * @return
- *   When no valid id was given, FALSE, otherwise the vid.
+ *   The filter array.
  */
-function _hs_taxonomy_views_parse_vocabulary_id_from_id($id) {
-  $vid = FALSE;
+function _hs_taxonomy_views_get_filter($view, $display_id, $filter_id) {
+  $filters = $view->display[$display_id]->display_options['filters'];
+  return (!isset($filters[$filter_id])) ? FALSE : $filters[$filter_id];
+}
 
-  if (preg_match("/term_node_(\d+)\.tid/", $id, $matches)) {
-    $vid = $matches[1];
-  }
-  return $vid;
+/**
+ * Get a filter's label from a view object.
+ *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
+ * @return
+ *   The filter's label.
+ */
+function _hs_taxonomy_views_get_filter_label($view, $display_id, $filter_id) {
+  $filter = _hs_taxonomy_views_get_filter($view, $display_id, $filter_id);
+  return ($filter === FALSE) ? FALSE : $filter['expose']['label'];
+}
+
+/**
+ * Generate the path at which the configuration form of the given filter is
+ * available.
+ *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
+ * @return
+ *   The Drupal path for the desired config form..
+ */
+function _hs_taxonomy_views_config_path($view_name, $display_id, $filter_id) {
+  return "admin/build/views/hs_config/$view_name/$display_id/$filter_id";
+}
+
+/**
+ * Find out what the name is of the display with the most specific settings
+ * for the given filter ID.
+ * If a display has overriden the default display, then that display's name
+ * will be returned instead of 'default'. That's also how Views picks which
+ * filter settings to use.
+ *
+ * @param $view
+ *   A view object.
+ * @param $display_id
+ *   The ID of a display within the given view object.
+ * @param $filter_id
+ *   The ID of a filter used within the given view object.
+ * @return
+ *   The most specfic display name.
+ */
+function _hs_taxonomy_views_get_display_id_for_filter($view, $filter_id) {
+  $current_display = $view->current_display;
+  $current_display_filters = $view->display[$current_display]->display_options['filters'];
+  return (isset($current_display_filters[$filter_id])) ? $current_display : 'default';
 }
Index: modules/hs_taxonomy_views_handler_filter_term_node_tid.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/hierarchical_select/modules/hs_taxonomy_views_handler_filter_term_node_tid.inc,v
retrieving revision 1.1
diff -u -F^f -r1.1 hs_taxonomy_views_handler_filter_term_node_tid.inc
--- modules/hs_taxonomy_views_handler_filter_term_node_tid.inc	25 Jul 2009 10:27:59 -0000	1.1
+++ modules/hs_taxonomy_views_handler_filter_term_node_tid.inc	12 Aug 2009 16:13:44 -0000
@@ -0,0 +1,228 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * This file defines a new filter handler for using Hierarchical Select in
+ * exposed Taxonomy term filters.
+ */
+
+class hs_taxonomy_views_handler_filter_term_node_tid extends views_handler_filter_term_node_tid {
+
+  function init(&$view, $options) {
+    parent::init($view, $options);
+
+    // The following code should logically be wrapped in a
+    //   $this->select_type_is_hierarchical_select()
+    // check. However, if we'd do this, you wouldn't be able to dynamically
+    // switch between Hierarchical Select and another Selection Type.
+    // This incurs a possibly unnecessary load (i.e. loading unneeded JS), but
+    // is worth it because of the ease of use and because it's likely that
+    // Hierarchical Select will be used, otherwise the user shouldn't install
+    // this module in the first place.
+    // If you can live with a reload of the View edit form, you can wrap the
+    // code below in such a check.
+
+    // Add JS and CSS required for Hierarchical Select to work.
+    _hierarchical_select_setup_js();
+
+    // Ensure that Drupal.HierarchicalSelect.prepareGETSubmit() gets called.
+    require_once(drupal_get_path('module', 'hierarchical_select') . '/includes/common.inc');
+    hierarchical_select_common_add_views_js();
+  }
+
+  function value_form(&$form, &$form_state) {
+    $vocabulary = taxonomy_vocabulary_load($this->options['vid']);
+    $view_name  = $this->view->name;
+    $filter_id  = $this->options['id'];
+    $display_id = _hs_taxonomy_views_get_display_id_for_filter($this->view, $filter_id);
+    $optional   = $this->options['expose']['optional'];
+
+    $config_id = "taxonomy-views-$view_name-$display_id-$filter_id";
+
+    // When not exposed: settings form.
+    if (empty($form_state['exposed'])) {
+      // When the 'Selection type' is 'Hierarchical Select', user our own
+      // value_form, otherwise use the parent's class form.
+      if ($this->options['type'] == 'textfield' || $this->options['type'] == 'select') {
+        parent::value_form($form, $form_state);
+      }
+      else {
+        $config = hierarchical_select_common_config_get($config_id);
+        $form['value'] = array(
+          '#type'          => 'hierarchical_select',
+          '#title'         => t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)),
+          '#default_value' => !empty($this->value) ? $this->value : array(),
+          '#config' => array(
+            'module' => 'hs_taxonomy',
+            'params' => array(
+              'vid'         => $vocabulary->vid,
+              'exclude_tid' => NULL,
+              'root_term'   => NULL,
+            ),
+            'save_lineage'    => $config['save_lineage'],
+            'enforce_deepest' => $config['enforce_deepest'],
+            'entity_count'    => $config['entity_count'],
+            'resizable'       => 1,
+            'level_labels' => array(
+              'status' => $config['level_labels']['status'],
+              'labels' => $config['level_labels']['labels'],
+            ),
+            'dropbox' => array(
+              'status'   => $config['dropbox']['status'],
+              'title'    => t('Terms to filter by'),
+              'limit'    => $config['dropbox']['limit'],
+              'reset_hs' => $config['dropbox']['reset_hs'],
+            ),
+            // Use our custom callback, because this is part of
+            // views_ui_config_item_form(), which requires access to the
+            // $view object, which will be restored automatically through
+            // this special menu callback.
+            'path' => "hs_taxonomy_views_json/$view_name/$display_id",
+          ),
+        );
+      }
+    }
+    // When exposed: filter form.
+    else {
+      // When the 'Selection type' is 'Hierarchical Select', user our own
+      // value_form, otherwise use the parent's class form.
+      if (!$this->select_type_is_hierarchical_select()) {
+        parent::value_form($form, $form_state);
+      }
+      else {
+        $default_value = (isset($this->value) && !empty($this->value)) ? $this->value : array();
+
+        // Basic settings for the form item.
+        $form['value']['#type']          = 'hierarchical_select';
+        $form['value']['#default_value'] = $default_value;
+        $form['value']['#required']      = !((bool) $optional);
+
+        // Apply the Hierarchical Select configuration to the form item.
+        $defaults_override = array(
+         'module' => 'hs_taxonomy_views',
+         'params' => array(
+           'optional'    => (bool) $optional,
+           'filter_id'   => $filter_id,
+           'vid'         => $vocabulary->vid,
+           'exclude_tid' => NULL,
+           'root_term'   => NULL,
+         ),
+         // When the 'All' option is selected, nothing else should be and it
+         // should replace the '<none>' option.
+         'special_items' => array(
+           HS_TAXONOMY_VIEWS_ALL_OPTION => array('none', 'exclusive'),
+         ),
+         // This is a GET form, so also render the flat select.
+         'render_flat_select' => 1,
+         // Use our custom callback.
+         'path' => "hs_taxonomy_views_json/$view_name/$display_id",
+        );
+        hierarchical_select_common_config_apply($form['value'], $config_id, $defaults_override);
+      }
+    }
+  }
+
+  function expose_form_right(&$form, &$form_state) {
+    // The form with the "Optional", "Force single" and "Remember" checkboxes.
+    parent::expose_form_right($form, $form_state);
+
+    // When the selection type is Hierarchical Select, remove the "Force
+    // single" checkbox.
+    if ($this->select_type_is_hierarchical_select()) {
+      unset($form['expose']['single']);
+    }
+  }
+
+  function extra_options_form(&$form, &$form_state) {
+    parent::extra_options_form($form, $form_state);
+
+    $form['type'] = array(
+      '#type'    => 'radios',
+      '#title'   => t('Selection type'),
+      '#options' => array(
+        'select'              => t('Dropdown'),
+        'textfield'           => t('Autocomplete'),
+        'hierarchical_select' => t('Hierarchical Select'),
+      ),
+      '#default_value' => $this->options['type'],
+    );
+
+    $filter_id  = $form_state['id'];
+    $display_id = _hs_taxonomy_views_get_display_id_for_filter($this->view, $filter_id);
+    $form['configure_hs'] = array(
+      '#prefix'     => '<div class="form-item"><div id="configure-hierarchical-select-link" style="display: inline-block">',
+      '#value'      => l(t('Configure Hierarchical Select'), _hs_taxonomy_views_config_path($this->view->name, $display_id, $filter_id)),
+      '#suffix'     => '</div></div>',
+      // Doesn't work because #process is not called for #type = markup form items.
+      '#process'    => array('views_process_dependency'),
+      '#dependency' => array('radio:options[type]' => array('hierarchical_select')),
+      // Set #input = TRUE so that #process will be called.
+      '#input'      => TRUE,
+      // Set #id manually because that is not generated for #type = markup.
+      // This is the same id attribute as in #prefix.
+      '#id'         => 'configure-hierarchical-select-link',
+    );
+
+    // Ensure the configure_hs form item is before the markup_end form item.
+    unset($form['markup_end']);
+    $form['markup_end'] = array(
+      '#value' => '</div>',
+    );
+  }
+
+  /**
+   * Validate the exposed filter form
+   */
+  function exposed_validate(&$form, &$form_state) {
+    // No validation necessary when the filter is not exposed or when no
+    // identifier is set.
+    if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) {
+      return;
+    }
+
+    if (!$this->select_type_is_hierarchical_select()) {
+      parent::exposed_validate($form, $form_state);
+    }
+    else {
+      $identifier = $this->options['expose']['identifier'];
+      $input = $form_state['values'][$identifier];
+
+      // If the HS_TAXONOMY_VIEWS_ALL_OPTION option is selected, then the
+      // results should not be filtered at all.
+      if ($input != HS_TAXONOMY_VIEWS_ALL_OPTION) {
+        $this->validated_exposed_input = $input;
+      }
+    }
+  }
+
+  /**
+   * Take input from exposed filters and assign to this handler, if necessary.
+   */
+  function accept_exposed_input($input) {
+    // No need to override the parrent class' accept_exposed_input() method.
+    // It returns TRUE (and therefor results in an altered query and therefor
+    // filtered view) whenever the filter is not exposed or when a new value
+    // was validated.
+    // This method checks if $this->validated_exposed_input is set, and if so,
+    // results are filtered by those values.
+    return parent::accept_exposed_input($input);
+  }
+
+  function admin_summary() {
+    $this->value = (array) $this->value;
+    return parent::admin_summary();
+  }
+
+  /**
+   * Check whether the "Selection type" (in the configuration of the exposed
+   * filter) is Hierarchical Select.
+   *
+   * This function is used in almost every overridden method to determine
+   * whether our custom logic should be used or the parent class's, i.e. the
+   * parent method in the views_handler_filter_term_node_tid class.
+   */
+  function select_type_is_hierarchical_select() {
+    return $this->options['type'] == 'hierarchical_select';
+  }
+}
