diff --git a/cck_select_other.js b/cck_select_other.js
index c5d6617..bd95a33 100644
--- a/cck_select_other.js
+++ b/cck_select_other.js
@@ -26,7 +26,11 @@
// We need to go up further up the element chain to work around 'add another item'
$('select#edit-' + select_id).bind(ActionBind,function() {
// Add parent() to hide input wrapper
- $('input#edit-' + text_id).parent().css('display', ($(this).val() == "other") ? 'block' : 'none');
+ var selected_other = 'none';
+ $(this).children(':selected').each(function() {
+ selected_other = ($(this).val() == 'other') ? 'block' : 'none';
+ });
+ $('input#edit-' + text_id).parent().css('display', selected_other);
}).trigger(ActionBind);
});
});
diff --git a/cck_select_other.module b/cck_select_other.module
index ac8404b..b9d1c93 100644
--- a/cck_select_other.module
+++ b/cck_select_other.module
@@ -153,7 +153,7 @@ function cck_select_other_field_widget_form(&$form, &$form_state, $field, $insta
'#prefix' => '
',
'#suffix' => '
',
'#field_name' => $field['field_name'], // Required fields for field_conditional_state.
- '#field_parents' => $form['#parents'],
+ '#field_parents' => isset($form['#parents']) ? $form['#parents'] : array(),
'#bundle' => $instance['bundle'],
);
@@ -218,7 +218,7 @@ function cck_select_other_widget_validate($element, &$form_state) {
// Empty other field.
if ($field[$langcode]['instance']['required'] && $form_state['values'][$field_name][$langcode][$delta]['select_other_list'] == 'other' && empty($form_state['values'][$field_name][$langcode][$delta]['select_other_text_input'])) {
- form_set_error($field_name . '[' . $langcode . '][' . $delta . '][select_other_text_input]', t('A non-empty value is required for this option.'));
+ form_set_error($element['#name'], t('A non-empty value is required for this option.'));
}
// Non-required field value.
@@ -361,6 +361,15 @@ function cck_select_other_process($element, &$form_state) {
function cck_select_other_pre_render($element, $form_state = NULL) {
static $js;
+ $errors = form_get_errors();
+ if (!empty($errors)) {
+ // Validation errors for the text input box get lost so need to be injected.
+ $text_element = $element['#name'] . '[select_other_text_input]';
+ if (in_array($text_element, array_keys($errors))) {
+ $element['select_other_text_input']['#attributes']['class'][] = 'error';
+ }
+ }
+
if (!isset($form_state)) {
return $element;
}
diff --git a/views/cck_select_other.views.inc b/views/cck_select_other.views.inc
index 6543e80..3be4467 100644
--- a/views/cck_select_other.views.inc
+++ b/views/cck_select_other.views.inc
@@ -15,6 +15,8 @@ function cck_select_other_views_data_alter(&$data) {
$field = $instance['field_name'] . '_value';
$data[$table]['entity_id']['field']['handler'] = 'cck_select_other_handler_field';
$data[$table][$field]['filter']['handler'] = 'cck_select_other_handler_filter';
+ $data[$table][$field]['filter']['entity_type'] = $instance['entity_type'];
+ $data[$table][$field]['filter']['bundle'] = $instance['bundle'];
}
}
}
diff --git a/views/cck_select_other_handler_filter.inc b/views/cck_select_other_handler_filter.inc
index 2ab2019..e889077 100644
--- a/views/cck_select_other_handler_filter.inc
+++ b/views/cck_select_other_handler_filter.inc
@@ -5,25 +5,185 @@
/**
- * Extends Content Handler Filter Many To One for CCK Select Other
+ * Extends Views in operator filter.
*/
-class cck_select_other_handler_filter extends views_handler_filter_field_list {
+class cck_select_other_handler_filter extends views_handler_filter_in_operator {
+
+ /**
+ * Init
+ */
+ function init(&$view, &$options) {
+ parent::init($view, $options);
+
+ $this->instance = field_info_instance($this->definition['entity_type'], $this->definition['field_name'], $this->definition['bundle']);
+ }
+
+ /**
+ * Exposed form
+ */
+ function exposed_form(&$form, &$form_state) {
+ parent::exposed_form($form, $form_state);
+
+ $identifier = $this->options['expose']['identifier'];
+
+ // Populate other default value if any.
+ $otherdef = '';
+ $other_values = array_diff($this->value, $this->value_options);
+ $otherdef = empty($other_values) ? '' : array_pop($other_values);
+
+ $form[$identifier]['select_other_text_input'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Other'),
+ '#title_display' => 'invisible',
+ '#attributes' => array(
+ 'class' => array('form-text select_other_text_input'),
+ ),
+ '#default_value' => $otherdef,
+ '#parents' => array('options', 'value', 'select_other_text_input'),
+ '#size' => 10,
+ );
+
+ $form[$identifier]['#parents'] = array('options', $identifier);
+ $form[$identifier]['select_other_list']['#type'] = 'select';
+ $form[$identifier]['select_other_list']['#multiple'] = $this->options['expose']['multiple'];
+ $form[$identifier]['select_other_list']['#parents'] = array('options', $identifier, 'select_other_list');
+ $form[$identifier]['select_other_text_input']['#parents'] = array('options', $identifier, 'select_other_text_input');
+
+ $field_id = str_replace('_', '-', 'options-' . $identifier);
+ drupal_add_js(array('CCKSelectOther' => array(array('field_id' => $field_id))), array('type' => 'setting'));
+ }
+
+ function exposed_submit($form, &$form_state) {
+ $identifier = $this->options['expose']['identifier'];
+ $values = $form_state['values']['options'][$identifier];
+ $form_state['values'][$identifier] = array();
+
+ foreach ($values['select_other_list'] as $key => $value) {
+ if ($value && $key == $value) {
+ if ($value <> 'other') {
+ $form_state['values'][$identifier][] = $value;
+ }
+ else {
+ // Set the other value instead of 'other'
+ $form_state['values'][$identifier][] = $values['select_other_text_input'];
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Value form
+ */
+ function value_form(&$form, &$form_state) {
+ static $js;
+
+ parent::value_form($form, $form_state);
+
+ $default = array();
+ foreach ($this->value as $key => $value) {
+ // Populate default values.
+ if (in_array($value, $this->value_options)) {
+ $default[] = $value;
+ }
+ else {
+ $default[] = 'other';
+ }
+ }
+
+ $options = $form['value']['#options'];
+ $form['value'] = array(
+ '#type' => 'container',
+ '#tree' => TRUE,
+ '#parents' => array('options', 'value'),
+ 'select_other_list' => array(
+ // @note I am using checkboxes instead of select in the filter.
+ '#type' => 'checkboxes',
+ '#options' => $options,
+ '#default_value' => $default,
+ '#parents' => array('options', 'value', 'select_other_list'),
+ ),
+ );
+
+ if (!$js) {
+ drupal_add_js(drupal_get_path('module', 'cck_select_other') . '/cck_select_other.js');
+ $js = TRUE;
+ }
+ drupal_add_js(array('CCKSelectOther' => array(array('field_id' => 'options-value'))), array('type' => 'setting'));
+ }
+
+ function value_submit($form, &$form_state) {
+ // Capture the values into a separate array and reset the value array.
+ $values = $form_state['values']['options']['value'];
+ $form_state['values']['options']['value'] = array();
+
+ foreach ($values['select_other_list'] as $key => $value) {
+ if ($value && $key == $value) {
+ $form_state['values']['options']['value'][] = $value;
+ }
+ }
+ }
function get_value_options() {
- // This is a gigantic hack because views and views documentation suck.
- $n = preg_match_all("/(\S+):(\S+)/", $this->definition['help'], $matches);
- $entity_type = isset($matches[1]) ? $matches[1] : '';
- $bundle = isset($matches[2]) ? $matches[2] : '';
+ $this->value_options = cck_select_other_options($this->instance);
- $instance = field_read_instance($entity_type, $this->definition['field_name'], $bundle);
- $this->value_options = cck_select_other_options($instance);
+ // Get rid of none options.
+ unset($this->value_options['']);
+ unset($this->value_options['_none']);
+ }
+
+ function accept_exposed_input($input) {
+ $ret = parent::accept_exposed_input($input);
+ return $ret;
}
function query() {
- if (isset($this->value[0]) && $this->value[0] == 'other') {
+ if (!empty($this->value)) {
+ // Only query if we have a value.
+
+ if (in_array('other', $this->value)) {
+ // Remove other from values and add condition for any value not in values.
+ $this->value = array_diff($this->value, array('other'));
+ }
+ else {
+ // Query as normal.
+ parent::query();
+ }
+
}
- else {
- parent::query();
+ }
+
+ function admin_summary() {
+ if (!empty($this->options['exposed'])) {
+ return t('exposed');
+ }
+
+ $info = $this->operators();
+
+ $this->get_value_options();
+
+ if (!is_array($this->value)) {
+ return;
}
+
+ $operator = check_plain($info[$this->operator]['short']);
+ $values = '';
+
+ $count = count($this->value);
+ $i = 1;
+ foreach ($this->value as $value) {
+ if (isset($this->value_options[$value])) {
+ $values .= check_plain($this->value_options[$value]);
+ }
+ else {
+ $values .= t('%value', array('%value' => $value));
+ }
+ if ($i < $count) {
+ $values .= ', ';
+ }
+ $i++;
+ }
+
+ return $operator . (($values !== '') ? ' (' . $values . ')' : '');
}
}