aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
authorNathan Guse <nathaniel.guse@gmail.com>2013-10-07 18:27:18 -0700
committerNathan Guse <nathaniel.guse@gmail.com>2013-10-07 18:27:18 -0700
commitca619cb4a9223876f3b9c512ae987c3de6e820b9 (patch)
tree6a7af210fdbd407bd6e475bca2fd6555d1943d91 /phpBB
parent1e2ceb456f24f53560bdb15094759e40bff49ea7 (diff)
parent98a1694c7c1022d50c30b7dcd46f9f0fc9f5f7b4 (diff)
downloadforums-ca619cb4a9223876f3b9c512ae987c3de6e820b9.tar
forums-ca619cb4a9223876f3b9c512ae987c3de6e820b9.tar.gz
forums-ca619cb4a9223876f3b9c512ae987c3de6e820b9.tar.bz2
forums-ca619cb4a9223876f3b9c512ae987c3de6e820b9.tar.xz
forums-ca619cb4a9223876f3b9c512ae987c3de6e820b9.zip
Merge pull request #1757 from prototech/ticket/10383
[ticket/10383] AJAXify poll voting
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/styles/prosilver/template/ajax.js101
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_body.html23
-rw-r--r--phpBB/styles/prosilver/theme/content.css6
-rw-r--r--phpBB/viewtopic.php28
4 files changed, 144 insertions, 14 deletions
diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js
index 394aca749b..28656d47d3 100644
--- a/phpBB/styles/prosilver/template/ajax.js
+++ b/phpBB/styles/prosilver/template/ajax.js
@@ -157,7 +157,108 @@ phpbb.addAjaxCallback('zebra', function(res) {
}
});
+/**
+ * This callback updates the poll results after voting.
+ */
+phpbb.addAjaxCallback('vote_poll', function(res) {
+ if (typeof res.success !== 'undefined') {
+ var poll = $('.topic_poll');
+ var panel = poll.find('.panel');
+ var results_visible = poll.find('dl:first-child .resultbar').is(':visible');
+
+ // Set min-height to prevent the page from jumping when the content changes
+ var update_panel_height = function (height) {
+ var height = (typeof height === 'undefined') ? panel.find('.inner').outerHeight() : height;
+ panel.css('min-height', height);
+ };
+ update_panel_height();
+
+ // Remove the View results link
+ if (!results_visible) {
+ poll.find('.poll_view_results').hide(500);
+ }
+
+ if (!res.can_vote) {
+ poll.find('.polls, .poll_max_votes, .poll_vote, .poll_option_select').fadeOut(500, function () {
+ poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show();
+ });
+ } else {
+ // If the user can still vote, simply slide down the results
+ poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500);
+ }
+
+ // Update the total votes count
+ poll.find('.poll_total_vote_cnt').html(res.total_votes);
+
+ // Update each option
+ poll.find('[data-poll-option-id]').each(function() {
+ var option = $(this);
+ var option_id = option.attr('data-poll-option-id');
+ var voted = (typeof res.user_votes[option_id] !== 'undefined') ? true : false;
+ var percent = (!res.total_votes) ? 0 : Math.round((res.vote_counts[option_id] / res.total_votes) * 100);
+
+ option.toggleClass('voted', voted);
+
+ // Update the bars
+ var bar = option.find('.resultbar div');
+ var bar_time_lapse = (res.can_vote) ? 500 : 1500;
+ var new_bar_class = (percent == 100) ? 'pollbar5' : 'pollbar' + (Math.floor(percent / 20) + 1);
+
+ setTimeout(function () {
+ bar.animate({width: percent + '%'}, 500).removeClass('pollbar1 pollbar2 pollbar3 pollbar4 pollbar5').addClass(new_bar_class);
+ bar.html(res.vote_counts[option_id]);
+
+ var percent_txt = (!percent) ? res.NO_VOTES : percent + '%';
+ option.find('.poll_option_percent').html(percent_txt);
+ }, bar_time_lapse);
+ });
+
+ if (!res.can_vote) {
+ poll.find('.polls').delay(400).fadeIn(500);
+ }
+
+ // Display "Your vote has been cast." message. Disappears after 5 seconds.
+ var confirmation_delay = (res.can_vote) ? 300 : 900;
+ poll.find('.vote-submitted').delay(confirmation_delay).slideDown(200, function() {
+ if (results_visible) {
+ update_panel_height();
+ }
+ $(this).delay(5000).fadeOut(500, function() {
+ resize_panel(300);
+ });
+ });
+
+ // Remove the gap resulting from removing options
+ setTimeout(function() {
+ resize_panel(500);
+ }, 1500);
+
+ var resize_panel = function (time) {
+ var panel_height = panel.height();
+ var inner_height = panel.find('.inner').outerHeight();
+
+ if (panel_height != inner_height) {
+ panel.css({'min-height': '', 'height': panel_height}).animate({height: inner_height}, time, function () {
+ panel.css({'min-height': inner_height, 'height': ''});
+ });
+ }
+ };
+ }
+});
+
+/**
+ * Show poll results when clicking View results link.
+ */
+$('.poll_view_results a').click(function(e) {
+ // Do not follow the link
+ e.preventDefault();
+
+ var poll = $(this).parents('.topic_poll');
+
+ poll.find('.resultbar, .poll_option_percent, .poll_total_votes').show(500);
+ poll.find('.poll_view_results').hide(500);
+});
$('[data-ajax]').each(function() {
var $this = $(this),
diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html
index e104257e12..e678ea8f8c 100644
--- a/phpBB/styles/prosilver/template/viewtopic_body.html
+++ b/phpBB/styles/prosilver/template/viewtopic_body.html
@@ -60,46 +60,45 @@
<div class="clear"></div>
<!-- IF S_HAS_POLL -->
- <form method="post" action="{S_POLL_ACTION}">
+ <form method="post" action="{S_POLL_ACTION}" data-ajax="vote_poll" data-overlay="false" class="topic_poll">
<div class="panel">
<div class="inner">
<div class="content">
<h2>{POLL_QUESTION}</h2>
- <p class="author">{L_POLL_LENGTH}<!-- IF S_CAN_VOTE and L_POLL_LENGTH --><br /><!-- ENDIF --><!-- IF S_CAN_VOTE -->{L_MAX_VOTES}<!-- ENDIF --></p>
+ <p class="author">{L_POLL_LENGTH}<!-- IF S_CAN_VOTE and L_POLL_LENGTH --><br /><!-- ENDIF --><!-- IF S_CAN_VOTE --><span class="poll_max_votes">{L_MAX_VOTES}</span><!-- ENDIF --></p>
<fieldset class="polls">
<!-- BEGIN poll_option -->
- <dl class="<!-- IF poll_option.POLL_OPTION_VOTED -->voted<!-- ENDIF -->"<!-- IF poll_option.POLL_OPTION_VOTED --> title="{L_POLL_VOTED_OPTION}"<!-- ENDIF -->>
+ <dl class="<!-- IF poll_option.POLL_OPTION_VOTED -->voted<!-- ENDIF -->"<!-- IF poll_option.POLL_OPTION_VOTED --> title="{L_POLL_VOTED_OPTION}"<!-- ENDIF --> data-poll-option-id="{poll_option.POLL_OPTION_ID}">
<dt><!-- IF S_CAN_VOTE --><label for="vote_{poll_option.POLL_OPTION_ID}">{poll_option.POLL_OPTION_CAPTION}</label><!-- ELSE -->{poll_option.POLL_OPTION_CAPTION}<!-- ENDIF --></dt>
- <!-- IF S_CAN_VOTE --><dd style="width: auto;"><!-- IF S_IS_MULTI_CHOICE --><input type="checkbox" name="vote_id[]" id="vote_{poll_option.POLL_OPTION_ID}" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> /><!-- ELSE --><input type="radio" name="vote_id[]" id="vote_{poll_option.POLL_OPTION_ID}" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> /><!-- ENDIF --></dd><!-- ENDIF -->
- <!-- IF S_DISPLAY_RESULTS --><dd class="resultbar"><div class="<!-- IF poll_option.POLL_OPTION_PCT < 20 -->pollbar1<!-- ELSEIF poll_option.POLL_OPTION_PCT < 40 -->pollbar2<!-- ELSEIF poll_option.POLL_OPTION_PCT < 60 -->pollbar3<!-- ELSEIF poll_option.POLL_OPTION_PCT < 80 -->pollbar4<!-- ELSE -->pollbar5<!-- ENDIF -->" style="width:{poll_option.POLL_OPTION_PERCENT};">{poll_option.POLL_OPTION_RESULT}</div></dd>
- <dd><!-- IF poll_option.POLL_OPTION_RESULT == 0 -->{L_NO_VOTES}<!-- ELSE -->{poll_option.POLL_OPTION_PERCENT}<!-- ENDIF --></dd><!-- ENDIF -->
+ <!-- IF S_CAN_VOTE --><dd style="width: auto;" class="poll_option_select"><!-- IF S_IS_MULTI_CHOICE --><input type="checkbox" name="vote_id[]" id="vote_{poll_option.POLL_OPTION_ID}" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> /><!-- ELSE --><input type="radio" name="vote_id[]" id="vote_{poll_option.POLL_OPTION_ID}" value="{poll_option.POLL_OPTION_ID}"<!-- IF poll_option.POLL_OPTION_VOTED --> checked="checked"<!-- ENDIF --> /><!-- ENDIF --></dd><!-- ENDIF -->
+ <dd class="resultbar<!-- IF not S_DISPLAY_RESULTS --> hidden<!-- ENDIF -->"><div class="<!-- IF poll_option.POLL_OPTION_PCT < 20 -->pollbar1<!-- ELSEIF poll_option.POLL_OPTION_PCT < 40 -->pollbar2<!-- ELSEIF poll_option.POLL_OPTION_PCT < 60 -->pollbar3<!-- ELSEIF poll_option.POLL_OPTION_PCT < 80 -->pollbar4<!-- ELSE -->pollbar5<!-- ENDIF -->" style="width:{poll_option.POLL_OPTION_PERCENT};">{poll_option.POLL_OPTION_RESULT}</div></dd>
+ <dd class="poll_option_percent<!-- IF not S_DISPLAY_RESULTS --> hidden<!-- ENDIF -->"><!-- IF poll_option.POLL_OPTION_RESULT == 0 -->{L_NO_VOTES}<!-- ELSE -->{poll_option.POLL_OPTION_PERCENT}<!-- ENDIF --></dd>
</dl>
<!-- END poll_option -->
- <!-- IF S_DISPLAY_RESULTS -->
- <dl>
+ <dl class="poll_total_votes<!-- IF not S_DISPLAY_RESULTS --> hidden<!-- ENDIF -->">
<dt>&nbsp;</dt>
- <dd class="resultbar">{L_TOTAL_VOTES}{L_COLON} {TOTAL_VOTES}</dd>
+ <dd class="resultbar">{L_TOTAL_VOTES}{L_COLON} <span class="poll_total_vote_cnt">{TOTAL_VOTES}</span></dd>
</dl>
- <!-- ENDIF -->
<!-- IF S_CAN_VOTE -->
- <dl style="border-top: none;">
+ <dl style="border-top: none;" class="poll_vote">
<dt>&nbsp;</dt>
<dd class="resultbar"><input type="submit" name="update" value="{L_SUBMIT_VOTE}" class="button1" /></dd>
</dl>
<!-- ENDIF -->
<!-- IF not S_DISPLAY_RESULTS -->
- <dl style="border-top: none;">
+ <dl style="border-top: none;" class="poll_view_results">
<dt>&nbsp;</dt>
<dd class="resultbar"><a href="{U_VIEW_RESULTS}">{L_VIEW_RESULTS}</a></dd>
</dl>
<!-- ENDIF -->
</fieldset>
+ <div class="vote-submitted hidden">{L_VOTE_SUBMITTED}</div>
</div>
</div>
diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css
index c56c7f9ef8..60475aea7d 100644
--- a/phpBB/styles/prosilver/theme/content.css
+++ b/phpBB/styles/prosilver/theme/content.css
@@ -662,6 +662,12 @@ fieldset.polls dd div {
border-right: 1px solid transparent;
}
+.vote-submitted {
+ font-size: 1.2em;
+ font-weight: bold;
+ text-align: center;
+}
+
/* Poster profile block
----------------------------------------*/
.postprofile {
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 69a972ed3e..3a7e633c99 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -689,10 +689,12 @@ if (!empty($topic_data['poll_start']))
ORDER BY o.poll_option_id";
$result = $db->sql_query($sql);
- $poll_info = array();
+ $poll_info = $vote_counts = array();
while ($row = $db->sql_fetchrow($result))
{
$poll_info[] = $row;
+ $option_id = (int) $row['poll_option_id'];
+ $vote_counts[$option_id] = (int) $row['poll_option_total'];
}
$db->sql_freeresult($result);
@@ -774,6 +776,8 @@ if (!empty($topic_data['poll_start']))
AND topic_id = ' . (int) $topic_id;
$db->sql_query($sql);
+ $vote_counts[$option]++;
+
if ($user->data['is_registered'])
{
$sql_ary = array(
@@ -798,6 +802,8 @@ if (!empty($topic_data['poll_start']))
AND topic_id = ' . (int) $topic_id;
$db->sql_query($sql);
+ $vote_counts[$option]--;
+
if ($user->data['is_registered'])
{
$sql = 'DELETE FROM ' . POLL_VOTES_TABLE . '
@@ -821,9 +827,27 @@ if (!empty($topic_data['poll_start']))
$db->sql_query($sql);
$redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id" . (($start == 0) ? '' : "&amp;start=$start"));
+ $message = $user->lang['VOTE_SUBMITTED'] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>');
+
+ if ($request->is_ajax())
+ {
+ // Filter out invalid options
+ $valid_user_votes = array_intersect(array_keys($vote_counts), $voted_id);
+
+ $data = array(
+ 'NO_VOTES' => $user->lang['NO_VOTES'],
+ 'success' => true,
+ 'user_votes' => array_flip($valid_user_votes),
+ 'vote_counts' => $vote_counts,
+ 'total_votes' => array_sum($vote_counts),
+ 'can_vote' => !sizeof($valid_user_votes) || ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']),
+ );
+ $json_response = new \phpbb\json_response();
+ $json_response->send($data);
+ }
meta_refresh(5, $redirect_url);
- trigger_error($user->lang['VOTE_SUBMITTED'] . '<br /><br />' . sprintf($user->lang['RETURN_TOPIC'], '<a href="' . $redirect_url . '">', '</a>'));
+ trigger_error($message);
}
$poll_total = 0;