Index: includes/webform.components.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/webform/includes/webform.components.inc,v retrieving revision 1.7 diff -u -r1.7 webform.components.inc --- includes/webform.components.inc 6 Nov 2009 00:27:40 -0000 1.7 +++ includes/webform.components.inc 10 Jan 2010 00:30:52 -0000 @@ -409,6 +409,75 @@ '#description' => t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'), '#weight' => 4, ); + + // Add conditional fields. + $component_options = array(); + $counter = 0; + $last_pagebreak_slice = 0; + foreach ($node->webform['components'] as $cid => $test_component) { + // Only components before the pagebreak can be considered. + if ($test_component['type'] == 'pagebreak') { + $last_pagebreak_slice = $counter; + } + if ($test_component['name'] == $component['name']) { + break; + } + if ($test_component['type'] != 'pagebreak') { + $component_options[$test_component['form_key']] = $test_component['name']; + } + $counter++; + } + if ($component['type'] != 'pagebreak') { + $fieldset_description = t('Create a rule to control whether or not to skip this page.'); + } + else { + $fieldset_description = t('Create a rule to control whether or not to show this form element.'); + } + $component_options = array_slice($component_options, 0, $last_pagebreak_slice, TRUE); + $form['conditional'] = array( + '#weight' => 5, + '#type' => 'fieldset', + '#title' => t('Conditional rules'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => t('Create a rule to control whether or not to show this form element.'), + '#tree' => FALSE, + ); + $form['conditional']['extra'] = array( + '#tree' => TRUE, + ); + $form['conditional']['extra']['conditional_component'] = array( + '#type' => 'select', + '#title' => t('Component'), + '#options' => $component_options, + '#description' => t('Select another component to decide whether to show or hide this component. You can only select components occurring before the most recent pagebreak.'), + '#default_value' => $component['extra']['conditional_component'], + ); + $form['conditional']['extra']['conditional_operator'] = array( + '#type' => 'select', + '#title' => t('Operator'), + '#options' => array( + '=' => t('Is one of'), + '!=' => t('Is not one of') + ), + '#description' => t('Determines whether the list below is inclusive or exclusive.'), + '#default_value' => $component['extra']['conditional_operator'], + ); + $form['conditional']['extra']['conditional_values'] = array( + '#type' => 'textarea', + '#title' => t('Values'), + '#description' => t('List values, one per line, that will trigger this action. If you leave this blank, this component will always display.'), + '#default_value' => $component['extra']['conditional_values'], + ); + if (empty($component_options)) { + $form['conditional']['extra']['conditional_component']['#options'] = array(''); + $form['conditional']['#description'] = t('You cannot set display options for a component appearing before the first pagebreak.'); + foreach ($form['conditional']['extra'] as &$el) { + if (is_array($el)) { + $el['#disabled'] = TRUE; + } + } + } // Add the fields specific to this component type: webform_load_components(); // Load all component types. @@ -632,5 +701,10 @@ $component['extra'][$extra] = $default; } } + $component['extra'] += array( + 'conditional_component' => '', + 'conditional_operator' => '=', + 'conditional_values' => '', + ); } } Index: webform.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/webform/webform.module,v retrieving revision 1.142 diff -u -r1.142 webform.module --- webform.module 22 Dec 2009 02:32:30 -0000 1.142 +++ webform.module 10 Jan 2010 00:30:51 -0000 @@ -1187,48 +1187,23 @@ ); // Put the components into a tree structure. - $component_tree = array(); - $page_count = 1; - $page_num = 1; - _webform_components_tree_build($node->webform['components'], $component_tree, 0, $page_count); + if (!isset($form_state['storage']['component_tree'])) { + $form_state['storage']['component_tree'] = array(); + $form_state['storage']['page_count'] = 1; + $form_state['storage']['page_num'] = 1; + _webform_components_tree_build($node->webform['components'], $form_state['storage']['component_tree'], 0, $form_state['storage']['page_count']); + } + + // Shorten up our variable names. + $component_tree = $form_state['storage']['component_tree']; + $page_count = $form_state['storage']['page_count']; + $page_num = $form_state['storage']['page_num']; if ((!isset($node->build_mode) || $node->build_mode != NODE_BUILD_PREVIEW) && $enabled) { if ($page_count > 1) { $next_page = t('Next Page >'); $prev_page = t('< Previous Page'); - // Check if we're in a multipage form and determine the page number. - if (!empty($form_state['storage']['submitted'])) { - $page_num = $form_state['values']['details']['page_num']; - $errors = form_get_errors(); - if (empty($errors)) { - if (end($form_state['clicked_button']['#parents']) == 'prev' && $page_num > 1) { - $page_num--; - } - elseif (end($form_state['clicked_button']['#parents']) == 'next' && $page_num < $page_count) { - $page_num++; - } - } - } - else { - $page_num = 1; - } - - $form['details']['page_num'] = array( - '#type' => 'hidden', - '#value' => $page_num, - ); - - $form['details']['page_count'] = array( - '#type' => 'hidden', - '#value' => $page_count, - ); - - $form['details']['page_count'] = array( - '#type' => 'hidden', - '#value' => $page_count, - ); - // Add the submit button(s). if ($page_num > 1) { $form['previous'] = array( @@ -1253,7 +1228,6 @@ } } else { - $page_num = 1; // Add the submit button. $form['submit'] = array( '#type' => 'submit', @@ -1267,7 +1241,9 @@ $microweight = 0.001; foreach ($component_tree['children'] as $cid => $component) { $component_value = isset($form_state['values']['submitted'][$component['form_key']]) ? $form_state['values']['submitted'][$component['form_key']] : NULL; - _webform_client_form_add_component($cid, $component, $component_value, $form['submitted'], $form, $submission, $page_num, $enabled, $filter); + if (_webform_client_form_rule_check($form_state, $component, $page_num)) { + _webform_client_form_add_component($cid, $component, $component_value, $form['submitted'], $form, $submission, $page_num, $enabled, $filter); + } if (isset($form['submitted'][$component['form_key']])) { $form['submitted'][$component['form_key']]['#weight'] += $microweight; $microweight += 0.001; @@ -1275,13 +1251,13 @@ } $form['details']['nid'] = array( - '#type' => 'value', - '#value' => $node->nid, + '#type' => 'value', + '#value' => $node->nid, ); if (isset($submission->sid)) { $form['details']['sid'] = array( - '#type' => 'hidden', - '#value' => $submission->sid, + '#type' => 'hidden', + '#value' => $submission->sid, ); } } @@ -1289,6 +1265,25 @@ return $form; } +/** + * Check if a component should be displayed on the current page. + */ +function _webform_client_form_rule_check($form_state, $component, $page_num) { + $show_component = TRUE; + if (isset($component['extra']['conditional_values']) && strlen(trim($component['extra']['conditional_values'])) && $component['page_num'] == $page_num) { + $input_value = $form_state['values']['submitted'][$component['extra']['conditional_component']]; + $test_values = array_map('trim', explode("\n", $component['extra']['conditional_values'])); + $show_component = in_array($input_value, $test_values); + if ($component['extra']['conditional_operator'] == '!=') { + $show_component = !$show_component; + } + } + return $show_component; +} + +/** + * Add a component to the form. Called recursively for fieldsets. + */ function _webform_client_form_add_component($cid, $component, $component_value, &$parent_fieldset, &$form, $submission, $page_num, $enabled = FALSE, $filter = TRUE) { // Load with submission information if necessary. if (!$enabled) { @@ -1361,7 +1356,7 @@ module_load_include('inc', 'webform', 'includes/webform.submissions'); webform_load_components(); - $node = node_load(array('nid' => $form_state['values']['details']['nid'])); + $node = node_load($form_state['values']['details']['nid']); // Check for a multi-page form that is not yet complete. $submit_op = empty($node->webform['submit_text']) ? t('Submit') : $node->webform['submit_text']; @@ -1383,9 +1378,49 @@ } } - // Rebuild the form, allowing the rebuild to determine the next page. - $form_state['rebuild'] = TRUE; - return; + // Set the page number. + if (!isset($form_state['storage']['page_num'])) { + $form_state['storage']['page_num'] = 1; + } + if ($form_state['clicked_button']['#value'] == t('Next Page >')) { + $direction = 1; + } + else { + $direction = 0; + } + + // If the next page has no components that need to be displayed, skip it. + if (isset($direction)) { + $components = $direction ? $node->webform['components'] : array_reverse($node->webform['components'], TRUE); + $last_component = end($node->webform['components']); + foreach ($components as $component) { + if ($component['type'] == 'pagebreak' && ( + $direction == 1 && $component['page_num'] >= $form_state['storage']['page_num'] || + $direction == 0 && $component['page_num'] < $form_state['storage']['page_num'])) { + $previous_pagebreak = $component; + continue; + } + if (isset($previous_pagebreak)) { + $page_num = $previous_pagebreak['page_num'] + $direction; + // If we've found an component on this page, advance to that page. + if (_webform_client_form_rule_check($form_state, $component, $page_num)) { + $form_state['storage']['page_num'] = $page_num; + break; + } + // If we've gotten to the end of the form without finding any more + // components, set the page number more than the max, ending the form. + elseif ($direction && $component['cid'] == $last_component['cid']) { + $form_state['storage']['page_num'] = $page_num + 1; + } + } + } + } + + // Rebuild the form and display the next page. + if ($form_state['storage']['page_num'] <= $form_state['storage']['page_count']) { + $form_state['rebuild'] = TRUE; + return; + } } if (isset($form_state['storage']['submitted'])) {