Dec 04, 2008, 12:51 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
Search via SMF or Google: modx forums all of modxcms.com web
  MODxCMS.com   Forums   Help Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: Developing new Poll Module for MODx [Now Ready for testing]  (Read 1807 times)
0 Members and 1 Guest are viewing this topic.
banal
Full Member
***
Posts: 155


« on: Jan 29, 2008, 11:31 AM »

Hi all.

I'm in desperate need for a Poll Module for MODx. I installed the Poll Module by garryn but it doesn't meet my requirements, since i will use it primarily on multilingual sites. I can't see any other alternative, so i started to develop a new Poll Module, loosely based on the work by garryn.
Let me list the planned features so that you might add ideas/wishes while it's hot...

Administration (Module for MODX, work in progress)
  • A unlimited amount of polls can be created. done
  • Polls can be limited to a certain date-range (by setting a start- and end-date). done
  • Polls can be set active/inactive. done
  • Polls may consist of a variable amount of possible answers. done
  • The user may setup different languages inside the PollManager. done
  • PollManager will keep track of the current "translation status" by looking up if question and answers are translated for all the poll-languages (if a language isn't completely translated, it won't be accessible by the snippet thats responsible for output). done

Output
This is basically where i started.. developing a AJAX based replacement for garryns "PollResults" and "PollVote" Snippets. Now it's just a single snippet, that shows a poll and sends your vote and updates the results via AJAX. This will be extended to work with multiple languages (not too much additional work to do to get there...)
  • Voting and displaying of the results using AJAX. done
  • Degrades/works nicely on a browser without JavaScript. done
  • Works with friendly urls (garryns snippet only worked without the "alias-path"). done
  • Very easy to integrate. Just one Snippet that does all. done
  • Hard-coded text can easily be translated to different languages due to external language-files. done
  • Custom JavaScript callback function to build your own "transition" from vote-screen to the results-screen. done
  • Support for multi-language Polls. done
  • Limiting user to one vote per Poll by setting a cookie and/or logging the IP (same as in garryns module).  done
  • Complete customization of Poll appearance with own chunks and css stylesheet. done

Planned features for later release...
  • Poll Archive

