Commit 4a635709 by Xavier Antoviaque

Merge pull request #8 from aboudreault/mcq-tip-popup

Display tips & general feedback for MCQs like for MRQs, in a side popup.
parents c520ab40 d46601e3
......@@ -53,24 +53,34 @@ class MCQBlock(QuestionnaireAbstractBlock):
log.debug(u'Received MCQ submission: "%s"', submission)
completed = True
tips_fragments = []
for tip in self.get_tips():
completed = completed and self.is_tip_completed(tip, submission)
if submission in tip.display_with_defaults:
tips_fragments.append(tip.render())
formatted_tips = render_template('templates/html/tip_question_group.html', {
'self': self,
'tips_fragments': tips_fragments,
'submission': submission,
'submission_display': self.get_submission_display(submission),
})
tips = []
choices = [choice.value for choice in self.custom_choices]
# ensure rating tips are included
if self.type == 'rating':
choices += [str(n) for n in range(1,6)]
for choice in choices:
choice_tips_fragments = []
for tip in self.get_tips():
completed = completed and self.is_tip_completed(tip, submission)
if choice in tip.display_with_defaults:
choice_tips_fragments.append(tip.render())
tips.append({
'choice': choice,
'tips': render_template('templates/html/tip_choice_group.html', {
'self': self,
'tips_fragments': choice_tips_fragments,
'completed': completed,
})
})
self.student_choice = submission
result = {
'submission': submission,
'completed': completed,
'tips': formatted_tips,
'tips': tips,
}
log.debug(u'MCQ submission result: %s', result)
return result
......
.mentoring .rating .choices-list {
margin: 5px 0 10px;
}
.mentoring .choices .choices-list {
.mentoring .questionnaire .choices-list {
position: relative;
padding-top: 10px;
margin-bottom: 10px;
}
.mentoring .choices .choice {
.mentoring .questionnaire .choice {
margin: 10px 0;
}
......@@ -17,27 +14,28 @@
margin-bottom: 5px;
}
.mentoring .choices .choice-result {
.mentoring .questionnaire .choice-result {
display: inline-block;
width: 40px;
vertical-align: middle;
cursor: pointer;
}
.mentoring .choices .choice-result.correct, .choice-answer.correct {
.mentoring .questionnaire .choice-result.correct,
.mentoring .questionnaire .choice-answer.correct {
cursor: pointer;
color: #006600;
position: relative;
top: -3px;
}
.mentoring .choices .choice-result.incorrect {
.mentoring .questionnaire .choice-result.incorrect {
text-align:center;
color: #ff0000;
}
.mentoring .choices .choice-tips,
.mentoring .choices .choice-message {
.mentoring .questionnaire .choice-tips,
.mentoring .questionnaire .choice-message {
display: none;
color: #fff;
position: absolute;
......@@ -52,19 +50,20 @@
width: 300px;
}
.mentoring .choices .choice-tips .title {
.mentoring .questionnaire .choice-tips .title {
margin: 0 0 5px;
font-size: 18px;
font-family: arial;
}
.mentoring .choices .choice-tips .tip-choice-group,
.mentoring .choices .choice-message .message-content {
.mentoring .questionnaire .choice-tips .tip-choice-group,
.mentoring .questionnaire .choice-message .tip-choice-group,
.mentoring .questionnaire .choice-message .message-content {
position: relative;
}
.mentoring .choices .choice-tips .close,
.mentoring .choices .choice-message .close {
.mentoring .questionnaire .choice-tips .close,
.mentoring .questionnaire .choice-message .close {
background-image: url({{ close_icon_url }});
cursor: pointer;
position: absolute;
......@@ -74,14 +73,11 @@
height: 21px;
}
.mentoring .choices .choice-tips p {
.mentoring .questionnaire .choice-tips p,
.mentoring .questionnaire .choice-message p {
color: #fff;
}
.mentoring .rating .choice {
margin-right: 10px;
}
.mentoring .choices-list .choice-selector {
margin-right: 5px;
}
......
// TODO: Split in two files
var mrqAttemptsTemplate = _.template($('#xblock-mrq-attempts').html());
function MessageView(element) {
return {
messageDOM: $('.choice-message', element),
allPopupsDOM: $('.choice-tips, .choice-message', element),
clearPopupEvents: function() {
this.allPopupsDOM.hide();
$('.close', this.allPopupsDOM).off('click');
},
showPopup: function(popupDOM) {
var self = this;
this.clearPopupEvents();
popupDOM.show();
popupDOM.on('click', function() {
self.clearPopupEvents();
});
},
showMessage: function(message) {
if (_.isString(message)) {
this.messageDOM.html(message);
this.showPopup(this.messageDOM);
}
else {
this.showPopup(message); // already a DOM
}
}
}
}
function MCQBlock(runtime, element) {
return {
......@@ -14,17 +40,58 @@ function MCQBlock(runtime, element) {
},
handleSubmit: function(result) {
var tipsDom = $(element).parent().find('.messages'),
tipHtml = (result || {}).tips || '';
var messageView = MessageView(element);
var choiceInputs = $('.choice input', element);
$.each(choiceInputs, function(index, choiceInput) {
var choiceInputDOM = $(choiceInput),
choiceDOM = choiceInputDOM.closest('.choice'),
choiceResultDOM = $('.choice-result', choiceDOM),
choiceTipsDOM = $('.choice-tips', choiceDOM),
choiceTipsCloseDOM;
if(tipHtml) {
tipsDom.append(tipHtml);
choiceResultDOM.removeClass('incorrect icon-exclamation correct icon-ok');
if (result.completed && choiceInputDOM.val() === result.submission) {
choiceResultDOM.addClass('correct icon-ok');
}
else if (choiceInputDOM.val() === result.submission || _.isNull(result.submission)) {
choiceResultDOM.addClass('incorrect icon-exclamation');
}
var tips = _.find(result.tips, function(obj) {
return obj.choice === choiceInputDOM.val();
});
if (tips) {
choiceTipsDOM.html(tips.tips);
}
choiceTipsCloseDOM = $('.close', choiceTipsDOM);
choiceResultDOM.off('click').on('click', function() {
if (choiceTipsDOM.html() != '') {
messageView.showMessage(choiceTipsDOM);
}
});
});
if (_.isNull(result.submission)) {
messageView.showMessage('<div class="message-content"><div class="close"></div>' +
'You have not provided an answer.' + '</div>');
}
}
else if (result.tips) {
var tips = _.find(result.tips, function(obj) {
return obj.choice === result.submission;
});
if (tips) {
messageView.showMessage(tips.tips);
} else {
messageView.clearPopupEvents();
}
}
}
};
}
function MRQBlock(runtime, element) {
var mrqAttemptsTemplate = _.template($('#xblock-mrq-attempts').html());
return {
renderAttempts: function() {
var data = $('.mrq-attempts', element).data();
......@@ -59,26 +126,11 @@ function MRQBlock(runtime, element) {
},
handleSubmit: function(result) {
var messageDOM = $('.choice-message', element),
allPopupsDOM = $('.choice-tips, .choice-message', element),
clearPopupEvents = function() {
allPopupsDOM.hide();
$('.close', allPopupsDOM).off('click');
},
showPopup = function(popupDOM) {
clearPopupEvents();
popupDOM.show();
popupDOM.on('click', function() {
clearPopupEvents();
choiceTipsDOM.hide();
});
};
var messageView = MessageView(element);
if (result.message) {
messageDOM.html('<div class="message-content"><div class="close"></div>' +
result.message + '</div>');
showPopup(messageDOM);
messageView.showMessage('<div class="message-content"><div class="close"></div>' +
result.message + '</div>');
}
var answers = []; // used in displayAnswers
......@@ -110,11 +162,11 @@ function MRQBlock(runtime, element) {
choiceTipsCloseDOM = $('.close', choiceTipsDOM);
choiceResultDOM.off('click').on('click', function() {
showPopup(choiceTipsDOM);
messageView.showMessage(choiceTipsDOM);
});
choiceAnswerDOM.off('click').on('click', function() {
showPopup(choiceTipsDOM);
messageView.showMessage(choiceTipsDOM);
});
});
......
<fieldset class="choices">
<fieldset class="choices questionnaire">
<legend class="question">{{ self.question }}</legend>
<div class="choices-list">
{% for choice in custom_choices %}
<div class="choice">
<span class="choice-result"></span>
<span class="choice-result icon-2x"></span>
<label class="choice-label">
<input class="choice-selector" type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == choice.value %} checked{% endif %}> {{ choice.content }}
</label>
<div class="choice-tips"></div>
</div>
{% endfor %}
<div class="choice-message"></div>
</div>
</fieldset>
<fieldset class="rating">
<fieldset class="rating questionnaire">
<legend class="question">{{ self.question }}</legend>
<div class="choices-list">
<span class="low">{{ self.low }}</span>
<span class="choice">
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="1"{% if self.student_choice == '1' %} checked{% endif %}>1</label>
</span>
<span class="choice">
<span class="low"> - {{ self.low }}</span>
<div class="choice-tips"></div>
</div>
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="2"{% if self.student_choice == '2' %} checked{% endif %}>2</label>
</span>
<span class="choice">
<div class="choice-tips"></div>
</div>
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="3"{% if self.student_choice == '3' %} checked{% endif %}>3</label>
</span>
<span class="choice">
<div class="choice-tips"></div>
</div>
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="4"{% if self.student_choice == '4' %} checked{% endif %}>4</label>
</span>
<span class="choice">
<div class="choice-tips"></div>
</div>
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input class="choice-selector" type="radio" name="{{ self.name }}" value="5"{% if self.student_choice == '5' %} checked{% endif %}>5</label>
</span>
<span class="low">{{ self.high }}</span>
<span class="low"> - {{ self.high }}</span>
<div class="choice-tips"></div>
</div>
{% for choice in custom_choices %}
<span class="choice">
<div class="choice">
<span class="choice-result icon-2x"></span>
<label><input type="radio" name="{{ self.name }}" value="{{ choice.value }}"{% if self.student_choice == '{{ choice.value }}' %} checked{% endif %}> {{ choice.content }}</label>
</span>
<div class="choice-tips"></div>
</div>
{% endfor %}
<div class="choice-message"></div>
</div>
</fieldset>
<h2 class="problem-header">Multiple Response</h2>
<fieldset class="choices">
<fieldset class="choices questionnaire">
<legend class="question">{{ self.question }}</legend>
<div class="choices-list">
{% for choice in custom_choices %}
......
<div class="tip-question-group">
<strong>
To the question <span class="italic">"{{ self.question }}"</span>,
{% if submission %}
you answered <span class="italic">"{{ submission_display }}"</span>.
{% else %}
you have not provided an answer.
{% endif %}
</strong>
{% for tip_fragment in tips_fragments %}
{{ tip_fragment.body_html|safe }}
{% endfor %}
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment