I'm writing a JS for vertical tabs so when some element fails on validation the tab(li element) gets 'error' class. I was struggling with a bug where some tabs would get the class properly and others would be skipped and next tab woud get the error class instead.
This was due to missing '#weight' value in form_process_vertical_tabs. I have set weights to my tabs and they have values from -10 to 8. So one of my tabs gets #weight => 0. This is the tab that splits the tabs that are working correctly with my JS and tabs that are not working correctly. The reason is because the __active tab input is put behind my tab with weight => 0 so indexes(position of fieldset) won't match tab li element index(position in ul).
So to fix this there needs to be weight parameter set in form_process_vertical_tabs which will place the __active tab element at the end of the form.
function form_process_vertical_tabs($element, &$form_state) {
// Inject a new fieldset as child, so that form_process_fieldset() processes
// this fieldset like any other fieldset.
$element['group'] = array(
'#type' => 'fieldset',
'#theme_wrappers' => array(),
'#parents' => $element['#parents'],
);
// The JavaScript stores the currently selected tab in this hidden
// field so that the active tab can be restored the next time the
// form is rendered, e.g. on preview pages or when form validation
// fails.
$name = implode('__', $element['#parents']);
if (isset($form_state['values'][$name . '__active_tab'])) {
$element['#default_tab'] = $form_state['values'][$name . '__active_tab'];
}
$element[$name . '__active_tab'] = array(
'#type' => 'hidden',
'#default_value' => $element['#default_tab'],
'#attributes' => array('class' => array('vertical-tabs-active-tab'))
);
return $element;
}
function form_process_vertical_tabs($element, &$form_state) {
// Inject a new fieldset as child, so that form_process_fieldset() processes
// this fieldset like any other fieldset.
$element['group'] = array(
'#type' => 'fieldset',
'#theme_wrappers' => array(),
'#parents' => $element['#parents'],
);
// The JavaScript stores the currently selected tab in this hidden
// field so that the active tab can be restored the next time the
// form is rendered, e.g. on preview pages or when form validation
// fails.
$name = implode('__', $element['#parents']);
if (isset($form_state['values'][$name . '__active_tab'])) {
$element['#default_tab'] = $form_state['values'][$name . '__active_tab'];
}
$element[$name . '__active_tab'] = array(
'#type' => 'hidden',
'#default_value' => $element['#default_tab'],
'#attributes' => array('class' => array('vertical-tabs-active-tab')),
'#weight' => 1000
);
return $element;
}
This is my script so you can see what I'm talking about:
$('div.vertical-tabs-panes > fieldset').has('.error').each(function(i) {
$('ul.vertical-tabs-list > li').eq($(this).index()).addClass('error');
});
Comments
Comment #1
Anonymous (not verified) CreditAttribution: Anonymous commentedComment #2
Anonymous (not verified) CreditAttribution: Anonymous commentedMaybe there is no need for this but vertical tabs should have some 'mapping' to them. Currently there is no way to tell which tab belongs to which tab-content other than using $.each and relying on the index/key value.
Comment #15
smustgrave CreditAttribution: smustgrave at Mobomo commentedTo my knowledge the tabs do have a weight parameter.
If I'm wrong please reopen.