? .svn
? ajax-decisions-links.patch
? ajax-decisions.patch
? modes/.svn
? modes/selection.js
? po/.svn
Index: decisions.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/decisions/decisions.module,v
retrieving revision 1.229
diff -u -p -r1.229 decisions.module
--- decisions.module	11 Feb 2010 16:24:10 -0000	1.229
+++ decisions.module	15 Feb 2010 03:22:47 -0000
@@ -12,7 +12,7 @@
  * all the that was already written. (...and debugged!)
  */
 
-// $Id: decisions.module,v 1.229 2010/02/11 16:24:10 ezrag Exp $
+// $Id: decisions.module,v 1.228 2010/02/08 23:45:33 anarcat Exp $
 
 define('DECISIONS_DEFAULT_ELECTORAL_LIST', 0);
 // always, aftervote, or afterclose
@@ -215,6 +215,20 @@ function decisions_admin() {
     '#options' => $view_results,
   );
 
+  $form['main']['decisions_1click'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable one-click voting where available'),
+    '#description' => t('Some modules offer one-click voting with buttons or links instead of radios.'),
+    '#default_value' => variable_get('decisions_1click', 0),
+  );
+
+  $form['main']['decisions_ahah'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable asynchronous (AJAX) voting where available'),
+    '#description' => t('Some modules allow votes to be submitted with an asynchronous interface.'),
+    '#default_value' => variable_get('decisions_ahah', 0),
+  );
+  
   return system_settings_form($form);
 }
 
Index: modes/selection.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/decisions/modes/selection.module,v
retrieving revision 1.18
diff -u -p -r1.18 selection.module
--- modes/selection.module	11 Feb 2010 16:24:11 -0000	1.18
+++ modes/selection.module	15 Feb 2010 03:22:47 -0000
@@ -6,7 +6,68 @@
  * This file implements a selection voting mode
  */
 
