Commit 866f7529 by Jonathan Piacenti

Studio view and images implemented for Surveys.

parent 21ab57d0
......@@ -78,10 +78,18 @@ li.poll-result .poll-image {
margin-left: 0;
}
.poll-image img{
.poll-image-td {
width: 25%;
}
.poll-image img, .poll-image-td img{
width: 100%;
}
.poll-image-td{
display: inline-block;
}
.poll-percent-container {
display: table-cell;
text-align: left;
......@@ -154,7 +162,9 @@ li.poll-result .poll-image {
th.survey-answer {
text-align: center;
width: 2em;
width: 7%;
line-height: 1em;
padding-bottom: .25em;
}
.poll-header {
......@@ -168,6 +178,7 @@ th.survey-answer {
.survey-question {
font-weight: bold;
vertical-align: middle;
}
.survey-choice {
......
<script id="answer-form-component" type="text/html">
<script id="poll-form-component" type="text/html">
{{#each items}}
<li class="field comp-setting-entry is-set poll-{{noun}}-studio-item">
<div class="wrapper-comp-setting">
......
......@@ -11,6 +11,12 @@
</thead>
{{#each tally}}
<tr class="survey-row">
{{#if img}}
<div class="poll-image-td">
<img src="{{img}}" />
</div>
{{/if}}
{% endif %}
<td class="survey-question">{{{text}}}</td>
{{#each answers}}
<td class="survey-percentage survey-option{{#if choice}} survey-choice{{/if}}{{#if top}} poll-top-choice{{/if}}">{{percent}}%</td>
......
......@@ -3,13 +3,21 @@
<form id="poll-form">
<ul class="list-input settings-list" id="poll-line-items">
<li class="field comp-setting-entry is-set">
<h2><label for="poll-question-editor">Question/Prompt</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
<div id="poll-question-editor-container">
<textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea>
</div>
<span class="tip setting-help">Enter the prompt for the user.</span>
<div class="wrapper-comp-setting">
<label class="label setting-label poll-setting-label" for="display_name">Display Name</label>
<input class="input setting-input" name="display_name" id="poll-display-name" value="{{ display_name }}" type="text" />
</div>
</li>
{% if not multiquestion %}
<li class="field comp-setting-entry is-set">
<h2><label for="poll-question-editor">Question/Prompt</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
<div id="poll-question-editor-container">
<textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea>
</div>
<span class="tip setting-help">Enter the prompt for the user.</span>
</li>
{% endif %}
<li class="field comp-setting-entry is-set">
<h2><label for="poll-feedback-editor">Feedback</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
......@@ -29,15 +37,29 @@
If you delete an answer, any votes for that answer will also be deleted. Students whose choices are deleted
may vote again, but will not lose course progress.
</p>
{% if multiquestion %}
<p>
Questions must be similarly cared for. If a question's text is changed, any votes for that question will remain.
If a question is deleted, any student who previously took the survey will be permitted to retake it, but will not
lose course progress.
</p>
{% endif %}
</li>
<li id="poll-answer-marker"></li>
<li id="poll-answer-end-marker">
<li id="poll-answer-end-marker"></li>
<li id="poll-question-marker"></li>
<li id="poll-question-end-marker"></li>
</ul>
<div class="xblock-actions">
<ul>
<li class="action-item" id="poll-add-answer">
<a href="#" class="button action-button" class="poll-add-answer-link" onclick="return false;">Add Answer</a>
<a href="#" class="button action-button" class="poll-add-item-link" onclick="return false;">Add Answer</a>
</li>
{% if multiquestion %}
<li class="action-item" id="poll-add-question">
<a href="#" class="button action-button" class="poll-add-item-link" onclick="return false;">Add Question</a>
</li>
{% endif %}
<li class="action-item">
<input id="poll-submit-options" type="submit" class="button action-primary save-button" value="Save" onclick="return false;" />
</li>
......
......@@ -16,6 +16,11 @@
{% for key, question in questions %}
<tr class="survey-row">
<td class="survey-question">
{% if question.img %}
<div class="poll-image-td">
<img src="{{question.img}}" />
</div>
{% endif %}
{{question.label}}
</td>
{% for answer, answer_details in answers %}
......
......@@ -2,49 +2,60 @@
function PollEditUtil(runtime, element, pollType) {
var self = this;
// These URLs aren't validated in real time, so even if they don't exist for a type of block
// we can create a reference to them.
this.loadAnswers = runtime.handlerUrl(element, 'load_answers');
this.loadQuestions = runtime.handlerUrl(element, 'load_questions');
this.init = function () {
// Set up the editing form for a Poll or Survey.
self.loadAnswers = runtime.handlerUrl(element, 'load_answers');
var temp = $('#answer-form-component', element).html();
var temp = $('#poll-form-component', element).html();
self.answerTemplate = Handlebars.compile(temp);
$(element).find('.cancel-button', element).bind('click', function() {
runtime.notify('cancel', {});
});
var mapping = self.mappings[pollType]['buttons'];
for (var key in mapping) {
if (mapping.hasOwnProperty(key)) {
var button_mapping = self.mappings[pollType]['buttons'];
for (var key in button_mapping) {
if (button_mapping.hasOwnProperty(key)) {
$(key, element).click(
// The nature of the closure forces us to make a custom function here.
function (context_key, topMarker, bottomMarker) {
function (context_key) {
return function () {
// The degree of precision on date should be precise enough to avoid
// collisions in the real world.
var bottom = $(bottomMarker);
$(self.answerTemplate(mapping[context_key]['itemList'])).before(bottom);
var new_item = bottom.prev();
var bottom = $(button_mapping[context_key]['bottomMarker']);
var new_item = $(self.answerTemplate(button_mapping[context_key]['itemList']));
bottom.before(new_item);
self.empowerDeletes(new_item);
self.empowerArrows(
new_item, mapping[context_key]['topMarker'],
mapping[context_key]['bottomMarker']
new_item, button_mapping[context_key]['topMarker'],
button_mapping[context_key]['bottomMarker']
);
new_item.fadeOut(250).fadeIn(250);
}
}(key, self.mappings[pollType])
}(key)
)
}
}
$(element).find('.save-button', element).bind('click', self.pollSubmitHandler);
$(function ($) {
$.ajax({
type: "POST",
url: self.loadAnswers,
data: JSON.stringify({}),
success: self.displayAnswers
});
});
var mapping = self.mappings[pollType]['onLoad'];
for (var task in mapping) {
function load (taskItem){
$(function ($) {
$.ajax({
type: "POST",
url: taskItem['url'],
data: JSON.stringify({}),
success: taskItem['function']
});
});
}
load(mapping[task]);
}
};
this.extend = function (obj1, obj2) {
......@@ -65,32 +76,6 @@ function PollEditUtil(runtime, element, pollType) {
return self.extend({'key': new Date().getTime(), 'text': '', 'img': ''}, extra)
};
// This object is used to swap out values which differ between Survey and Poll blocks.
this.mappings = {
'poll': {
'buttons': {
'#poll-add-answer': {
'itemList': {'items': [self.makeNew({'image': true, 'noun': 'answer'})]},
'topMarker': '#poll-answer-marker', 'bottomMarker': '#poll-answer-end-marker'
}
},
'onLoad': {
}
},
'survey': {
'buttons': {
'#poll-add-answer': {
'itemList': {'items': [self.makeNew({'image': false, 'noun': 'answer'})]},
'topMarker': '#poll-answer-marker', 'bottomMarker': '#poll-answer-end-marker'
},
'#poll-add-question': {
'itemList': {'items': [self.makeNew({'image': true, 'noun': 'question'})]}
}
}
}
};
this.empowerDeletes = function (scope) {
// Activates the delete buttons on rendered line items.
$('.poll-delete-answer', scope).click(function () {
......@@ -122,9 +107,44 @@ function PollEditUtil(runtime, element, pollType) {
self.displayItems(data, '#poll-answer-marker', '#poll-answer-end-marker')
};
this.displayQuestions = function (data) {
self.displayItems(data, "#poll-question-marker", '#poll-question-end-marker')
};
// This object is used to swap out values which differ between Survey and Poll blocks.
this.mappings = {
'poll': {
'buttons': {
'#poll-add-answer': {
'itemList': {'items': [self.makeNew({'image': true, 'noun': 'answer'})]},
'topMarker': '#poll-answer-marker', 'bottomMarker': '#poll-answer-end-marker'
}
},
'onLoad': [{'url': self.loadAnswers, 'function': self.displayAnswers}],
'gather': [{'prefix': 'answer', 'field': 'answers'}]
},
'survey': {
'buttons': {
'#poll-add-answer': {
'itemList': {'items': [self.makeNew({'image': false, 'noun': 'answer'})]},
'topMarker': '#poll-answer-marker', 'bottomMarker': '#poll-answer-end-marker'
},
'#poll-add-question': {
'itemList': {'items': [self.makeNew({'image': true, 'noun': 'question'})]},
'topMarker': '#poll-question-marker', 'bottomMarker': '#poll-question-end-marker'
}
},
'onLoad': [
{'url': self.loadQuestions, 'function': self.displayQuestions},
{'url': self.loadAnswers, 'function': self.displayAnswers}
],
'gather': [{'prefix': 'answer', 'field': 'answers'}, {'prefix': 'question', 'field': 'questions'}]
}
};
this.displayItems = function(data, topMarker, bottomMarker) {
// Loads the initial set of items that the block needs to edit.
$('#poll-answer-end-marker').before(self.answerTemplate(data));
$(bottomMarker).before(self.answerTemplate(data));
self.empowerDeletes(element, topMarker, bottomMarker);
self.empowerArrows(element, topMarker, bottomMarker);
};
......@@ -142,31 +162,44 @@ function PollEditUtil(runtime, element, pollType) {
alert(data['errors'].join('\n'));
};
this.pollSubmitHandler = function() {
this.gather = function (scope, tracker, data, prefix, field) {
var key = 'label';
var name = scope.name.replace(prefix + '-', '');
if (scope.name.indexOf('img-') == 0){
name = name.replace('img-', '');
key = 'img'
}
if (! (scope.name.indexOf(prefix + '-') >= 0)) {
return
}
if (tracker.indexOf(name) == -1){
tracker.push(name);
data[field].push({'key': name})
}
var index = tracker.indexOf(name);
console.log(data[field]);
console.log(index);
data[field][index][key] = scope.value;
return true
};
this.pollSubmitHandler = function () {
// Take all of the fields, serialize them, and pass them to the
// server for saving.
var handlerUrl = runtime.handlerUrl(element, 'studio_submit');
var data = {'answers': []};
var tracker = [];
$('#poll-form input', element).each(function() {
var key = 'label';
if (this.name.indexOf('answer-') >= 0){
var name = this.name.replace('answer-', '');
if (this.name.indexOf('img-') == 0){
name = name.replace('img-', '');
key = 'img'
}
if (tracker.indexOf(name) == -1){
tracker.push(name);
data['answers'].push({'key': name})
}
var index = tracker.indexOf(name);
data['answers'][index][key] = this.value;
return
}
data[this.name] = this.value
});
data['title'] = $('#poll-title', element).val();
var data = {};
var tracker;
var gatherings = self.mappings[pollType]['gather'];
for (var gathering in gatherings) {
tracker = [];
var field = gatherings[gathering]['field'];
var prefix = gatherings[gathering]['prefix'];
data[field] = [];
$('#poll-form input', element).each(function () {
self.gather(this, tracker, data, prefix, field)
});
}
data['display_name'] = $('#poll-display-name', element).val();
data['question'] = $('#poll-question-editor', element).val();
data['feedback'] = $('#poll-feedback-editor', element).val();
......
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