Commit 866f7529 by Jonathan Piacenti

Studio view and images implemented for Surveys.

parent 21ab57d0
...@@ -54,58 +54,68 @@ class PollBase(XBlock, ResourceMixin, PublishEventMixin): ...@@ -54,58 +54,68 @@ class PollBase(XBlock, ResourceMixin, PublishEventMixin):
choice_data, choice_data,
) )
@XBlock.json_handler @staticmethod
def load_answers(self, data, suffix=''): def any_image(field):
return {
'items': [
{
'key': key, 'text': value['label'], 'img': value['img'],
'noun': 'answer', 'image': True,
}
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, 'display_name': self.display_name,
}
@XBlock.json_handler
def vote(self, data, suffix=''):
""" """
Sets the user's vote. Find out if any answer has an image, since it affects layout.
""" """
result = {'success': False, 'errors': []} return any(value['img'] for value in dict(field).values())
if self.get_choice() is not None:
result['errors'].append('You have already voted in this poll.')
return result
try:
choice = data['choice']
except KeyError:
result['errors'].append('Answer not included with request.')
return result
# Just to show data coming in...
try:
OrderedDict(self.answers)[choice]
except KeyError:
result['errors'].append('No key "{choice}" in answers table.'.format(choice=choice))
return result
self.clean_tally() @staticmethod
self.choice = choice def gather_items(data, result, noun, field, image=True):
self.tally[choice] = self.tally.get(choice, 0) + 1 """
Gathers a set of label-img pairs from a data dict and puts them in order.
"""
items = []
if field not in data or not isinstance(data[field], list):
source_items = []
result['success'] = False
result['errors'].append(
"'{0}' is not present, or not a JSON array.".format(field))
else:
source_items = data[field]
result['success'] = True # Make sure all components are present and clean them.
for item in source_items:
if not isinstance(item, dict):
result['success'] = False
result['errors'].append(
"{0} {1} not a javascript object!".format(noun, item))
continue
key = item.get('key', '').strip()
if not key:
result['success'] = False
result['errors'].append(
"{0} {1} contains no key.".format(noun, item))
image_link = item.get('img', '').strip()
label = item.get('label', '').strip()
if not label:
if image and not image_link:
result['success'] = False
result['errors'].append(
"{0} has no text or img. Please make sure all {0}s "
"have one or the other, or both.".format(noun))
elif not image:
result['success'] = False
# If there's a bug in the code or the user just forgot to relabel a question,
# votes could be accidentally lost if we assume the omission was an
# intended deletion.
result['errors'].append("{0} was added with no label. "
"All {1}s must have labels. Please check the form. "
"Check the form and explicitly delete {1}s "
"if not needed.".format(noun, noun.lower()))
if image:
# Labels might have prefixed space for markdown, though it's unlikely.
items.append((key, {'label': label, 'img': image_link.strip()}))
else:
items.append([key, label])
self.send_vote_event({'choice': self.choice}) if not len(items) > 1:
result['errors'].append(
"You must include at least two {0}s.".format(noun.lower()))
result['success'] = False
return result return items
class PollBlock(PollBase): class PollBlock(PollBase):
...@@ -145,12 +155,6 @@ class PollBlock(PollBase): ...@@ -145,12 +155,6 @@ class PollBlock(PollBase):
if key not in answers: if key not in answers:
del self.tally[key] del self.tally[key]
def any_image(self):
"""
Find out if any answer has an image, since it affects layout.
"""
return any(value['img'] for value in dict(self.answers).values())
def tally_detail(self): def tally_detail(self):
""" """
Return a detailed dictionary from the stored tally that the Return a detailed dictionary from the stored tally that the
...@@ -162,7 +166,7 @@ class PollBlock(PollBase): ...@@ -162,7 +166,7 @@ class PollBlock(PollBase):
total = 0 total = 0
self.clean_tally() self.clean_tally()
source_tally = self.tally source_tally = self.tally
any_img = self.any_image() any_img = self.any_image(self.answers)
for key, value in answers.items(): for key, value in answers.items():
count = int(source_tally[key]) count = int(source_tally[key])
tally.append({ tally.append({
...@@ -225,7 +229,7 @@ class PollBlock(PollBase): ...@@ -225,7 +229,7 @@ class PollBlock(PollBase):
# Mustache is treating an empty string as true. # Mustache is treating an empty string as true.
'feedback': markdown(self.feedback) or False, 'feedback': markdown(self.feedback) or False,
'js_template': js_template, 'js_template': js_template,
'any_img': self.any_image(), 'any_img': self.any_image(self.answers),
# The SDK doesn't set url_name. # The SDK doesn't set url_name.
'url_name': getattr(self, 'url_name', ''), 'url_name': getattr(self, 'url_name', ''),
"display_name": self.display_name, "display_name": self.display_name,
...@@ -246,6 +250,7 @@ class PollBlock(PollBase): ...@@ -246,6 +250,7 @@ class PollBlock(PollBase):
js_template = self.resource_string('/public/handlebars/poll_studio.handlebars') js_template = self.resource_string('/public/handlebars/poll_studio.handlebars')
context.update({ context.update({
'question': self.question, 'question': self.question,
'display_name': self.display_name,
'feedback': self.feedback, 'feedback': self.feedback,
'js_template': js_template 'js_template': js_template
}) })
...@@ -254,57 +259,79 @@ class PollBlock(PollBase): ...@@ -254,57 +259,79 @@ class PollBlock(PollBase):
"/public/css/poll_edit.css", "public/js/poll_edit.js", "PollEdit") "/public/css/poll_edit.css", "public/js/poll_edit.js", "PollEdit")
@XBlock.json_handler @XBlock.json_handler
def load_answers(self, data, suffix=''):
return {
'items': [
{
'key': key, 'text': value['label'], 'img': value['img'],
'noun': 'answer', 'image': True,
}
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, 'display_name': self.display_name,
}
@XBlock.json_handler
def vote(self, data, suffix=''):
"""
Sets the user's vote.
"""
result = {'success': False, 'errors': []}
if self.get_choice() is not None:
result['errors'].append('You have already voted in this poll.')
return result
try:
choice = data['choice']
except KeyError:
result['errors'].append('Answer not included with request.')
return result
# Just to show data coming in...
try:
OrderedDict(self.answers)[choice]
except KeyError:
result['errors'].append('No key "{choice}" in answers table.'.format(choice=choice))
return result
self.clean_tally()
self.choice = choice
self.tally[choice] = self.tally.get(choice, 0) + 1
result['success'] = True
self.send_vote_event({'choice': self.choice})
return result
@XBlock.json_handler
def studio_submit(self, data, suffix=''): def studio_submit(self, data, suffix=''):
# I wonder if there's something for live validation feedback already. # I wonder if there's something for live validation feedback already.
result = {'success': True, 'errors': []} result = {'success': True, 'errors': []}
question = data.get('question', '').strip() question = data.get('question', '').strip()
feedback = data.get('feedback', '').strip() feedback = data.get('feedback', '').strip()
display_name = data.get('display_name', '').strip()
if not question: if not question:
result['errors'].append("You must specify a question.") result['errors'].append("You must specify a question.")
result['success'] = False result['success'] = False
answers = []
if 'answers' not in data or not isinstance(data['answers'], list):
source_answers = []
result['success'] = False
result['errors'].append(
"'answers' is not present, or not a JSON array.")
else:
source_answers = data['answers']
# Make sure all components are present and clean them.
for answer in source_answers:
if not isinstance(answer, dict):
result['success'] = False
result['errors'].append(
"Answer {0} not a javascript object!".format(answer))
continue
key = answer.get('key', '').strip()
if not key:
result['success'] = False
result['errors'].append(
"Answer {0} contains no key.".format(answer))
img = answer.get('img', '').strip()
label = answer.get('label', '').strip()
if not (img or label):
result['success'] = False
result['errors'].append(
"Answer {0} has no text or img. One is needed.".format(answer))
answers.append((key, {'label': label, 'img': img}))
if not len(answers) > 1:
result['errors'].append(
"You must include at least two answers.")
result['success'] = False
if not result['success']: if not result['success']:
return result return result
answers = self.gather_items(data, result, 'Answer', 'answers')
self.answers = answers self.answers = answers
self.question = question self.question = question
self.feedback = feedback self.feedback = feedback
self.display_name = display_name
# Tally will not be updated until the next attempt to use it, per # Tally will not be updated until the next attempt to use it, per
# scoping limitations. # scoping limitations.
...@@ -379,6 +406,7 @@ class SurveyBlock(PollBase): ...@@ -379,6 +406,7 @@ class SurveyBlock(PollBase):
'answers': self.answers, 'answers': self.answers,
'js_template': js_template, 'js_template': js_template,
'questions': self.questions, 'questions': self.questions,
'any_img': self.any_image(self.questions),
# Mustache is treating an empty string as true. # Mustache is treating an empty string as true.
'feedback': markdown(self.feedback) or False, 'feedback': markdown(self.feedback) or False,
# The SDK doesn't set url_name. # The SDK doesn't set url_name.
...@@ -396,13 +424,14 @@ class SurveyBlock(PollBase): ...@@ -396,13 +424,14 @@ class SurveyBlock(PollBase):
js_template = self.resource_string('/public/handlebars/poll_studio.handlebars') js_template = self.resource_string('/public/handlebars/poll_studio.handlebars')
context.update({ context.update({
'question': self.question,
'feedback': self.feedback, 'feedback': self.feedback,
'js_template': js_template 'display_name': self.display_name,
'js_template': js_template,
'multiquestion': True,
}) })
return self.create_fragment( return self.create_fragment(
context, "public/html/poll_edit.html", context, "public/html/poll_edit.html",
"/public/css/poll_edit.css", "public/js/poll_edit.js", "SurveyEditBlock") "/public/css/poll_edit.css", "public/js/poll_edit.js", "SurveyEdit")
def tally_detail(self): def tally_detail(self):
""" """
...@@ -569,6 +598,30 @@ class SurveyBlock(PollBase): ...@@ -569,6 +598,30 @@ class SurveyBlock(PollBase):
return result return result
@XBlock.json_handler
def studio_submit(self, data, suffix=''):
# I wonder if there's something for live validation feedback already.
result = {'success': True, 'errors': []}
feedback = data.get('feedback', '').strip()
display_name = data.get('display_name', '').strip()
answers = self.gather_items(data, result, 'Answer', 'answers', image=False)
questions = self.gather_items(data, result, 'Question', 'questions')
if not result['success']:
return result
self.answers = answers
self.questions = questions
self.feedback = feedback
self.display_name = display_name
# Tally will not be updated until the next attempt to use it, per
# scoping limitations.
return result
@staticmethod @staticmethod
def workbench_scenarios(): def workbench_scenarios():
""" """
......
...@@ -78,10 +78,18 @@ li.poll-result .poll-image { ...@@ -78,10 +78,18 @@ li.poll-result .poll-image {
margin-left: 0; margin-left: 0;
} }
.poll-image img{ .poll-image-td {
width: 25%;
}
.poll-image img, .poll-image-td img{
width: 100%; width: 100%;
} }
.poll-image-td{
display: inline-block;
}
.poll-percent-container { .poll-percent-container {
display: table-cell; display: table-cell;
text-align: left; text-align: left;
...@@ -154,7 +162,9 @@ li.poll-result .poll-image { ...@@ -154,7 +162,9 @@ li.poll-result .poll-image {
th.survey-answer { th.survey-answer {
text-align: center; text-align: center;
width: 2em; width: 7%;
line-height: 1em;
padding-bottom: .25em;
} }
.poll-header { .poll-header {
...@@ -168,6 +178,7 @@ th.survey-answer { ...@@ -168,6 +178,7 @@ th.survey-answer {
.survey-question { .survey-question {
font-weight: bold; font-weight: bold;
vertical-align: middle;
} }
.survey-choice { .survey-choice {
......
<script id="answer-form-component" type="text/html"> <script id="poll-form-component" type="text/html">
{{#each items}} {{#each items}}
<li class="field comp-setting-entry is-set poll-{{noun}}-studio-item"> <li class="field comp-setting-entry is-set poll-{{noun}}-studio-item">
<div class="wrapper-comp-setting"> <div class="wrapper-comp-setting">
......
...@@ -11,6 +11,12 @@ ...@@ -11,6 +11,12 @@
</thead> </thead>
{{#each tally}} {{#each tally}}
<tr class="survey-row"> <tr class="survey-row">
{{#if img}}
<div class="poll-image-td">
<img src="{{img}}" />
</div>
{{/if}}
{% endif %}
<td class="survey-question">{{{text}}}</td> <td class="survey-question">{{{text}}}</td>
{{#each answers}} {{#each answers}}
<td class="survey-percentage survey-option{{#if choice}} survey-choice{{/if}}{{#if top}} poll-top-choice{{/if}}">{{percent}}%</td> <td class="survey-percentage survey-option{{#if choice}} survey-choice{{/if}}{{#if top}} poll-top-choice{{/if}}">{{percent}}%</td>
......
...@@ -3,13 +3,21 @@ ...@@ -3,13 +3,21 @@
<form id="poll-form"> <form id="poll-form">
<ul class="list-input settings-list" id="poll-line-items"> <ul class="list-input settings-list" id="poll-line-items">
<li class="field comp-setting-entry is-set"> <li class="field comp-setting-entry is-set">
<h2><label for="poll-question-editor">Question/Prompt</label></h2> <div class="wrapper-comp-setting">
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported. <label class="label setting-label poll-setting-label" for="display_name">Display Name</label>
<div id="poll-question-editor-container"> <input class="input setting-input" name="display_name" id="poll-display-name" value="{{ display_name }}" type="text" />
<textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea> </div>
</div>
<span class="tip setting-help">Enter the prompt for the user.</span>
</li> </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"> <li class="field comp-setting-entry is-set">
<h2><label for="poll-feedback-editor">Feedback</label></h2> <h2><label for="poll-feedback-editor">Feedback</label></h2>
<a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported. <a href="//daringfireball.net/projects/markdown/syntax" target="_blank">Markdown Syntax</a> is supported.
...@@ -29,15 +37,29 @@ ...@@ -29,15 +37,29 @@
If you delete an answer, any votes for that answer will also be deleted. Students whose choices are deleted 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. may vote again, but will not lose course progress.
</p> </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>
<li id="poll-answer-marker"></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> </ul>
<div class="xblock-actions"> <div class="xblock-actions">
<ul> <ul>
<li class="action-item" id="poll-add-answer"> <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> </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"> <li class="action-item">
<input id="poll-submit-options" type="submit" class="button action-primary save-button" value="Save" onclick="return false;" /> <input id="poll-submit-options" type="submit" class="button action-primary save-button" value="Save" onclick="return false;" />
</li> </li>
......
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
{% for key, question in questions %} {% for key, question in questions %}
<tr class="survey-row"> <tr class="survey-row">
<td class="survey-question"> <td class="survey-question">
{% if question.img %}
<div class="poll-image-td">
<img src="{{question.img}}" />
</div>
{% endif %}
{{question.label}} {{question.label}}
</td> </td>
{% for answer, answer_details in answers %} {% for answer, answer_details in answers %}
......
...@@ -2,49 +2,60 @@ ...@@ -2,49 +2,60 @@
function PollEditUtil(runtime, element, pollType) { function PollEditUtil(runtime, element, pollType) {
var self = this; 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 () { this.init = function () {
// Set up the editing form for a Poll or Survey. // Set up the editing form for a Poll or Survey.
self.loadAnswers = runtime.handlerUrl(element, 'load_answers'); var temp = $('#poll-form-component', element).html();
var temp = $('#answer-form-component', element).html();
self.answerTemplate = Handlebars.compile(temp); self.answerTemplate = Handlebars.compile(temp);
$(element).find('.cancel-button', element).bind('click', function() { $(element).find('.cancel-button', element).bind('click', function() {
runtime.notify('cancel', {}); runtime.notify('cancel', {});
}); });
var mapping = self.mappings[pollType]['buttons']; var button_mapping = self.mappings[pollType]['buttons'];
for (var key in mapping) { for (var key in button_mapping) {
if (mapping.hasOwnProperty(key)) { if (button_mapping.hasOwnProperty(key)) {
$(key, element).click( $(key, element).click(
// The nature of the closure forces us to make a custom function here. // The nature of the closure forces us to make a custom function here.
function (context_key, topMarker, bottomMarker) { function (context_key) {
return function () { return function () {
// The degree of precision on date should be precise enough to avoid // The degree of precision on date should be precise enough to avoid
// collisions in the real world. // collisions in the real world.
var bottom = $(bottomMarker); var bottom = $(button_mapping[context_key]['bottomMarker']);
$(self.answerTemplate(mapping[context_key]['itemList'])).before(bottom); var new_item = $(self.answerTemplate(button_mapping[context_key]['itemList']));
var new_item = bottom.prev(); bottom.before(new_item);
self.empowerDeletes(new_item); self.empowerDeletes(new_item);
self.empowerArrows( self.empowerArrows(
new_item, mapping[context_key]['topMarker'], new_item, button_mapping[context_key]['topMarker'],
mapping[context_key]['bottomMarker'] button_mapping[context_key]['bottomMarker']
); );
new_item.fadeOut(250).fadeIn(250); new_item.fadeOut(250).fadeIn(250);
} }
}(key, self.mappings[pollType]) }(key)
) )
} }
} }
$(element).find('.save-button', element).bind('click', self.pollSubmitHandler); $(element).find('.save-button', element).bind('click', self.pollSubmitHandler);
$(function ($) { var mapping = self.mappings[pollType]['onLoad'];
$.ajax({ for (var task in mapping) {
type: "POST", function load (taskItem){
url: self.loadAnswers, $(function ($) {
data: JSON.stringify({}), $.ajax({
success: self.displayAnswers type: "POST",
}); url: taskItem['url'],
}); data: JSON.stringify({}),
success: taskItem['function']
});
});
}
load(mapping[task]);
}
}; };
this.extend = function (obj1, obj2) { this.extend = function (obj1, obj2) {
...@@ -65,32 +76,6 @@ function PollEditUtil(runtime, element, pollType) { ...@@ -65,32 +76,6 @@ function PollEditUtil(runtime, element, pollType) {
return self.extend({'key': new Date().getTime(), 'text': '', 'img': ''}, extra) 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) { this.empowerDeletes = function (scope) {
// Activates the delete buttons on rendered line items. // Activates the delete buttons on rendered line items.
$('.poll-delete-answer', scope).click(function () { $('.poll-delete-answer', scope).click(function () {
...@@ -122,9 +107,44 @@ function PollEditUtil(runtime, element, pollType) { ...@@ -122,9 +107,44 @@ function PollEditUtil(runtime, element, pollType) {
self.displayItems(data, '#poll-answer-marker', '#poll-answer-end-marker') 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) { this.displayItems = function(data, topMarker, bottomMarker) {
// Loads the initial set of items that the block needs to edit. // 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.empowerDeletes(element, topMarker, bottomMarker);
self.empowerArrows(element, topMarker, bottomMarker); self.empowerArrows(element, topMarker, bottomMarker);
}; };
...@@ -142,31 +162,44 @@ function PollEditUtil(runtime, element, pollType) { ...@@ -142,31 +162,44 @@ function PollEditUtil(runtime, element, pollType) {
alert(data['errors'].join('\n')); 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 // Take all of the fields, serialize them, and pass them to the
// server for saving. // server for saving.
var handlerUrl = runtime.handlerUrl(element, 'studio_submit'); var handlerUrl = runtime.handlerUrl(element, 'studio_submit');
var data = {'answers': []}; var data = {};
var tracker = []; var tracker;
$('#poll-form input', element).each(function() { var gatherings = self.mappings[pollType]['gather'];
var key = 'label'; for (var gathering in gatherings) {
if (this.name.indexOf('answer-') >= 0){ tracker = [];
var name = this.name.replace('answer-', ''); var field = gatherings[gathering]['field'];
if (this.name.indexOf('img-') == 0){ var prefix = gatherings[gathering]['prefix'];
name = name.replace('img-', ''); data[field] = [];
key = 'img' $('#poll-form input', element).each(function () {
} self.gather(this, tracker, data, prefix, field)
if (tracker.indexOf(name) == -1){ });
tracker.push(name); }
data['answers'].push({'key': name}) data['display_name'] = $('#poll-display-name', element).val();
}
var index = tracker.indexOf(name);
data['answers'][index][key] = this.value;
return
}
data[this.name] = this.value
});
data['title'] = $('#poll-title', element).val();
data['question'] = $('#poll-question-editor', element).val(); data['question'] = $('#poll-question-editor', element).val();
data['feedback'] = $('#poll-feedback-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