-// $Id: selection.module,v 1.18 2010/02/11 16:24:11 ezrag Exp $
+/*
+ * Implementation of hook_menu().
+ */
+function selection_menu() {
+  $items['decisions_selection/vote'] = array(
+    'title' => 'Vote',
+    'page callback' => 'selection_vote',
+    'access arguments' => array('vote on decisions'),
+    'type' => MENU_CALLBACK,
+  );
+  return $items;
+}
+
+function selection_vote($nid = 0, $cid = -1) {
+  global $user;
+  if (drupal_valid_token($_REQUEST['token'], "selection-vote-$nid-$cid") && user_access('vote on decisions')) {
+    $label = db_result(db_query("SELECT label FROM {decisions_choices} WHERE nid = %d AND vote_offset = %d", $nid, $cid));
+    if (empty($label)) {
+      if (empty($_REQUEST['ajax'])) {
+        drupal_goto(drupal_get_destination());
+      }
+      else {
+        return;
+      }
+    }
+    $voted = selection_get_votes($nid, $user->uid);
+    if (empty($voted)) {
+      $vote = array(
+        'value' => 1,
+        'tag' => $label, 
+        'value_type' => 'option',
+        'content_type' => 'decisions',
+        'content_id' => $nid,
+      );
+      $votes[] = $vote;
+      votingapi_add_votes($votes);
+      //If this becomes a performance problem, we can result on votingapi_set_votes and use the site-wide recalculation time.
+      votingapi_recalculate_results('decisions', $nid);
+    }
+    else {
+      if (empty($_REQUEST['ajax'])) {
+        drupal_set_message(t("You have already voted."));
+        drupal_goto(drupal_get_destination());
+      }
+      else {
+        return;
+      }
+    }
+    //Render the results
+    if (empty($_REQUEST['ajax'])) {
+      drupal_set_message(t('Your vote was registered.'));
+      drupal_goto(drupal_get_destination());
+    }
+    else {
+      //Sadly, we must reload the node.
+      $node = node_load($nid);
+      print selection_decisions_view_results($node, FALSE, FALSE);
+      exit();
+    }
+  }
+}
+// $Id: selection.module,v 1.17 2010/02/04 17:32:54 anarcat Exp $
 
 function selection_help($section) {
   $help = "";
@@ -46,15 +107,24 @@ function selection_decisions_algorithms(
   return array('plurality' => t('The plurality algorithm determines the winner based solely on the number of votes received: the one with the larger number of votes wins. See the <a href="http://en.wikipedia.org/wiki/Plurality_voting_system">Plurality voting system on Wikipedia</a> for more information'));
 }
 
+function selection_token($nid = 0, $cid = 0) {
+  return drupal_get_token("selection-vote-$nid-$cid");
+}
 /**
  * Implementation of decisions_hook_voting_form.
  * Presents a list of choices for the user to vote on.
  */
 function decisions_selection_voting_form($form_state, &$node, $teaser, $page) {
+  $one_click = variable_get('decisions_1click', 0);
+  global $user;
+
   $form['node'] = array(
     '#type' => 'value',
     '#value' => $node,
   );
+  $form['#prefix'] = '<div class="decisions_selection_voting">';
+  //The decisions_selection_results div exists as a workaround for 1click voting when jQuery 1.3+'s live() is unavailable.
+  $form['#suffix'] = '</div><div class="decisions_selection_results" style="display: none;"></div>';
 
   if ($node->choice) {
     $list = array();
@@ -63,14 +133,40 @@ function decisions_selection_voting_form
     if ($node->randomize) {
       $node->choice = _decisions_randomize_options($node->choice, $node->choices);
     }
+    //Single choice, "Plurality" voting.
     if ($node->maxchoices == 1) {
-      // plurality voting
-      foreach ($node->choice as $i => $choice) {
-        if ($choice['label']) {
-          $list[$i] = check_plain($choice['label']);
+      //Are we using the 1-click form?
+      if ($one_click == 1) {
+        $links = '';
+        foreach ($node->choice as $i => $choice) {
+          $options['attributes']['class'] = 'decisions_selection_vote';
+          $options['query'] = drupal_get_destination() . '&token='. selection_token($node->nid, $i);
+          $links .= l($choice['label'], "decisions_selection/vote/$node->nid/$i/", $options);
+        }
+        if (!empty($links)) {
+          $output .= '<div class="decisions_selection_1click">';
+          $output .= $links;
+          $output .= '</div>';
+        }
+        $form['choices']['1click'] = array(
+          '#value' => $output,
+        );
+        
+        //If asynchronous voting is enabled, add the necessary JS.
+        if (variable_get('decisions_ahah', 0) == 1) {
+          drupal_add_js(drupal_get_path('module', 'selection') . '/selection.js');
+        }
+        //At this point, we can return the form since 1-click uses its own callback for vote submission.
+        return $form;
+      }
+      //Not using 1-click. Use radios.
+      else {
+        foreach ($node->choice as $i => $choice) {
+          if ($choice['label']) {
+            $list[$i] = check_plain($choice['label']);
+          }
         }
       }
-
       $form['choice'] = array(
         '#type' => 'radios',
         '#title' => $page ? '' : check_plain($node->title),
@@ -78,8 +174,8 @@ function decisions_selection_voting_form
         '#options' => $list,
       );
     }
+    //Approval/multiple-choice voting.
     else {
-      // approval voting
       foreach ($node->choice as $i => $choice) {
         if ($choice['label']) {
           $list[$i] = check_plain($choice['label']);
@@ -92,6 +188,7 @@ function decisions_selection_voting_form
       );
     }
   }
+  //Add the submit button. 1click has already returned the form by this point.
   $form['vote'] = array(
     '#type' => 'submit',
     '#value' => t('Vote'),
@@ -107,10 +204,9 @@ function decisions_selection_voting_form
 function selection_decisions_view_results($node, $teaser, $page) {
 
   $output = "";
-  $results = votingapi_select_votes(array('content_id' => $node->nid, 'content_type' => 'decisions'));
+  $results = votingapi_select_results(array('content_id' => $node->nid, 'content_type' => 'decisions'));
   // Count the votes for each choice
   $votes = array();
-
   foreach ($results as $result) {
 
     // approval
@@ -135,7 +231,10 @@ function selection_decisions_view_result
   if ($node->choice && $total_votes > 0) {
     // TODO: Those <div>s and <br />s should be in a theme function. First collect all the data in a structure, then theme it.
     // display results for each possible choice
-    $output .= '<div class="poll">';
+    if (!empty($_REQUEST['ajax'])) {
+      $output .= t('Your vote has been counted');
+    }
+    $output .= '<div class="poll"'. $style .'>';
     $max_votes = 0;
     foreach ($votes as $i => $vote) {
       $max_votes = ($vote > $max_votes ? $vote : $max_votes);
@@ -146,7 +245,6 @@ function selection_decisions_view_result
     }
     $output .= '</div>';
   }
-
   $output .= '<br />';
   return $output;
 }
@@ -169,11 +267,38 @@ function selection_decisions_format_vote
   return implode(', ', $unordered_votes);
 }
 
+function selection_get_votes($nid, $uid) {
+  $criteria['content_id'] = $nid;
+  $criteria['value_type'] = 'option';
+  $criteria['content_type'] = 'decisions';
+  $criteria['content_id'] = $nid;
+  if ($uid == 0) {
+    $criteria['vote_source'] = ip_address();
+  }
+  else {
+    $criteria['uid'] = $uid;
+  }
+  $results = votingapi_select_votes($criteria);
+  return count($results);
+}
 /**
  * Registers the vote as a key for this node using votingapi_set_vote().
  */
 function decisions_selection_voting_form_submit($form, &$form_state) {
   $node = $form_state['values']['node'];
+  $one_click = variable_get('decisions_1click', 0);
+
+  global $user;
+  $voted = selection_get_votes($form_state['values']['node']->nid, $user->uid);
+  if ($voted) {
+    //Prevent users from re-voting if they make the same post request multiple times.
+    if (empty($_POST['ajax'])) {
+      drupal_set_message(t('You have already voted.'));
+    }
+    return;
+  }
+  $node = $form_state['values']['node'];
+
   $votes = array();
   if ($node->maxchoices == 1) {
     // plurality voting
@@ -202,6 +327,8 @@ function decisions_selection_voting_form
     }
   }
   votingapi_add_votes($votes);
+  //If this becomes a performance problem, we can result on votingapi_set_votes and use the site-wide recalculation time.
+  votingapi_recalculate_results('decisions', $node->nid);
   drupal_set_message(t('Your vote was registered.'));
 }
 
@@ -213,26 +340,19 @@ function decisions_selection_voting_form
  * @returns boolean true if the form is valid
  */
 function decisions_selection_voting_form_validate($form, &$form_state) {
+  $one_click = variable_get('decisions_1click', 0);
   $node = $form_state['values']['node'];
+
   if ($node->maxchoices == 1) {
-    // plurality voting
-    if (!array_key_exists($form_state['values']['choice'], $node->choice)) {
-      form_set_error('choice', 'At least one choice must be selected.');
+    if ($one_click != 1 && !array_key_exists($form_state['values']['choice'], $node->choice)) {
+        form_set_error('choice', 'At least one choice must be selected.');
     }
   }
   else {
-    // approval voting
-
+    //Approval/Multiple-choice voting
     // array used to check which values are set
     $setvalues = array();
     foreach ($node->choice as $key => $choice) {
-
-      // need a minchoices choice to do this
-      //if (empty($_POST['edit']['Choice_' . $key])) {
-      //form_set_error('Choice_'.$key, "choice $key cannot be empty");
-      //$ok = FALSE;
-      //}
-
       // see if the box is checked
       if (!empty($form_state['values']['choice'][$key])) {
         $numchoices++;
@@ -247,7 +367,6 @@ function decisions_selection_voting_form
         )
       );
     }
-
     // not enough choices ranked
     $minchoices = 1;
     if ($numchoices < $minchoices) {
