/polling-station

Primary LanguageJavaScriptMIT LicenseMIT

#Table of Contents

polling-station.js

##Description

A standalone library that creates scaffolding for interactive polls and questionnaires. Has support for saving and fetching from HTML5 localstorage as well as remote API endpoints

Written in 100% vanilla JavaScript

Developed with ❤️ at PolicyMic

====

Version

0.1

Installation

Include the library in your polling page as followed:

<script src="polling-station.min.js"></script>

Building and Testing

Run grunt build to produce minified versions of the scripts into the dist/ folder

Run grunt mocha to run unit tests using Mocha BDD assertions and Phantom-JS (npm install will provide these dependencies)

Run grunt server to enable browser-sync and livereload of testing development (css + js) on localhost:8080. Afterwards, view the pages in examples/ folder with your browser to see demos of various ways to construct a poll

Usage

Set up the data for the poll

The poll-data object must be set with the following schema:

Property Subpropertes Description
question The prompt of the poll; the question being asked
answers id, value, count, percent An array of objects that represent the options avaliable for selection
  • id: Represents the ID of the particular vote option
  • value: The description of the selection
  • count: Number of votes on this current selection
  • percent: A numeric value between 0-100 that represents the ratio of this selection to the poll total
total The total amount of votes made for all selections in the poll

HTML hooks and template rendering

At the very least, a parent element is required to exist on the page. By default, vanilla-poll will look for an element with the id #polling-widget, otherwise it will search for the CSS selector id passed in with the el context attribute upon instantiation

From this there are two ways to proceed:

Static HTML

The following HTML schema is needed when writting static HTML elements to the page:

Basic:
  • Element with CSS id #poll-question to display poll question
  • Container elements with CSS id #poll-answers and #poll-results as respective parents (this can be a <div or <ul>, etc)
  • Individual elements with CSS group .poll-answer and .poll-result nested under their parent container element, along with a data attribute data-id which corresponds to the ID field of their respective answer property
Advanced:
  • For image scaffolding, make sure that an empy <img/ tag is situated within your .poll-answer groups.
  • .poll-answer-text will fetch the answer selection option and display it within this element
  • For dynamic and animated graphs, be sure to construct your #poll-resuls element as followed:
    <div id="poll-results">
            <ul>
                <li class="poll-result" data-id="1">
                    <div class="poll-result-text"></div>
                    <div class="bar">
                        <div class="graph"></div>
                        <div class="poll-result-caption"></div>
                    </div>
                </li>
                <li class="poll-result" data-id="2">
                    <div class="poll-result-text"></div>
                    <div class="bar">
                        <div class="graph"></div>
                        <div class="poll-result-caption"></div>
                    </div>
                </li>
            </ul>
        </div>

Note that there is not much flexibility in rendering the DOM, the default templating function will overwrite anything that does not conform to this standard.

To tweak this behaviour, simply modify defaultTemplateFunc within the PollingStation.prototype declaration

Templating function

The polling widget will also accept a custom templating function that can be passed into the template context attribute. The template exists as nested underneath the parent el element and must follow the same schema as above. However there is more flexibility, as you can include additional HTML elements as well as more freedom with positioning and arrangement of elements

Here is an example using a Handlebars template:

var myCustomTemplateFunc = Handlebars.compile(document.getElementById('poll-template').innerHTML);
var myPoll = new PollingStation({
    url: "http://myapirooturl.com/api",
    template: myCustomTemplateFunc
});

myPoll.init();

Note that in the embed script, a mini templating engine is used to dynamically construct the DOM, see the source code for more information.

Instantiate and start the polling widget

The polling widget object is created with a context argument that provides instructions for how you want to set up the poll. Here is an example

    var myPollingStation = new PollingStation({
        el: '#idOfWidgetDiv', // this defaults to #polling-widget
        url: 'http://myapirooturl.com/api', // this defaults to ''
    });

You can also pass in a local poll-data object as well through the poll parameter, to use as a starting point of you have no url endpoint or data in localstorage. Make sure to set the localStorage flag to persist this data:

var local_poll_data = {
        "id": 1,
        "question": "Is this poll loaded remotely?",
        "answers": [{
            "id": 1,
            "value": "Yes",
            "count": 10,
            "percent": 33
        }, {
            "id": 2,
            "value": "No",
            "count": 20,
            "percent": 66
        }],
        "total": 0
    }

var myPollingStation = new PollingStation({
    poll: local_poll_data,
    localStorage: true
});

Then, once instantiated, start polling with:

    myPollingStation.init();

Which will render the poll into the DOM and set up the event binding

Embed Script:

This entire package can also be run as a single, embeddable script tag that allows for portability ease-of-use.

For reference, the script tag appears as follows:

<script data-base="../" data-url="http://remote-end-point" data-localstorage="true" 
data-css="assets/css/yes-no.css" data-lib="src/polling-station.js" 
src="../src/polling-station-embed.js" data-poll-id="5" id="polling-station-script"></script>

And as a result consists of the following fields:

Attribute Required ? Description
data-base Yes The path of the base folder, in which every other folder and resource is located. This can be local to the script itself, or at a remote URL path
data-url No Represents the API end point host URL if doing remote persistent polling
data-localstorage No Set if you wish to have localStorage fetching on the poll
data-css No(But recommended) The path to an external CSS styling sheet relative to the base path you provided
data-lib Yes The path to the polling-station.js library relative to the base path you provided
data-poll-id No The ID of the poll to fetch and save to if you are using localStorage or remote API persistence
id Yes Identifer of the <script> tag, must be called #polling-station-script
src Yes The path to the polling-station embed script, relative to the base path you provided

Note that when using the embeddable script, you may wish to assign callbacks to happen for event binding that occurs after the poll has been rendered and instantiated. In that case, see the source code for how to pass in callbacks to the init() call -- in the example we use this functionality to allow for event binding on the image hovers

Also of note is the fact that CSS styles are completely customizable and up to the user. Many of the effects in the demoes are a result of tweaking CSS to fit specific needs (mainly that of a Yes-No poll). You will have to implement custom solutions for various other polls.

TODO:

  • Context argument description
  • Elaborate behaviours/bugs

Suggestions/Feedback

Always welcome! Feel free to give a shout to @luckycevans

Copyright

The MIT License (MIT)

Copyright (c) 2014 Christopher Michael Evans

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.