Index: modules/poll/poll.css =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.css,v retrieving revision 1.4 diff -u -r1.4 poll.css --- modules/poll/poll.css 2 Aug 2007 10:46:53 -0000 1.4 +++ modules/poll/poll.css 5 Oct 2007 16:55:06 -0000 @@ -31,6 +31,6 @@ font-weight: bold; } -.node-form .poll-form fieldset { - display: block; +.node-form .poll-form .form-item { + margin-top: 0; } Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.242 diff -u -r1.242 poll.module --- modules/poll/poll.module 6 Sep 2007 12:18:01 -0000 1.242 +++ modules/poll/poll.module 5 Oct 2007 16:55:06 -0000 @@ -96,6 +96,14 @@ 'type' => MENU_LOCAL_TASK, 'file' => 'poll.pages.inc', ); + + $items['poll/js'] = array( + 'title' => 'Javascript Choice Form', + 'page callback' => 'poll_choice_js', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; } @@ -168,64 +176,65 @@ function poll_form(&$node, $form_state) { $admin = user_access('administer nodes'); $type = node_get_types('type', $node); + + $form = array( + '#cache' => TRUE, + ); + $form['title'] = array( '#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => $node->title, - '#weight' => -1 + '#weight' => -5, ); - if (isset($form_state['choices'])) { - $choices = $form_state['choices']; + if (isset($form_state['choice_count'])) { + $choice_count = $form_state['choice_count']; } else { - $choices = max(2, empty($node->choice) ? 5 : count($node->choice)); + $choice_count = max(2, empty($node->choice) ? 5 : count($node->choice)); } - $form['choices'] = array( - '#type' => 'hidden', - '#value' => $choices, - ); - - // Poll choices - $form['choice'] = array( + // Add a wrapper for the choices and more button. + $form['choice_wrapper'] = array( '#type' => 'fieldset', '#title' => t('Choices'), - '#prefix' => '
', - '#suffix' => '
', - '#tree' => TRUE + '#tree' => FALSE, + '#attributes' => array('class' => 'clear-block'), + '#weight' => -5, ); - // We'll manually set the #parents property of this checkbox so that - // it appears in the fieldset visually, but its value won't pollute - // the $form_state['values']['choice'] array. - $form['choice']['morechoices'] = array( - '#type' => 'checkbox', - '#parents' => array('morechoices'), - '#title' => t('Need more choices'), - '#default_value' => 0, - '#description' => t("If the amount of boxes above isn't enough, check this box and click the Preview button below to add some more."), - '#weight' => 1, + // Container for just the poll choices. + $form['choice_wrapper']['choice'] = array( + '#prefix' => '
', + '#suffix' => '
', ); - for ($a = 0; $a < $choices; $a++) { - $form['choice'][$a]['chtext'] = array( - '#type' => 'textfield', - '#title' => t('Choice @n', array('@n' => ($a + 1))), - '#default_value' => isset($node->choice[$a]) ? $node->choice[$a]['chtext'] : '', - ); + // Add the current choices to the form. + for ($delta = 0; $delta < $choice_count; $delta++) { + $text = isset($node->choice[$delta]['chtext']) ? $node->choice[$delta]['chtext'] : ''; + $votes = isset($node->choice[$delta]['chvotes']) ? $node->choice[$delta]['chvotes'] : ''; - if ($admin) { - $form['choice'][$a]['chvotes'] = array( - '#type' => 'textfield', - '#title' => t('Votes for choice @n', array('@n' => ($a + 1))), - '#default_value' => isset($node->choice[$a]) ? (int)$node->choice[$a]['chvotes'] : 0, - '#size' => 5, '#maxlength' => 7 - ); - } + $form['choice_wrapper']['choice'][$delta] = _poll_choice_form($delta, $text, $votes); } + // We name our button 'poll_more' to avoid conflicts with other modules using + // AHAH-enabled buttons with the id 'more'. + $form['choice_wrapper']['poll_more'] = array( + '#type' => 'submit', + '#value' => t('Add another choice'), + '#description' => t("If the amount of boxes above isn't enough, click here to add more choices."), + '#weight' => 1, + '#submit' => array('poll_more_choices_submit'), // If no javascript action. + '#ahah' => array( + 'path' => 'poll/js', + 'wrapper' => 'poll-choices', + 'method' => 'append', + 'effect' => 'slide', + ), + ); + // Poll attributes $_duration = array(0 => t('Unlimited')) + drupal_map_assoc(array(86400, 172800, 345600, 604800, 1209600, 2419200, 4838400, 9676800, 31536000), "format_interval"); $_active = array(0 => t('Closed'), 1 => t('Active')); @@ -253,16 +262,88 @@ } /** + * Submit handler to add more choices to a poll form. This handler is used when + * javascript is not available. It makes changes to the form state and the + * entire form is rebuilt during the page reload. + */ +function poll_more_choices_submit($form, &$form_state) { + // Set rebuild to true to make Drupal re-render the form with our changes. + $form_state['rebuild'] = TRUE; + + // Make the changes we want to the form state. + $form_state['node'] = $form_state['values']; + if ($form_state['values']['poll_more']) { + $form_state['choice_count'] = count($form_state['values']['choice']) + 5; + } +} + +function _poll_choice_form($delta, $value = NULL, $votes = NULL) { + $admin = user_access('administer nodes'); + + $form = array( + '#tree' => TRUE, + ); + + // We'll manually set the #parents property of these fields so that + // their values appear in the $form_state['values']['choice'] array. + $form['chtext'] = array( + '#type' => 'textfield', + '#title' => t('Choice @n', array('@n' => ($delta + 1))), + '#default_value' => isset($value) ? $value : '', + '#parents' => array('choice', $delta,'chtext'), + ); + + if ($admin) { + $form['chvotes'] = array( + '#type' => 'textfield', + '#title' => t('Votes for choice @n', array('@n' => ($delta + 1))), + '#default_value' => $votes ? $votes : 0, + '#size' => 5, + '#maxlength' => 7, + '#parents' => array('choice', $delta, 'chvotes'), + ); + } + + return $form; +} + +/** + * Menu callback for AHAH additions. + */ +function poll_choice_js() { + $delta = count($_POST['choice']); + + // Build our new form element. + $form_element = _poll_choice_form($delta); + drupal_alter('form', $form_element, array(), 'poll_choice_js'); + + // Add the new element to the stored form state. Without adding the element + // to the form, Drupal is not aware of this new elements existence and will + // not process it. We retreive the cached form, add the element, and resave. + $form = cache_get('form_'. $_POST['form_build_id'], 'cache_form'); + $form->data['choice_wrapper']['choice'][$delta] = $form_element; + cache_set('form_'. $_POST['form_build_id'], $form->data, 'cache_form', $form->expire); + + // Render the new output. + $form_state = array('submitted' => FALSE); + $form_element += array( + '#post' => $_POST, + '#programmed' => FALSE, + ); + $form_element = form_builder('poll_choice_js', $form_element, $form_state); + $output = theme('status_messages') . drupal_render($form_element); + + // Return the new output. + drupal_json(array('status' => TRUE, 'data' => $output)); +} + +/** * Implementation of hook_submit(). */ function poll_node_form_submit(&$form, &$form_state) { // Renumber fields $form_state['values']['choice'] = array_values($form_state['values']['choice']); $form_state['values']['teaser'] = poll_teaser((object)$form_state['values']); - $form_state['choices'] = $form_state['values']['choices']; - if ($form_state['values']['morechoices']) { - $form_state['choices'] *= 2; - } } /** Index: misc/ahah.js =================================================================== RCS file: /cvs/drupal/drupal/misc/ahah.js,v retrieving revision 1.3 diff -u -r1.3 ahah.js --- misc/ahah.js 5 Oct 2007 09:35:08 -0000 1.3 +++ misc/ahah.js 5 Oct 2007 16:55:06 -0000 @@ -128,11 +128,6 @@ progress_element.remove(); $(this.element).removeClass('progess-disabled').attr('disabled', false); - // Hide the new content before adding to page. - if (this.showEffect != 'show') { - new_content.hide(); - } - // Add the new content to the page. Drupal.freezeHeight(); if (this.method == 'replace') { @@ -142,10 +137,18 @@ wrapper[this.method](new_content); } + // Immediately hide the new content if we're using any effects. + if (this.showEffect != 'show') { + new_content.hide(); + } + // Determine what effect use and what content will receive the effect, then // show the new content. For browser compatibility, Safari is excluded from // using effects on table rows. - if ($('.ahah-new-content', new_content).size() > 0 && !($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) { + if (($.browser.safari && $("tr.ahah-new-content", new_content).size() > 0)) { + new_content.show(); + } + else if ($('.ahah-new-content', new_content).size() > 0) { $('.ahah-new-content', new_content).hide(); new_content.show(); $(".ahah-new-content", new_content)[this.showEffect](this.showSpeed);