Congratulations! Voting is now enabled for that page.
That's it!, pages are now listed according to their votes!
The recommended method to install Up Down Vote Lister, is simply using your target website marketplace page. However, if you wish not to use concrete5 internal feature, you can follow the next instructions :
After installing Up Down Vote Lister (either through downloading or preferably directly through your concrete5 website interface), you will be provided with 2 blocks under the Audience Voting block set:
Up Down Vote Lister will also install two page attributes
To add a vote to a page, you only need to add an instance of the Ballot Box to your page. The add block dialog will let you customize the way the vote should appear on your page, as well as let you define the voting options. Apart from the message to display, the default options should suit most usages.
If you need more control, the Ballot Box edit/add dialog will let you customize about anything from the look to the vote behavior:
The first pane (
) will let you define how the vote will be shown on the page :The comment to show let you define a customized message. This message can contain patterns which will be replaced in the actual page with their respective meaning. Those patterns include:
The %THUMB% and %THUMB_WxH% will fetch the page thumbnail, either the first image block of the Thumbnail Image area of the page (BlogEntry style) or from the Thumbnail Image page attribute (shipped with this addon). In case both are present, the Thumbnail Image is used.
The Widget Template Images table will let you choose images that are displayed on the voting widget for different scenarios/state/direction and for each voting button (up or down). The two following scenario are available :
For each scenario, 2 different state are then available :
Finally for each state, you can define the image corresponding to the up vote button, and the down vote button.
To change an image just click on the image, and you will be able to select a file from the file manager (or upload one to the website).
The default image can be restored by clicking on the Reset button. Default images are read from the template used to display the block (see the following sections on how to write a vote template).
The
pane defines all options of the voting system:The following options are available :
In short, those options should let you define precisely how you want the vote to be available. Setting the Enable Voting to off will still show the votes, but new votes will not be accepted from this widget. You can decide weather non logged in users (anonymous) can vote or not. In case you decide not to let them vote, you can then decide to send them to login first, or redirect them to a page of your site or even an external url. (The Send Anonymous To option is only available if the Allow anonymous vote option is disabled).
Since recording the statistics on vote can decrease a little the page rendering performance (it involves a few more SQL requests), and since in some occasion, you may just not want to record those statistics, the Record vote statistics option will let you decide to record the stats or not. (You can change this switch later on if you change your mind).
Additionally, the Vote Opening and Vote Closing lets you define votes available for a limited period of time.
Finally, Votes are stored in ballot boxes attribute. There is one instance of attribute per page (you can add multiple attributes to a page, see multiple votes on a page). You can add multiple instance of the Ballot Box pointing to the same ballot box on the same page. In case you defined multiple ballot boxes (by adding attributes as shown later in this document), you can decide where the votes will be stored. If you add multiple Ballot Box pointing to the same ballot box attribute, they will all get updated simultaneously when user vote (through a JSON/AJAX handler).
The Ballot Box comes with several custom templates. To change the template used to render the block, in edit mode, click on the block, then click on the menu entry (in the context pop-up menu), and finally click on the button in the toolbar appearing.
Here are the currently available templates :
All mentioned templates are using the JSON module shipped to perform the vote, and update the votes results. This might not be the easiest way to develop a new template (but this method yields better results in terms of response time). As an easier way, Ballot Box also comes with an AJAX based example (which duplicates the "Both Sides" template). This template should only be used as an example to build your own templates (see the developers section of this documentation).
In case you need more templates, feel free to contact us directly for quotation.
To remove a vote, simply remove the block. However, removing a block does not remove the corresponding attribute. If you wish to remove a vote andremove the corresponding page from Page Lists, you should also remove the attribute manually from the page (in the page properties, then attributes).
Votes are stored in page attributes. To list the pages according to votes, we shipped a specific page list (Vote Page List) which will allow you to list all these pages in a block.
In order to create a page listing other pages, just add the Vote Page Listto that page, and configure it appropriately.
The
tab let you choose where the pages will be search from :(You can then apply filters to these pages, see the Filters section).
The search pages can then be sorted by different factors :
Pages can be sorted by ascending order or descending order.
Finally, If you choose a sort criteria within a time frame, you will be prompted the time frame characteristics :
Available time frames are
the time frame boundary can end 'now' or at the last relevant timeframe (in this case, you will be prompted how many sitewide votes minimum a timeframe must contain to be relevant, all timeframes having a number of votes inferior to that will be ignored for defining the time frame end).
Within the pages found and ordered in the
menu, you can then apply filters to restrict further the pages shown in the results. The following filters are available:Each checkbox (grouped with number inputs) will activate the corresponding boundary. When you enter a number in any boundary, the corresponding checkbox will be automatically activated for you.
Additionally, you can filter results with a keyword search. The search itself comes in 3 different flavours:
Using the last choice, you will then be prompted a variable name (to get the keyword search from), by default, the variable name is set to query, which is the default variable name used by the concrete5 search block. In order to use the search block, add a search block anywhere in the page or from another page, set it to send the results to the page you added the page list, and use the Read Keyword from _REQUEST variable option.
Finally, if you decided to use the last choice, an option box Allow Empty Searches lets you decide the behavior of the page list in case no keyword search was sent to the page in the corresponding $_REQUEST variable. If the checkbox is ticked, all results will be shown (all pages), if the checkbox is not ticked, no page will be shown at all.
The
pane let you customize how the list is to be rendered :In case the Number of pages to show option is not filled, all page results are shown. If it is filled, for example to 20, and the Pagination controls is not set, then only the first (20) results are shown. If the Pagination controls is set, an interface will be shown to access the next result pages.
Finally, this pane allow you to directly change the images used in the voting template widget (in the same way you could change the images used in the voting block).
The Ballot Box block.
However, one option had been added to allow vote on pages which do not yet have a voting attribute. If the Enable vote for 'voteless' pages is selected, then all pages shown in the list will be votable. In case the user vote for a page which did not have the voting attribute, then the voting attribute will be added to the page automatically.
The page list is shipped with several custom templates :
Page list custom templates are compatible with the blog-entry-list custom CSS class (used by concrete5 default Elemental theme). You can add a custom CSS class in the same dialog used to change the display template.
The Blog Thumbnail List template list pages as blog entries. The thumbnail is retrieved from the Thumbnail Image page attribute or from the first block of the Thumbnail Image area if it is an Image block (in the same way the default Page List did on concrete 5.6 for Blog Entry page types).
The Blog Index Template will show a preview of the main area of the page in the list. Those areas can also contain ballot boxes, and if so, they will be rendered just fine. Voting on those block will actually vote for the target page' attribute (just as expected).
Each page list template can be combined with various vote widget templates. Vote widget templates are widgets used to allow the user to vote for the targeted page. %PROJECT_NAME comes with several vote widget templates, accessible from the page list edit dialog (in the pane, under Vote Template select list).
Here is an example of an item of the page list using the blog thumbnail template, combined with the different vote widget templates (here shown using the custom template "Blog Thumbnail" with the blog-entry-list CSS class added).
Vote widget template is independent from the block custom template used to display the page list. If you wish to create vote templates for your site or distribute vote widget templates through an extension, please look at the corresponding Developers section of this documentation. Creating a new voting widget template can be done very easily by copying an existing template to your site override or to your addon (in the appropriate path), and modifying it. %PROJECT_NAME will automatically find it and it will then be made available to all page lists.
The page list block includes a modified version of the Blog Entry Thumbnails template. This template will look for a thumbnail in the same location than the %THUMB% will, that is, first in the Thumbnail Image page attribute, then in the Thumbnail Image area of the page (this area should be available for Blog Entry).
Votes are stored in the page attribute. You can manually edit the votes by going to the page attribute and entering new votes values in the edit dialog :
The attribute dialog is split into two parts, the attribute edit and the log/value control buttons (on the left). The attribute edit form is the following:
From this page you can also clear all existing vote logs (enabling users to vote again, but not changing the vote score) by clicking the Clear Log button. The Reset button will reset the values to 0 and clear the vote log as well.
Vote ballot boxes are in fact Page Attributes. By default, only one attribute is added to your page attributes after installation. To add other ballot boxes (thus enabling multiple and different votes on pages),
You now have multiple vote targets available in your ballot box blocks, page list, and page attributes.
If you selected the record stats option in the vote widgets or ballot box block, you can then visualize votes statistics in the dashboard by visiting the > > page.
This page will let you filter statistics by page, ballot box, user name, and show them on the last 3 hours, last day, month, or year.
By default, all data are aggregated, and only up votes, down votes, and total votes are shown. If you filter by page, the total score evolution will then be drawn as well.
To manage votes, go to the
> > :From this page, you can view all vote scores, count and logs, grouped by page and vote type :
Users Vote Records (that is, what they voted), is recorded in order to prevent users to vote twice and to allow them to change their vote later on. Clearing vote logs will clear that history, but will not alter the vote score (that is the number of Up and Down Votes).
To prevent infinite recursion loops, the number of page list viewed in a single page is limited to (by default) 100. You can change this setting in
> > . This setting prevents you from creating a recursion loop where one page list in Blog Index template will render itself over and over.Custom templates for the Up/Down Vote ballot box are very simple to create. The best way is probably to copy/paste an existing template to your site override in blocks/gnt_ballotbox/templates.
Templates provided by Ballot Box includes 4 comments lines at the beginning of the file to define the default images used in the template :
<?php # IMAGE_UP_ON thumbs/on/thumbup-full-left.png thumbs/on/thumbup-empty-left.png # IMAGE_UP_OFF thumbs/off/thumbup-full-left.png thumbs/off/thumbup-empty-left.png # IMAGE_DOWN_ON thumbs/on/thumbdn-full-right.png thumbs/on/thumbdn-empty-right.png # IMAGE_DOWN_OFF thumbs/off/thumbdn-full-right.png thumbs/off/thumbdn-empty-right.png
Those comments define the defaults image to use for each direction (UP/DOWN) and for each situation (Voting ON or OFF). Each line contains two image references, the first one is used when the ballot box actually contains votes (full), the second is used when the ballot box does not contain any vote (empty).
The images path is relative to the package image directory (that is /packages/gnt_vote_list/images). If the image path begins with a /, then it is considered an absolute url (from the root of your website). You can either use provided images or specify your own (it is then probably a wiser idea to place those images in your site override, for instance in /images and use a path like /images/my_image.png).
The edit dialog will first read the template file to know what should be the defaults, then allow the user to change the file to be shown. In order to use the selected image, instead of the default one, you should use the following variables :
The block will automatically pick the right image depending on the situation. For example, the following code will show the image used for the up vote button :
<img src="<?=$imageUp?>" />
The following variables are available in your templates :
To vote, you will have to use the provided GntBallotBox.vote function:
GntBallotBox.vote(1,<?=$bID?>,<?=$targetCID?>) // vote up GntBallotBox.vote(-1,<?=$bID?>,<?=$targetCID?>) // vote down
If you want to create your own templates, keep in mind that votes can be refreshed in two different ways:
For both method, the best way to start is to get your hands on an existing template, and customize it.
The ajax refresher will refresh the complete template after voting. To do so you must first initialize the GntBallotBox library with the refresh link to be used, and then register the block to be refreshed with the GntBallotBox.registerWidget() function
<script type="text/javascript"> $(function(){ if ( 'undefined' == typeof ( GntBallotBox ) ) return; GntBallotBox.init("<?=$refreshLink?>"); GntBallotBox.registerBlock(<?=$bID?>, "ballotBox_<?=$bID?>","<?=$akHandle?>","<?=html_entity_decode($this->action('json_vote'))?>", <?=$targetCID?> ); }); </script>
To use the JSON provided tool, you will have to create a new BallotBoxWidget and register it. Up Down Vote Lister comes with a default implementation which handles all the voting and the text/image replacements occurring after the votes update. To use the default implementation though, you will need to have specific elements marked up as follow:
for example, the following markup will get updated by a widget with the score and upVotes :
<div id="MyWidgetID"> <!-- whatever code you want --> This page have a score of : <span class="score"><?=$score?></span> (so far, <span class="upVotes"><?=$upVotes?></span> voted up for this page) </div>
To create a BallotBoxWidget you will need the ID of your markup structure (htmlID in our preceding example), the handle of the Ballotbox attribute to vote in, and the images array (so that the widget can choose the correct image according to the situation). To register that widget in the GntBallotBox you will also need the block bID.
Here is an example of a code creating and registering a BallotBoxWidget within a view template:
<script type="text/javascript"> $(function(){ if ( 'undefined' == typeof ( GntBallotBox ) ) return; var imagesArray = <?=JavascriptHelper::arrayToJsDict($images)?>; GntBallotBox.registerWidget( <?=$bID?>, new BallotBoxWidget("ballotBox_<?=$bID?>", imagesArray ), "<?=$akHandle?>", "<?=html_entity_decode( $this->action('json_vote') ) ?>", <?=$targetCID?> ); }); </script>
Here is an example of a full template :
<?php defined('C5_EXECUTE') or die('Access Denied.'); # IMAGE_UP_ON thumbs/on/thumbup-full-right.png thumbs/on/thumbup-empty-right.png # IMAGE_UP_OFF thumbs/off/thumbup-full-right.png thumbs/off/thumbup-empty-right.png # IMAGE_DOWN_ON thumbs/on/thumbdn-full-right.png thumbs/on/thumbdn-empty-right.png # IMAGE_DOWN_OFF thumbs/off/thumbdn-full-right.png thumbs/off/thumbdn-empty-right.png Loader::helper( 'javascript', 'gnt_vote_list' ); $link = $redirectLink ? $redirectLink : 'javascript:void(0)'; $hasLink = $canVote || $redirectLink; ?> <div class="gnt_vote_list_ballotbox" id="ballotBox_<?=$bID?>"> <span class="votesComments"><?=$boxComment?></span> <span class="votes"> <span class="upVotes"><?=$upVotes?></span> <?php if($hasLink){?><a href="<?=$link?>" <?=$redirectLink?'':"onclick=\"GntBallotBox.vote(1,$bID,$targetCID);return false;\""?> ><?php }?><img class="upVotes" src="<?=$imageUp?>"/><?php if($hasLink){?></a><?php }?> <span class="downVotes"><?=$downVotes?></span> <?php if ($hasLink){?><a href="<?=$link?>" <?=$redirectLink?'':"onclick=\"GntBallotBox.vote(-1,$bID,$targetCID);return false;\""?> ><?php }?><img class="downVotes" src="<?=$imageDown?>"/><?php if($hasLink){?></a><?php }?> </span> </div> <?php if ( $canVote ) { ?> <script type="text/javascript"> $(function(){ if ( 'undefined' == typeof ( GntBallotBox ) ) return; var imagesArray = <?=JavascriptHelper::arrayToJsDict($images)?>; GntBallotBox.registerWidget( <?=$bID?>, new BallotBoxWidget("ballotBox_<?=$bID?>", imagesArray ), "<?=$akHandle?>", "<?=html_entity_decode( $this->action('json_vote') ) ?>", <?=$targetCID?> ); }); </script> <?php }
For more information on how to use the javascript library, please see the shipped templates.
As mentioned, the Vote Page List block uses vote widget templates to allow users to vote for a particular page. Users can choose the template to use from the edit dialog. This dialog will look for any vote widget template installed within the website. To create a vote widget template as usual, it is a lot easier to copy/paste an existing template to a new file and start modifying it.
Shipped vote widget templates are located in packages/gnt_vote_list/blocks/gnt_vote_list/vote_templates.
To create your own vote widget template, copy paste one of the file (except the none.php which is an empty template to allow users to hide the vote widget), into your site override : blocks/gnt_vote_list/vote_templates/ (if this directory does not exist, create it).
Addon developers can also include vote widget templates by adding a template into your_package/blocks/gnt_vote_list/vote/templates.
Vote widget templates are looked up in the following order :
Which means that a site override template can actually override a shipped vote widget template, but a package vote widget template can not. (For obvious security reasons). As a general rule, the site override can override anything but nothing can override the site override).
Templates names listed in the edit dialog come from the template file name in which underscores (_) are replaced by spaces.
Creating a vote widget template works pretty much the same way you would create a custom template for the Ballot Box block, except that this time, the code is executed in the BlockController scope (instead of running in the BlockView scope for a normal custom template). Beside this minor different, in fact very few things change …
The vote template have access to the following variables :
As opposed to the Up/Down vote ballot box block, vote widgets do not display a message, thus you don't have access to a $boxComment variable. Moreover, since vote widgets are not blocks, you can not use the AJAX block refresher, you will have to use the provided JSON refresher (for this reason as well, there is no $refreshLink variable available).
Vote widget templates use the same comment syntax for images, (in fact, they are processed by the same library), you can then simply use those comments to set default images used for the template.
All the voting and refreshing mechanism is identical to the block template, if using the JSON refresher. Please refer to the block template documentation (in the above sections), or directly to the code itself.
Actually, creating a vote widget template from a corresponding block custom template is a breeze (just remove the text display, and ensure that the HTML id will remain unique in the final output).
As an example, here is a complete example of a vote widget template :
<?php defined('C5_EXECUTE') or die('Access Denied.'); # IMAGE_UP_ON thumbs/on/thumbup-full-right.png thumbs/on/thumbup-empty-right.png # IMAGE_UP_OFF thumbs/off/thumbup-full-right.png thumbs/off/thumbup-empty-right.png # IMAGE_DOWN_ON thumbs/on/thumbdn-full-right.png thumbs/on/thumbdn-empty-right.png # IMAGE_DOWN_OFF thumbs/off/thumbdn-full-right.png thumbs/off/thumbdn-empty-right.png $metID = "${bID}_$targetCID"; $divID = "ballotBoxList_$metID"; Loader::helper( 'javascript', 'gnt_vote_list' ); $link = $redirectLink ? $redirectLink : 'javascript:void(0)'; $hasLink = $canVote || $redirectLink; ?> <div class="gnt_vote_list_voteWidget" id="<?=$divID?>"> <span class="votes"> <span class="upVotes"><?=$upVotes?></span> <?php if($hasLink){?><a href="<?=$link?>" <?=$redirectLink?'':"onclick=\"GntBallotBox.vote(1,'$metID',$targetCID);return false;\""?> ><?php }?><img class="upVotes" src="<?=$imageUp?>"/><?php if($hasLink){?></a><?php }?> <span class="downVotes"><?=$downVotes?></span> <?php if ($hasLink){?><a href="<?=$link?>" <?=$redirectLink?'':"onclick=\"GntBallotBox.vote(-1,'$metID',$targetCID);return false;\""?> ><?php }?><img class="downVotes" src="<?=$imageDown?>"/><?php if($hasLink){?></a><?php }?> </span> </div> <?php if ( $canVote ) { ?> <script type="text/javascript"> $(function(){ if ( 'undefined' == typeof ( GntBallotBox ) ) return; var imageArray = <?=JavascriptHelper::arrayToJsDict( $images ) ?>; GntBallotBox.registerWidget ( "<?=$metID ?>", new BallotBoxWidget("<?=$divID?>", imageArray ), "<?=$akHandle?>", "<?=html_entity_decode( $jsONVote ) ?>", <?=$targetCID?> ); }); </script> <? } // vim: set noexpandtab ts=4 :
This addon provides a model for manipulating the votes. This model can be found in packages/models/gnt_vote_list/models/ballotbox.php. To use the model from a page in your site you must first load the model using the following code :
Loader::model("ballotbox", "gnt_vote_list" );
This model includes following main classes :
The main class you will be using is the PageBallotBox, but this model in fact allow you to create your own VoteTarget to vote for any CollectionType! (see the model directly for details).
Here is a quick example of the PageBallotBox usage :
<?php defined('C5_EXECUTE') or die('Access Denied.'); $c = Page::getCurrentPage(); Loader::model( 'ballotbox', 'gnt_vote_list'); // Load the model $list = PageVoteTarget::getBallotBoxList(); // get all existing ballot boxes for pages $akHandle = current(array_keys($list)); // get the attribute handle of the first ballot box $ballotbox = new PageBallotBox( $c->getCollectionID(), $akHandle ); if ( !$ballotBox->isInstalled() ) { echo t("This page does not have vote enabled yet!"); $ballotBox->install(); // initiate votes } else { echo t("Total votes for this page : %s\n", $ballotBox->getTotalVotes() ); echo t("Up votes : %s\n", $ballotBox->getUpVotes() ); } if ( $ballotBox->didVote() ) echo t("We voted already!"); // Voting if ( $ballotBox->canVote() ) { $ballotBox->vote( BallotBox::VOTE_UP ); // Vote up ! $ballotBox->vote( BallotBox::VOTE_DOWN ); // Vote down (probably rejected) // actually, at least the last will be rejected if this ballot box only allow single votes } if ( $ballotBox->allowVoteChange() ) { $ballotBox->change( BallotBox::VOTE_DOWN ); // change the vote unless the change is forbidden } // vim: set noexpandtab ts=4 :
Please refer to the class file directly for more information about those two classes public interface.
You can contact me for support or question through the Concrete5.org PM system, or you can use the support system builtin. I usually answer within the hour if I am online, or within 1 business day otherwise. (Please just keep in mind that we might sit in different timezones which might end up in me answering you while you sleep ...).
Need a feature ? need to make sure you can use this addon in a specific situation, just ask!