Simple polling
Overview
This rule provides a very simple widget that can be added to any container, presenting users with a question and list of options then displaying the results after they choose.
The Rule Component
The component is placed in /packages/rules/ in your project or plugin.
rulePoll.cfc
<cfcomponent displayname="Utility: Poll" hint="A simple polling rule" extends="farcry.core.packages.rules.rules" output="false"> <cfproperty ftSeq="1" ftWizardStep="" ftFieldset="Question" name="question" type="longchar" ftLabel="Question" hint="The poll question" ftType="string" /> <cfproperty ftSeq="11" ftWizardStep="" ftFieldset="Option 1" name="answer1" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="12" ftWizardStep="" ftFieldset="Option 1" name="result1" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="13" ftWizardStep="" ftFieldset="Option 2" name="answer2" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="14" ftWizardStep="" ftFieldset="Option 2" name="result2" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="15" ftWizardStep="" ftFieldset="Option 3" name="answer3" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="16" ftWizardStep="" ftFieldset="Option 3" name="result3" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="17" ftWizardStep="" ftFieldset="Option 4" name="answer4" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="18" ftWizardStep="" ftFieldset="Option 4" name="result4" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="19" ftWizardStep="" ftFieldset="Option 5" name="answer5" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="20" ftWizardStep="" ftFieldset="Option 5" name="result5" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="21" ftWizardStep="" ftFieldset="Option 6" name="answer6" type="longchar" ftLabel="Answer" hint="Poll answer" ftType="string" /> <cfproperty ftSeq="22" ftWizardStep="" ftFieldset="Option 6" name="result6" type="string" ftLabel="Result" hint="Poll result" ftType="integer" ftDefault="0" /> <cfproperty ftSeq="31" ftWizardStep="" ftFieldset="Submitting" name="submitlabel" type="string" ftLabel="Submit button label" hint="The label used for the poll submit button" ftType="string" ftDefault="Submit" /> </cfcomponent>
The Webskin
The webskin is placed in /webskin/rulePoll/ in your project or plugin.
execute.cfm
<cfsetting enablecfoutputonly="true" /> <!--- @@displayname: Execute Poll ---> <!--- @@description: ---> <cfimport taglib="/farcry/core/tags/formtools" prefix="ft" /> <cfimport taglib="/farcry/core/tags/webskin" prefix="skin" /> <cfset pollid = replace(stObj.objectid,'-','','ALL') /> <cfparam name="url.showresult" default="" /> <!--- Process poll ---> <ft:processform action="#stObj.submitlabel#"> <cfif structkeyexists(form,pollid)> <cfset stObj["result#form[pollid]#"] = stObj["result#form[pollid]#"]+1 /> <!--- set user to anonymous; otherwise setData() will try and pick up the active session requiring users to login ---> <cfset setData(stProperties=stObj,user="anonymous") /> <cfparam name="session.polls" default="#structnew()#" /> <cfset session.polls[pollid] = true /> </cfif> </ft:processform> <ft:processform action="View Results #pollid#"> <cfset url.showresult = pollid /> </ft:processform> <!--- View poll ---> <cfif url.showresult eq pollid or structkeyexists(session,"polls") and structkeyexists(session.polls,pollid) and session.polls[pollid]> <!--- User has already answered the poll, show results ---> <!--- Calculate total ---> <cfset total = 0 /> <cfloop from="1" to="6" index="i"> <cfset total = total + stObj["result#i#"] /> </cfloop> <cfoutput> <div class="poll"> <p class="pollquestion">#stObj.question#</p> </cfoutput> <cfloop from="1" to="6" index="i"> <cfif len(trim(stObj["answer#i#"]))> <cfoutput> <table class="pollresult"> <tr> <td class="pollanswer" colspan="2">#stObj["answer#i#"]#</td> </tr> <tr> <td class="resultbar" width="#round(stObj['result#i#']/total*70)#%"></td> <td class="resultlabel">#round(stObj['result#i#']/total*100)#%</td> </tr> </table> </cfoutput> </cfif> </cfloop> <cfif url.showresult eq pollid> <skin:buildLink objectid="#request.stObj.objectid#"><cfoutput>Return to Poll</cfoutput></skin:buildLink> </cfif> <cfoutput> </div> </cfoutput> <cfelse> <!--- User has not answered the poll, show the poll form ---> <ft:form> <cfoutput> <div class="poll"> <p class="pollquestion">#stObj.question#</p> <table class="pollanswers"> </cfoutput> <cfloop from="1" to="6" index="i"> <cfif len(trim(stObj["answer#i#"]))> <cfoutput> <tr class="pollanswer"> <td class="answerradio" valign="top"><input class="answerinput" type="radio" value="#i#" name="#pollid#" value="#i#" id="#pollid#_#i#" /></td> <td class="answerlabel"><label class="answerlabel" for="#pollid#_#i#">#stObj["answer#i#"]#</label></td> </tr> </cfoutput> </cfif> </cfloop> <cfoutput> </table> </cfoutput> <skin:buildLink objectid="#request.stObj.objectid#" urlParameters="showresult=#pollid#"><cfoutput>View Results</cfoutput></skin:buildLink> <ft:button value="#stObj.submitlabel#" size="small" /> <cfoutput> </div> </cfoutput> </ft:form> </cfif> <cfsetting enablecfoutputonly="false" />
The CSS
The css can be placed in /www/css/ in your project or plugin. If you put it in your plugin you should have a virtual directory named after the plugin pointing to the plugin's /www/ directory. Add a link to this stylesheet to your template header.
style.css
/* rulePoll */ div.poll { font-size:93%; } p.pollquestion { margin:0; font-size:93%; font-weight:bold; } table.pollresult {} td.pollanswer { padding-top: 5px; } td.resultbar { background-color:#CE171F; } td.resultlabel { padding-left:3px; } table.pollanswers tr.pollanswer td { padding-top:5px; } td.answerradio {} td.answerlabel {} td.answerlabel label.answerlabel { width:auto; text-align:left; }