public function subquestion(question_attempt $qa, question_display_options $options, qtype_combined_combinable_base $subq, $placeno) { $question = $subq->question; $place = $placeno + 1; $group = $question->places[$place]; $fieldname = $subq->step_data_name($question->field($place)); $value = $qa->get_last_qt_var($fieldname); $attributes = array('id' => str_replace(':', '_', $qa->get_qt_field_name($fieldname))); if ($options->readonly) { $attributes['disabled'] = 'disabled'; } $orderedchoices = $question->get_ordered_choices($group); $selectoptions = array(); foreach ($orderedchoices as $orderedchoicevalue => $orderedchoice) { $selectoptions[$orderedchoicevalue] = $orderedchoice->text; } $feedbackimage = ''; if ($options->correctness) { $response = $qa->get_last_qt_data(); if (array_key_exists($fieldname, $response)) { $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place)); $attributes['class'] = $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } } $selecthtml = html_writer::select($selectoptions, $qa->get_qt_field_name($fieldname), $value, get_string('choosedots'), $attributes) . ' ' . $feedbackimage; return html_writer::tag('span', $selecthtml, array('class' => 'control')); }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $response = $qa->get_last_qt_var('answer', ''); $inputname = $qa->get_qt_field_name('answer'); $trueattributes = array('type' => 'radio', 'name' => $inputname, 'value' => 1, 'id' => $inputname . 'true'); $falseattributes = array('type' => 'radio', 'name' => $inputname, 'value' => 0, 'id' => $inputname . 'false'); if ($options->readonly) { $trueattributes['disabled'] = 'disabled'; $falseattributes['disabled'] = 'disabled'; } // Work out which radio button to select (if any). $truechecked = false; $falsechecked = false; $responsearray = array(); if ($response) { $trueattributes['checked'] = 'checked'; $truechecked = true; $responsearray = array('answer' => 1); } else { if ($response !== '') { $falseattributes['checked'] = 'checked'; $falsechecked = true; $responsearray = array('answer' => 1); } } // Work out visual feedback for answer correctness. $trueclass = ''; $falseclass = ''; $truefeedbackimg = ''; $falsefeedbackimg = ''; if ($options->correctness) { if ($truechecked) { $trueclass = ' ' . $this->feedback_class((int) $question->rightanswer); $truefeedbackimg = $this->feedback_image((int) $question->rightanswer); } else { if ($falsechecked) { $falseclass = ' ' . $this->feedback_class((int) (!$question->rightanswer)); $falsefeedbackimg = $this->feedback_image((int) (!$question->rightanswer)); } } } $radiotrue = html_writer::empty_tag('input', $trueattributes) . html_writer::tag('label', get_string('true', 'qtype_truefalse'), array('for' => $trueattributes['id'])); $radiofalse = html_writer::empty_tag('input', $falseattributes) . html_writer::tag('label', get_string('false', 'qtype_truefalse'), array('for' => $falseattributes['id'])); $result = ''; $result .= html_writer::tag('div', $question->format_questiontext($qa), array('class' => 'qtext')); $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::tag('div', get_string('selectone', 'qtype_truefalse'), array('class' => 'prompt')); $result .= html_writer::start_tag('div', array('class' => 'answer')); $result .= html_writer::tag('div', $radiotrue . ' ' . $truefeedbackimg, array('class' => 'r0' . $trueclass)); $result .= html_writer::tag('div', $radiofalse . ' ' . $falsefeedbackimg, array('class' => 'r1' . $falseclass)); $result .= html_writer::end_tag('div'); // Answer. $result .= html_writer::end_tag('div'); // Ablock. if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error($responsearray), array('class' => 'validationerror')); } return $result; }
/** * Output hidden form fields to clear any wrong parts of the student's response. * * This method will only be called if the question is in read-only mode. * @param question_attempt $qa the question attempt to display. * @return string HTML fragment. */ public function clear_wrong(question_attempt $qa) { $response = $qa->get_last_qt_data(); if (!$response) { return ''; } $cleanresponse = $qa->get_question()->clear_wrong_from_response($response); $output = ''; foreach ($cleanresponse as $name => $value) { $attr = array('type' => 'hidden', 'name' => $qa->get_qt_field_name($name), 'value' => s($value)); $output .= html_writer::empty_tag('input', $attr); } return $output; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $questiontext = $question->questiontextinstantiated; // Replace inputs. $inputstovaldiate = array(); $qaid = null; foreach ($question->inputs as $name => $input) { $fieldname = $qa->get_qt_field_name($name); $state = $question->get_input_state($name, $response); $questiontext = str_replace("[[input:{$name}]]", $input->render($state, $fieldname, $options->readonly), $questiontext); $feedback = $this->input_validation($fieldname . '_val', $input->render_validation($state, $fieldname)); $questiontext = str_replace("[[validation:{$name}]]", $feedback, $questiontext); $qaid = $qa->get_database_id(); if ($input->requires_validation()) { $inputstovaldiate[] = $name; } } // Replace PRTs. foreach ($question->prts as $index => $prt) { $feedback = ''; if ($options->feedback) { $feedback = $this->prt_feedback($index, $response, $qa, $options, true); } else { if (in_array($qa->get_behaviour_name(), array('interactivecountback', 'adaptivemulipart'))) { // The behaviour name test here is a hack. The trouble is that interactive // behaviour or adaptivemulipart does not show feedback if the input // is invalid, but we want to show the CAS errors from the PRT. $result = $question->get_prt_result($index, $response, $qa->get_state()->is_finished()); $feedback = html_writer::nonempty_tag('div', $result->errors, array('class' => 'stackprtfeedback stackprtfeedback-' . $name)); } } $questiontext = str_replace("[[feedback:{$index}]]", $feedback, $questiontext); } // Now format the questiontext. This should be done after the subsitutions of inputs and PRTs. $questiontext = $question->format_text(stack_maths::process_display_castext($questiontext, $this), $question->questiontextformat, $qa, 'question', 'questiontext', $question->id); // Initialise automatic validation, if enabled. if ($qaid && stack_utils::get_config()->ajaxvalidation) { $this->page->requires->yui_module('moodle-qtype_stack-input', 'M.qtype_stack.init_inputs', array($inputstovaldiate, $qaid, $qa->get_field_prefix())); } $result = ''; $result .= $this->question_tests_link($question, $options) . $questiontext; if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error($response), array('class' => 'validationerror')); } return $result; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $currentanswer = $qa->get_last_qt_var('answer'); $inputname = $qa->get_qt_field_name('answer'); $inputattributes = array('type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80, 'style' => 'display:none', 'spellcheck' => 'true'); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { $answer = $question->get_matching_answer(array('answer' => $currentanswer)); if ($answer) { $fraction = $answer->fraction; } else { $fraction = 0; } $inputattributes['class'] = $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($placeholder) { $inputinplace = html_writer::tag('label', get_string('answer'), array('for' => $inputattributes['id'], 'class' => 'accesshide')); $inputinplace .= $input; $questiontext = substr_replace($questiontext, $inputinplace, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::tag('label', get_string('answer', 'qtype_shortanswer', html_writer::tag('span', $input, array('class' => 'answer'))), array('for' => $inputattributes['id'])); $result .= html_writer::end_tag('div'); } if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); } $formatted = " <link href=\"../../jquery-spellchecker-demo-master/js/lib/redactor/redactor.css\" rel=\"stylesheet\" />\n <link href=\"../../jquery-spellchecker-demo-master/css/bootstrap.min.css\" rel=\"stylesheet\">\n <link href=\"../../jquery-spellchecker-demo-master/css/jquery.spellchecker.css\" rel=\"stylesheet\" />\n <link href=\"../../jquery-spellchecker-demo-master/css/demos.css\" rel=\"stylesheet\" />\n \n\n<style>\n@import url('//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css');\n \n.warning {margin: 10px 0px; padding:12px;}\n.warning {color: #9F6000; background-color: #FEEFB3; font-weight:normal;}\n.warning i, {margin:10px 22px; font-size:2em;vertical-align:middle;}\n</style>\n\n \n <style type=\"text/css\">\n .redactor_toolbar li a.redactor_btn_spellchecker {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHtSURBVDjLY/j//z8DJZiBKgY49drM9J3idhLEtu+xjvea4nLNqsVspnWr2S6QmF6+Zol2ltpq5QSlmcpxijMxDABp9pjkuMuu28rIpsMi3rLZFKzIus38mm6OuqRxpf41nC5w7rOJd+i1ngnUXGLTbj7Tsskk3rbL8ppZreEu7Ry1mWpJSvHK8Uoz0TWK5U/nYIg8y8rgPsl+l12P1WqgbTPdJtk/AtoWb1CkBdagnqyyWilawVM/Rw/FBQyx540ZGm/eYIg8P43BdYLdSZiEcYXeTJB/TaoNroH8q5OldVIhXE5SKUqhXSNRfZdKvPKVkOrED+L9d/8wN998w+B4XIL40I48K8FQf/O6+7In/7mbb35hsD2qjBKNDLU3ExjKb7pi1Rx61ke89+6fwBVP/jPXXn/HYHlYGiMdMJTe1JJc/PgHQ/X1xQyplznBYuFnmRiiz062nPfof8DSJ/8ZSq8/ZzA9KIEzIQE1Vvuuf/6fufv2M4bgsz4MxVdPui8Cal4C1Jx/+RGDPqpmTANiz7MAvXI+bO2L/5ZzHvzP2Pjif8DCx/8ZMi/fY9DcL0FUUmbwPKkg3Hr7T+WOV//95j/8z5B6/jaD6l4JkvIC0J9FTtPu/2dIPn+PQXG3BFmZiUFzbweDLH7NVMmNAOGld33BRiNUAAAAAElFTkSuQmCC) !important;\n background-repeat: no-repeat;\n background-position: center center;\n }\n </style>\n\n <script type=\"text/javascript\">\n var _gaq = _gaq || [];\n _gaq.push(['_setAccount', 'UA-1636725-34']);\n _gaq.push(['_trackPageview']);\n (function() {\n var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n\n })();\n </script>\n\n\n \n\n \n \n\n <div class=\"container\" id=\"spellarea\" style=\"width: 100%;\">\n \n\n <div class=\"row-fluid\">\n \n\n <div class=\"tab-content\">\n\n<div class=\"warning\"> <i class=\"fa fa-warning\"></i> (Cheque a grafia correta das palavras)</div>\n\n <div class=\"tab-pane active\" id=\"demo\">\n <textarea id=\"text-area\" class=\"textarea\" style=\"width:90%\" rows=\"10\">\n <p id='answer'> Suua Resposta </p>\n </textarea>\n </script> \n\n\n\n </div>\n <div class=\"tab-pane\" id=\"usage\">\n\n <p>Include the neccessary files:</p>\n <pre class=\"prettyprint linenums\">\n<link rel=\"stylesheet\" href=\"redactor/redactor.css\" />\n<link rel=\"stylesheet\" href=\"jquery.spellchecker.css\" />\n\n<script src=\"../../jquery-spellchecker-demo-master/js/jquery-1.8.2.min.js\"></script>\n<script src=\"../../jquery-spellchecker-demo-master/js/jquery.spellchecker.js\"></script>\n<script src=\"../../redactor/redactor.min.js\"></script></pre>\n <p>Add the following CSS:</p>\n <pre class=\"prettyprint linenums lang-css\">\n.redactor_toolbar li a.redactor_btn_spellchecker {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHtSURBVDjLY/j//z8DJZiBKgY49drM9J3idhLEtu+xjvea4nLNqsVspnWr2S6QmF6+Zol2ltpq5QSlmcpxijMxDABp9pjkuMuu28rIpsMi3rLZFKzIus38mm6OuqRxpf41nC5w7rOJd+i1ngnUXGLTbj7Tsskk3rbL8ppZreEu7Ry1mWpJSvHK8Uoz0TWK5U/nYIg8y8rgPsl+l12P1WqgbTPdJtk/AtoWb1CkBdagnqyyWilawVM/Rw/FBQyx540ZGm/eYIg8P43BdYLdSZiEcYXeTJB/TaoNroH8q5OldVIhXE5SKUqhXSNRfZdKvPKVkOrED+L9d/8wN998w+B4XIL40I48K8FQf/O6+7In/7mbb35hsD2qjBKNDLU3ExjKb7pi1Rx61ke89+6fwBVP/jPXXn/HYHlYGiMdMJTe1JJc/PgHQ/X1xQyplznBYuFnmRiiz062nPfof8DSJ/8ZSq8/ZzA9KIEzIQE1Vvuuf/6fufv2M4bgsz4MxVdPui8Cal4C1Jx/+RGDPqpmTANiz7MAvXI+bO2L/5ZzHvzP2Pjif8DCx/8ZMi/fY9DcL0FUUmbwPKkg3Hr7T+WOV//95j/8z5B6/jaD6l4JkvIC0J9FTtPu/2dIPn+PQXG3BFmZiUFzbweDLH7NVMmNAOGld33BRiNUAAAAAElFTkSuQmCC) !important;\n background-repeat: no-repeat;\n background-position: center center;\n}</pre>\n<p>Create the spellchecker plugin and init the Reactor editor:</p>\n\n <pre class=\"prettyprint linenums\">\n</pre>\n </div></div></div>\n\n </div> <!-- /container -->\n\n <script src=\"../../jquery-spellchecker-demo-master/js/lib/jquery/jquery-1.8.2.min.js\"></script>\n <script src=\"../../jquery-spellchecker-demo-master/js/lib/redactor/redactor.min.js\"></script>\n <script src=\"../../jquery-spellchecker-demo-master/js/lib/bootstrap/bootstrap.min.js\"></script>\n <script src=\"../../jquery-spellchecker-demo-master/js/lib/prettyprint/prettyprint.js\"></script>\n <script src=\"../../jquery-spellchecker-demo-master/js/jquery.spellchecker.js\"></script>\n\n <script>\n(function() {\n var update = function(){\n try{\n var answer = document.getElementById(\"answer\").innerHTML.trim();\n\n// document.getElementById(\"answer\").innerHTML = ' ' +answer;\n// answer = document.getElementById(\"answer\").innerHTML.trim();\n\n\nvar is_chrome = window.chrome;\nconsole.log(is_chrome);\n \n if (typeof is_chrome != 'undefined'){\n //document.getElementById(\"answer\").innerHTML = \" - \";\ndocument.getElementById(\"answer\").innerHTML = ' ' +answer;\nanswer = document.getElementById(\"answer\").innerHTML.trim();\n }\n\n var tmp = document.createElement(\"DIV\");\n tmp.innerHTML = answer;\n answer = tmp.textContent || tmp.innerText || \"\";\n\n document.getElementById(\"" . $inputname . "\").value = answer.trim();\n console.log( answer +\"- \"+answer.length );//document.getElementById(\"" . $inputname . "\").value);\n \n } catch (e) {}}\n\n if ( \$('input[name=\"" . $inputname . "\"]').is('[readonly]') ) {\n document.getElementById(\"" . $inputname . "\").style.display = \"block\";\n //window.alert('ok');\n document.getElementById(\"spellarea\").style.display = \"none\";\n };\n\n\n\n if (typeof window.RedactorPlugins === 'undefined') window.RedactorPlugins = {};\n \n window.RedactorPlugins.spellchecker = {\n init: function() {\n \n this.addBtn('spellchecker', 'Checar grafia das palavras!', function(obj) {\n \n obj.toggle();\n });\n },\n create: function() {\n //window.alert(document.getElementById(\"text-area\").value);\n this.spellchecker = new \$.SpellChecker(this.\$editor, {\n\n lang: 'pt-br',\n parser: 'html',\n webservice: {\n path: \"../webservices/php/SpellChecker.php\",\n driver: 'pspell'\n },\n suggestBox: {\n position: 'below'\n }\n });\n\n // var answer = document.getElementById(\"answer\").innerHTML;\n // document.getElementById(\"" . $inputname . "\").value = answer;\n // console.log( document.getElementById(\"" . $inputname . "\").value);\n update();\n\n // Bind spellchecker handler functions\n this.spellchecker.on('check.success', function() {\n alert('Sem erros de escrita!');\n });\n },\n toggle: function() {\n if (!this.spellchecker) {\n this.setBtnActive('spellchecker');\n this.create();\n this.spellchecker.check();\n } else {\n this.setBtnInactive('spellchecker');\n this.spellchecker.destroy();\n this.spellchecker = null;\n }\n //var answer = document.getElementById(\"answer\").innerHTML;\n //document.getElementById(\"" . $inputname . "\").value = answer;\n //console.log( document.getElementById(\"" . $inputname . "\").value);\n\n update();\n var classname = document.getElementsByClassName(\"words\");\n var myFunction = function() {\n setTimeout(function(){\n update();\n //var answer = document.getElementById(\"answer\").innerHTML;\n //document.getElementById(\"" . $inputname . "\").value = answer;\n //console.log( document.getElementById(\"" . $inputname . "\").value);\n }, 1000);\n \n };\n\n for(var i=0;i<classname.length;i++){\n classname[i].addEventListener('click', myFunction, false);\n }\n\n }\n };\n \n\n// Init redactor\n \$('.textarea').redactor({ \n plugins: ['spellchecker'],\n blurCallback: function(e)\n {\n //var answer = document.getElementById(\"answer\").innerHTML;\n //console.log(answer);\n //show();\n \n \n //document.getElementById(\"" . $inputname . "\").value = answer;\n \n //console.log( document.getElementById(\"" . $inputname . "\").value);\n },\n keyupCallback: function(x)\n {\n //var answer = document.getElementById(\"answer\").innerHTML;\n //console.log(answer);\n //show();\n \n update();\n //document.getElementById(\"" . $inputname . "\").value = answer;\n \n //console.log( document.getElementById(\"" . $inputname . "\").value);\n }\n\n });\n\n})();\n\n\n\$('.redactor_btn_formatting').remove();\n\$('.redactor_separator').remove();\n\$('.redactor_btn_bold').remove();\n\$('.redactor_btn_italic').remove();\n\$('.redactor_btn_html').remove();\n\$('.redactor_btn_image').remove();\n\$('.redactor_btn_table').remove();\n\$('.redactor_btn_link').remove();\n\$('.redactor_btn_fontcolor').remove();\n\$('.redactor_btn_backcolor').remove();\n\$('.redactor_btn_alignment').remove();\n\$('.redactor_btn_horizontalrule').remove();\n\$('.redactor_btn_deleted').remove();\n\$('.redactor_btn_unorderedlist').remove();\n\$('.redactor_btn_video').remove();\n\$('.redactor_btn_orderedlist').remove();\n\$('.redactor_btn_outdent').remove();\n\$('.redactor_btn_indent').remove();\n \n\n\n\n\n \n </script>\n "; $result .= $formatted; return $result; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $currentanswer = $qa->get_last_qt_var('answer'); $inputname = $qa->get_qt_field_name('answer'); $inputattributes = array('type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { $answer = $question->get_matching_answer(array('answer' => $currentanswer)); if ($answer) { $fraction = $answer->fraction; } else { $fraction = 0; } $inputattributes['class'] = $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($placeholder) { $inputinplace = html_writer::tag('label', get_string('answer'), array('for' => $inputattributes['id'], 'class' => 'accesshide')); $inputinplace .= $input; $questiontext = substr_replace($questiontext, $inputinplace, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::tag('label', get_string('answer', 'qtype_shortanswer', html_writer::tag('span', $input, array('class' => 'answer'))), array('for' => $inputattributes['id'])); $result .= html_writer::end_tag('div'); } if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); } return $result; }
/** * Displays the input control for when the student should upload a single file. * @param question_attempt $qa the question attempt to display. * @param int $numallowed the maximum number of attachments allowed. -1 = unlimited. * @param question_display_options $options controls what should and should * not be displayed. Used to get the context. */ public function files_input(question_attempt $qa, $numallowed, question_display_options $options) { global $CFG; require_once $CFG->dirroot . '/lib/form/filemanager.php'; $pickeroptions = new stdClass(); $pickeroptions->mainfile = null; $pickeroptions->maxfiles = $numallowed; $pickeroptions->itemid = $qa->prepare_response_files_draft_itemid('attachments', $options->context->id); $pickeroptions->context = $options->context; $pickeroptions->itemid = $qa->prepare_response_files_draft_itemid('attachments', $options->context->id); return form_filemanager_render($pickeroptions) . html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $qa->get_qt_field_name('attachments'), 'value' => $pickeroptions->itemid)); }
protected function box_id(question_attempt $qa, $place) { return str_replace(':', '_', $qa->get_qt_field_name($place)); }
protected function hidden_field_for_qt_var(question_attempt $qa, $varname) { $value = $qa->get_last_qt_var($varname, ''); $fieldname = $qa->get_qt_field_name($varname); $attributes = array('type' => 'hidden', 'id' => str_replace(':', '_', $fieldname), 'class' => $varname, 'name' => $fieldname, 'value' => $value); return html_writer::empty_tag('input', $attributes); }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $currentanswer = $qa->get_last_qt_var('answer'); if ($question->unitdisplay == qtype_numerical::UNITSELECT) { $selectedunit = $qa->get_last_qt_var('unit'); } else { $selectedunit = null; } $inputname = $qa->get_qt_field_name('answer'); $inputattributes = array( 'type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80, ); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { list($value, $unit) = $question->ap->apply_units($currentanswer, $selectedunit); $answer = $question->get_matching_answer($value); if ($answer) { $fraction = $question->apply_unit_penalty($answer->fraction, $unit); } else { $fraction = 0; } $inputattributes['class'] = $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($question->unitdisplay == qtype_numerical::UNITSELECT) { $unitselect = html_writer::select($question->ap->get_unit_options(), $qa->get_qt_field_name('unit'), $selectedunit, array(''=>'choosedots'), array('disabled' => $options->readonly)); if ($question->ap->are_units_before()) { $input = $unitselect . ' ' . $input; } else { $input = $input . ' ' . $unitselect; } } if ($placeholder) { $questiontext = substr_replace($questiontext, $input, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= get_string('answer', 'qtype_shortanswer', html_writer::tag('div', $input, array('class' => 'answer'))); $result .= html_writer::end_tag('div'); } if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); } return $result; }
protected function get_input_id(question_attempt $qa, $value) { return $qa->get_qt_field_name('answer' . $value); }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $DB; $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $question->update_current_response($response); $currentresponse = $question->currentresponse; $correctresponse = $question->correctresponse; // generate fieldnames and ids // response_fieldname : 1_response_319 // response_name : q27:1_response_319 // response_id : id_q27_1_response_319 // sortable_id : id_sortable_q27_1_response_319 $response_fieldname = $question->get_response_fieldname(); $response_name = $qa->get_qt_field_name($response_fieldname); $response_id = 'id_' . preg_replace('/[^a-zA-Z0-9]+/', '_', $response_name); $sortable_id = 'id_sortable_' . $question->id; $result = ''; if ($options->readonly || $options->correctness) { // don't allow items to be dragged and dropped } else { $script = "\n"; $script .= "//<![CDATA[\n"; $script .= "if (window.\$) {\n"; // $ is an alias for jQuery $script .= " \$(function() {\n"; $script .= " \$('#{$sortable_id}').sortable({\n"; $script .= " update: function(event, ui) {\n"; $script .= " var ItemsOrder = \$(this).sortable('toArray').toString();\n"; $script .= " \$('#{$response_id}').attr('value', ItemsOrder);\n"; $script .= " },\n"; $script .= " opacity: 0.6\n"; $script .= " });\n"; $script .= " \$('#{$sortable_id}').disableSelection();\n"; $script .= " });\n"; $script .= " \$(document).ready(function() {\n"; $script .= " var ItemsOrder = \$('#{$sortable_id}').sortable('toArray').toString();\n"; $script .= " \$('#{$response_id}').attr('value', ItemsOrder);\n"; $script .= " });\n"; $script .= "}\n"; $script .= "//]]>\n"; $result .= html_writer::tag('script', $script, array('type' => 'text/javascript')); } $result .= html_writer::tag('div', $question->format_questiontext($qa), array('class' => 'qtext')); $printeditems = false; if (count($currentresponse)) { // generate ordering items foreach ($currentresponse as $position => $answerid) { if (!array_key_exists($answerid, $question->answers)) { continue; // shouldn't happen !! } if (!array_key_exists($position, $correctresponse)) { continue; // shouldn't happen !! } if ($printeditems == false) { $printeditems = true; $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::start_tag('div', array('class' => 'answer')); $result .= html_writer::start_tag('ul', array('class' => 'sortablelist', 'id' => $sortable_id)); } if ($options->correctness) { if ($correctresponse[$position] == $answerid) { $class = 'correctposition'; $img = $this->feedback_image(1); } else { $class = 'wrongposition'; $img = $this->feedback_image(0); } $img = "{$img} "; } else { $class = 'sortableitem'; $img = ''; } // the original "id" revealed the correct order of the answers // because $answer->fraction holds the correct order number // $id = 'ordering_item_'.$answerid.'_'.intval($question->answers[$answerid]->fraction); $answer = $question->answers[$answerid]; $params = array('class' => $class, 'id' => $answer->md5key); $result .= html_writer::tag('li', $img . $answer->answer, $params); } } if ($printeditems) { $result .= html_writer::end_tag('ul'); $result .= html_writer::end_tag('div'); // answer $result .= html_writer::end_tag('div'); // ablock $result .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $response_name, 'id' => $response_id, 'value' => '')); $result .= html_writer::tag('div', '', array('style' => 'clear:both;')); } return $result; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $currentanswer = $qa->get_last_qt_var('answer'); if ($question->has_separate_unit_field()) { $selectedunit = $qa->get_last_qt_var('unit'); } else { $selectedunit = null; } $inputname = $qa->get_qt_field_name('answer'); $inputattributes = array( 'type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80, 'class' => 'form-control', ); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { list($value, $unit, $multiplier) = $question->ap->apply_units( $currentanswer, $selectedunit); $answer = $question->get_matching_answer($value, $multiplier); if ($answer) { $fraction = $question->apply_unit_penalty($answer->fraction, $answer->unitisright); } else { $fraction = 0; } $inputattributes['class'] .= ' ' . $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($question->has_separate_unit_field()) { if ($question->unitdisplay == qtype_numerical::UNITRADIO) { $choices = array(); $i = 1; foreach ($question->ap->get_unit_options() as $unit) { $id = $qa->get_qt_field_name('unit') . '_' . $i++; $radioattrs = array('type' => 'radio', 'id' => $id, 'value' => $unit, 'name' => $qa->get_qt_field_name('unit')); if ($unit == $selectedunit) { $radioattrs['checked'] = 'checked'; } $choices[] = html_writer::tag('label', html_writer::empty_tag('input', $radioattrs) . $unit, array('for' => $id, 'class' => 'unitchoice')); } $unitchoice = html_writer::tag('span', implode(' ', $choices), array('class' => 'unitchoices')); } else if ($question->unitdisplay == qtype_numerical::UNITSELECT) { $unitchoice = html_writer::label(get_string('selectunit', 'qtype_numerical'), 'menu' . $qa->get_qt_field_name('unit'), false, array('class' => 'accesshide')); $unitchoice .= html_writer::select($question->ap->get_unit_options(), $qa->get_qt_field_name('unit'), $selectedunit, array(''=>'choosedots'), array('disabled' => $options->readonly)); } if ($question->ap->are_units_before()) { $input = $unitchoice . ' ' . $input; } else { $input = $input . ' ' . $unitchoice; } } if ($placeholder) { $inputinplace = html_writer::tag('label', get_string('answer'), array('for' => $inputattributes['id'], 'class' => 'accesshide')); $inputinplace .= $input; $questiontext = substr_replace($questiontext, $inputinplace, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock form-inline')); $result .= html_writer::tag('label', get_string('answercolon', 'qtype_numerical'), array('for' => $inputattributes['id'])); $result .= html_writer::tag('span', $input, array('class' => 'answer')); $result .= html_writer::end_tag('div'); } if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer, 'unit' => $selectedunit)), array('class' => 'validationerror')); } return $result; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $currentanswerwithhint; require_once $CFG->dirroot . '/question/type/regexp/locallib.php'; $question = $qa->get_question(); $inputname = $qa->get_qt_field_name('answer'); $ispreview = !isset($options->attempt); $currentanswer = remove_blanks($qa->get_last_qt_var('answer')); $response = $qa->get_last_qt_data(); $laststep = $qa->get_reverse_step_iterator(); $hintadded = false; foreach ($qa->get_reverse_step_iterator() as $step) { $hintadded = $step->has_behaviour_var('_helps') === true; break; } $closest = find_closest($question, $currentanswer, $correct_response = false, $hintadded); $question->closest = $closest; $currentanswer = $closest[0]; //js script for showing / hiding regexp generated alternative sentences (for teacher only) if ($ispreview) { $alternateanswers = get_alternateanswers($question); $response = $question->get_correct_response(); $correctanswer = $response['answer']; $id = "showhidebutton"; echo html_writer::start_tag('div'); echo html_writer::empty_tag('input', array('type' => 'button', 'value' => get_string("showalternate", "qtype_regexp"), 'id' => $id, 'name' => $id)); echo html_writer::end_tag('div'); $this->page->requires->js_init_call('M.qtype_regexp.showhidealternate', array('#' . $id, '#alternateanswers'), false, array('name' => 'qtype_regexp', 'fullpath' => '/question/type/regexp/module.js', 'requires' => array('base', 'node', 'event'), 'strings' => array(array('showalternate', 'qtype_regexp'), array('hidealternate', 'qtype_regexp')))); echo html_writer::start_tag('div', array('id' => 'alternateanswers', 'style' => 'display:none;')); echo '<hr />'; if ($question->usecase) { $case = get_string('caseyes', 'qtype_regexp'); } else { $case = get_string('caseno', 'qtype_regexp'); } echo get_string('casesensitive', 'qtype_regexp') . ' : <b>' . $case . '</b><hr />'; foreach ($alternateanswers as $key => $alternateanswer) { echo get_string('answer') . ' ' . $key . ' (' . $alternateanswer['fraction'] . ') ', '<span class="regexp">' . $alternateanswer['regexp'] . '</span>'; $list = ''; foreach ($alternateanswer['answers'] as $alternate) { $list .= '<li>' . $alternate . '</li>'; } echo '<ul class="square">' . $list . '</ul>'; } echo "<hr />"; echo html_writer::end_tag('div'); } $inputattributes = array('type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { $answer = $question->get_matching_answer(array('answer' => $currentanswer)); if ($answer) { $fraction = $answer->fraction; } else { $fraction = 0; } $inputattributes['class'] = $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($placeholder) { $questiontext = substr_replace($questiontext, $input, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= get_string('answer', 'qtype_shortanswer', html_writer::tag('div', $input, array('class' => 'answer'))); $result .= html_writer::end_tag('div'); } if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); } return $result; }
public function subquestion(question_attempt $qa, question_display_options $options, $index, question_graded_automatically $subq) { $fieldprefix = 'sub' . $index . '_'; $fieldname = $fieldprefix . 'answer'; $response = $qa->get_last_qt_var($fieldname); $inputattributes = array( 'type' => 'radio', 'name' => $qa->get_qt_field_name($fieldname), ); if ($options->readonly) { $inputattributes['disabled'] = 'disabled'; } $result = $this->all_choices_wrapper_start(); $fraction = null; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; $inputattributes['value'] = $value; $inputattributes['id'] = $inputattributes['name'] . $value; $isselected = $subq->is_choice_selected($response, $value); if ($isselected) { $inputattributes['checked'] = 'checked'; $fraction = $ans->fraction; } else { unset($inputattributes['checked']); } $class = 'r' . ($value % 2); if ($options->correctness && $isselected) { $feedbackimg = $this->feedback_image($ans->fraction); $class .= ' ' . $this->feedback_class($ans->fraction); } else { $feedbackimg = ''; } $result .= $this->choice_wrapper_start($class); $result .= html_writer::empty_tag('input', $inputattributes); $result .= html_writer::tag('label', $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ansid), array('for' => $inputattributes['id'])); $result .= $feedbackimg; if ($options->feedback && $isselected && trim($ans->feedback)) { $result .= html_writer::tag('div', $subq->format_text($ans->feedback, $ans->feedbackformat, $qa, 'question', 'answerfeedback', $ansid), array('class' => 'specificfeedback')); } $result .= $this->choice_wrapper_end(); } $result .= $this->all_choices_wrapper_end(); $feedback = array(); if ($options->feedback && $options->marks >= question_display_options::MARK_AND_MAX && $subq->maxmark > 0) { $a = new stdClass(); $a->mark = format_float($fraction * $subq->maxmark, $options->markdp); $a->max = format_float($subq->maxmark, $options->markdp); $feedback[] = html_writer::tag('div', get_string('markoutofmax', 'question', $a)); } if ($options->rightanswer) { foreach ($subq->answers as $ans) { if (question_state::graded_state_for_fraction($ans->fraction) == question_state::$gradedright) { $feedback[] = get_string('correctansweris', 'qtype_multichoice', $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ansid)); break; } } } $result .= html_writer::nonempty_tag('div', implode('<br />', $feedback), array('class' => 'outcome')); return $result; }
public function response_area_input($name, question_attempt $qa, question_attempt_step $step, $lines, $context) { $response = $step->get_qt_var($name); $inputname = $qa->get_qt_field_name($name); $textarea = $this->textarea($response, $lines, array('name' => $inputname)); $formattag = $this->get_format_tag($inputname); $countarea = $this->get_count_area_input($qa, $response); return $textarea.$formattag.$countarea; }
/** * Returns a hidden field for a qt variable * * @param object $qa Question attempt object * @param string $varname The hidden var name * @param string $value The hidden value * @param array $classes Any additional css classes to apply * @return array Array with field name and the html of the tag */ protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null, $classes = null) { if ($value === null) { $value = $qa->get_last_qt_var($varname); } $fieldname = $qa->get_qt_field_name($varname); $attributes = array('type' => 'hidden', 'id' => str_replace(':', '_', $fieldname), 'name' => $fieldname, 'value' => $value); if ($classes !== null) { $attributes['class'] = join(' ', $classes); } return array($fieldname, html_writer::empty_tag('input', $attributes) . "\n"); }
protected function get_input_name(question_attempt $qa, $value) { return $qa->get_qt_field_name('choice' . $value); }
/** * Output the content of the subquestion. * * @param question_attempt $qa * @param question_display_options $options * @param int $index * @param question_graded_automatically $subq * @return string */ public function subquestion(question_attempt $qa, question_display_options $options, $index, question_graded_automatically $subq) { if (!$subq instanceof qtype_multichoice_multi_question) { throw new coding_exception('Expecting subquestion of type qtype_multichoice_multi_question'); } $fieldprefix = 'sub' . $index . '_'; $fieldname = $fieldprefix . 'choice'; // Extract the responses that related to this question + strip off the prefix. $fieldprefixlen = strlen($fieldprefix); $response = []; foreach ($qa->get_last_qt_data() as $name => $val) { if (substr($name, 0, $fieldprefixlen) == $fieldprefix) { $name = substr($name, $fieldprefixlen); $response[$name] = $val; } } $basename = $qa->get_qt_field_name($fieldname); $inputattributes = array( 'type' => 'checkbox', 'value' => 1, ); if ($options->readonly) { $inputattributes['disabled'] = 'disabled'; } $result = $this->all_choices_wrapper_start(); // Calculate the total score (as we need to know if choices should be marked as 'correct' or 'partial'). $fraction = 0; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; if ($subq->is_choice_selected($response, $value)) { $fraction += $ans->fraction; } } // Display 'correct' answers as correct, if we are at 100%, otherwise mark them as 'partial'. $answerfraction = ($fraction > 0.999) ? 1.0 : 0.5; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; $name = $basename.$value; $inputattributes['name'] = $name; $inputattributes['id'] = $name; $isselected = $subq->is_choice_selected($response, $value); if ($isselected) { $inputattributes['checked'] = 'checked'; } else { unset($inputattributes['checked']); } $class = 'r' . ($value % 2); if ($options->correctness && $isselected) { $thisfrac = ($ans->fraction > 0) ? $answerfraction : 0; $feedbackimg = $this->feedback_image($thisfrac); $class .= ' ' . $this->feedback_class($thisfrac); } else { $feedbackimg = ''; } $result .= $this->choice_wrapper_start($class); $result .= html_writer::empty_tag('input', $inputattributes); $result .= html_writer::tag('label', $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ansid), array('for' => $inputattributes['id'])); $result .= $feedbackimg; if ($options->feedback && $isselected && trim($ans->feedback)) { $result .= html_writer::tag('div', $subq->format_text($ans->feedback, $ans->feedbackformat, $qa, 'question', 'answerfeedback', $ansid), array('class' => 'specificfeedback')); } $result .= $this->choice_wrapper_end(); } $result .= $this->all_choices_wrapper_end(); $feedback = array(); if ($options->feedback && $options->marks >= question_display_options::MARK_AND_MAX && $subq->maxmark > 0) { $a = new stdClass(); $a->mark = format_float($fraction * $subq->maxmark, $options->markdp); $a->max = format_float($subq->maxmark, $options->markdp); $feedback[] = html_writer::tag('div', get_string('markoutofmax', 'question', $a)); } if ($options->rightanswer) { $correct = []; foreach ($subq->answers as $ans) { if (question_state::graded_state_for_fraction($ans->fraction) != question_state::$gradedwrong) { $correct[] = $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ans->id); } } $correct = '<ul><li>'.implode('</li><li>', $correct).'</li></ul>'; $feedback[] = get_string('correctansweris', 'qtype_multichoice', $correct); } $result .= html_writer::nonempty_tag('div', implode('<br />', $feedback), array('class' => 'outcome')); return $result; }