From 5c935a1560403dfbb83700ce00abcc2f7c83c5cb Mon Sep 17 00:00:00 2001 From: Elena Date: Mon, 14 Dec 2015 12:02:16 +0000 Subject: [PATCH 01/27] Quiz feature - prepared code for initial review --- both/collections/quizzes.js | 1 + both/model/quizModel.js | 166 ++++++++++++++++++ client/helpers/editMode.js | 17 ++ client/templates/course/course.js | 7 +- client/templates/course/lesson/lesson.css | 8 + client/templates/course/lesson/lesson.html | 26 +-- client/templates/course/lesson/lesson.js | 7 + client/templates/course/lesson/lesson.less | 9 + .../partials/deleteQuizQuestionButton.html | 3 + .../partials/deleteQuizQuestionButton.js | 16 ++ .../partials/editableTitleDescription.html | 29 +++ .../partials/editableTitleDescription.js | 14 ++ .../questions/partials/multipleChoice.html | 30 ++++ .../quiz/questions/partials/multipleChoice.js | 95 ++++++++++ .../partials/multipleChoiceInputOption.html | 20 +++ .../partials/multipleChoiceInputOption.js | 33 ++++ .../partials/questionInputControl.html | 15 ++ .../partials/questionInputControl.js | 41 +++++ .../quiz/questions/partials/trueOrFalse.html | 23 +++ .../quiz/questions/partials/trueOrFalse.js | 51 ++++++ .../lesson/quiz/questions/questionWrapper.css | 3 + .../quiz/questions/questionWrapper.html | 27 +++ .../lesson/quiz/questions/questionWrapper.js | 34 ++++ .../course/lesson/quiz/quiz-content.css | 25 +++ .../course/lesson/quiz/quiz-content.html | 46 +++++ .../course/lesson/quiz/quiz-content.js | 86 +++++++++ .../sidebar/section/add-quiz/add-quiz.css | 0 .../sidebar/section/add-quiz/add-quiz.html | 23 +++ .../sidebar/section/add-quiz/add-quiz.js | 41 +++++ .../sidebar/section/add-quiz/add-quiz.less | 3 + .../course/sidebar/section/add-quiz/quiz.js | 36 ++++ .../course/sidebar/section/lesson/lesson.html | 10 ++ .../course/sidebar/section/lesson/lesson.js | 15 ++ .../course/sidebar/section/quiz/quiz.html | 22 +++ .../course/sidebar/section/quiz/quiz.js | 18 ++ client/templates/course/sidebar/sidebar.less | 5 + server/publications/quizzes.js | 7 + 37 files changed, 1001 insertions(+), 11 deletions(-) create mode 100644 both/collections/quizzes.js create mode 100644 both/model/quizModel.js create mode 100644 client/templates/course/lesson/lesson.css create mode 100644 client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.js create mode 100644 client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.js create mode 100644 client/templates/course/lesson/quiz/questions/partials/multipleChoice.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/multipleChoice.js create mode 100644 client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.js create mode 100644 client/templates/course/lesson/quiz/questions/partials/questionInputControl.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/questionInputControl.js create mode 100644 client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html create mode 100644 client/templates/course/lesson/quiz/questions/partials/trueOrFalse.js create mode 100644 client/templates/course/lesson/quiz/questions/questionWrapper.css create mode 100644 client/templates/course/lesson/quiz/questions/questionWrapper.html create mode 100644 client/templates/course/lesson/quiz/questions/questionWrapper.js create mode 100644 client/templates/course/lesson/quiz/quiz-content.css create mode 100644 client/templates/course/lesson/quiz/quiz-content.html create mode 100644 client/templates/course/lesson/quiz/quiz-content.js create mode 100644 client/templates/course/sidebar/section/add-quiz/add-quiz.css create mode 100644 client/templates/course/sidebar/section/add-quiz/add-quiz.html create mode 100644 client/templates/course/sidebar/section/add-quiz/add-quiz.js create mode 100644 client/templates/course/sidebar/section/add-quiz/add-quiz.less create mode 100644 client/templates/course/sidebar/section/add-quiz/quiz.js create mode 100644 client/templates/course/sidebar/section/quiz/quiz.html create mode 100644 client/templates/course/sidebar/section/quiz/quiz.js create mode 100644 server/publications/quizzes.js diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js new file mode 100644 index 00000000..5044d00b --- /dev/null +++ b/both/collections/quizzes.js @@ -0,0 +1 @@ +Quizzes = new Mongo.Collection('quizzes'); diff --git a/both/model/quizModel.js b/both/model/quizModel.js new file mode 100644 index 00000000..12ab151d --- /dev/null +++ b/both/model/quizModel.js @@ -0,0 +1,166 @@ +Quiz = function(){ + var quiz = this; + this.addNewQuestion = function(val){ + //check if the question already exists + if (quiz.questions == undefined){ + quiz.questions = []; + } + for (var q in quiz.questions){ + + }; + + quiz.questions.push(val); + }; + +}; + +Quiz.convertToQuizObject = function(object){ + + if (object == undefined) return; + var quiz = new Quiz(); + + quiz._id = object._id; + quiz.title = object.title; + quiz.lessonID = object.lessonID; + quiz.questions = object.questions; + quiz.userAttempts = object.userAttempts; + + return quiz; +}; + + +Object.defineProperty(Quiz, "_title", { + get: function title(){ + return this._title; + }, + set: function title(val){ + this._title = val; + } +}); +Object.defineProperty(Quiz, "_questions", { + get: function question(){ + return this._questions; + }, + set: function questions(val){ + this._questions = val; + } +}); + +Object.defineProperty(Quiz, "_lessonID", { + get: function lessonID(){ + return this._lessonIDs + }, + set: function lessonID(val){ + this._lessonID = val; + } +}); + +Object.defineProperty(Quiz, "_userAttempts", { //an array of objects containig user ids, date and result + get: function userAttempts(){ + return this._userAttempts; + }, + set: function userAttempts(val){ + this._userAttempts = val; + } +}) + + + + +QuizOptions = {}; + +QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER = "Multiple Choice - single answer"; +QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS = "Multiple Choice - multiple answers"; +QuizOptions.TRUE_OR_FALSE = "True or False"; +QuizOptions.QUESTION_TYPES = + [ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, + QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS, + QuizOptions.TRUE_OR_FALSE + ]; + + + +QuizQuestion = function(){}; +Object.defineProperty(QuizQuestion, "_questionType", { + get: function questionType() { + return this._quiztype; + }, + set: function questionType(val) { + this._quiztype = val; + } +}); + +//array of lesson IDs - the quiz can be used in more than one lesson +Object.defineProperty(QuizQuestion, "_quizId", { + get: function quizId(){ + return this._quizId + }, + set: function quizId(val){ + this._lessonIDs = val; + } +}); + +Object.defineProperty(QuizQuestion, "_title", { + get: function title(){ + return this._title; + }, + set: function title(val){ + this._title = val; + } +}); + +Object.defineProperty(QuizQuestion, "_description", { + get: function description(){ + return this._description; + }, + set: function description(val){ + this._description = val; + } +}); + +Object.defineProperty(QuizQuestion, "_options", { + get: function options(){ + return this._options; + }, + set: function options(val){ + this._questions = val; + } +}); + +Object.defineProperty(QuizQuestion, "_saved",{ + get: function saved(){ + return this._saved; + }, + set: function saved(val){ + this._saved = val; + } +}); + +Object.defineProperty(QuizQuestion, "_answered", { + get: function answered(){ + return this._answered; + }, + set: function answered(val){ + this._answered = val; + } +}) + +Object.defineProperty(QuizQuestion, "_isMultipleAnswer", { + get: function isMultipleAnswer(){ + return this._questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + } +}); + +Object.defineProperty(QuizQuestion, "_isSingleAnswer", { + get: function isSingleAnswer(){ + return this._questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; + } +}); + +Object.defineProperty(QuizQuestion, "_isTrueOrFalse", { + get: function isTrueOrfalse(){ + return this._questionType == QuizOptions.TRUE_OR_FALSE; + } +}) + + diff --git a/client/helpers/editMode.js b/client/helpers/editMode.js index 21399f52..4836f40d 100644 --- a/client/helpers/editMode.js +++ b/client/helpers/editMode.js @@ -2,3 +2,20 @@ Template.registerHelper('editMode', function () { // get edit mode session variable return Session.get('editMode'); }); + +Template.registerHelper('isEditingCurrentCourse', function() { + // Get reference to current router + var router = Router.current(); + + // Get Course ID from router + var currentCourseId = router.params._id; + + // Get value of editing course session variable + var editingCourseId = Session.get('editingCourseId') + + // See if user is editing current course + var editingCurrentCourse = (editingCourseId === currentCourseId); + + // return true if user is editing this course + return editingCurrentCourse; +}); \ No newline at end of file diff --git a/client/templates/course/course.js b/client/templates/course/course.js index 8a90503a..266c023b 100644 --- a/client/templates/course/course.js +++ b/client/templates/course/course.js @@ -13,6 +13,10 @@ Template.course.created = function () { // Set the empty active lesson ID variable activeLessonID = new ReactiveVar(undefined); + + //Set an ampty active quiz Id var + activeQuizID = new ReactiveVar(undefined); + }; Template.course.helpers({ @@ -24,5 +28,6 @@ Template.course.helpers({ var course = Courses.findOne(instance.courseId); return course; - } + }, + }); diff --git a/client/templates/course/lesson/lesson.css b/client/templates/course/lesson/lesson.css new file mode 100644 index 00000000..79364610 --- /dev/null +++ b/client/templates/course/lesson/lesson.css @@ -0,0 +1,8 @@ +#addQuizBtn { + margin-left: 12px; + margin-top: 5px; +} +.add-quiz-text { + cursor: pointer; + font-size: 11px; +} diff --git a/client/templates/course/lesson/lesson.html b/client/templates/course/lesson/lesson.html index b7072804..2c6bc7f6 100644 --- a/client/templates/course/lesson/lesson.html +++ b/client/templates/course/lesson/lesson.html @@ -1,14 +1,20 @@ diff --git a/client/templates/course/lesson/lesson.js b/client/templates/course/lesson/lesson.js index 107ed361..652ccfe7 100644 --- a/client/templates/course/lesson/lesson.js +++ b/client/templates/course/lesson/lesson.js @@ -7,5 +7,12 @@ Template.lesson.helpers({ var lesson = Lessons.findOne({_id: lessonID}); return lesson; + }, + + 'activeQuiz': function(){ + var quizId = activeQuizID.get(); + + var quiz = Quiz.convertToQuizObject(Quizzes.findOne({ _id: quizId })); + return quiz; } }); diff --git a/client/templates/course/lesson/lesson.less b/client/templates/course/lesson/lesson.less index e69de29b..ec4d88aa 100644 --- a/client/templates/course/lesson/lesson.less +++ b/client/templates/course/lesson/lesson.less @@ -0,0 +1,9 @@ +#addQuizBtn{ + margin-left: 12px; + margin-top: 5px; +} + +.add-quiz-text{ + cursor: pointer; + font-size: 11px; +} \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.html b/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.html new file mode 100644 index 00000000..37a87b8d --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.js b/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.js new file mode 100644 index 00000000..b861c1c3 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/deleteQuizQuestionButton.js @@ -0,0 +1,16 @@ +Template.deleteQuizQuestionButton.events({ + 'click .delete-template-button': function(event){ + var question = Template.currentData().question; + + //create a custom event + //use document.createEvent as the CustomEvent is not supported by IE + var deleteQuestionEvent = document.createEvent("HTMLEvents"); + deleteQuestionEvent.initEvent("deleteQuestion", true, true); + deleteQuestionEvent.question = question; + + //dispatch the event from the target button + var btn = event.target; + btn.dispatchEvent(deleteQuestionEvent); + + } +}); \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.html b/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.html new file mode 100644 index 00000000..928f12ad --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.html @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.js b/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.js new file mode 100644 index 00000000..92174e98 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/editableTitleDescription.js @@ -0,0 +1,14 @@ +Template.editableTitleDescription.events({ + 'keyup #questionTitle': function(event){ + var titleStr = $(event.target).val(); + var question = Template.currentData().question; + question.title = titleStr; + }, + + 'keyup #questionDescription': function(event){ + var description = $(event.target).val(); + var question = Template.currentData().question; + question.description = description; + }, +}); + diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.html b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.html new file mode 100644 index 00000000..f03c25e2 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.html @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js new file mode 100644 index 00000000..60ed4d67 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js @@ -0,0 +1,95 @@ +Template.multipleChoiceTemplate.created = function(){ + this.numQuizOptions = new ReactiveVar(0); +}; + +Template.multipleChoiceTemplate.helpers({ + isMultipleAnswers: function(){ + var question = Template.currentData().question; + return question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + }, + + isPreviewMode: function(){ + return Blaze._globalHelpers['isEditingCurrentCourse']() == false; + }, + + selectInputOptions: function(){ + var selectOptions = []; + var optionObj = {}; + + //check if the question has a saved configuration + var question = Template.currentData().question; + + //set the title (prompt) row for the select input component: + optionObj.text = "Select number of options"; + optionObj.value = ""; + optionObj.disabled = true; + var selectedOptionIndex = 0; + if (question.options) + { + //if the options have been set: + selectedOptionIndex = question.options.length - 1; //the numbering starts with 2 (min number of options) + } + else{ + optionObj.selected = true; + } + + selectOptions.push(optionObj); + + for (var i = 1; i < 8; i++){ // the min number of options should be 2, so starting the loop from 1 + optionObj = {}; + optionObj.text = i+1; + optionObj.value = i+1; + selectOptions.push(optionObj); + } + selectOptions[selectedOptionIndex].selected = true; + return selectOptions; + }, + + selectedNumberOfOptions: function(){ + var num = Template.instance().numQuizOptions.get(); + var options = []; + + //check if the question has a saved configuration + var question = Template.currentData().question; + if (question.options){ + num = question.options.length; + } + + for (var i=0 ; i < num; i++) + { + if (question.options) + { + options.push(question.options[i]) + }else{ + options.push({title:"", isCorrect: false}); + } + } + return options; + }, + + optionsDisabled: function(){ + return Blaze._globalHelpers['isEditingCurrentCourse']() == false; + } +}); + +Template.multipleChoiceTemplate.events({ + 'change #numQuestions': function(event){ + + var numOptions = $(event.target).val(); + Template.instance().numQuizOptions.set(numOptions); + + var question = Template.currentData().question; + question.numAnswerOptions = numOptions; + + var options = []; + for ( var i= 0; i< numOptions; i++){ + var option = {}; + option.title = ""; + option.isCorrect = false; + options.push(option); + } + question.options = options; + }, + + +}); \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.html b/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.html new file mode 100644 index 00000000..2499fa36 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.js b/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.js new file mode 100644 index 00000000..f5d32130 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoiceInputOption.js @@ -0,0 +1,33 @@ +Template.multipleChoiceInputField.helpers({ + isPreviewMode: function(){ + return Blaze._globalHelpers['isEditingCurrentCourse']() == false; + }, + multipleAnswersAllowed: function(){ + return Template.currentData().multipleAnswersAllowed; + }, + + option: function(){ + return Template.currentData().option; + }, + + index: function(){ + return Template.currentData().index; + }, + + isChecked: function(){ + var option = Template.currentData().option; + var isEdit = Blaze._globalHelpers['isEditingCurrentCourse']() == true; + + return option.isCorrect && isEdit; + } +}); + +Template.multipleChoiceInputField.events({ + 'keyup .js-option-title-input': function(event){ + var index = parseInt(event.target.id); + var text = $(event.target).val(); + var question = Template.currentData().question; + var option = Template.currentData().option; + option.title = text; + }, +}) \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/questionInputControl.html b/client/templates/course/lesson/quiz/questions/partials/questionInputControl.html new file mode 100644 index 00000000..a4c93865 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/questionInputControl.html @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/questionInputControl.js b/client/templates/course/lesson/quiz/questions/partials/questionInputControl.js new file mode 100644 index 00000000..76843b90 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/questionInputControl.js @@ -0,0 +1,41 @@ +Template.questionInputControl.helpers({ + isMultipleAnswers: function(){ + var question = Template.currentData().question; + return question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + }, + + isChecked: function(){ + var option = Template.currentData().option; + var isEdit = Blaze._globalHelpers['isEditingCurrentCourse']() == true; + + return option.isCorrect && isEdit; + } +}); + +Template.questionInputControl.events({ + + 'change .js-option-selected': function(event){ + var index = parseInt(event.target.id); + + var question = Template.currentData().question; + var option = question.options[index]; + + isEditMode = Blaze._globalHelpers['isEditingCurrentCourse']() == true; + + //only allow to set answers as correct in the edit mode + if (isEditMode) + { + //if it's a single-answer question, clear all other options + if (question.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER + || question.questionType == QuizOptions.TRUE_OR_FALSE){ + + for( var i = 0; i < question.options.length; i++){ + question.options[i].isCorrect = false; + } + } + option.isCorrect = event.target.checked; + }else{ + question.answered = true; + } + } +}); \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html new file mode 100644 index 00000000..e9dfe8c0 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.js b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.js new file mode 100644 index 00000000..dc8e1ebf --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.js @@ -0,0 +1,51 @@ +Template.trueOrFalseTemplate.helpers({ + optionsDisabled: function(){ + return Blaze._globalHelpers['isEditingCurrentCourse']() == false; + }, + + isTrue: function(){ + //do not display correct answer in the preview mode + var isPreviewMode = Blaze._globalHelpers['isEditingCurrentCourse']() == false; + var question = Template.currentData().question; + + if (question.correctAnswer) + { + return question.correctAnswer.toLowerCase() == "true" && !isPreviewMode; + } + return false + }, + + isFalse: function(){ + //do not display correct answer in the preview mode + var isPreviewMode = Blaze._globalHelpers['isEditingCurrentCourse']() == false + var question = Template.currentData().question; + + if (question.correctAnswer) + { + return question.correctAnswer.toLowerCase() == "false" && !isPreviewMode; + } + return false + } + +}); + +Template.trueOrFalseTemplate.events({ + 'change .js-option-selected': function(event){ + var value = event.target.value; + var question = Template.currentData().question; + + var isPreviewMode = Blaze._globalHelpers['isEditingCurrentCourse']() == false; + if (!isPreviewMode) + { + //mark the answer as correct for this question + question.correctAnswer = value; + } + else + { + //mark the question as answered + question.answered = true; + } + + + } +}) \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/questionWrapper.css b/client/templates/course/lesson/quiz/questions/questionWrapper.css new file mode 100644 index 00000000..72a41d8f --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/questionWrapper.css @@ -0,0 +1,3 @@ +.delete-template-button{ + float: right; +} \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/questionWrapper.html b/client/templates/course/lesson/quiz/questions/questionWrapper.html new file mode 100644 index 00000000..429a3b2e --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/questionWrapper.html @@ -0,0 +1,27 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/questionWrapper.js b/client/templates/course/lesson/quiz/questions/questionWrapper.js new file mode 100644 index 00000000..3ba660dd --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/questionWrapper.js @@ -0,0 +1,34 @@ +Template.questionWrapper.helpers({ + isMultipleAnswer: function(){ + var question = Template.currentData().question; + return question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + }, + isSingleAnswer: function(){ + var question = Template.currentData().question; + return question.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; + }, + isTrueOrFalse: function(){ + var question = Template.currentData().question; + return question.questionType == QuizOptions.TRUE_OR_FALSE; + }, + + questionIndex: function(){ + return Template.currentData().index + 1; + } +}); + +Template.questionWrapper.events({ + 'deleteQuestion .question-wrapper-row': function(event){ + var quiz = Template.parentData().activeQuiz; + var question = Template.currentData().question; + + //remove the question + var index = quiz.questions.indexOf(question); + quiz.questions.splice(index, 1); + + var updateEvent = document.createEvent("Event"); + updateEvent.initEvent("questionDeleted", true, true); + event.target.dispatchEvent(updateEvent); + } +}); + diff --git a/client/templates/course/lesson/quiz/quiz-content.css b/client/templates/course/lesson/quiz/quiz-content.css new file mode 100644 index 00000000..aca3dd3a --- /dev/null +++ b/client/templates/course/lesson/quiz/quiz-content.css @@ -0,0 +1,25 @@ +.save-quiz-btn{ + float: right; +} + +.quiz-content{ +} +.question-wrapper{ + border: 1px dotted #dc681d; + border-radius: 4px; + background-color: #f5f5f5; + padding: 10px; + margin-top: 7px; +} + +.form-group-sm { + margin-bottom: 5px; +} + +.form-control-label{ + font-weight: normal !important; +} + +.footer-section{ + padding: 30px; +} \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html new file mode 100644 index 00000000..bdd5ac21 --- /dev/null +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -0,0 +1,46 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js new file mode 100644 index 00000000..27dfd367 --- /dev/null +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -0,0 +1,86 @@ +Template.quizContent.created = function(){ + this.addQuestionButtonDisabled = new ReactiveVar(true); + this.quizQuestions = new ReactiveVar([]); + this.quizValidator = new ReactiveVar({}); +}; + +Template.quizContent.helpers({ + currentQuiz: function(){ + return Template.currentData().activeQuiz; + }, + + questionTypes: function(){ + return QuizOptions.QUESTION_TYPES; + }, + + questions: function(){ + + //bind to a reactive var updates + Template.instance().quizQuestions.get(); + + var activeQuiz = Template.currentData().activeQuiz; + return activeQuiz.questions; + }, + + addQuestionButtonDisabled: function(){ + + return Template.instance().addQuestionButtonDisabled.get() == true; + }, + + submitButtonLabel: function(){ + return Blaze._globalHelpers['isEditingCurrentCourse']() == true ? "Save" : "Submit"; + } +}); + +Template.quizContent.events({ + 'change #questionTypesSelector': function(event){ + Template.instance().addQuestionButtonDisabled.set(false); + }, + 'click #addQuestionBtn': function(event){ + var activeQuiz = Template.currentData().activeQuiz; + + var question = new QuizQuestion(); + question.quizId = activeQuiz._id; + question.id = Random.id(); //assign an id to the question - need this for checking and validating answers + question.questionType = $('#questionTypesSelector').val(); + question.saved = false; + question.answered = false; + + activeQuiz.addNewQuestion(question); + + Template.instance().quizQuestions.set(activeQuiz.questions); + Template.instance().addQuestionButtonDisabled.set(true); + $('#questionTypesSelector :first-child').prop('selected', true) + }, + 'click, .submit-quiz-btn': function(event){ + + var isPreview = Blaze._globalHelpers['isEditingCurrentCourse']() == false; + var activeQuiz = Template.currentData().activeQuiz; + var questions = activeQuiz.questions; + + if (!isPreview){ //edit mode + var activeQuiz = Template.currentData().activeQuiz; + var questions = activeQuiz.questions; + //mark the questions as saved + for (var q in questions ){ + var question = questions[q]; + question.saved = true; + } + Quizzes.update(activeQuiz._id, {$set: {'questions': questions}}) + } + else{ // preview/exam mode + for(var question in questions){ + //console.log("answered : " + question.answered); + } + console.log(" should submit the quiz") + } + + }, + + 'deleteQuestion .question-content': function(event){ + + //set the reactive var to update the list of questions + Template.instance().quizQuestions.set(Template.currentData().activeQuiz.questions); + } + +}); \ No newline at end of file diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.css b/client/templates/course/sidebar/section/add-quiz/add-quiz.css new file mode 100644 index 00000000..e69de29b diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.html b/client/templates/course/sidebar/section/add-quiz/add-quiz.html new file mode 100644 index 00000000..9614ed6d --- /dev/null +++ b/client/templates/course/sidebar/section/add-quiz/add-quiz.html @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.js b/client/templates/course/sidebar/section/add-quiz/add-quiz.js new file mode 100644 index 00000000..a0a79622 --- /dev/null +++ b/client/templates/course/sidebar/section/add-quiz/add-quiz.js @@ -0,0 +1,41 @@ +Template.addQuiz.created = function(){ + this.showInput = new ReactiveVar(false) +}; + +Template.addQuiz.helpers({ + showInput: function (){ + return Template.instance().showInput.get(); + } + +}); + +Template.addQuiz.events({ + 'submit .add-new-quiz-form': function (event, instance) { + event.preventDefault(); // prevent page from refreshing + + var quizTitle, // Title of new quiz, from template + newQuizId; // ID of created quiz, returned from db insert + + // Get the title of new section + quizTitle = instance.find('#quiz-title').value; + + var quizObj = new Quiz(); + quizObj.title = quizTitle; + quizObj.lessonID = Template.currentData(); //current data is the lesson ID + //{'title': quizTitle, 'lessonID': Template.currentData()}; + + // Insert new quiz into database + newQuizId = Quizzes.insert(quizObj); + + // Reset the value of section title field + $("#quiz-title").val(""); + instance.showInput.set(false); + }, + + 'click .sidebar-add-quiz-link': function(event, template){ + event.preventDefault(); + var currentShowInput = template.showInput.get(); + var newShowInput = !currentShowInput + template.showInput.set(newShowInput); + } +}); \ No newline at end of file diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.less b/client/templates/course/sidebar/section/add-quiz/add-quiz.less new file mode 100644 index 00000000..8e84055f --- /dev/null +++ b/client/templates/course/sidebar/section/add-quiz/add-quiz.less @@ -0,0 +1,3 @@ +.add-new-quiz-form{ + padding-top: 10px; +} \ No newline at end of file diff --git a/client/templates/course/sidebar/section/add-quiz/quiz.js b/client/templates/course/sidebar/section/add-quiz/quiz.js new file mode 100644 index 00000000..57fdbc5c --- /dev/null +++ b/client/templates/course/sidebar/section/add-quiz/quiz.js @@ -0,0 +1,36 @@ +/*function QuizOptions(){} + + + +QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER = "Multiple Choice - single answer"; +QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS = "Multiple Choice - multiple answers"; +QuizOptions.TRUE_OR_FALSE = "True or False"; +QuizOptions.QUESTION_TYPES = + [ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, + QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS, + QuizOptions.TRUE_OR_FALSE + ]; + + + +function Quiz(){ + Object.defineProperty(this, "quiztype", { + get: function quiztype() { + return this.quiztype; + }, + set: function quiztype(val) { + this.quiztype = val; + } + }); + + //array of lesson IDs - the quiz can be used in more than one lesson + Object.defineProperty(this, "lessonIDs", { + get: function lessonIDs(){ + return this.lessonIDs + }, + set: function lessonIDs(val){ + this.lessonIDs = val; + } + }) +};*/ + diff --git a/client/templates/course/sidebar/section/lesson/lesson.html b/client/templates/course/sidebar/section/lesson/lesson.html index fe40dcce..5835ae77 100644 --- a/client/templates/course/sidebar/section/lesson/lesson.html +++ b/client/templates/course/sidebar/section/lesson/lesson.html @@ -16,6 +16,16 @@ {{/ with }} {{/ if }} + + + {{/ if }} diff --git a/client/templates/course/sidebar/section/lesson/lesson.js b/client/templates/course/sidebar/section/lesson/lesson.js index 9e18b7f2..e350a12e 100644 --- a/client/templates/course/sidebar/section/lesson/lesson.js +++ b/client/templates/course/sidebar/section/lesson/lesson.js @@ -4,6 +4,7 @@ Template.sectionLesson.created = function () { // Subscribe to single section lesson this.subscribe('singleLesson', this.lessonID); + this.subscribe('quizzes'); }; Template.sectionLesson.helpers({ @@ -34,6 +35,17 @@ Template.sectionLesson.helpers({ var lessonObject = Lessons.findOne(lessonID); return lessonObject; + }, + + 'quizzes': function() { + var instance = Template.instance(); + + var lessonID = instance.lessonID; + + //quizzes for the lesson: + var quizzes = Quizzes.find({'lessonID': lessonID}).fetch(); + + return quizzes; } }); @@ -47,5 +59,8 @@ Template.sectionLesson.events({ // set active lesson ID reactive variable // to the value of clicked lesson activeLessonID.set(lessonID); + + //TODO[EM] temporary code + activeQuizID.set(undefined); } }); diff --git a/client/templates/course/sidebar/section/quiz/quiz.html b/client/templates/course/sidebar/section/quiz/quiz.html new file mode 100644 index 00000000..710b8e89 --- /dev/null +++ b/client/templates/course/sidebar/section/quiz/quiz.html @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/client/templates/course/sidebar/section/quiz/quiz.js b/client/templates/course/sidebar/section/quiz/quiz.js new file mode 100644 index 00000000..154e4266 --- /dev/null +++ b/client/templates/course/sidebar/section/quiz/quiz.js @@ -0,0 +1,18 @@ +Template.lessonQuizTemplate.events({ + 'click .sidebar-quiz-link': function(event){ + event.preventDefault(); + + var data = Template.currentData(); + var quizId = String(data._id); + activeQuizID.set(quizId); + + //TODO [EM] temporary code to toggle lesson and quiz + activeLessonID.set(undefined); + } +}); + +Template.lessonQuizTemplate.helpers({ + quiz: function(){ + return Template.currentData(); + } +}) \ No newline at end of file diff --git a/client/templates/course/sidebar/sidebar.less b/client/templates/course/sidebar/sidebar.less index 05402648..c7009284 100644 --- a/client/templates/course/sidebar/sidebar.less +++ b/client/templates/course/sidebar/sidebar.less @@ -14,3 +14,8 @@ .course-navigation { margin-top: 1.4em; } + +.course-navigation ul > li .sidebar-quiz-link{ + padding: 2px 30px; + +} diff --git a/server/publications/quizzes.js b/server/publications/quizzes.js new file mode 100644 index 00000000..8219ee5b --- /dev/null +++ b/server/publications/quizzes.js @@ -0,0 +1,7 @@ +Meteor.publish('quizzes', function () { + return Quizzes.find(); +}); + +Meteor.publish('singleQuiz', function (quizID) { + return Quizzes.find({"_id": quizID}); +}); From ab12970adee3ed0729f34f169983d4453c9d7314 Mon Sep 17 00:00:00 2001 From: Elena Date: Thu, 24 Dec 2015 06:00:56 +0000 Subject: [PATCH 02/27] adding a simple schema to quiz - started --- both/collections/quizzes.js | 79 +++++++++++++++++++ .../quiz/questions/partials/multipleChoice.js | 2 +- .../course/lesson/quiz/quiz-content.js | 3 + .../sidebar/section/add-quiz/add-quiz.js | 1 - 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index 5044d00b..ddd0c024 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -1 +1,80 @@ Quizzes = new Mongo.Collection('quizzes'); + +QuizOptions = {}; + +QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER = "Multiple Choice - single answer"; +QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS = "Multiple Choice - multiple answers"; +QuizOptions.TRUE_OR_FALSE = "True or False"; +QuizOptions.QUESTION_TYPES = + [ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, + QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS, + QuizOptions.TRUE_OR_FALSE + ]; + + +//this schema will validate the overall questions collection +/*QuizzesQuestionsSchema = new SimpleSchema({ + questions: { + type: Array + } +});*/ + +QuizQuestionOptionSchema = new SimpleSchema({ + +}) + +//This schema will validate the initial creation of a quiz +QuizzesSchema = new SimpleSchema({ + title: { + type:String, + label: "Quiz Title", + min: 4, + max: 140 + }, + questions: { + type: [Object], + optional: true + }, + + "questions.$.id": { + type: String, + optional: true + }, + "questions.$.questionType": { + type:String, + optional: true + }, + "questions.$.quizId": { + type:String, + optional: true + }, + "questions.$.title": { + type:String, + optional: true + }, + "questions.$.description" : { + type:String, + optional: true + }, + /* "questions.$.options" : { + type: Array, + optional: true + },*/ + "questions.$.numAnswerOptions": { + type:String, + optional: true + }, + "questions.$.saved" : { + type: Boolean, + optional: true + }, + "questions.$.answered": { + type:Boolean, + optional: true + }, + lessonID: { + type:String, + }, +}); + +Quizzes.attachSchema(QuizzesSchema); diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js index 60ed4d67..df55cfcd 100644 --- a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js @@ -88,7 +88,7 @@ Template.multipleChoiceTemplate.events({ option.isCorrect = false; options.push(option); } - question.options = options; + //question.options = options; }, diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index 27dfd367..6f54b11e 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -66,6 +66,9 @@ Template.quizContent.events({ var question = questions[q]; question.saved = true; } + + console.log("updating quiz with questions"); + console.log(questions); Quizzes.update(activeQuiz._id, {$set: {'questions': questions}}) } else{ // preview/exam mode diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.js b/client/templates/course/sidebar/section/add-quiz/add-quiz.js index a0a79622..88cd8420 100644 --- a/client/templates/course/sidebar/section/add-quiz/add-quiz.js +++ b/client/templates/course/sidebar/section/add-quiz/add-quiz.js @@ -22,7 +22,6 @@ Template.addQuiz.events({ var quizObj = new Quiz(); quizObj.title = quizTitle; quizObj.lessonID = Template.currentData(); //current data is the lesson ID - //{'title': quizTitle, 'lessonID': Template.currentData()}; // Insert new quiz into database newQuizId = Quizzes.insert(quizObj); From 5c267a7241b4d3aa24c974f2b3676bd92eaec8ea Mon Sep 17 00:00:00 2001 From: Elena Date: Thu, 24 Dec 2015 11:21:44 +0000 Subject: [PATCH 03/27] questions schema --- both/collections/quizzes.js | 8 ++------ .../quiz/questions/partials/multipleChoice.js | 5 ++--- .../course/lesson/quiz/quiz-content.js | 18 +++++++++++++----- .../sidebar/section/add-quiz/add-quiz.js | 2 +- {both/model => lib}/quizModel.js | 2 +- 5 files changed, 19 insertions(+), 16 deletions(-) rename {both/model => lib}/quizModel.js (99%) diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index ddd0c024..fba90e4a 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -56,12 +56,8 @@ QuizzesSchema = new SimpleSchema({ type:String, optional: true }, - /* "questions.$.options" : { - type: Array, - optional: true - },*/ - "questions.$.numAnswerOptions": { - type:String, + "questions.$.options" : { + type: [Object], optional: true }, "questions.$.saved" : { diff --git a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js index df55cfcd..11f5b41d 100644 --- a/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js +++ b/client/templates/course/lesson/quiz/questions/partials/multipleChoice.js @@ -24,7 +24,7 @@ Template.multipleChoiceTemplate.helpers({ optionObj.value = ""; optionObj.disabled = true; var selectedOptionIndex = 0; - if (question.options) + if (question.options && question.options.length > 0) { //if the options have been set: selectedOptionIndex = question.options.length - 1; //the numbering starts with 2 (min number of options) @@ -79,7 +79,6 @@ Template.multipleChoiceTemplate.events({ Template.instance().numQuizOptions.set(numOptions); var question = Template.currentData().question; - question.numAnswerOptions = numOptions; var options = []; for ( var i= 0; i< numOptions; i++){ @@ -88,7 +87,7 @@ Template.multipleChoiceTemplate.events({ option.isCorrect = false; options.push(option); } - //question.options = options; + question.options = options; }, diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index 6f54b11e..e9f59efb 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -39,12 +39,15 @@ Template.quizContent.events({ 'click #addQuestionBtn': function(event){ var activeQuiz = Template.currentData().activeQuiz; - var question = new QuizQuestion(); + var question = new Object();// new QuizQuestion(); question.quizId = activeQuiz._id; question.id = Random.id(); //assign an id to the question - need this for checking and validating answers question.questionType = $('#questionTypesSelector').val(); question.saved = false; question.answered = false; + question.description = ""; + question.title = ""; + question.options = []; activeQuiz.addNewQuestion(question); @@ -64,12 +67,17 @@ Template.quizContent.events({ //mark the questions as saved for (var q in questions ){ var question = questions[q]; - question.saved = true; + //question.saved = true; + } + + if (questions != undefined){ + console.log("updating quiz with questions"); + console.log(questions); + + var quizToUpdate = Quizzes.findOne({_id: activeQuiz._id}); + Quizzes.update(activeQuiz._id, {$set: {'questions': questions}}) } - console.log("updating quiz with questions"); - console.log(questions); - Quizzes.update(activeQuiz._id, {$set: {'questions': questions}}) } else{ // preview/exam mode for(var question in questions){ diff --git a/client/templates/course/sidebar/section/add-quiz/add-quiz.js b/client/templates/course/sidebar/section/add-quiz/add-quiz.js index 88cd8420..5c2ca517 100644 --- a/client/templates/course/sidebar/section/add-quiz/add-quiz.js +++ b/client/templates/course/sidebar/section/add-quiz/add-quiz.js @@ -22,7 +22,7 @@ Template.addQuiz.events({ var quizObj = new Quiz(); quizObj.title = quizTitle; quizObj.lessonID = Template.currentData(); //current data is the lesson ID - + quizObj.questions = []; // Insert new quiz into database newQuizId = Quizzes.insert(quizObj); diff --git a/both/model/quizModel.js b/lib/quizModel.js similarity index 99% rename from both/model/quizModel.js rename to lib/quizModel.js index 12ab151d..fe288fb3 100644 --- a/both/model/quizModel.js +++ b/lib/quizModel.js @@ -80,7 +80,7 @@ QuizOptions.QUESTION_TYPES = -QuizQuestion = function(){}; +QuizQuestion = function() {}; Object.defineProperty(QuizQuestion, "_questionType", { get: function questionType() { return this._quiztype; From e17f45022db42737962c92e67868a205816bd95f Mon Sep 17 00:00:00 2001 From: Elena Date: Thu, 24 Dec 2015 11:29:43 +0000 Subject: [PATCH 04/27] options field schema - fields set to optional --- both/collections/quizzes.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index fba90e4a..6dadcead 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -60,6 +60,15 @@ QuizzesSchema = new SimpleSchema({ type: [Object], optional: true }, + "questions.$.options.$.title": { + type:String, + optional: true, + defaultValue: "" + }, + "questions.$.options.$.isCorrect": { + type: Boolean, + defaultValue: false + }, "questions.$.saved" : { type: Boolean, optional: true From 2b36aa7e5206a392c54aac7816d85f383efc0eae Mon Sep 17 00:00:00 2001 From: Elena Date: Thu, 24 Dec 2015 11:37:02 +0000 Subject: [PATCH 05/27] fixed typo --- client/templates/course/lesson/quiz/quiz-content.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index e9f59efb..73899895 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -55,7 +55,7 @@ Template.quizContent.events({ Template.instance().addQuestionButtonDisabled.set(true); $('#questionTypesSelector :first-child').prop('selected', true) }, - 'click, .submit-quiz-btn': function(event){ + 'click .submit-quiz-btn': function(event){ var isPreview = Blaze._globalHelpers['isEditingCurrentCourse']() == false; var activeQuiz = Template.currentData().activeQuiz; From 42940bcf5c6c15d209a5d47062e8084b9f0f906b Mon Sep 17 00:00:00 2001 From: Elena Date: Thu, 24 Dec 2015 12:11:37 +0000 Subject: [PATCH 06/27] created subschemas --- both/collections/quizzes.js | 73 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index 6dadcead..cd2bc92c 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -12,71 +12,70 @@ QuizOptions.QUESTION_TYPES = ]; -//this schema will validate the overall questions collection -/*QuizzesQuestionsSchema = new SimpleSchema({ - questions: { - type: Array - } -});*/ - -QuizQuestionOptionSchema = new SimpleSchema({ - -}) - -//This schema will validate the initial creation of a quiz -QuizzesSchema = new SimpleSchema({ +AnswerOptionSchema = new SimpleSchema({ title: { type:String, - label: "Quiz Title", - min: 4, - max: 140 + optional: true, + defaultValue: "" }, - questions: { - type: [Object], - optional: true + isCorrect: { + type: Boolean, + defaultValue: false }, +}) - "questions.$.id": { +//this schema will validate the overall questions collection +QuestionsSchema = new SimpleSchema({ + id: { type: String, optional: true }, - "questions.$.questionType": { + questionType: { type:String, optional: true }, - "questions.$.quizId": { + quizId: { type:String, optional: true }, - "questions.$.title": { + title: { type:String, optional: true }, - "questions.$.description" : { + description : { type:String, optional: true }, - "questions.$.options" : { - type: [Object], + options : { + type: [AnswerOptionSchema], optional: true }, - "questions.$.options.$.title": { - type:String, - optional: true, - defaultValue: "" - }, - "questions.$.options.$.isCorrect": { - type: Boolean, - defaultValue: false - }, - "questions.$.saved" : { + + saved : { type: Boolean, optional: true }, - "questions.$.answered": { + answered: { type:Boolean, optional: true }, +}); + + +//This schema will validate the initial creation of a quiz +QuizzesSchema = new SimpleSchema({ + title: { + type:String, + label: "Quiz Title", + min: 4, + max: 140 + }, + questions: { + //type: [Object], + type: [QuestionsSchema], + optional: true + }, + lessonID: { type:String, }, From ee82cbf4fe94638117d2a68b0fd4681b6c535b89 Mon Sep 17 00:00:00 2001 From: Elena Date: Sat, 26 Dec 2015 09:33:05 +0000 Subject: [PATCH 07/27] true/false template --- both/collections/quizzes.js | 53 ++++++++++++++++--- .../quiz/questions/partials/trueOrFalse.html | 7 +++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index cd2bc92c..1918cd08 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -22,33 +22,45 @@ AnswerOptionSchema = new SimpleSchema({ type: Boolean, defaultValue: false }, +}); + +BooleanAnswerOptionSchema = new SimpleSchema({ + label: { + type:String, + optional:false, + allowedValues: ['True', 'False'] + }, + isCorrect:{ + type:Boolean, + defaultValue: false + } }) //this schema will validate the overall questions collection QuestionsSchema = new SimpleSchema({ id: { type: String, - optional: true + optional: false }, questionType: { type:String, - optional: true + optional: false }, quizId: { type:String, - optional: true + optional: false }, title: { type:String, - optional: true + optional: false }, description : { type:String, - optional: true + optional: false }, options : { type: [AnswerOptionSchema], - optional: true + optional: false }, saved : { @@ -82,3 +94,32 @@ QuizzesSchema = new SimpleSchema({ }); Quizzes.attachSchema(QuizzesSchema); + +/* + level: { + label: "Level", + type: String, + optional: false, + allowedValues: ['Freshman', 'Sophomore', 'Junior', 'Senior'], + autoform: { + group: studentData, + type: 'select-radio-inline' + } + }, + */ + +//schema for validation of specific question types +TrueOrFalseSchema = new SimpleSchema({ + + group:{ + label: "", + type:String, + optional: true, + allowedValues: ["True", "False"], + autoform: { + type: "select-radio" + } + } + + +}) diff --git a/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html index e9dfe8c0..7449e5a8 100644 --- a/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html +++ b/client/templates/course/lesson/quiz/questions/partials/trueOrFalse.html @@ -1,8 +1,15 @@ \ No newline at end of file diff --git a/client/templates/course/sidebar/section/lesson/lesson.js b/client/templates/course/sidebar/section/lesson/lesson.js index e350a12e..9bca0120 100644 --- a/client/templates/course/sidebar/section/lesson/lesson.js +++ b/client/templates/course/sidebar/section/lesson/lesson.js @@ -5,6 +5,7 @@ Template.sectionLesson.created = function () { // Subscribe to single section lesson this.subscribe('singleLesson', this.lessonID); this.subscribe('quizzes'); + this.subscribe('questions'); }; Template.sectionLesson.helpers({ diff --git a/server/publications/quizzes.js b/server/publications/quizzes.js index 8219ee5b..397ec1a4 100644 --- a/server/publications/quizzes.js +++ b/server/publications/quizzes.js @@ -5,3 +5,8 @@ Meteor.publish('quizzes', function () { Meteor.publish('singleQuiz', function (quizID) { return Quizzes.find({"_id": quizID}); }); + +Meteor.publish('questions', function(){ + return Questions.find(); +}); + From de75f0dd2e8b0aa4921646ecd84041bc9805341a Mon Sep 17 00:00:00 2001 From: Elena Date: Tue, 29 Dec 2015 18:38:12 +0000 Subject: [PATCH 11/27] autoform - true/false question --- both/collections/questions.js | 5 +- both/collections/quizzes.js | 2 - .../quiz/questions/questionWrapper.html | 2 +- .../lesson/quiz/questions/questionWrapper.js | 17 ++-- .../course/lesson/quiz/quiz-content.html | 19 +++- .../course/lesson/quiz/quiz-content.js | 91 ++++++++++++------- .../course/sidebar/section/lesson/lesson.js | 1 + server/methods/questions.js | 8 ++ 8 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 server/methods/questions.js diff --git a/both/collections/questions.js b/both/collections/questions.js index a54060d0..216ce7cf 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -1,11 +1,10 @@ Questions = new Mongo.Collection('questions'); -//this schema will validate the overall questions collection -//this schema will validate the overall questions collection QuestionsSchema = new SimpleSchema({ id: { type: String, - optional: false + optional: false, + unique: true }, questionType: { type:String, diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index 323fdfde..b34a1c9d 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -1,7 +1,5 @@ Quizzes = new Mongo.Collection('quizzes'); - - QuizzesSchema.AnswerOptionSchema = new SimpleSchema({ title: { type:String, diff --git a/client/templates/course/lesson/quiz/questions/questionWrapper.html b/client/templates/course/lesson/quiz/questions/questionWrapper.html index 75e99541..822ff579 100644 --- a/client/templates/course/lesson/quiz/questions/questionWrapper.html +++ b/client/templates/course/lesson/quiz/questions/questionWrapper.html @@ -2,7 +2,7 @@
{{#if isEditingCurrentCourse}} -

{{ questionIndex }} Question type: +

Question type: {{#if isTrueOrFalse}} True or False {{else}} diff --git a/client/templates/course/lesson/quiz/questions/questionWrapper.js b/client/templates/course/lesson/quiz/questions/questionWrapper.js index 58111b7d..7f24ce98 100644 --- a/client/templates/course/lesson/quiz/questions/questionWrapper.js +++ b/client/templates/course/lesson/quiz/questions/questionWrapper.js @@ -1,22 +1,21 @@ Template.questionWrapper.helpers({ isMultipleAnswer: function(){ console.log("is multiple answer"); - console.log(Template.currentData()); - console.log(Template.parentData()); - console.log(this); - var question = Template.currentData().question; - return question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + console.log( Session.get("currentQuestionToBuild")); + + var question = Session.get("currentQuestionToBuild");; + return question? question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS : false; }, isSingleAnswer: function(){ - var question = Template.currentData().question; - return question.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; + var question = Session.get("currentQuestionToBuild");; + return question? question.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER : false; }, isTrueOrFalse: function(){ - var question = Template.currentData().question; + var question = Session.get("currentQuestionToBuild");; console.log(" is true of false"); console.log( question ); - return question.questionType == QuizOptions.TRUE_OR_FALSE; + return question ? question.questionType == QuizOptions.TRUE_OR_FALSE : false; }, questionIndex: function(){ diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index 34d66e74..f0506922 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -26,12 +26,23 @@

{{/if}}
- {{#each question in questions }} - {{>questionWrapper question=question }} + {{#if currentQuestionToBuild}} + {{>questionWrapper question=currentQeustionToBuild }}
- {{> quickForm collection="Questions" id="insertPostForm" type="insert"}} - {{/each}} + {{#autoForm collection="Questions" + id="insertPostForm" type="method" meteormethod="addQuestion" doc=currentQuestionToBuild validation="keyup"}} +
+ {{> afQuickField name='title'}} + {{> afQuickField name='description' rows=3}} + {{> afQuickField name="quizId" value=quizId}} + {{> afQuickField name="questionType" value=qType}} + {{> afQuickField name="id" value=questionId}} +
+ + {{/autoForm}} + {{/if}} +
diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index 74778dbc..4c7dce68 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -13,44 +13,71 @@ Template.quizContent.helpers({ return QuizOptions.QUESTION_TYPES; }, - questions: function(){ - - //bind to a reactive var updates - Template.instance().quizQuestions.get(); - - var activeQuiz = Template.currentData().activeQuiz; - return activeQuiz.questions; + currentQuestionToBuild:function(){ + return Session.get("currentQuestionToBuild"); }, - addQuestionButtonDisabled: function(){ - - return Template.instance().addQuestionButtonDisabled.get() == true; - }, + isMultipleAnswer: function(){ - submitButtonLabel: function(){ - //return Blaze._globalHelpers['isEditingCurrentCourse']() == true ? "Save" : "Submit"; - return "Add to Quiz" - }, + var editedQuestion = Session.get("currentQuestionToBuild"); + console.log(" IS MULTIPLE ANSWERS"); + console.log(Session.get("currentQuestionToBuild")); - isMultipleAnswer: function(){ + if (editedQuestion) + { + return editedQuestion.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; + } + return false; - console.log(Template.instance().data) - var question = Template.instance().data; - return question.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; }, isSingleAnswer: function(){ - var question = Template.instance().data; - return question.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; + console.log(" IS SINGLE ANSWER"); + var editedQuestion = Session.get("currentQuestionToBuild"); + console.log(Session.get("currentQuestionToBuild")); + if (editedQuestion) + { + return editedQuestion.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; + } + return false; }, isTrueOrFalse: function(){ - var question = Template.instance().data; - return question.questionType == QuizOptions.TRUE_OR_FALSE; + var editedQuestion = Session.get("currentQuestionToBuild"); + console.log(" IS TRUE OR FALSE"); + console.log(Session.get("currentQuestionToBuild")); + if (editedQuestion) + { + return editedQuestion.questionType == QuizOptions.TRUE_OR_FALSE;; + } + return false; + }, + + quizId: function(){ + var editedQuestion = Session.get("currentQuestionToBuild"); + if (editedQuestion) + { + return editedQuestion.quizId + } + return null; + }, + questionId: function(){ + var editedQuestion = Session.get("currentQuestionToBuild"); + if (editedQuestion) + { + return editedQuestion.id; + } + return null; }, - questionIndex: function(){ - return Template.currentData().index + 1; + qType: function(){ + var editedQuestion = Session.get("currentQuestionToBuild"); + if (editedQuestion) + { + return editedQuestion.questionType; + } + return null; } + }); Template.quizContent.events({ @@ -58,21 +85,23 @@ Template.quizContent.events({ Template.instance().addQuestionButtonDisabled.set(false); var activeQuiz = Template.currentData().activeQuiz; + console.log("on change, activeQuiz"); + console.log(activeQuiz); + var question = new Object();// new QuizQuestion(); question.quizId = activeQuiz._id; question.id = Random.id(); //assign an id to the question - need this for checking and validating answers question.questionType = $('#questionTypesSelector').val(); - question.saved = false; - question.answered = false; question.description = ""; question.title = ""; question.options = []; - activeQuiz.addNewQuestion(question); + console.log("new form should contain a question template : ") + console.log(question); + + $('#questionTypesSelector :first-child').prop('selected', true); - Template.instance().quizQuestions.set(activeQuiz.questions); - Template.instance().addQuestionButtonDisabled.set(true); - $('#questionTypesSelector :first-child').prop('selected', true) + Session.set("currentQuestionToBuild", question); }, 'click .submit-quiz-btn': function(event){ diff --git a/client/templates/course/sidebar/section/lesson/lesson.js b/client/templates/course/sidebar/section/lesson/lesson.js index 9bca0120..0d4a074a 100644 --- a/client/templates/course/sidebar/section/lesson/lesson.js +++ b/client/templates/course/sidebar/section/lesson/lesson.js @@ -2,6 +2,7 @@ Template.sectionLesson.created = function () { // Save lesson ID as instance variable this.lessonID = this.data; + AutoForm.debug(); // Subscribe to single section lesson this.subscribe('singleLesson', this.lessonID); this.subscribe('quizzes'); diff --git a/server/methods/questions.js b/server/methods/questions.js new file mode 100644 index 00000000..bbe94cf2 --- /dev/null +++ b/server/methods/questions.js @@ -0,0 +1,8 @@ +Meteor.methods({ + 'addQuestion': function( question){ + + console.log(" METEOR METHODS add question : "); + console.log(question); + Questions.insert(question) + } +}) \ No newline at end of file From c1d82fdca1278fa0ae45e05b1103a46eb2fd45f0 Mon Sep 17 00:00:00 2001 From: Elena Date: Tue, 29 Dec 2015 19:32:54 +0000 Subject: [PATCH 12/27] added hooks for question insert --- .../course/lesson/quiz/questions/autoform.js | 14 ++++++++++++++ .../templates/course/lesson/quiz/quiz-content.html | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 client/templates/course/lesson/quiz/questions/autoform.js diff --git a/client/templates/course/lesson/quiz/questions/autoform.js b/client/templates/course/lesson/quiz/questions/autoform.js new file mode 100644 index 00000000..f4b0ff41 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/autoform.js @@ -0,0 +1,14 @@ +var addQuestionFormHooks = { + onSuccess: function(operation, result, template) { + + //clear the session cache of the currently edited question + Session.set("currentQuestionToBuild", null) + return sAlert.success("question added"); + }, + onError: function(operation, error, template) { + return sAlert.error(error); + }, +}; + + +AutoForm.addHooks('addQuestionForm', addQuestionFormHooks); \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index f0506922..13ef3e9b 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -31,7 +31,11 @@ {{>questionWrapper question=currentQeustionToBuild }}
{{#autoForm collection="Questions" - id="insertPostForm" type="method" meteormethod="addQuestion" doc=currentQuestionToBuild validation="keyup"}} + id="addQuestionForm" + type="method" meteormethod="addQuestion" + doc=currentQuestionToBuild + validation="keyup" + resetOnSuccess=true}}
{{> afQuickField name='title'}} {{> afQuickField name='description' rows=3}} From febfb5fb5de68481434032f71e45107250e2d070 Mon Sep 17 00:00:00 2001 From: Elena Date: Tue, 29 Dec 2015 20:11:02 +0000 Subject: [PATCH 13/27] options for true/false questions --- both/collections/questions.js | 21 ++++++++++++--- both/collections/quizzes.js | 26 ------------------- .../course/lesson/quiz/quiz-content.html | 2 ++ 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/both/collections/questions.js b/both/collections/questions.js index 216ce7cf..2f1bb78f 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -23,10 +23,25 @@ QuestionsSchema = new SimpleSchema({ optional: false }, options : { - type: [QuizzesSchema.TrueOrFalseSchema], - optional: true - }, + type: String, + optional: false, + autoform: { + type: "select-radio", + options: function(){ + return[ + { + label: "True", + value: "true" + }, + { + label: "False", + value: "false" + } + ] + } + } + }, }); Questions.attachSchema(QuestionsSchema); diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index b34a1c9d..f44d2679 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -12,31 +12,6 @@ QuizzesSchema.AnswerOptionSchema = new SimpleSchema({ }, }); -QuizzesSchema.TrueOrFalseSchema = new SimpleSchema({ - - group:{ - label: "", - type:String, - optional: true, - allowedValues: ["True", "False"], - autoform: { - type: "select-radio" - } - } -}) - -QuizzesSchema.BooleanAnswerOptionSchema = new SimpleSchema({ - label: { - type:String, - optional:false, - allowedValues: ['True', 'False'] - }, - isCorrect:{ - type:Boolean, - defaultValue: false - } -}) - //this schema will validate the overall questions collection QuizzesSchema.QuestionsSchema = new SimpleSchema({ id: { @@ -84,7 +59,6 @@ QuizzesSchema.QuizzesSchema = new SimpleSchema({ max: 140 }, questions: { - //type: [Object], type: [QuizzesSchema.QuestionsSchema], optional: true }, diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index 13ef3e9b..d0e68c5b 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -32,6 +32,7 @@
{{#autoForm collection="Questions" id="addQuestionForm" + schema=QuestionsSchema type="method" meteormethod="addQuestion" doc=currentQuestionToBuild validation="keyup" @@ -39,6 +40,7 @@
{{> afQuickField name='title'}} {{> afQuickField name='description' rows=3}} + {{> afFormGroup name="options" type="select-radio"}} {{> afQuickField name="quizId" value=quizId}} {{> afQuickField name="questionType" value=qType}} {{> afQuickField name="id" value=questionId}} From 867f44dc391e2d05719bef690a5071b08103f945 Mon Sep 17 00:00:00 2001 From: Elena Date: Wed, 30 Dec 2015 10:16:27 +0000 Subject: [PATCH 14/27] true false schema --- both/collections/questions.js | 4 ++-- both/collections/quizzes.js | 4 ++-- client/templates/course/lesson/quiz/questions/autoform.js | 8 ++++++++ client/templates/course/lesson/quiz/quiz-content.html | 6 ++---- client/templates/course/lesson/quiz/quiz-content.js | 2 ++ server/methods/questions.js | 3 +-- 6 files changed, 17 insertions(+), 10 deletions(-) diff --git a/both/collections/questions.js b/both/collections/questions.js index 2f1bb78f..f1e88625 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -1,6 +1,6 @@ Questions = new Mongo.Collection('questions'); -QuestionsSchema = new SimpleSchema({ +TrueFalseQuestionSchema = new SimpleSchema({ id: { type: String, optional: false, @@ -44,4 +44,4 @@ QuestionsSchema = new SimpleSchema({ }, }); -Questions.attachSchema(QuestionsSchema); +Questions.attachSchema(TrueFalseQuestionSchema); diff --git a/both/collections/quizzes.js b/both/collections/quizzes.js index f44d2679..9d81d209 100644 --- a/both/collections/quizzes.js +++ b/both/collections/quizzes.js @@ -13,7 +13,7 @@ QuizzesSchema.AnswerOptionSchema = new SimpleSchema({ }); //this schema will validate the overall questions collection -QuizzesSchema.QuestionsSchema = new SimpleSchema({ +QuizzesSchema.TrueFalseQuestionSchema = new SimpleSchema({ id: { type: String, optional: false @@ -59,7 +59,7 @@ QuizzesSchema.QuizzesSchema = new SimpleSchema({ max: 140 }, questions: { - type: [QuizzesSchema.QuestionsSchema], + type: [QuizzesSchema.TrueFalseQuestionSchema], optional: true }, diff --git a/client/templates/course/lesson/quiz/questions/autoform.js b/client/templates/course/lesson/quiz/questions/autoform.js index f4b0ff41..895e1389 100644 --- a/client/templates/course/lesson/quiz/questions/autoform.js +++ b/client/templates/course/lesson/quiz/questions/autoform.js @@ -1,4 +1,12 @@ var addQuestionFormHooks = { + + before: { + method: function(doc){ + doc.quizId = Template.parentData().activeQuiz._id; + doc.id = Random.id(); + return doc; + } + }, onSuccess: function(operation, result, template) { //clear the session cache of the currently edited question diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index d0e68c5b..5d9c0c7b 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -32,7 +32,7 @@
{{#autoForm collection="Questions" id="addQuestionForm" - schema=QuestionsSchema + schema=TrueFalseQuestionSchema type="method" meteormethod="addQuestion" doc=currentQuestionToBuild validation="keyup" @@ -41,9 +41,7 @@ {{> afQuickField name='title'}} {{> afQuickField name='description' rows=3}} {{> afFormGroup name="options" type="select-radio"}} - {{> afQuickField name="quizId" value=quizId}} - {{> afQuickField name="questionType" value=qType}} - {{> afQuickField name="id" value=questionId}} + {{> afQuickField name="questionType" value=qType type="hidden"}}
{{/autoForm}} diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index 4c7dce68..a82bd7f3 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -4,6 +4,8 @@ Template.quizContent.created = function(){ this.quizValidator = new ReactiveVar({}); }; +AutoForm.debug(); + Template.quizContent.helpers({ currentQuiz: function(){ return Template.currentData().activeQuiz; diff --git a/server/methods/questions.js b/server/methods/questions.js index bbe94cf2..72621513 100644 --- a/server/methods/questions.js +++ b/server/methods/questions.js @@ -1,8 +1,7 @@ Meteor.methods({ - 'addQuestion': function( question){ + 'addQuestion': function( question, params){ console.log(" METEOR METHODS add question : "); - console.log(question); Questions.insert(question) } }) \ No newline at end of file From e0bba16f581c24e5855305bf426df8e6ccdbfe79 Mon Sep 17 00:00:00 2001 From: Elena Date: Wed, 30 Dec 2015 16:11:34 +0000 Subject: [PATCH 15/27] added list of all options to the schema --- both/collections/questions.js | 41 +++++++++++++ {lib => both}/quizModel.js | 4 +- .../course/lesson/quiz/questions/autoform.js | 4 ++ .../course/lesson/quiz/quiz-content.html | 57 ++++++++++++++----- .../course/lesson/quiz/quiz-content.js | 38 +++++++++---- 5 files changed, 117 insertions(+), 27 deletions(-) rename {lib => both}/quizModel.js (97%) diff --git a/both/collections/questions.js b/both/collections/questions.js index f1e88625..7c5ef1cc 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -1,5 +1,36 @@ Questions = new Mongo.Collection('questions'); +SingleOptionQuestionSchema = new SimpleSchema({ + id: { + type: String, + optional: false, + unique: true + }, + questionType: { + type:String, + optional: false + }, + quizId: { + type:String, + optional: false + }, + title: { + type:String, + optional: false + }, + description : { + type:String, + optional: false + }, + numberOfOptions: { + + type: Number, + optional: true, + max: 10, + min: 2 + } +}) + TrueFalseQuestionSchema = new SimpleSchema({ id: { type: String, @@ -22,6 +53,16 @@ TrueFalseQuestionSchema = new SimpleSchema({ type:String, optional: false }, + numberOfOptions: { + type: Number, + optional: true, + max: 10, + min: 2 + }, + optionTitles: { + type: [String], + optional: false + }, options : { type: String, optional: false, diff --git a/lib/quizModel.js b/both/quizModel.js similarity index 97% rename from lib/quizModel.js rename to both/quizModel.js index 1bb45e5a..e8c578f3 100644 --- a/lib/quizModel.js +++ b/both/quizModel.js @@ -73,8 +73,8 @@ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER = "Multiple Choice - single answer"; QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS = "Multiple Choice - multiple answers"; QuizOptions.TRUE_OR_FALSE = "True or False"; QuizOptions.QUESTION_TYPES = - [ /* QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, - QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS,*/ + [ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, + /* QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS,*/ QuizOptions.TRUE_OR_FALSE ]; diff --git a/client/templates/course/lesson/quiz/questions/autoform.js b/client/templates/course/lesson/quiz/questions/autoform.js index 895e1389..de562b3d 100644 --- a/client/templates/course/lesson/quiz/questions/autoform.js +++ b/client/templates/course/lesson/quiz/questions/autoform.js @@ -4,6 +4,10 @@ var addQuestionFormHooks = { method: function(doc){ doc.quizId = Template.parentData().activeQuiz._id; doc.id = Random.id(); + + if (doc.questionType == QuizOptions.TRUE_OR_FALSE){ + doc.optionTitles = ["True", "False"]; + } return doc; } }, diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index 5d9c0c7b..a6abf5c4 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -30,21 +30,48 @@ {{#if currentQuestionToBuild}} {{>questionWrapper question=currentQeustionToBuild }}
- {{#autoForm collection="Questions" - id="addQuestionForm" - schema=TrueFalseQuestionSchema - type="method" meteormethod="addQuestion" - doc=currentQuestionToBuild - validation="keyup" - resetOnSuccess=true}} -
- {{> afQuickField name='title'}} - {{> afQuickField name='description' rows=3}} - {{> afFormGroup name="options" type="select-radio"}} - {{> afQuickField name="questionType" value=qType type="hidden"}} -
- - {{/autoForm}} + {{#if isTrueOrFalse }} + {{#autoForm collection="Questions" + id="addQuestionForm" + schema=TrueFalseQuestionSchema + type="method" meteormethod="addQuestion" + doc=currentQuestionToBuild + validation="keyup" + resetOnSuccess=true}} +
+ {{> afQuickField name='title'}} + {{> afQuickField name='description' rows=3}} + {{> afFormGroup name="options" type="select-radio"}} + {{> afQuickField name="questionType" value=qType type="hidden"}} + +
+ + {{/autoForm}} + {{/if}} + + {{#if isSingleAnswer}} + {{#autoForm collection="Questions" + id="addSingleAnswerQuestionForm" + schema=SingleOptionQuestionSchema + type="method" meteormethod="addSingleAnswerQuestion" + doc=currentQuestionToBuild + resetOnSuccess=true}} +
+ {{> afQuickField name='title'}} + {{> afQuickField name='description' rows=3}} + {{> afQuickField class="js-number-of-options" name="numberOfElements" type="select" + options=selectDropdownOptions + firstOption=" -- Select a number of options to chose from -- "}} + {{> afQuickField name="questionType" value=qType type="hidden"}} + {{#each currentSelectionNumberOfChoices }} +
blah blah blah
+ {{/each}} +
{{ currentSelectionNumberOfChoices }}
+
+ + {{/autoForm}} + + {{/if}} {{/if}} diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index a82bd7f3..ff90c96a 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -78,7 +78,30 @@ Template.quizContent.helpers({ return editedQuestion.questionType; } return null; - } + }, + + selectDropdownOptions: function(){ + return [ + {label: "2 choices", value: 2}, + {label: "3 choices", value: 3}, + {label: "4 choices", value: 4}, + {label: "5 choices", value: 5}, + {label: "6 choices", value: 6}, + {label: "7 choices", value: 7}, + {label: "8 choices", value: 8} + ] + }, + currentSelectionNumberOfChoices: function() { + var formId = AutoForm.getFormId(); + var selection = AutoForm.getFieldValue("numberOfElements", formId); + var selectionDropDown = $('.js-number-of-options'); + var numOfOptions = parseInt(selectionDropDown.val()); + var optionsArray = []; + for (var i=0; i < numOfOptions; i++){ + optionsArray.push(i); + } + return optionsArray; + }, }); @@ -86,10 +109,6 @@ Template.quizContent.events({ 'change #questionTypesSelector': function(event){ Template.instance().addQuestionButtonDisabled.set(false); var activeQuiz = Template.currentData().activeQuiz; - - console.log("on change, activeQuiz"); - console.log(activeQuiz); - var question = new Object();// new QuizQuestion(); question.quizId = activeQuiz._id; question.id = Random.id(); //assign an id to the question - need this for checking and validating answers @@ -98,14 +117,15 @@ Template.quizContent.events({ question.title = ""; question.options = []; - console.log("new form should contain a question template : ") - console.log(question); - $('#questionTypesSelector :first-child').prop('selected', true); Session.set("currentQuestionToBuild", question); }, + 'change .js-number-of-options': function(event){ + + }, + 'click .submit-quiz-btn': function(event){ var isPreview = Blaze._globalHelpers['isEditingCurrentCourse']() == false; @@ -122,8 +142,6 @@ Template.quizContent.events({ } if (questions != undefined){ - console.log("updating quiz with questions"); - console.log(questions); var quizToUpdate = Quizzes.findOne({_id: activeQuiz._id}); Quizzes.update(activeQuiz._id, {$set: {'questions': questions}}) From bec302f97e45f593f00e5607c587381398918625 Mon Sep 17 00:00:00 2001 From: Elena Date: Sun, 3 Jan 2016 12:05:03 +0000 Subject: [PATCH 16/27] autoform work for quiz --- both/collections/questions.js | 38 ++++++++++++++++++- .../course/lesson/quiz/questions/autoform.js | 26 ++++++++++++- .../autoform/afFieldRadioWithTextInput.html | 11 ++++++ .../autoform/afFieldRadioWithTextInput.js | 22 +++++++++++ .../course/lesson/quiz/quiz-content.html | 19 ++++++---- .../course/lesson/quiz/quiz-content.js | 22 +++++++++-- server/methods/questions.js | 4 ++ 7 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html create mode 100644 client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js diff --git a/both/collections/questions.js b/both/collections/questions.js index 7c5ef1cc..c964e326 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -28,6 +28,37 @@ SingleOptionQuestionSchema = new SimpleSchema({ optional: true, max: 10, min: 2 + }, + optionTitles: { + label: "Options", + type: [Object], + optional: false, + autoform: { + type: "radio-with-text-input" + }, + custom: function(){ + console.log("THIS IS FROM CUSTOM VALIDATION"); + return "OPTION TITLES field not validated !!!" + } + }, + + "optionTitles.$.title": { + type:String, + optional: false + }, + + "optionTitles.$.isSelected": { + type:String, + optional: false + }, + + + options:{ + label: "Options", + type: [Object], + autoform: { + type: "radio-with-text-input" + } } }) @@ -50,6 +81,7 @@ TrueFalseQuestionSchema = new SimpleSchema({ optional: false }, description : { + label: "My Description", type:String, optional: false }, @@ -61,9 +93,10 @@ TrueFalseQuestionSchema = new SimpleSchema({ }, optionTitles: { type: [String], - optional: false + optional: false, }, options : { + label: "Answer options", type: String, optional: false, autoform: { @@ -85,4 +118,5 @@ TrueFalseQuestionSchema = new SimpleSchema({ }, }); -Questions.attachSchema(TrueFalseQuestionSchema); +//Questions.attachSchema(TrueFalseQuestionSchema); +Questions.attachSchema(SingleOptionQuestionSchema); diff --git a/client/templates/course/lesson/quiz/questions/autoform.js b/client/templates/course/lesson/quiz/questions/autoform.js index de562b3d..0ece313e 100644 --- a/client/templates/course/lesson/quiz/questions/autoform.js +++ b/client/templates/course/lesson/quiz/questions/autoform.js @@ -22,5 +22,29 @@ var addQuestionFormHooks = { }, }; +var addSingleAnswerFormHooks = { + before: { + method: function(doc, params){ + doc.quizId = Template.parentData().activeQuiz._id; + doc.id = Random.id(); + + console.log("before hooks"); + console.log(doc); + console.log(Template.currentData()); + return doc; + } + }, + onSuccess: function(operation, result, template) { + + //clear the session cache of the currently edited question + Session.set("currentQuestionToBuild", null) + return sAlert.success("question added"); + }, + onError: function(operation, error, template) { + return sAlert.error(error); + }, +} + -AutoForm.addHooks('addQuestionForm', addQuestionFormHooks); \ No newline at end of file +AutoForm.addHooks('addQuestionForm', addQuestionFormHooks); +AutoForm.addHooks('addSingleAnswerQuestionForm', addSingleAnswerFormHooks); \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html new file mode 100644 index 00000000..6b92d8eb --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js new file mode 100644 index 00000000..045519b1 --- /dev/null +++ b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js @@ -0,0 +1,22 @@ +AutoForm.addInputType("radio-with-text-input", { + template: "afFieldRadioWithTextInput", + valueOut: function(){ + console.log("from the custom template this ; "); + console.log(this); + return "some string"; + }, + + valueIn: function(val){ + + for (var i in val){ + val[i].title = val[i].title + " _append"; + } + return val; + }, + contextAdjust: function(context){ + + console.log(" ---- context"); + console.log(context); + return context; + } +}) \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index a6abf5c4..6427d563 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -36,7 +36,6 @@ schema=TrueFalseQuestionSchema type="method" meteormethod="addQuestion" doc=currentQuestionToBuild - validation="keyup" resetOnSuccess=true}}
{{> afQuickField name='title'}} @@ -52,21 +51,27 @@ {{#if isSingleAnswer}} {{#autoForm collection="Questions" id="addSingleAnswerQuestionForm" - schema=SingleOptionQuestionSchema type="method" meteormethod="addSingleAnswerQuestion" doc=currentQuestionToBuild resetOnSuccess=true}}
{{> afQuickField name='title'}} {{> afQuickField name='description' rows=3}} - {{> afQuickField class="js-number-of-options" name="numberOfElements" type="select" + {{> afQuickField class="js-number-of-options" name="numberOfOptions" type="select" options=selectDropdownOptions firstOption=" -- Select a number of options to chose from -- "}} {{> afQuickField name="questionType" value=qType type="hidden"}} - {{#each currentSelectionNumberOfChoices }} -
blah blah blah
- {{/each}} -
{{ currentSelectionNumberOfChoices }}
+ + + {{#if currentSelectionNumberOfChoices }} + {{> afFieldInput + name="optionTitles" + type="radio-with-text-input" + data-schema-key="optionTitles" + }} + + {{/if}} +
{{/autoForm}} diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index ff90c96a..84578317 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -93,13 +93,27 @@ Template.quizContent.helpers({ }, currentSelectionNumberOfChoices: function() { var formId = AutoForm.getFormId(); - var selection = AutoForm.getFieldValue("numberOfElements", formId); + var selection = AutoForm.getFieldValue("numberOfOptions", formId); var selectionDropDown = $('.js-number-of-options'); var numOfOptions = parseInt(selectionDropDown.val()); - var optionsArray = []; - for (var i=0; i < numOfOptions; i++){ - optionsArray.push(i); + var optionsArray; + if (numOfOptions > 0){ + optionsArray = []; + for (var i=0; i < numOfOptions; i++){ + var obj = { + "title": "some title", + "isSelected": true + } + optionsArray.push(obj); + } + var editedQuestion = Session.get("currentQuestionToBuild"); + editedQuestion.optionTitles = optionsArray; + Session.set("currentQuestionToBuild", editedQuestion); } + + console.log("optoins array : "); + console.log(optionsArray); + return optionsArray; }, diff --git a/server/methods/questions.js b/server/methods/questions.js index 72621513..336e9339 100644 --- a/server/methods/questions.js +++ b/server/methods/questions.js @@ -3,5 +3,9 @@ Meteor.methods({ console.log(" METEOR METHODS add question : "); Questions.insert(question) + }, + 'addSingleAnswerQuestion': function(question, params){ + console.log(" METEOR METHODS add SINGLE option question : "); + Questions.insert(question) } }) \ No newline at end of file From 86f2f5137f2bb4baac34c26731c087bf1dd7991c Mon Sep 17 00:00:00 2001 From: Elena Date: Sun, 3 Jan 2016 23:46:53 +0000 Subject: [PATCH 17/27] single answer question --- both/collections/questions.js | 16 ++--- .../course/lesson/quiz/questions/autoform.js | 13 ++-- .../autoform/afFieldRadioWithTextInput.html | 18 +++--- .../autoform/afFieldRadioWithTextInput.js | 57 ++++++++++++----- .../course/lesson/quiz/quiz-content.html | 27 +++++--- .../course/lesson/quiz/quiz-content.js | 63 ++++++++++++++----- 6 files changed, 130 insertions(+), 64 deletions(-) diff --git a/both/collections/questions.js b/both/collections/questions.js index c964e326..c2b3499d 100644 --- a/both/collections/questions.js +++ b/both/collections/questions.js @@ -33,13 +33,6 @@ SingleOptionQuestionSchema = new SimpleSchema({ label: "Options", type: [Object], optional: false, - autoform: { - type: "radio-with-text-input" - }, - custom: function(){ - console.log("THIS IS FROM CUSTOM VALIDATION"); - return "OPTION TITLES field not validated !!!" - } }, "optionTitles.$.title": { @@ -48,7 +41,11 @@ SingleOptionQuestionSchema = new SimpleSchema({ }, "optionTitles.$.isSelected": { - type:String, + type:Boolean, + optional: false + }, + "optionTitles.$.index":{ + type:Number, optional: false }, @@ -56,9 +53,6 @@ SingleOptionQuestionSchema = new SimpleSchema({ options:{ label: "Options", type: [Object], - autoform: { - type: "radio-with-text-input" - } } }) diff --git a/client/templates/course/lesson/quiz/questions/autoform.js b/client/templates/course/lesson/quiz/questions/autoform.js index 0ece313e..e4282d46 100644 --- a/client/templates/course/lesson/quiz/questions/autoform.js +++ b/client/templates/course/lesson/quiz/questions/autoform.js @@ -25,13 +25,14 @@ var addQuestionFormHooks = { var addSingleAnswerFormHooks = { before: { method: function(doc, params){ - doc.quizId = Template.parentData().activeQuiz._id; - doc.id = Random.id(); - console.log("before hooks"); - console.log(doc); - console.log(Template.currentData()); - return doc; + console.log(doc) + console.log(Session.get("currentQuestionToBuild")); + var editedQuestion = Session.get("currentQuestionToBuild"); + editedQuestion.title = doc.title; + editedQuestion.description = doc.description; + + return editedQuestion; } }, onSuccess: function(operation, result, template) { diff --git a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html index 6b92d8eb..64e1ef3a 100644 --- a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html +++ b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html @@ -1,11 +1,13 @@ \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js index 045519b1..db89795c 100644 --- a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js +++ b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.js @@ -1,22 +1,49 @@ -AutoForm.addInputType("radio-with-text-input", { - template: "afFieldRadioWithTextInput", - valueOut: function(){ - console.log("from the custom template this ; "); - console.log(this); - return "some string"; - }, +Template.afFieldRadioWithTextInput.helpers({ + isHidden: function(){ + var question = Session.get("currentQuestionToBuild"); + var totalQuestions = question.optionTitles; + if (totalQuestions && parseInt(this.index) < totalQuestions.length ){ + return false; + } + return true; + } +}); - valueIn: function(val){ +Template.afFieldRadioWithTextInput.events({ + 'keyup .js-answer-option-input': function(event){ + var question = Session.get("currentQuestionToBuild"); + var editedOption = this; + //update the questions - for (var i in val){ - val[i].title = val[i].title + " _append"; + var options = question.optionTitles; + + for (var i= 0; i< options.length; i++){ + if (options[i].index.toString() == editedOption.index.toString()){ + options[i].title = $(event.target).val(); + //update the session var + Session.set("currentQuestionToBuild", question); + } } - return val; + }, - contextAdjust: function(context){ - console.log(" ---- context"); - console.log(context); - return context; + 'change .js-answer-option-radio': function(event){ + var question = Session.get("currentQuestionToBuild"); + var editedOption = this; + //update the questions + + var options = question.optionTitles; + + for (var i= 0; i< options.length; i++){ + if (options[i].index.toString() == editedOption.index.toString()){ + console.log("checked : " + $(event.target).val()) + options[i].isSelected = $(event.target).val() == "on"; + //update the session var + + }else{ + options[i].isSelected = false; + } + } + Session.set("currentQuestionToBuild", question); } }) \ No newline at end of file diff --git a/client/templates/course/lesson/quiz/quiz-content.html b/client/templates/course/lesson/quiz/quiz-content.html index 6427d563..7862e1a1 100644 --- a/client/templates/course/lesson/quiz/quiz-content.html +++ b/client/templates/course/lesson/quiz/quiz-content.html @@ -52,7 +52,6 @@ {{#autoForm collection="Questions" id="addSingleAnswerQuestionForm" type="method" meteormethod="addSingleAnswerQuestion" - doc=currentQuestionToBuild resetOnSuccess=true}}
{{> afQuickField name='title'}} @@ -63,17 +62,27 @@ {{> afQuickField name="questionType" value=qType type="hidden"}} - {{#if currentSelectionNumberOfChoices }} - {{> afFieldInput - name="optionTitles" - type="radio-with-text-input" - data-schema-key="optionTitles" - }} + + {{>afFieldRadioWithTextInput index="0" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="1" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="2" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="3" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="4" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="5" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="6" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} + {{>afFieldRadioWithTextInput index="7" + totalNumQuestions=currentSelectionNumberOfChoices name="optionTitles" }} - {{/if}}
- + {{/autoForm}} {{/if}} diff --git a/client/templates/course/lesson/quiz/quiz-content.js b/client/templates/course/lesson/quiz/quiz-content.js index 84578317..dbf3ea2b 100644 --- a/client/templates/course/lesson/quiz/quiz-content.js +++ b/client/templates/course/lesson/quiz/quiz-content.js @@ -1,3 +1,23 @@ +AutoForm.addInputType("radio-with-text-input", { + template: "afFieldRadioWithTextInput", + valueOut: function(){ + console.log("from the custom template this ; "); + console.log(this); + return "some string"; + }, + + valueIn: function(val){ + + return val; + }, + contextAdjust: function(context){ + + console.log(" ---- context"); + console.log(context); + return context; + } +}); + Template.quizContent.created = function(){ this.addQuestionButtonDisabled = new ReactiveVar(true); this.quizQuestions = new ReactiveVar([]); @@ -22,9 +42,6 @@ Template.quizContent.helpers({ isMultipleAnswer: function(){ var editedQuestion = Session.get("currentQuestionToBuild"); - console.log(" IS MULTIPLE ANSWERS"); - console.log(Session.get("currentQuestionToBuild")); - if (editedQuestion) { return editedQuestion.questionType == QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS; @@ -33,9 +50,7 @@ Template.quizContent.helpers({ }, isSingleAnswer: function(){ - console.log(" IS SINGLE ANSWER"); var editedQuestion = Session.get("currentQuestionToBuild"); - console.log(Session.get("currentQuestionToBuild")); if (editedQuestion) { return editedQuestion.questionType == QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER; @@ -45,8 +60,6 @@ Template.quizContent.helpers({ isTrueOrFalse: function(){ var editedQuestion = Session.get("currentQuestionToBuild"); - console.log(" IS TRUE OR FALSE"); - console.log(Session.get("currentQuestionToBuild")); if (editedQuestion) { return editedQuestion.questionType == QuizOptions.TRUE_OR_FALSE;; @@ -96,24 +109,45 @@ Template.quizContent.helpers({ var selection = AutoForm.getFieldValue("numberOfOptions", formId); var selectionDropDown = $('.js-number-of-options'); var numOfOptions = parseInt(selectionDropDown.val()); + + var editedQuestion = Session.get("currentQuestionToBuild"); + var existingOptions = []; + if (editedQuestion && editedQuestion.optionTitles){ + existingOptions = editedQuestion.optionTitles; + } + + if(existingOptions && existingOptions.length == numOfOptions){ + //the number of options hasn't changed + return existingOptions; + } + + if (existingOptions){ + numOfOptions = Math.max(numOfOptions, existingOptions.length); + } + var optionsArray; if (numOfOptions > 0){ optionsArray = []; + for (var i=0; i < numOfOptions; i++){ - var obj = { - "title": "some title", - "isSelected": true + var option; + if(existingOptions && existingOptions.length > i){ + option = existingOptions[i]; + }else{ + option = { + "title": "", + "isSelected": false, + "index": i + } } - optionsArray.push(obj); + optionsArray.push(option); } + var editedQuestion = Session.get("currentQuestionToBuild"); editedQuestion.optionTitles = optionsArray; Session.set("currentQuestionToBuild", editedQuestion); } - console.log("optoins array : "); - console.log(optionsArray); - return optionsArray; }, @@ -130,7 +164,6 @@ Template.quizContent.events({ question.description = ""; question.title = ""; question.options = []; - $('#questionTypesSelector :first-child').prop('selected', true); Session.set("currentQuestionToBuild", question); From e1e195335ab2a4506d8b8d564815fae1e4a3ab02 Mon Sep 17 00:00:00 2001 From: Elena Date: Mon, 4 Jan 2016 16:46:13 +0000 Subject: [PATCH 18/27] form inputs for multiple choice - multiple answers question --- both/quizModel.js | 2 +- .../autoform/afFieldRadioWithTextInput.html | 18 ++++++-- .../autoform/afFieldRadioWithTextInput.js | 10 +++- .../course/lesson/quiz/quiz-content.html | 46 +++++++++---------- .../course/lesson/quiz/quiz-content.js | 11 ++++- 5 files changed, 56 insertions(+), 31 deletions(-) diff --git a/both/quizModel.js b/both/quizModel.js index e8c578f3..1b11fcba 100644 --- a/both/quizModel.js +++ b/both/quizModel.js @@ -74,7 +74,7 @@ QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS = "Multiple Choice - multiple answe QuizOptions.TRUE_OR_FALSE = "True or False"; QuizOptions.QUESTION_TYPES = [ QuizOptions.MULTIPLE_CHOICE_SINGLE_ANSWER, - /* QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS,*/ + QuizOptions.MULTIPLE_CHOICE_MULTIPLE_ANSWERS, QuizOptions.TRUE_OR_FALSE ]; diff --git a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html index 64e1ef3a..309dd50f 100644 --- a/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html +++ b/client/templates/course/lesson/quiz/questions/autoform/afFieldRadioWithTextInput.html @@ -1,10 +1,18 @@