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'] = '';
// 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");
}