Dependencies/Requirements
  • MODx 0.9.5 (thats the platform i'm currently developing and testing on)
  • mootools for AJAX functionality
  • PHP5 or higher
  • MySQL Version 4.1 or higher

Hope this will help somebody when it's done.
Cheers -- banal

Edit (2008-01-29)
Added some features and the Requirements/Dependencies section.

Edit (2008-02-01)
Added some snippet features and changed MySQL Requirements

Edit (2008-02-05)
The EasyPoll Module is ready for testing. Have a look at the development thread.
http://modxcms.com/forums/index.php/topic,22457.0.html
« Last Edit: Feb 05, 2008, 03:49 AM by banal » Logged
pixelchutes
Coding Team
*
Posts: 814



WWW
« Reply #1 on: Jan 29, 2008, 11:52 AM »

@banal,

I am excited to see what you have come up with! It sounds like a great addition for the community.
Logged

Mike Reid - www.pixelchutes.com
MODx Team Member / Contributor
[Module] SiteSearch / [Snippet] DocPassword / [Plugin] EditArea / We support FoxyCart
________________________________
Where every pixel matters.
dflock
Jr. Member
*
Posts: 45



WWW
« Reply #2 on: Jan 31, 2008, 08:37 PM »

This sounds awesome - and saves me the trouble of doing it!!

I started using the old polls module for a site the other day and decided it needed a re-write but unfortunately I'm totally swamped at the moment. I got as far as re-writing the 2 snippets to output more reasonable markup, adding HTML+CSS bar-chart results and re-doing the CSS.

This is what the modified poll looks like, if you use my CSS:



The rounded corners are provided by jQuery and this plugin: http://blue-anvil.com/archives/anti-aliased-rounded-corners-with-jquery

I'm posting my mods here, in case they're any use to you:

pollvote snippet:

Code:
<?php
// +----------------------------------------------------------------------+
// | Polls Vote Snippet                                                   |
// +----------------------------------------------------------------------+
// | Created: February 2006 Version: 3                                    |
// +----------------------------------------------------------------------+
//
// &pollid - Poll ID to be used
// &redirect - Document ID to redirect to (eg Results page)
// &onevote - Boolean value, if true, uses a cookie to allow only one vote per visitor
// &useip - Boolean value, if true, logs IP addresses and a user can only have a single vote
// &ovtime - Time limit to set the cookie time, by default expires in a week
// &ovmessage - Message to display if a user tries to vote more than once if $onevote/$useip is enabled                     |
// &resultsbutton - Boolean value, if true, show a 'Results' button - MUST have &redirect defined
//
// +----------------------------------------------------------------------+

//-- Try to get poll id, if no poll id then no point carrying on
if (!isset ($pollid))
return false;

$pageID = (isset($_GET['id'])) ? intval($_GET['id']) : $modx->config['site_start'];

//-- set form placeholder
$cur_url = $modx->makeURL($pageID,$modx->getDocumentIdentifier('alias'),'');
$modx->setPlaceholder('formaction', $cur_url);

//-- setup initial variables
$output = '';
$pollid = intval($pollid);
$redirect = (isset ($redirect)) ? intval($redirect) : '';
$onevote = (isset ($onevote)) ? $onevote : 1;
$ovtime = (isset ($ovtime)) ? $ovtime : 608400; // default: expires in one week
$useip = (isset ($useip)) ? $useip : 0;
$ovmessage = (isset ($ovmessage)) ? $ovmessage : 'You are only allowed to vote once';
$resultsbutton = (isset ($resultsbutton)) ? $resultsbutton : 0;
$fields = array ();

//-- make url for redirect if required
if ($redirect <> '') {
$doc = $modx->getDocument($redirect);
$r_id = $doc['id'];
$r_alias = $doc['alias'];
$url = $modx->makeURL($r_id, $r_alias,'');
}

//-- setup DB table names
$polltable = $modx->getFullTableName("polls");
$choicetable = $modx->getFullTableName("poll_choices");
$iptable = $modx->getFullTableName("pollip");

//-- if 'Results' button has been selected
if (isset ($_POST['results'])) {
$modx->sendRedirect($url);
}
/*
// Debug stuff
echo '<h1>onevote: '.print_r($onevote).'</h1>';
echo '<h1>poll_pollid: '.$_POST['poll_pollid'].'</h1>';
echo '<h1>poll_choice_id: '.$_POST['poll_choice_id()'].'</h1>';
echo print_r($_POST);
*/
//-- if vote was submitted increment polls and poll_choices vote counts
if (isset ($_POST['vote']) && isset ($_POST['poll_choice_id()'])) {

//-- cookie check - if $onevote, check if visitor is allowed to vote
if ($onevote == true) {
if (isset ($_COOKIE['poll' . $_POST['poll_pollid']])) {
$novote = true;
} else {
//-- set cookie
setcookie('poll' . $_POST['poll_pollid'], 'novote', time() + $ovtime);
}
}

//-- ip check, if $useip, check if visitor is allowed to vote
if ($useip == true) {
$useraddy = userIP();
$results = $modx->db->select('*', $iptable, 'ipaddress=\'' . $useraddy . '\' AND pollid=' . $_POST['poll_pollid'], '');
if ($modx->db->getRecordCount($results) > 0) {
$novote = true;
}
}
if (!isset ($novote)) {
$sql = "UPDATE " . $polltable . " SET votes=votes+1 WHERE id=" . $_POST['poll_pollid'] . ";";
$modx->db->query($sql);
$sql = "UPDATE " . $choicetable . " SET votes=votes+1 WHERE id=" . $_POST['poll_choice_id()'] . ";";
$modx->db->query($sql);
//-- log ip address if required
if ($useip) {
$ipsql = 'INSERT INTO ' . $iptable . ' (pollid,ipaddress) VALUES (' . $pollid . ',\'' . $useraddy . '\')';
$modx->db->query($ipsql);
}
//-- send redirect if required
if ($redirect <> '') {
$modx->sendRedirect($url);
} else {
//echo '<h1>Results go here</h1>';
}
}

}

//-- query for the poll to be displayed and assign local variables
$where = "id=" . $pollid;
$rs = $modx->db->select("*", $polltable, $where, "id ASC", "");
$limit = $modx->db->getRecordCount($rs);
if (
$limit > 0) {
$poll = $modx->db->getRow($rs);
}

//-- query for poll choice results
$where = "pollid=" . $pollid;
$choices_rs = $modx->db->select("*", $choicetable, $where, "id ASC", "");
$limit2 = $modx->db->getRecordCount($choices_rs);

if (
$limit > 0) {

//-- start the CSS poll voting display
$output .= '
<form class="poll" name="pollvote" method="post" action="[+formaction+]">
<input type="hidden" name="poll_pollid" value="'
. $poll['id'] . '" />
<h3>'
. stripslashes($poll['question']).'</h3>
<div>
'
;

//-- loop through choice results
for ($i = 0; $i < $limit2; $i++) {
$row = $modx->db->getRow($choices_rs);

//-- display each poll choice
$output .= '
<input type="radio" id="poll_choice_'
.$i.'" name="poll_choice_id()" value="' . $row['id'] . '" />
<label for="poll_choice_id">'
. stripslashes($row['choice']) . '</label><br />';
}

//-- display buttons
$output .= '</div>'."\n".'<input type="submit" name="vote" value="Vote" class="vote" />';
if ($resultsbutton == true && $redirect <> '') {
$output .= '<input type="submit" name="results" value="Results" class="vote" />';
}
if (isset ($novote)) {
$output .= '<h3 class="poll_reject">' . $ovmessage . '</h3>';
}

$output .= '</form>';
}

return
$output;

//-- gets the visitors ip address
function userIP() {
// This returns the True IP of the client calling the requested page
// Checks to see if HTTP_X_FORWARDED_FOR
// has a value then the client is operating via a proxy
if ($_SERVER['HTTP_CLIENT_IP'] <> '') {
$userIP = $_SERVER['HTTP_CLIENT_IP'];
}
elseif ($_SERVER['HTTP_X_FORWARDED_FOR'] <> '') {
$userIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif ($_SERVER['HTTP_X_FORWARDED'] <> '') {
$userIP = $_SERVER['HTTP_X_FORWARDED'];
}
elseif ($_SERVER['HTTP_FORWARDED_FOR'] <> '') {
$userIP = $_SERVER['HTTP_FORWARDED_FOR'];
}
elseif ($_SERVER['HTTP_FORWARDED_FOR'] <> '') {
$userIP = $_SERVER['HTTP_FORWARDED_FOR'];
} else {
$userIP = $_SERVER['REMOTE_ADDR'];
}
// return the IP we've figured out:
return $userIP;
}
?>

pollresults snippet:

Code:
<?php
// +----------------------------------------------------------------------+
// | Polls Results Snippet                                                |
// +----------------------------------------------------------------------+
// | Created: January 2006 Version: 1                                     |
// +----------------------------------------------------------------------+
//
// &pollid  - Poll ID to be used
// &decimal - Display decimal places, (number is how many dp's to display)
//
// +----------------------------------------------------------------------+

//-- Try to get poll id, if no poll id then no point carrying on
if (!isset ($pollid))
return false;

$output = '';
$pollid = intval($pollid);

$decimal = (isset ($decimal)) ? intval($decimal) : 1;

//-- Setup DB table names
$polltable = $modx->getFullTableName("polls");
$choicetable = $modx->getFullTableName("poll_choices");
//$resultstable = $modx->getFullTableName('poll_results');

//-- Query for the poll to be displayed and assign local variables
$where = "id=" . $pollid;
$rs = $modx->db->select("*", $polltable, $where, "id ASC", "");
$limit = $modx->db->getRecordCount($rs);


if (
$limit > 0) {
$poll = $modx->db->getRow($rs);
$name = $poll['name'];
$question = $poll['question'];
$totalvotes = $poll['votes'];
}

//-- Query for poll choice results
$where = "pollid=" . $pollid;
$choices_rs = $modx->db->select("*", $choicetable, $where, "id ASC", "");
$climit = $modx->db->getRecordCount($choices_rs);


if (
$limit > 0) {
//-- Start the CSS poll results display
$output .= '
<div class="corner poll">
<h3>'
. stripslashes($question) . '</h3>
<hr />
<dl class="complex_bar">
'
;

//-- Loop through choice results
for ($i = 0; $i < $climit; $i++) {
$row = $modx->db->getRow($choices_rs);
$choice = $row['choice'];
$votes = $row['votes'];

if (($votes < 1) || ($totalvotes < 1)) {
$percent = 0;
} else {
$percent = ($votes / $totalvotes) * 100;
}

if ($percent > 0) {
$percent = number_format($percent, $decimal, '.', '');
}

//-- Display the details of each poll choice
$output .= '<dt>'.stripslashes($choice).'</dt>'."\n";
$output .= '<dd><div style="width:'.$percent.'%;"><strong>'.$percent.'%</strong></div></dd>'."\n";
}

//-- Display total votes for the poll so far and close the table
$output .= '</dl>
<br class="clear" />
<h4>Total Votes: ['
. $totalvotes . ']</h4>
</div>
'
;
}

return
$output;
?>

and here is the CSS (which hasn't has much cross browser testing and mostly came from here: http://applestooranges.com/blog/post/css-for-bar-graphs/?id=55:)

Code:
/*

Poll Styles

*/

div.corner {
width: 50%;
padding: 0 1em;
background-color: #e5f3ff;
border: 1px solid #CBE7FF;
}
.poll input[type="radio"] {
margin-bottom: 0.25em;
}
.poll h3 {
font-size: 100%;
line-height: 1.2;
margin: 0 auto 0.3em auto;
}
.poll h4 {
font-size: 85%;
line-height: 1.1;
margin: 0 auto 0.3em auto;
}
div.corner form.poll {
margin-bottom: 1em;
}

/* Basic Bar Graph */
.graph {
position: relative; /* IE is dumb */
width: 200px;
border: 1px solid #B1D632;
padding: 2px;
margin-bottom: .5em;
}
.graph .bar {
display: block;
position: relative;
background: #B1D632;
text-align: center;
color: #333;
height: 2em;
line-height: 2em;
}
/* This extra markup is necessary because IE doesn't want to follow the rules for overflow: visible */
.graph .bar span { position: absolute; left: 1em; }

/* Complex Bar Graph */

dl.complex_bar dt {
position: relative; /* IE is dumb */
clear: both;
display: block;
height: 20px;
font-weight: normal;
}
dl.complex_bar dd {
position: relative; /* IE is dumb */
display: block;
float: left;
width: 95%;
height: 20px;
margin: 0 0 5px;
background: #fff;
border: 1px solid #CBE7FF;
}

dl.complex_bar dd div {
background-color: #2A567A;
background-color: #8AB1CE;
position: relative;
height: 20px;
width: 75%;
text-align:right;
}
dl.complex_bar dd div strong {
position: relative;
text-align: left;
top: -2px;
font-size: 80%;
margin-right: 0.5em;
}

Hope this helps, in some small way Smiley

Cheers,
Dunc
Logged
plavet
Member
**
Posts: 57


« Reply #3 on: Jan 31, 2008, 10:26 PM »

Wow, thats great banal! I have one wish Roll Eyes -to be compatible with PHP 4 if that is not too much trouble Smiley
Great news about your poll,cant wait to try it out!
Logged
banal
Full Member
***
Posts: 155


« Reply #4 on: Feb 01, 2008, 04:34 AM »

Hi pixelchutes, dunc and plavet

Thanks for your replies. The module is coming along nicely. I hope to release a test-version very soon... got other stuff to do at the moment as well.
I already did a re-write of the Poll Vote Snippet. I'm going to change that in order that the people may customize it's appearance by chunk-templates and own css. So everybody may style it his own way.

PHP4 is considered deprecated (no longer supported/maintained by the php developers) and i'm not sure if it makes sense to further develop stuff for php4?
Logged
banal
Full Member
***
Posts: 155


« Reply #5 on: Feb 05, 2008, 03:29 AM »

Hello readers of this post

I released the EasyPoll Module for testing.
Read my post in the Development forum to run your own tests Smiley

Please post feedback in the other thread as well!
http://modxcms.com/forums/index.php/topic,22457.0.html

Logged
Pages: [1]   Go Up
  Print  
 
Jump to: