apeisa Posted May 12, 2011 Share Posted May 12, 2011 Client needs to create simple polls (or questionnaires) like this: Choose what describes you best: 1) Awesome 2) Smart 3) Polite And then on the site people can click on one options and see results. I started to think that this should be done with pages, where poll is just template. But what is difficult now is to create those options (this goes back to "matrix" again, I think). So we need 2-n options, which should have title, but also value inside. I'm in little bit hurry with this one, so I am ok with not-so-perfect solution. My plan is to create new FieldtypeValueKey, which holds just text title + value. These should also work like images, files etc, that you can put more than one in one field. This FieldtypeValueKey should be usable on other cases than only polls, so I think it is better solution than custom poll module. It is nowhere near "matrix" vision, but could prove useful. If there is simpler solution or something else I haven't figured, please tell me now I'll probably code this during weekend / tomorrow. Link to comment Share on other sites More sharing options...
ryan Posted May 12, 2011 Share Posted May 12, 2011 I like your idea of the FieldtypeValueKey! But if you needed to do something really quickly, here are two other options to consider: 1. Use polldaddy and be done with it. 2. OR: Use pages: Templates: - poll_question (fields: title) [set required child template to be poll_answer] - poll_answer (fields: title, total:integer) Pages: - poll_question: title=Choose what describes you best: - poll_answer: title=Awesome - poll_answer: title=Smart - poll_answer: title=Polite Here's one way the poll_question template might work (written in the browser, so please excuse errors). But this might have similarities to how you'd implement it with a Fieldtype too. <?php // display the question echo "<h1>{$page->title}</h1>"; $displayResults = false; if($session->get("poll" . $page->id)) { // if they already answered the poll this session, just display results $displayResults = true; } else if($input->post->submit_answer) { // if answer submitted, save it $answer_id = (int) $input->post->answer; $answer = $page->child("id=$answer_id"); if($answer->id) { $answer->total = $answer->total + 1; $answer->save(); } echo "<p>Your answer was saved.</p>"; // save the poll ID in session to remember they already did it $session->set("poll" . $page->id, true); $displayResults = true; } else { // they haven't answered the poll yet, show the form: echo "<form action='./' method='post'>"; foreach($page->children as $answer) { echo "<label><input type='radio' name='answer' value='{$answer->id}' /> {$answer->title}</label>"; } echo "<input type='submit' name='submit_answer' value='submit' />"; echo "</form>"; } if($displayResults) { // display the poll results $allTotal = 0; foreach($page->children as $answer) $allTotal += $answer->total; echo "<h2>$allTotal people responded to the poll:</h2>"; foreach($page->children as $answer) { $percent = round(($answer->total / $allTotal) * 100) . "%"; echo "<p>{$answer->title}: $percent</p>"; } } Then, in the template where you want to display the poll: <?php $poll = $pages->get("/path/to/poll/you/want/"); echo $poll->render(); I know you know how to do all this, so this example is just for fun (and procrastination on another project, hehe) and and I'm sure you have something better in mind. But I'm particularly interested in learning more about the FieldtypeValueKey you mentioned. Thanks, Ryan Link to comment Share on other sites More sharing options...
almonk Posted May 18, 2011 Share Posted May 18, 2011 This goes back to the whole 'matrix' idea we brought up a while ago... I've been trying to do a similar sort of thing recently, and I still think that a matrix style solution is the best way to handle things like this. For example, on the backend the user may manage this page like so: http://cl.ly/2Z2O2c31230X36173j3v If we could define fields which could be repeatable, and sortable (drag and drop) - almost exactly how images work, this would be awesome. Thoughts? Link to comment Share on other sites More sharing options...
apeisa Posted May 18, 2011 Author Share Posted May 18, 2011 Ryan: thanks for your detailed (read: complete) example again! I ended up for even simpler solution here. In this case it will be always "yes" or "no" answer, so this went with super simple page where title = question and also two hidden integer fields (yes & no). I created simple ajax voting (works without js also - though I might change this, if it seems that bots and spiders are too eager to vote) here. Almonk: yes, in many scenarios (like images, files & comments currently) repeatable elements are very much needed. Often we can get good solution with different pages, but it really shows it's limits when things get more complicated than simple poll. If you would need new page for every image, it would be messy to have anything else under that page. But matrix is not very simple scenario, as we know. Currently focus is to get 2.1 out as stable version and after that hit language support. But I would love to use something like matrix in EE is in PW. Link to comment Share on other sites More sharing options...
apeisa Posted September 24, 2011 Author Share Posted September 24, 2011 I will build the full scale "poll" module soon, and started again thinking about building that ValueKey fieldtype / inputfield. Although I think that it could be named simply as FieldtypeList. Idea is to have repeatable text fields, that can have additional value also. UI could be very similar to what Almonk posted earlier: http://cl.ly/2Z2O2c31230X36173j3v What would be best (=simplest) way to build this? I am thinking between FieldtypeMulti or regular Fieldtype and saving values & keys as JSON and the latter feels like simpler solution here - although not sure how well it scales when I need to add things like sorting etc. Link to comment Share on other sites More sharing options...
Adam Kiss Posted September 25, 2011 Share Posted September 25, 2011 When I needed something like this (though not dynamically updated, only admin-updated), I create pure text field, without TinyMCE, and written the custom format in CSV there. If you select your character correctly, it's also quite readable, like so: option1 _ 540 _ I think it's very cool! option2 _ 650 _ I'd rather not do it option3 _ 20 _ Absolutely not! And then, I created custom field formatter (this is full code, only stripped of my header comments:). Just now I realized, that outside of the module, you could also add encoding function in static class (so it's globaly available everytime you call this file) <?php /** * Custom Textformatter * * Takes saved textarea and parses it into array of values * * */ class TextformatterCustomFormatter extends Textformatter { public static function getModuleInfo() { return array( 'title' => '-- stripped title--', 'version' => 100, 'summary' => "Parses textarea by new lines – \\n & '_'", ); } public function format(&$str) { if (empty($str)) return; $retArray = array(); $inArray = array(); $inArray = explode ("\n",trim($str)); foreach ($inArray as $i){ $i = explode('_',trim($i)); foreach($i as &$inItem) $inItem = trim($inItem); $returnItem = (object)array ( 'votes'=>intval($i[1]), 'text'=>$i[2] ); $retArray[$i[0]] = $returnItem; } $str = $retArray; } } public class CustomTF { public static function encode($inArray){ $outString = ''; foreach ($inArray as $opt=>&$iA){ $iA = implode (' _ ', array($opt, $iA->votes, $iA->text)); } $outString = implode ("\n", $inArray); return ($outString); } } and now, in your update function, you do this (I assume $answerVoted to have sanitized option ID ['option1' for instance]): <?php $pollOptions = $page->options; $pollOptions[$answerVoted]->votes++; $page->options = CustomTF::encode($pollOptions); $page->save('options'); Link to comment Share on other sites More sharing options...
apeisa Posted September 25, 2011 Author Share Posted September 25, 2011 Thanks for the example Adam. The UI is the most important thing here: It needs to be simple and easy solution. I don't want those values be editable (or at least behind setting) and it should be error free: no way to input it wrong. In templates usage should be something like this: <?php foreach($p->poll as $poll) { echo "{$poll->question} voted {$poll->value} times"; } The biggest reason why I don't like using pages & templates here is that it would be cumbersome to manage. You would need to have /polls/ page where you add all your polls. Then you would need to have page field where you choose what polls you want to show on page you are editing. I like it more straightforward: you just add "poll" field to templates where you allow polls and you can use this field to create polls on the fly. But now that I wrote that down I realize few mistakes in my thinking. There wouldn't be poll archive. Also polls created this way would need checkbox (active/unactive)... plus it would allow only one poll per page. Also that wouldn't allow things like "show latest poll" etc. So I might go back to what Ryan originally suggested (using pages and templates). That means though that I don't get my hands dirty with fieldtypes yet... Link to comment Share on other sites More sharing options...
ryan Posted September 26, 2011 Share Posted September 26, 2011 But now that I wrote that down I realize few mistakes in my thinking. There wouldn't be poll archive. Also polls created this way would need checkbox (active/unactive)... plus it would allow only one poll per page. Also that wouldn't allow things like "show latest poll" etc. I don't think that any of these would be actual limitations, it would just determine what approach you take. But if the subject is still "simple poll", then it's hard to get simpler than pages. You'd have a /tools/polls/ section or something, and then a page reference field would let you select what polls you want to show on any given page. Though I understand your desire to build this as a Fieldtype, so if you want to go that route lets keep talking about approach and we can figure out a good one. Link to comment Share on other sites More sharing options...
apeisa Posted September 26, 2011 Author Share Posted September 26, 2011 I don't think that any of these would be actual limitations, it would just determine what approach you take. But if the subject is still "simple poll", then it's hard to get simpler than pages. You'd have a /tools/polls/ section or something, and then a page reference field would let you select what polls you want to show on any given page. Yep - the more I think of it, the more likely I will build this with just templates & pages. Our upcoming default site profile will at least have image carousels and taxonomy managed under /tools/ tab, so it would be just wise to use that same natural "pw-way" here with polls too. Though I understand your desire to build this as a Fieldtype, so if you want to go that route lets keep talking about approach and we can figure out a good one. I am waiting for a perfect moment to dive into fieldtypes, since those are still little bit mysterious for me. But it seems that this is not that moment ,) Link to comment Share on other sites More sharing options...
nikola Posted October 9, 2011 Share Posted October 9, 2011 Using Ryan's example I've made some polls. I've made a field named poll (type:page) and it has "Parent of selectable pages" set to Poll (the page in the root that hold numerous polls). How can I set the default poll in various pages? For example, on home page I want to display "Poll One" and on some subpage I want to display "Poll Two"? I can select it through the admin by the poll field, but how can I output it in the templates that way? Link to comment Share on other sites More sharing options...
Soma Posted October 9, 2011 Share Posted October 9, 2011 Using Ryan's example I've made some polls. I've made a field named poll (type:page) and it has "Parent of selectable pages" set to Poll (the page in the root that hold numerous polls). How can I set the default poll in various pages? For example, on home page I want to display "Poll One" and on some subpage I want to display "Poll Two"? I can select it through the admin by the poll field, but how can I output it in the templates that way? Not sure where you got problems. I assume you have created it with the code of Ryan on this page further above? You can use this code as is, just insert following before $answer->save(); <?php $answer->setOutputFormatting(false); Make this code of Ryan a template "poll.php", in PW this will be the poll (question) template, containing the answer pages later. Now, you already got your reference page field called "poll" or "poll_selected". So on the template that uses this field to select a poll, you could make it like the following using the "render" method. This is a module under "Page" section called "Page render" you need to install in case you haven't already. This adds render method to all pages. Now using this method it's as simple as: <?php // output poll where you want in you page templates if($page->poll_selected){ echo $page->poll_selected->render(); { Link to comment Share on other sites More sharing options...
nikola Posted October 9, 2011 Share Posted October 9, 2011 Thanks Soma, for your answer. The thing is that I already have a working poll including <?php $answer->setOutputFormatting(false); ?> I use this code to render the poll <?php if(count($page->poll)) { foreach($page->poll as $poll) { echo $poll->render(); } } ?> and it renders poll just fine, but when I have more than one poll in Poll page located in root of the site, for example: Poll -- Poll 1 -- Poll 2 it renders both of the polls on the same page. I can render only one poll, but then I need to unpublish other polls located under same parent where all polls reside. Because of that I've made a field named poll (type: page) where I can select what polls I want to use. The question is: How can I use "Poll 1" for example on one page, and "Poll 2" on another page, given that page(s) uses template that contains field "poll" where I can select poll I want to appear? I want to avoid showing multiple polls on one page at the same time and I want to choose different poll for different pages... Link to comment Share on other sites More sharing options...
Soma Posted October 9, 2011 Share Posted October 9, 2011 Because of that I've made a field named poll (type: page) where I can select what polls I want to use. The question is: How can I use "Poll 1" for example on one page, and "Poll 2" on another page, given that page(s) uses template that contains field "poll" where I can select poll I want to appear? Exactly how you're doing it already and how I explained. I'm a little confused. To clarify again. You have a page field named "poll". This is set to allow only 1 page reference "Single page (Page) or boolean false when none selected", and set parent to be the parent page "Poll" containing all the polls (Poll1,Poll2). Then, on page you select the poll you wish to output like --Poll1. So you got 1 Poll selected, and in the template of the page there would be this code: <?php if($page->poll) { echo $page->poll->render(); } ?> Link to comment Share on other sites More sharing options...
nikola Posted October 9, 2011 Share Posted October 9, 2011 When I use this code it outputs title of the poll, not the poll itself, I have to click it to view it. When I use code that I've posted, I can see the poll normal. Link to comment Share on other sites More sharing options...
Soma Posted October 9, 2011 Share Posted October 9, 2011 Just noticed a typo in my code it should of course be: <?php if($page->poll) { echo $page->poll->render(); } ?> But I think you noticed that too? cause it wouldn't have outputed something at all with $poll->render(); If it still does not work, you're doing something wrong in setting this up all. Not sure how I can further help without seeing the code and field/template setup. 1. I 100% think you forgot this: Make sure the poll page select field is set to allow single pages only (like I mentioned in my previous post). Having different setup wouldn't work since it would return page array when with multiple. You would have to change my code to $page->poll->first()->render(); I think. <?php if(count($page->poll) > 0) { echo $page->poll->first()->render(); } ?> 2. The Poll1,Poll2 uses template that has code from ryan, thats going to render. I have set up a testcase locally within 5 minutes and it works well. Link to comment Share on other sites More sharing options...
nikola Posted October 9, 2011 Share Posted October 9, 2011 Everything works fine now. Thank you Soma! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now