/[drupal]/contributions/modules/hierarchical_select/hierarchical_select.module
ViewVC logotype

Diff of /contributions/modules/hierarchical_select/hierarchical_select.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.143, Sun Nov 30 01:56:35 2008 UTC revision 1.144, Mon Dec 1 02:21:17 2008 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: hierarchical_select.module,v 1.142 2008/11/30 01:15:01 wimleers Exp $  // $Id: hierarchical_select.module,v 1.143 2008/11/30 01:56:35 wimleers Exp $
3    
4  /**  /**
5   * @file   * @file
# Line 18  define('HS_DEVELOPER_MODE', 0); Line 18  define('HS_DEVELOPER_MODE', 0);
18  /**  /**
19   * Implementation of hook_menu().   * Implementation of hook_menu().
20   */   */
21  function hierarchical_select_menu($may_cache) {  function hierarchical_select_menu() {
22    if ($may_cache) {    $items['hierarchical_select_json'] = array(
23      $items[] = array(      'page callback'   => 'hierarchical_select_json',
24        'path'               => 'hierarchical_select_json',      'type'            => MENU_CALLBACK,
25        'callback'           => 'hierarchical_select_json',      // TODO: Needs improvements. Ideally, this would inherit the permissions
26        'type'               => MENU_CALLBACK,      // of the form the Hierarchical Select was in.
27        // TODO: Needs improvements. Ideally, this would inherit the permissions      'access callback' => TRUE,
28        // of the form the Hierarchical Select was in.    );
29        'access'             => TRUE,    $items['admin/settings/hierarchical_select'] = array(
30      );      'title'            => 'Hierarchical Select',
31      $items[] = array(      'description'      => 'Configure site-wide settings for the Hierarchical Select form element.',
32        'path'               => 'admin/settings/hierarchical_select',      'access arguments' => array('administer site configuration'),
33        'title'              => t('Hierarchical Select'),      'page callback'    => 'drupal_get_form',
34        'description'        => t('Configure site-wide settings for the Hierarchical Select form element.'),      'page arguments'   => array('hierarchical_select_admin_settings'),
35        'callback'           => 'drupal_get_form',      'type'             => MENU_NORMAL_ITEM,
36        'callback arguments' => array('hierarchical_select_admin_settings'),      'file'             => 'hierarchical_select.admin.inc',
37        'type'               => MENU_NORMAL_ITEM,    );
38      );    $items['admin/settings/hierarchical_select/settings'] = array(
39      $items[] = array(      'title'            => 'Site-wide settings',
40        'path'               => 'admin/settings/hierarchical_select/settings',      'access arguments' => array('administer site configuration'),
41        'title'              => t('Site-wide settings'),      'weight'           => -10,
42        'weight'             => -10,      'type'             => MENU_DEFAULT_LOCAL_TASK,
43        'type'               => MENU_DEFAULT_LOCAL_TASK,      'file'             => 'hierarchical_select.admin.inc',
44      );    );
45      $items[] = array(    $items['admin/settings/hierarchical_select/configs'] = array(
46        'path'               => 'admin/settings/hierarchical_select/configs',      'title'            => 'Configurations',
47        'title'              => t('Configurations'),      'description'      => 'All available Hierarchical Select configurations.',
48        'description'        => t('All available Hierarchical Select configurations.'),      'access arguments' => array('administer site configuration'),
49        'callback'           => 'hierarchical_select_admin_configs',      'page callback'    => 'hierarchical_select_admin_configs',
50        'type'               => MENU_LOCAL_TASK,      'type'             => MENU_LOCAL_TASK,
51      );      'file'             => 'hierarchical_select.admin.inc',
52      $items[] = array(    );
53        'path'               => 'admin/settings/hierarchical_select/implementations',    $items['admin/settings/hierarchical_select/implementations'] = array(
54        'title'              => t('Implementations'),      'title'            => 'Implementations',
55        'description'        => t('Features of each Hierarchical Select implementation.'),      'description'      => 'Features of each Hierarchical Select implementation.',
56        'callback'           => 'hierarchical_select_admin_implementations',      'access arguments' => array('administer site configuration'),
57        'type'               => MENU_LOCAL_TASK,      'page callback'    => 'hierarchical_select_admin_implementations',
58      );      'type'             => MENU_LOCAL_TASK,
59    }      'file'             => 'hierarchical_select.admin.inc',
60    else {    );
61      // Work-around for bug in Drupal 5 (fixed in Drupal 5.8).    $items['admin/settings/hierarchical_select/export/%hierarchical_select_config_id'] = array(
62      // See http://drupal.org/node/109459.      'title'            => 'Export',
63      global $user;      'access arguments' => array('administer site configuration'),
64      if (!isset($user->theme)) {      'page callback'    => 'drupal_get_form',
65        $user->theme = variable_get('theme_default', 'garland');      'page arguments'   => array('hierarchical_select_admin_export', 4),
66      }      'type'             => MENU_LOCAL_TASK,
67        'file'             => 'hierarchical_select.admin.inc',
68      if (arg(0) == 'admin' && arg(1) == 'settings' && arg(2) == 'hierarchical_select') {    );
69        require_once(drupal_get_path('module', 'hierarchical_select') .'/hierarchical_select.admin.inc');    $items['admin/settings/hierarchical_select/import/%hierarchical_select_config_id'] = array(
70        'title'            => 'Import',
71        if (in_array(arg(3), array('export', 'import'))) {      'access arguments' => array('administer site configuration'),
72          require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc');      'page callback'    => 'drupal_get_form',
73          $items[] = array(      'page arguments'   => array('hierarchical_select_admin_import', 4),
74            'path'               => 'admin/settings/hierarchical_select/export/'. arg(4),      'type'             => MENU_LOCAL_TASK,
75            'title'              => t('Export'),      'file'             => 'hierarchical_select.admin.inc',
76            'callback'           => 'drupal_get_form',    );
77            'callback arguments' => array('hierarchical_select_admin_export', arg(4)),  
           'type'               => MENU_LOCAL_TASK,  
         );  
         $items[] = array(  
           'path'               => 'admin/settings/hierarchical_select/import/'. arg(4),  
           'title'              => t('Import'),  
           'callback'           => 'drupal_get_form',  
           'callback arguments' => array('hierarchical_select_admin_import', arg(4)),  
           'type'               => MENU_LOCAL_TASK,  
         );  
       }  
     }  
   }  
78    return $items;    return $items;
79  }  }
80    
81  /**  /**
82   * Implementation of hook_form_alter().   * Implementation of hook_form_alter().
83   */   */
84  function hierarchical_select_form_alter($form_id, &$form) {  function hierarchical_select_form_alter(&$form, &$form_state, $form_id) {
85    if (_hierarchical_select_form_has_hierarchical_select($form)) {    if (_hierarchical_select_form_has_hierarchical_select($form)) {
86      $form['#after_build'][] = 'hierarchical_select_after_build';      $form['#after_build'][] = 'hierarchical_select_after_build';
87    }    }
# Line 105  function hierarchical_select_form_alter( Line 93  function hierarchical_select_form_alter(
93  function hierarchical_select_elements() {  function hierarchical_select_elements() {
94    $type['hierarchical_select'] = array(    $type['hierarchical_select'] = array(
95      '#input' => TRUE,      '#input' => TRUE,
96      '#process' => array('hierarchical_select_process' => array()),      '#process' => array('hierarchical_select_process'),
97      '#config' => array(      '#config' => array(
98        'module' => 'some_module',        'module' => 'some_module',
99        'params' => array(),        'params' => array(),
# Line 153  function hierarchical_select_requirement Line 141  function hierarchical_select_requirement
141      $current = drupal_get_installed_schema_version('hierarchical_select');      $current = drupal_get_installed_schema_version('hierarchical_select');
142    
143      $up_to_date = (end($updates) == $current);      $up_to_date = (end($updates) == $current);
144      $jquery_update_v2 = (file_exists(drupal_get_path('module', 'jquery_update') .'/compat.js'));  
     $jquery_interface = module_exists('jquery_interface');  
145      $hierarchical_select_weight = db_result(db_query("SELECT weight FROM {system} WHERE type = 'module' AND name = 'hierarchical_select'"));      $hierarchical_select_weight = db_result(db_query("SELECT weight FROM {system} WHERE type = 'module' AND name = 'hierarchical_select'"));
146      $core_overriding_modules = array('hs_book', 'hs_menu', 'hs_taxonomy');      $core_overriding_modules = array('hs_book', 'hs_menu', 'hs_taxonomy');
147      $path_errors = array();      $path_errors = array();
# Line 174  function hierarchical_select_requirement Line 161  function hierarchical_select_requirement
161          $weight_errors[] = t('!module (!weight)', array('!module' => $module_info['name'], '!weight' => $weight));          $weight_errors[] = t('!module (!weight)', array('!module' => $module_info['name'], '!weight' => $weight));
162        }        }
163      }      }
   
164    
165      if ($up_to_date && $jquery_update_v2 && !$jquery_interface && !count($path_errors) && !count($weight_errors)) {      if ($up_to_date && !count($path_errors) && !count($weight_errors)) {
166        $value = t('All updates installed. jQuery Update 2.x installed. Implementation modules are installed correctly.');        $value = t('All updates installed. Implementation modules are installed correctly.');
167        $description = '';        $description = '';
168        $severity = REQUIREMENT_OK;        $severity = REQUIREMENT_OK;
169      }      }
     elseif (!$up_to_date) {  
       $value = t('Not all updates installed!');  
       $description = t('Please run update.php to install the latest updates!  
         You have installed update !installed_update, but the latest update is  
         !latest_update!',  
         array(  
           '!installed_update' => $current,  
           '!latest_update' => end($updates),  
         )  
       );  
       $severity = REQUIREMENT_ERROR;  
     }  
     elseif (!$jquery_update_v2) {  
       $value = t('jQuery Update 1.x installed!');  
       $description = t('Please upgrade to jQuery Update 2.x! jQuery Update  
         1.x contains jQuery 1.1.x, which is incompatible with the Javascript  
         code of Hierarchical Select!'  
       );  
       $severity = REQUIREMENT_ERROR;  
     }  
     elseif ($jquery_interface) {  
       $value = t('jQuery Interface installed!');  
       $description = t('Please disable and uninstall jQuery Interface, as it  
         is incompatible with jQuery Update 2. It is very buggy anyway and any  
         module that uses it should upgrade to jQuery UI.'  
       );  
       $severity = REQUIREMENT_ERROR;  
     }  
170      elseif ($path_errors) {      elseif ($path_errors) {
171        $value = t('Modules incorrectly installed!');        $value = t('Modules incorrectly installed!');
172        $description = t(        $description = t(
# Line 229  function hierarchical_select_requirement Line 187  function hierarchical_select_requirement
187        ) .':'. theme('item_list', $weight_errors);        ) .':'. theme('item_list', $weight_errors);
188        $severity = REQUIREMENT_ERROR;        $severity = REQUIREMENT_ERROR;
189      }      }
190        else {
191          $value = t('Not all updates installed!');
192          $description = t('Please run update.php to install the latest updates!
193            You have installed update !installed_update, but the latest update is
194            !latest_update!',
195            array(
196              '!installed_update' => $current,
197              '!latest_update' => end($updates),
198            )
199          );
200          $severity = REQUIREMENT_ERROR;
201        }
202    
203      $requirements['hierarchical_select'] = array(      $requirements['hierarchical_select'] = array(
204        'title' => t('Hierarchical Select'),        'title' => t('Hierarchical Select'),
# Line 241  function hierarchical_select_requirement Line 211  function hierarchical_select_requirement
211    return $requirements;    return $requirements;
212  }  }
213    
214    /**
215     * Implementation of hook_theme().
216     */
217    function hierarchical_select_theme() {
218      return array(
219        'hierarchical_select' => array(
220          'file'      => 'includes/theme.inc',
221          'arguments' => array('element' => NULL),
222        ),
223        'hierarchical_select_select' => array(
224          'file'      => 'includes/theme.inc',
225          'arguments' => array('element' => NULL),
226        ),
227        'hierarchical_select_textfield' => array(
228          'file'      => 'includes/theme.inc',
229          'arguments' => array('element' => NULL),
230        ),
231        'hierarchical_select_dropbox_table' => array(
232          'file'      => 'includes/theme.inc',
233          'arguments' => array('element' => NULL),
234        ),
235        'hierarchical_select_common_config_form_level_labels' => array(
236          'file'      => 'includes/theme.inc',
237          'arguments' => array('form' => NULL),
238        ),
239        'hierarchical_select_common_config_form_editability' => array(
240          'file'      => 'includes/theme.inc',
241          'arguments' => array('form' => NULL),
242        ),
243      );
244    }
245    
246    
247  //----------------------------------------------------------------------------  //----------------------------------------------------------------------------
248  // Menu callbacks.  // Menu system callbacks.
249    
250    /**
251     * Wildcard loader for Hierarchical Select config ID's.
252     */
253    function hierarchical_select_config_id_load($config_id) {
254      if (empty($config_id)) {
255        return FALSE;
256      }
257    
258      // E.g.: extract "content_taxonomy" from "content-taxonomy_field_somefield".
259      $parts = explode('_', $config_id);
260      $module = str_replace(array('-'), array('_'), $parts[0]);
261      return in_array($config_id, array_keys(module_invoke($module, 'hierarchical_select_config_info')));
262    }
263    
264  /**  /**
265   * Menu callback; format=text/json; generates and outputs the appropriate HTML.   * Menu callback; format=text/json; generates and outputs the appropriate HTML.
# Line 257  function hierarchical_select_json() { Line 273  function hierarchical_select_json() {
273    
274    // Collect all necessary variables.    // Collect all necessary variables.
275    $cached = cache_get($hs_form_build_id, 'cache');    $cached = cache_get($hs_form_build_id, 'cache');
276    $storage = unserialize($cached->data);    $storage = $cached->data;
277    
278    // Ensure that the form id in the POST array is the same as the one of the    // Ensure that the form id in the POST array is the same as the one of the
279    // stored parameters of the original form. For 99% of the forms, this step    // stored parameters of the original form. For 99% of the forms, this step
# Line 271  function hierarchical_select_json() { Line 287  function hierarchical_select_json() {
287    }    }
288    
289    // Retrieve and process the form.    // Retrieve and process the form.
290      $form_state = &$storage['parameters'][1];
291      if (!empty($storage['file'])) {
292        require_once($storage['file']);
293      }
294    $form = call_user_func_array('drupal_retrieve_form', $storage['parameters']);    $form = call_user_func_array('drupal_retrieve_form', $storage['parameters']);
295    drupal_prepare_form($form_id, $form);    drupal_prepare_form($form_id, $form, $form_state);
296      $form['#post'] = $_POST;
297      $form = form_builder($form_id, $form, $form_state);
298    
299    // Render only the relevant part of the form (i.e. the hierarchical_select    // Render only the relevant part of the form (i.e. the hierarchical_select
300    // form item that has triggered this AJAX callback).    // form item that has triggered this AJAX callback).
# Line 308  function hierarchical_select_json() { Line 330  function hierarchical_select_json() {
330  /**  /**
331   * Hierarchical select form element type #process callback.   * Hierarchical select form element type #process callback.
332   */   */
333  function hierarchical_select_process($element) {  function hierarchical_select_process($element, $edit, $form_state, $form) {
334    static $hsid;    static $hsid;
335    
336    if (!isset($hsid)) {    if (!isset($hsid)) {
# Line 582  function hierarchical_select_process($el Line 604  function hierarchical_select_process($el
604    // is set to 'label_0' after an "Add" operation. When $element['#post'] is    // is set to 'label_0' after an "Add" operation. When $element['#post'] is
605    // NOT unset, the corresponding value in $element['#post'] will be used    // NOT unset, the corresponding value in $element['#post'] will be used
606    // instead of the default value that was set. This is undesired behavior.    // instead of the default value that was set. This is undesired behavior.
607    unset($element['#post']);    // TODO: find a work-around for this in D6.
608    //  unset($element['#post']);
609    
610    // Finally, calculate the return value of this hierarchical_select form    // Finally, calculate the return value of this hierarchical_select form
611    // element. This will be set in _hierarchical_select_validate(). (If we'd    // element. This will be set in _hierarchical_select_validate(). (If we'd
# Line 592  function hierarchical_select_process($el Line 615  function hierarchical_select_process($el
615    // Add a validate callback, which will:    // Add a validate callback, which will:
616    // - validate that the dropbox limit was not exceeded.    // - validate that the dropbox limit was not exceeded.
617    // - set the return value of this form element.    // - set the return value of this form element.
618    $element['#validate'] = array('_hierarchical_select_validate' => array());    $element['#element_validate'] = array('_hierarchical_select_validate');
619    
620    if (HS_DEVELOPER_MODE) {    if (HS_DEVELOPER_MODE) {
621      $element['log'] = array('#type' => 'value', '#value' => _hierarchical_select_log(NULL, TRUE));      $element['log'] = array('#type' => 'value', '#value' => _hierarchical_select_log(NULL, TRUE));
# Line 617  function hierarchical_select_process($el Line 640  function hierarchical_select_process($el
640    return $element;    return $element;
641  }  }
642    
643  /**   /**
644   * Hierarchical select form element type #after_build callback.    * Hierarchical select form element type #after_build callback.
645   */    */
646  function hierarchical_select_after_build($form, $form_values) {  function hierarchical_select_after_build($form, &$form_state) {
647    $names = _hierarchical_select_store_name(NULL, NULL, TRUE);    $names = _hierarchical_select_store_name(NULL, NULL, TRUE);
648    
649    if (!isset($_POST['hs_form_build_id']) && count($names)) {    if (!isset($_POST['hs_form_build_id']) && count($names)) {
650      $parameters = (isset($form['#parameters'])) ? $form['#parameters'] : array();      $parameters = (isset($form['#parameters'])) ? $form['#parameters'] : array();
651        $menu_item = menu_get_item();
652    
653      // Collect information in this array, which will be used in dynamic form      // Collect information in this array, which will be used in dynamic form
654      // updates, to …      // updates, to …
# Line 633  function hierarchical_select_after_build Line 657  function hierarchical_select_after_build
657        'parameters' => $parameters,        'parameters' => $parameters,
658        // … determine which part of $form should be rendered.        // … determine which part of $form should be rendered.
659        '#names'     => $names,        '#names'     => $names,
660          // … include the file in which the form function lives.
661          'file'       => $menu_item['file'],
662      );      );
663    
664      // Store the information needed for dynamic form updates in the cache, so      // Store the information needed for dynamic form updates in the cache, so
# Line 640  function hierarchical_select_after_build Line 666  function hierarchical_select_after_build
666      // render part of the form).      // render part of the form).
667      $expire = max(ini_get('session.cookie_lifetime'), 86400);      $expire = max(ini_get('session.cookie_lifetime'), 86400);
668      $hs_form_build_id = 'hs_form_'. md5(mt_rand());      $hs_form_build_id = 'hs_form_'. md5(mt_rand());
669      cache_set($hs_form_build_id, 'cache', serialize($storage), $expire);      cache_set($hs_form_build_id, $storage, 'cache', $expire);
   
670    }    }
671    elseif (isset($_POST['hs_form_build_id'])) {    elseif (isset($_POST['hs_form_build_id'])) {
672      // Don't generate a new hs_form_build_id if this is a re-rendering of the      // Don't generate a new hs_form_build_id if this is a re-rendering of the
# Line 658  function hierarchical_select_after_build Line 683  function hierarchical_select_after_build
683      // form_builder() has all info it needs to generate #name and #id.      // form_builder() has all info it needs to generate #name and #id.
684      '#parents' => array('hs_form_build_id'),      '#parents' => array('hs_form_build_id'),
685    );    );
686    $form['hs_form_build_id'] = form_builder($form['form_id']['#value'], $form_element);    $form['hs_form_build_id'] = form_builder($form['form_id']['#value'], $form_element, $form_state);
687    
688    // Pass the hs_form_build_id to a custom submit function that will clear    // Pass the hs_form_build_id to a custom submit function that will clear
689    // the associated values from the cache.    // the associated values from the cache.
690    $form['#submit']['_hierarchical_select_submit'] = array($_POST['hs_form_build_id']);    $form_state['hs_form_build_id'] = $_POST['hs_form_build_id'];
691      $form['#submit'][] = '_hierarchical_select_submit';
692    
693    return $form;    return $form;
694  }  }
695    
696  /**  /**
697   * Hierarchical select form element #validate callback.   * Hierarchical select form element #element_validate callback.
698   */   */
699  function _hierarchical_select_validate(&$element) {  function _hierarchical_select_validate(&$element, &$form_state) {
700    // If the dropbox is enabled and a dropbox limit is configured, check if    // If the dropbox is enabled and a dropbox limit is configured, check if
701    // this limit is not exceeded.    // this limit is not exceeded.
702    $config = $element['#config'];    $config = $element['#config'];
703    if ($config['dropbox']['status']) {    if ($config['dropbox']['status']) {
704      if ($config['dropbox']['limit'] > 0) { // Zero as dropbox limit means no limit.      if ($config['dropbox']['limit'] > 0) { // Zero as dropbox limit means no limit.
705        // TRICKY: #validate is not called upon the initial rendering (i.e. it        // TRICKY: #element_validate is not called upon the initial rendering
706        // is assumed that the default value is valid). However, Hierarchical        // (i.e. it is assumed that the default value is valid). However,
707        // Select's config can influence the validity (i.e. how many selections        // Hierarchical Select's config can influence the validity (i.e. how
708        // may be added to the dropbox). This means it's possible the user has        // many selections may be added to the dropbox). This means it's
709        // actually selected too many items without being notified of this.        // possible the user has actually selected too many items without being
710          // notified of this.
711        $lineage_count = count($element['#value']['dropbox']['hidden']['lineages_selections']);        $lineage_count = count($element['#value']['dropbox']['hidden']['lineages_selections']);
712        if ($lineage_count > $config['dropbox']['limit']) {        if ($lineage_count > $config['dropbox']['limit']) {
713          // TRICKY: this should propagate the error down to the children, but          // TRICKY: this should propagate the error down to the children, but
# Line 709  function _hierarchical_select_validate(& Line 736  function _hierarchical_select_validate(&
736    // detects as an empty form value.    // detects as an empty form value.
737    $value = (empty($element['#return_value'])) ? 0 : $element['#return_value'];    $value = (empty($element['#return_value'])) ? 0 : $element['#return_value'];
738    $element['#value'] = $value;    $element['#value'] = $value;
739    form_set_value($element, $value);    form_set_value($element, $value, $form_state);
740    
741    // We have to check again for errors. This line is taken litterally from    // We have to check again for errors. This line is taken litterally from
742    // form.inc, so it works in an identical way.    // form.inc, so it works in an identical way.
# Line 721  function _hierarchical_select_validate(& Line 748  function _hierarchical_select_validate(&
748  /**  /**
749   * Hierarchical select form element #submit callback.   * Hierarchical select form element #submit callback.
750   */   */
751  function _hierarchical_select_submit($form_id, $form_values, $hs_form_build_id) {  function _hierarchical_select_submit($form, &$form_state) {
752    // Delete the stored form information when the form is submitted.    // Delete the stored form information when the form is submitted.
753    cache_clear_all($hs_form_build_id, 'cache');    cache_clear_all($form_state['hs_form_build_id'], 'cache');
754  }  }
755    
756    
# Line 962  function _hierarchical_select_process_re Line 989  function _hierarchical_select_process_re
989        '#type' => 'select',        '#type' => 'select',
990        '#options' => $hierarchy->levels[$depth],        '#options' => $hierarchy->levels[$depth],
991        '#default_value' => $selected_item,        '#default_value' => $selected_item,
       // We need to skip the check of valid options, because they may be  
       // modified after each update.  
       '#DANGEROUS_SKIP_CHECK' => TRUE,  
992        // Use a #theme callback to prevent the select from being wrapped in a        // Use a #theme callback to prevent the select from being wrapped in a
993        // div. This simplifies the CSS and JS code. Also sets a special class        // div. This simplifies the CSS and JS code. Also sets a special class
994        // on the level label option, if any, to make level label styles        // on the level label option, if any, to make level label styles
# Line 2003  function _hierarchical_select_dropbox_li Line 2027  function _hierarchical_select_dropbox_li
2027  function _hierarchical_select_dropbox_lineage_item_get_value($item) {  function _hierarchical_select_dropbox_lineage_item_get_value($item) {
2028    return $item['value'];    return $item['value'];
2029  }  }
   
 /**  
  * This is an altered clone of form_select_options(). The reason: I need to be  
  * able to set a class on an option element if it contains a level label, to  
  * allow for level label styles.  
  * Secondly, I need to be able to mark childless items (i.e. "option"  
  * elements).  
  */  
 function _hierarchical_select_options($element) {  
   if (!isset($choices)) {  
     $choices = $element['#options'];  
   }  
   // array_key_exists() accommodates the rare event where $element['#value'] is NULL.  
   // isset() fails in this situation.  
   $value_valid = isset($element['#value']) || array_key_exists('#value', $element);  
   $value_is_array = is_array($element['#value']);  
   $options = '';  
   foreach ($choices as $key => $choice) {  
     $key = (string)$key;  
     if ($value_valid && (!$value_is_array && (string)$element['#value'] === $key || ($value_is_array && in_array($key, $element['#value'])))) {  
       $selected = ' selected="selected"';  
     }  
     else {  
       $selected = '';  
     }  
   
     // If an option DOES NOT have child info, then it's a special option:  
     // - label_\d+ (level label)  
     // - none ("<none>")  
     // - create_new_item ("<create new item>")  
     // Only when it's a level label, we have to add a class to this option.  
     if (!isset($element['#childinfo'][$key])) {  
       $class = (preg_match('/label_\d+/', $key)) ? ' level-label' : '';  
     }  
     else {  
       $class = ($element['#childinfo'][$key] == 0) ? 'has-no-children' : 'has-children';  
     }  
   
     $options .= '<option value="'. check_plain($key) .'" class="'. $class .'"'. $selected .'>'. check_plain($choice) .'</option>';  
   }  
   return $options;  
 }  
   
   
 //----------------------------------------------------------------------------  
 // Theming callbacks.  
   
 /**  
  * @ingroup themeable  
  * @{  
  */  
   
 /**  
  * Format a hierarchical select.  
  *  
  * @param $element  
  *   An associative array containing the properties of the element.  
  * @return  
  *   A themed HTML string representing the form element.  
  */  
 function theme_hierarchical_select($element) {  
   $output = '';  
   
   // Update $element['#attributes']['class'].  
   $hsid = $element['hsid']['#value'];  
   $level_labels_style = variable_get('hierarchical_select_level_labels_style', 'none');  
   $classes = array(  
    'hierarchical-select-wrapper',  
    "hierarchical-select-level-labels-style-$level_labels_style",  
   );  
   $element['#attributes']['class'] .= ' '. implode(' ', $classes);  
   $element['#attributes']['id'] = "hierarchical-select-$hsid-wrapper";  
   
   $output .= theme(  
     'form_element',  
     array(  
       '#title' => $element['#title'],  
       '#description' => $element['#description'],  
       '#id' => $element['#id'],  
       '#required' => $element['#required'],  
       '#error' => $element['#error'],  
     ),  
     '<div '. drupal_attributes($element['#attributes']) .'>'. $element['#children'] .'</div>'  
   );  
   
   return $output;  
 }  
   
 /**  
  * Format a select in the .hierarchial-select div: prevent it from being  
  * wrapped in a div. This simplifies the CSS and JS code.  
  *  
  * @param $element  
  *   An associative array containing the properties of the element.  
  * @return  
  *   A themed HTML string representing the form element.  
  */  
 function theme_hierarchical_select_select($element) {  
   $select = '';  
   $size = $element['#size'] ? ' size="'. $element['#size'] .'"' : '';  
   _form_set_class($element, array('form-select'));  
   $multiple = isset($element['#multiple']) && $element['#multiple'];  
   return '<select name="'. $element['#name'] .''. ($multiple ? '[]' : '') .'"'. ($multiple ? ' multiple="multiple" ' : '') . drupal_attributes($element['#attributes']) .' id="'. $element['#id'] .'" '. $size .'>'. _hierarchical_select_options($element) .'</select>';  
 }  
   
 /**  
  * Format a textfield in the .hierarchial-select div: prevent it from being  
  * wrapped in a div. This simplifies the CSS and JS code.  
  *  
  * @param $element  
  *   An associative array containing the properties of the element.  
  * @return  
  *   A themed HTML string representing the form element.  
  */  
 function theme_hierarchical_select_textfield($element) {  
   $size = $element['#size'] ? ' size="'. $element['#size'] .'"' : '';  
   $class = array('form-text');  
   $extra = '';  
   $output = '';  
   
   if ($element['#autocomplete_path']) {  
     drupal_add_js('misc/autocomplete.js');  
     $class[] = 'form-autocomplete';  
     $extra =  '<input class="autocomplete" type="hidden" id="'. $element['#id'] .'-autocomplete" value="'. check_url(url($element['#autocomplete_path'], NULL, NULL, TRUE)) .'" disabled="disabled" />';  
   }  
   _form_set_class($element, $class);  
   
   if (isset($element['#field_prefix'])) {  
     $output .= '<span class="field-prefix">'. $element['#field_prefix'] .'</span> ';  
   }  
   
   $output .= '<input type="text" maxlength="'. $element['#maxlength'] .'" name="'. $element['#name'] .'" id="'. $element['#id'] .'" '. $size .' value="'. check_plain($element['#value']) .'"'. drupal_attributes($element['#attributes']) .' />';  
   
   if (isset($element['#field_suffix'])) {  
     $output .= ' <span class="field-suffix">'. $element['#field_suffix'] .'</span>';  
   }  
   
   return $output . $extra;  
 }  
   
 /**  
  * Forms API theming callback for the dropbox. Renders the dropbox as a table.  
  *  
  * @param $element  
  *   An element for which the #theme property was set to this function.  
  * @return  
  *   A themed HTML string.  
  */  
 function theme_hierarchical_select_dropbox_table($element) {  
   $output = '';  
   
   
   $title     = $element['title']['#value'];  
   $separator = $element['separator']['#value'];  
   $is_empty  = $element['is_empty']['#value'];  
   
   $separator_html = '<span class="hierarchical-select-item-separator">'. $separator .'</span>';  
   
   $output .= '<div class="dropbox">';  
   $output .= '<table>';  
   $output .= '<caption class="dropbox-title">'. $title .'</caption>';  
   $output .= '<tbody>';  
   
   if (!$is_empty) {  
     // Each lineage in the dropbox corresponds to an entry in the dropbox table.  
     $lineage_count = count(element_children($element['lineages']));  
     for ($x = 0; $x < $lineage_count; $x++) {  
       $db_entry = $element['lineages'][$x];  
       $zebra = $db_entry['#zebra'];  
       $first = $db_entry['#first'];  
       $last  = $db_entry['#last'];  
       // The deepest level is the number of child levels minus one. This "one"  
       // is the element for the "Remove" checkbox.  
       $deepest_level = count(element_children($db_entry)) - 1;  
   
       $output .= '<tr class="dropbox-entry '. $first .' '. $last .' '. $zebra .'">';  
       $output .= '<td>';  
       // Each item in a lineage is separated by the separator string.  
       for ($depth = 0; $depth < $deepest_level; $depth++) {  
         $output .= drupal_render($db_entry[$depth]);  
   
         if ($depth < $deepest_level - 1) {  
           $output .= $separator_html;  
         }  
       }  
       $output .= '</td>';  
       $output .= '<td class="dropbox-remove">'. drupal_render($db_entry['remove']) .'</td>';  
       $output .= '</tr>';  
     }  
   }  
   else {  
     $output .= '<tr class="dropbox-entry first last dropbox-is-empty"><td>';  
     $output .= t('Nothing has been selected.');  
     $output .= '</td></tr>';  
   }  
   
   $output .= '</tbody>';  
   $output .= '</table>';  
   $output .= '</div>';  
   
   return $output;  
 }  
   
 /**  
  * @} End of "ingroup themeable".  
  */  

Legend:
Removed from v.1.143  
changed lines
  Added in v.1.144

  ViewVC Help
Powered by ViewVC 1.1.2