t('Better select'), 'description' => t('Configure better select settings.'), 'page callback' => 'drupal_get_form', 'page arguments' => array('betterselect_admin_settings'), 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); return $items; } /** * Build settings form(). */ function betterselect_admin_settings() { $form['betterselect_general'] = array( '#type' => 'fieldset', '#title' => t('General options'), ); $form['betterselect_general']['betterselect_scroll'] = array( '#type' => 'checkbox', '#title' => t('Scrollable div'), '#description' => t('Place options in a scrollable div'), '#default_value' => variable_get('betterselect_scroll', FALSE), ); $form['betterselect_general']['betterselect_node_form_only'] = array( '#type' => 'checkbox', '#title' => t('Node form only'), '#description' => t('Only convert select lists on node forms'), '#default_value' => variable_get('betterselect_node_form_only', FALSE), ); $form['betterselect_general']['betterselect_not_on_admin_pages'] = array( '#type' => 'checkbox', '#title' => t('Not on admin pages'), '#description' => t('Disable convertion of select lists on admin pages'), '#default_value' => variable_get('betterselect_not_on_admin_pages', FALSE), ); $form['betterselect_general']['betterselect_use_radioboxes'] = array( '#type' => 'checkbox', '#title' => t('Use radioboxes'), '#description' => t('Radioboxes will be used instead of a dropdown-box for single-select entries'), '#default_value' => variable_get('betterselect_use_radioboxes', FALSE), ); $form['betterselect_taxonomy'] = array( '#type' => 'fieldset', '#title' => t('Taxonomy options'), ); $form['betterselect_taxonomy']['betterselect_save_lineage'] = array( '#type' => 'checkbox', '#title' => t('Save lineage'), '#description' => t('If a user selects a child term when saving a node, automatically save the parent term too.'), '#default_value' => variable_get('betterselect_save_lineage', FALSE), ); $form['betterselect_taxonomy']['betterselect_add_depth_classes'] = array( '#type' => 'checkbox', '#title' => t('Add depth classes'), '#description' => t('Add an extra div to each betterselect option, with a class indicating depth in taxonomy hierarchy. Good for styling parent/child.'), '#default_value' => variable_get('betterselect_add_depth_classes', FALSE), ); return system_settings_form($form); } /** * Implementation of hook_elements(). */ function betterselect_elements() { $type = array(); $type['select']['#process'] = array('betterselect_process'); return $type; } /** * Form process callback; translates multiselect fields into checkboxes. */ function betterselect_process($element, $edit, $form_state, $complete_form) { if (!(variable_get('betterselect_not_on_admin_pages', FALSE) == TRUE && betterselect_is_admin_page(false, $complete_form)) && !(variable_get('betterselect_node_form_only', FALSE) == TRUE && $complete_form['#id'] != 'node-form') && (isset($element['#type']) && $element['#type'] == "select") && ( (variable_get('betterselect_use_radioboxes', FALSE) == TRUE && (isset($element['#multiple']) && $element['#multiple'] != TRUE)) || (isset($element['#multiple']) && $element['#multiple'] == TRUE)) ) { // To handle deselection of checkboxes in exposed Views-filters we need this if ((substr($complete_form['#id'],0,18) == 'views-exposed-form') && isset($element['#value'][0])) { $element['#value'] = array(); } // If we're dealing with taxonomy, fix the option titles. if (is_object($element['#options'][0])) { // Build new array of options in format that theme_checkboxes expects. $options = array(); $defaults = array(); foreach ($element['#options'] as $option) { if (is_array($option->option)) { foreach ($option->option as $tid => $name) { $options[$tid] = check_plain($name); } } } $element['#options'] = $options; } // Place options in a scrollable or non-scrollable div $div_class = variable_get('betterselect_scroll', FALSE) ? 'form-checkboxes-scroll' : 'form-checkboxes-noscroll'; $element['#attributes'] = array('class' => $div_class); // This sections is specific for multi-select if (isset($element['#multiple']) && $element['#multiple'] == TRUE) { // We now check that the element's options are correct. If they're not in // the right format, we abort. foreach($element['#options'] as $key => $val) { if (!is_numeric($key) || !is_string($val)) { return $element; } } // The default value should be an array, if it isn't expand_checkboxes() // will make it one. if (isset($element['#default_value']) && is_array($element['#default_value']) && count($element['#default_value'])) { // Fix the value arrays; checkboxes are the exact inverse of multiselect, // apparently for vindictive fun. // First make sure there's at least 1 non-blank array element $temp = $element['#default_value']; $temp = array_shift($element['#default_value']); if (!empty($temp)) { $element['#default_value'] = array_flip($element['#default_value']); $element['#value'] = array_flip($element['#value']); } } // Switch display to checkboxes instead. $element['#type'] = 'checkboxes'; unset($element['#theme']); $element = expand_checkboxes($element); // Hide the silly "None" option. (assumes array element with a blank key is the "None" option) if (!$element['#required'] && is_array($element[''])) { $element['']['#prefix'] = '
'; $element['']['#suffix'] = '
'; } } // End of multi-select specific code... // This sections is specific for single-select if (isset($element['#multiple']) && $element['#multiple'] != TRUE) { // Remove the "all"-option unset($element['#options']['All']); // Switch display to radioboxes instead. $element['#type'] = 'checkboxes'; unset($element['#theme']); $element = expand_radios($element); } // End of single-select specific code... // Include the JS and CSS files. static $path; if (!isset($path)) { $path = drupal_get_path('module', 'betterselect'); drupal_add_css($path . '/betterselect.css'); drupal_add_js($path . '/betterselect.js'); } // Add classes to items that indicate depth, for taxonomy, useful for // styling parent terms differently. if (variable_get('betterselect_add_depth_classes', FALSE)) { $prev = NULL; $prev_depth = 0; foreach (element_children($element) as $key) { $title = $element[$key]['#title']; $trim_title = ltrim($title, '-'); $depth = strlen($title) - strlen($trim_title); $extra_class = 'checkbox-depth-' . $depth; $element[$key]['#prefix'] = '
'; $element[$key]['#suffix'] = '
'; // Put a class on each element that contains children. We do this // retroactively, in other words, we operate on the previous element. if ($prev != NULL) { if ($depth > $prev_depth) { // Gone down a level, so previous must get 'has-children' class $alt_classes = 'checkbox-depth-' . $prev_depth . ' has-children'; $prev['#prefix'] = '
'; $prev['#suffix'] = '
'; } } $prev = &$element[$key]; $prev_depth = $depth; } } // Add the necessary prefix/suffix to make JS/CSS work. $size = isset($element['#size']) ? $element['#size'] : 10; $prefix = isset($element['#prefix']) ? $element['#prefix'] : ''; $suffix = isset($element['#suffix']) ? $element['#suffix'] : ''; $fixheight = count($element['#options']) > $size ? ' betterfixed' : ''; $id = 'better-select-' . $element['#id']; $element['#prefix'] = '
' . $prefix; $element['#suffix'] = $suffix . '
'; } return $element; } /** * Implementation of hook_form_alter(). */ function betterselect_form_alter(&$form, $form_state, $form_id) { // First make sure we should do any processing at all if(!(variable_get('betterselect_not_on_admin_pages', FALSE) == TRUE && betterselect_is_admin_page($form, false))) { // Add this to handle checkboxes in exposed Views-filters if (substr($form['#id'],0,18) == 'views-exposed-form' && !(variable_get('betterselect_node_form_only', FALSE))) { $form['#submit'][] = 'betterselect_views_filter_from_checkboxes'; } // Taxonomy stores its #options in a weird way; we need to move it back once we're done. if (($form['#id'] == 'node-form' && isset($form['taxonomy']))) { $form['#submit'][] = 'betterselect_taxonomy_from_checkboxes'; } elseif ($form_id == 'taxonomy_form_term' && !(variable_get('betterselect_node_form_only', FALSE))) { // This is the form that appears on the edit/term/xx page. Betterselect // has to process it before taxonomy module. array_unshift($form['#submit'], 'betterselect_taxonomy_form_term_from_checkboxes'); } } } /** * Additional submit handler for the views filter form. */ function betterselect_views_filter_from_checkboxes($form, &$form_state) { // First detect which filters that are tid-filters $tid_filters = array(); $i = 0; if(is_array($form['#info'])) { foreach ($form['#info'] as $key => $info_data) { $short_key = substr($key,0,10); if ($short_key == "filter-tid" && is_array($info_data) && array_key_exists('value', $info_data)) { $tid_filters[] = $info_data['value']; if($j > 0) { $tid_id[$i] = "tid_".$i; } else { $tid_id[$i] = "tid"; } $i++; } } } // Retrieve all content_taxonomy-fields if(is_array($form['#parameters'])) { foreach ($form['#parameters'] as $param_data) { if(is_array($param_data) && is_object($param_data['view']) && is_object($param_data['view']->display_handler) && is_array($param_data['view']->display_handler->handlers) && is_array($param_data['view']->display_handler->handlers['field']) && is_object($param_data['view']->display_handler->handlers['field']['title']) && is_object($param_data['view']->display_handler->handlers['field']['title']->view) && is_array($param_data['view']->display_handler->handlers['field']['title']->view->filter) ) { foreach($param_data['view']->display_handler->handlers['field']['title']->view->filter as $key => $filter_field) { if(is_object($filter_field) && is_array($filter_field->content_field) && isset($filter_field->content_field['type']) && $filter_field->content_field['type'] == "content_taxonomy") { if(isset($filter_field->options['expose']['identifier'])) { $tid_filters[] = $filter_field->options['expose']['identifier']; $tid_id[] = $key; } } } } } } // Create an array which is correct! $new_tid = array(); $i = 0; //betterselect_printit($form['#parameters'][1]['view']->display_handler->handlers['field']['title']->view->filter[field_product_portal_value] ); foreach($tid_filters as $tid_filter) { if (is_array($form_state['values'][$tid_filter]) && !array_key_exists(0, $form_state['values'][$tid_filter])) { //betterselect_printit($tid_id[$i]."apa och ko"); $new_tid = array(); foreach ($form_state['values'][$tid_filter] as $val) { if($val != 0) { $new_tid[$val] = $val; } } // This is for the of chance that we actually selected something ;) form_set_value($form[$tid_filter], $new_tid, $form_state); $form_state['values'][$tid_filter] = $new_tid; $form_state[view]->filter[$tid_id[$i]]->validated_exposed_input = $new_tid; $form_state[view]->filter[$tid_id[$i]]->view->exposed_data[$tid_filter] = $new_tid; } $i++; } //betterselect_printit($form_state[view]->filter['field_product_portal_value']->view->exposed_data); } // The following two funtions are for debugging, remove them when everything works! function betterselect_printit($it) { print("
");
	betterselect_print_struct($it,2);
	//print_r($it);
	print("
"); } // This prints a tree of arrays and objects up to a certain depth function betterselect_print_struct($struct,$max_level=1,$level=0){ $spaces=""; for($i=0;$i<$level;$i++) { $spaces .= '-'; } if (!(is_array($struct) || is_object($struct)) ) { print($spaces); print($struct); print("
"); return 1; } foreach($struct as $key => $val) { if ( (is_array($val) || is_object($val)) && ($level < $max_level) ) { if (is_array($val)) { $type = "array()"; } elseif(is_object($val)) { $type = "object()"; } print($spaces."[$key] => $type
"); $level++; betterselect_print_struct($val,$max_level,$level); $level--; } else { if (is_array($val)) { print($spaces."[$key] => array()
"); } elseif(is_object($val)) { print($spaces."[$key] => object()
"); } else { print($spaces."[$key] => $val
"); } } } } /** * Additional submit handler for the taxonomy term form. */ function betterselect_taxonomy_form_term_from_checkboxes($form, &$form_state) { $fix = array('parent', 'relations'); foreach ($fix as $select) { $options = array(); if (isset($form_state['values'][$select])) { foreach ($form_state['values'][$select] as $tid => $selected) { if ($selected) { $options[$tid] = $tid; } } $form_state['values'][$select] = $options; } } } /** * Restore submitted checkbox values back to format Taxonomy module expects. */ function betterselect_taxonomy_from_checkboxes($form, &$form_state) { foreach ($form_state['values']['taxonomy'] as $index => $properties) { if (is_numeric($index) && $form['taxonomy'][$index]['#multiple']) { $options = array(); foreach ($form_state['values']['taxonomy'][$index] as $tid => $selected) { if ($selected) { $options[$tid] = $tid; // Save lineage - automatically select all parents. if (variable_get('betterselect_save_lineage', FALSE)) { $parents = taxonomy_get_parents($tid); foreach ($parents as $key => $val) { $options[$key] = $key; } } } } $form_state['values']['taxonomy'][$index] = $options; } } } /** * Check if the current page is an admin-page * NOTE: I'm not sure this is a good way of doing this, but it works for me at the moment... * TODO: Write this in the correct Drupal-way! */ function betterselect_is_admin_page($form, $complete_form) { if($form != FALSE) { $action_split = split("/", $form['#action'],3); } if($complete_form != FALSE) { $action_split = split("/", $complete_form['#action'],3); } $action_split[] = "extra1"; // Just to make sure we have enough data in the array $action_split[] = "extra2"; // Just to make sure we have enough data in the array return ($action_split[0] == "admin" || $action_split[1] == "admin"); }