Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-poll
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
xblock-poll
Commits
30017854
Commit
30017854
authored
Jan 01, 2015
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored JS and Python classes for better code reuse.
parent
7fc0f64f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
89 additions
and
56 deletions
+89
-56
poll/poll.py
+37
-24
poll/public/html/survey.html
+1
-0
poll/public/js/poll.js
+51
-32
No files found.
poll/poll.py
View file @
30017854
...
...
@@ -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"
,
"
Poll
Block"
)
"public/js/poll.js"
,
"
Survey
Block"
)
@staticmethod
def
workbench_scenarios
():
...
...
poll/public/html/survey.html
View file @
30017854
{{ js_template|safe }}
<div
class=
"survey-block"
>
{# If no form is present, the Javascript will load the results instead. #}
{% if not choices %}
...
...
poll/public/js/poll.js
View file @
30017854
/* 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
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment