From 30017854ddecd0cd0a1046fcadcbf0acc4f97337 Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti <kelketek@gmail.com> Date: Thu, 1 Jan 2015 16:17:05 +0000 Subject: [PATCH] Refactored JS and Python classes for better code reuse. --- poll/poll.py | 61 +++++++++++++++++++++++++++++++++++++------------------------ poll/public/html/survey.html | 1 + poll/public/js/poll.js | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- 3 files changed, 89 insertions(+), 56 deletions(-) diff --git a/poll/poll.py b/poll/poll.py index 48e6071..a68dd97 100644 --- a/poll/poll.py +++ b/poll/poll.py @@ -35,7 +35,35 @@ class ResourceMixin(object): return frag -class PollBlock(XBlock, ResourceMixin, PublishEventMixin): +class PollBase(XBlock, ResourceMixin, PublishEventMixin): + """ + Base class for Poll-like XBlocks. + """ + event_namespace = 'xblock.pollbase' + + @XBlock.json_handler + def load_answers(self, data, suffix=''): + return { + 'answers': [ + { + 'key': key, 'text': value['label'], 'img': value['img'] + } + for key, value in self.answers + ] + } + + @XBlock.json_handler + def get_results(self, data, suffix=''): + self.publish_event_from_dict(self.event_namespace + '.view_results', {}) + detail, total = self.tally_detail() + return { + 'question': markdown(self.question), 'tally': detail, + 'total': total, 'feedback': markdown(self.feedback), + 'plural': total > 1, + } + + +class PollBlock(PollBase): """ Poll XBlock. Allows a teacher to poll users, and presents the results so far of the poll to the user when finished. @@ -54,16 +82,7 @@ class PollBlock(XBlock, ResourceMixin, PublishEventMixin): scope=Scope.user_state_summary, help="Total tally of answers from students.") choice = String(scope=Scope.user_state, help="The student's answer") - - @XBlock.json_handler - def get_results(self, data, suffix=''): - self.publish_event_from_dict('xblock.poll.view_results', {}) - detail, total = self.tally_detail() - return { - 'question': markdown(self.question), 'tally': detail, - 'total': total, 'feedback': markdown(self.feedback), - 'plural': total > 1, - } + event_namespace = 'xblock.poll' def clean_tally(self): """ @@ -173,17 +192,6 @@ class PollBlock(XBlock, ResourceMixin, PublishEventMixin): context, "public/html/poll.html", "public/css/poll.css", "public/js/poll.js", "PollBlock") - @XBlock.json_handler - def load_answers(self, data, suffix=''): - return { - 'answers': [ - { - 'key': key, 'text': value['label'], 'img': value['img'] - } - for key, value in self.answers - ] - } - def studio_view(self, context=None): if not context: context = {} @@ -321,7 +329,7 @@ class PollBlock(XBlock, ResourceMixin, PublishEventMixin): ] -class SurveyBlock(XBlock, ResourceMixin, PublishEventMixin): +class SurveyBlock(PollBase): display_name = String(default='Survey') answers = List( default=( @@ -345,6 +353,7 @@ class SurveyBlock(XBlock, ResourceMixin, PublishEventMixin): help="Total tally of answers from students." ) choices = Dict(help="The user's answers") + event_namespace = 'xblock.survey' def student_view(self, context=None): """ @@ -354,10 +363,14 @@ class SurveyBlock(XBlock, ResourceMixin, PublishEventMixin): if not context: context = {} + js_template = self.resource_string( + '/public/handlebars/poll_results.handlebars') + context.update({ 'choices': self.choices, # Offset so choices will always be True. 'answers': self.answers, + 'js_template': js_template, 'questions': self.questions, # Mustache is treating an empty string as true. 'feedback': markdown(self.feedback) or False, @@ -367,7 +380,7 @@ class SurveyBlock(XBlock, ResourceMixin, PublishEventMixin): return self.create_fragment( context, "public/html/survey.html", "public/css/poll.css", - "public/js/poll.js", "PollBlock") + "public/js/poll.js", "SurveyBlock") @staticmethod def workbench_scenarios(): diff --git a/poll/public/html/survey.html b/poll/public/html/survey.html index c84768c..972246c 100644 --- a/poll/public/html/survey.html +++ b/poll/public/html/survey.html @@ -1,3 +1,4 @@ +{{ js_template|safe }} <div class="survey-block"> {# If no form is present, the Javascript will load the results instead. #} {% if not choices %} diff --git a/poll/public/js/poll.js b/poll/public/js/poll.js index a17f846..10c9fb1 100644 --- a/poll/public/js/poll.js +++ b/poll/public/js/poll.js @@ -1,70 +1,89 @@ /* Javascript for PollBlock. */ -var PollUtil = { +function PollUtil (runtime, element) { - init: function(runtime, element) { + this.init = function(runtime, element) { this.voteUrl = runtime.handlerUrl(element, 'vote'); this.tallyURL = runtime.handlerUrl(element, 'get_results'); this.element = element; this.runtime = runtime; this.submit = $('input[type=button]', element); + this.answers = $('input[type=radio]', element); this.resultsTemplate = Handlebars.compile($("#poll-results-template", element).html()); - }, + }; - poll_init: function(){ + this.pollInit = function(){ // If the submit button doesn't exist, the user has already // selected a choice. var self = this; + var enableSubmit = self.enableSubmit(); + var getResults = self.getResults(); if (self.submit.length) { var radio = $('input[name=choice]:checked', self.element); - self.submit.click(function (event) { + self.submit.click(function () { // Refresh. - radio = $(radio.selector, element); + radio = $(radio.selector, self.element); var choice = radio.val(); $.ajax({ type: "POST", url: self.voteUrl, data: JSON.stringify({"choice": choice}), - success: self.getResults + success: getResults }); }); // If the user has refreshed the page, they may still have an answer // selected and the submit button should be enabled. var answers = $('input[type=radio]', self.element); if (! radio.val()) { - answers.bind("change.EnableSubmit", self.enableSubmit); + answers.bind("change.EnableSubmit", enableSubmit); } else { - self.enableSubmit(); + enableSubmit(); } } else { - self.getResults({'success': true}); + getResults({'success': true}); } - }, + }; - getResults: function(data) { + this.surveyInit = function () { + + }; + + this.getResults = function () { var self = this; - if (! data['success']) { - alert(data['errors'].join('\n')); - } - $.ajax({ - // Semantically, this would be better as GET, but we can use helper - // functions with POST. - type: "POST", - url: self.tallyURL, - data: JSON.stringify({}), - success: function (data) { - $('div.poll-block', self.element).html(self.resultsTemplate(data)); + return function(data) { + if (!data['success']) { + alert(data['errors'].join('\n')); } - }) - }, + $.ajax({ + // Semantically, this would be better as GET, but we can use helper + // functions with POST. + type: "POST", + url: self.tallyURL, + data: JSON.stringify({}), + success: function (data) { + console.log(self); + $('div.poll-block', self.element).html(self.resultsTemplate(data)); + } + }) + } + }; - enableSubmit: function () { - this.submit.removeAttr("disabled"); - this.answers.unbind("change.EnableSubmit"); - } -}; + this.enableSubmit = function () { + var self = this; + return function () { + self.submit.removeAttr("disabled"); + self.answers.unbind("change.EnableSubmit"); + } + }; + this.init(runtime, element); +} function PollBlock(runtime, element) { - PollUtil.init(runtime, element); - PollUtil.poll_init(); + var util = new PollUtil(runtime, element); + util.pollInit(); +} + +function SurveyBlock(runtime, element) { + var util = new PollUtil(runtime, element); + util.surveyInit(); } -- libgit2 0.26.0