/mod/hotpot/attempt/hp/6/jmix/renderer.php
PHP | 298 lines | 227 code | 17 blank | 54 comment | 14 complexity | ed0f37e00eeefb4cbe4b4d5f4b032d5f MD5 | raw file
- <?php
- // This file is part of Moodle - http://moodle.org/
- //
- // Moodle is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // Moodle is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
- /**
- * Render an attempt at a HotPot quiz
- * Output format: hp_6_jmix
- *
- * @package mod-hotpot
- * @copyright 2010 Gordon Bateson <gordon.bateson@gmail.com>
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
- defined('MOODLE_INTERNAL') || die();
- // get parent class
- require_once($CFG->dirroot.'/mod/hotpot/attempt/hp/6/renderer.php');
- class mod_hotpot_attempt_hp_6_jmix_renderer extends mod_hotpot_attempt_hp_6_renderer {
- public $icon = 'pix/f/jmx.gif';
- public $js_object_type = 'JMix';
- public $templatefile = 'jmix6.ht_';
- public $templatestrings = 'PreloadImageList|SegmentArray|AnswerArray';
- // Glossary autolinking settings
- public $headcontent_strings = 'CorrectResponse|IncorrectResponse|ThisMuchCorrect|TheseAnswersToo|YourScoreIs|NextCorrect|Segments';
- public $headcontent_arrays = '';
- public $response_num_fields = array(
- 'score', 'hints', 'checks' // remove: weighting, clues
- );
- /**
- * init
- *
- * @param xxx $quiz (passed by reference)
- */
- function init(&$quiz) {
- parent::init($quiz);
- array_push($this->javascripts, 'mod/hotpot/attempt/hp/6/jmix/jmix.js');
- }
- /**
- * fix_headcontent
- *
- * @return xxx
- */
- function fix_headcontent() {
- $this->fix_headcontent_DragAndDrop();
- // change number of drop lines if required (there is now setting for
- // this in the JMix application but it can be set in a cfg file)
- if ($drop_total = $this->expand_DropTotal()) {
- $this->headcontent = preg_replace('/(?<=var DropTotal = )\d+(?=;)/', $drop_total, $this->headcontent, 1);
- }
- // we must add a false return value to segment links in order not to trigger the onbeforeunload event handler
- // (this is only really required on v6 output format)
- $search = '/(?<='.'onclick="'.')'.'AddSegment\(\[SegmentNumber\]\)'.'(?='.'"'.')/';
- $replace = '\\0'.'; return false;';
- $this->headcontent = preg_replace($search, $replace, $this->headcontent);
- }
- /**
- * fix_bodycontent_DragAndDrop
- */
- function fix_bodycontent_DragAndDrop() {
- $search = '/for \(var i=0; i<DropTotal; i\+\+\)\{.*?\}/s';
- $replace = ''
- ."var myParentNode = null;\n"
- ."if (navigator.appName=='Microsoft Internet Explorer' && (document.documentMode==null || document.documentMode<8)) {\n"
- ." // IE8+ (compatible mode) IE7, IE6, IE5 ...\n"
- ."} else {\n"
- ." // Firefox, Safari, Opera, IE8+\n"
- ." var obj = document.getElementsByTagName('div');\n"
- ." if (obj && obj.length) {\n"
- ." myParentNode = obj[obj.length - 1].parentNode;\n"
- ." }\n"
- ."}\n"
- ."for (var i=0; i<DropTotal; i++){\n"
- ." if (myParentNode){\n"
- ." var div = document.createElement('div');\n"
- ." div.setAttribute('id', 'Drop' + i);\n"
- ." div.setAttribute('class', 'DropLine');\n"
- ." div.setAttribute('align', 'center');\n"
- ." div.innerHTML = ' <br /> ';\n"
- ." myParentNode.appendChild(div);\n"
- ." } else {\n"
- ." document.write('".'<div id="'."Drop' + i + '".'" class="DropLine" align="center"'."> <br /> </div>');\n"
- ." }\n"
- ."}"
- ;
- $this->bodycontent = preg_replace($search, $replace, $this->bodycontent, 1);
- $search = '/for \(var i=0; i<Segments\.length; i\+\+\)\{.*?\}/s';
- $replace = ''
- ."for (var i=0; i<Segments.length; i++){\n"
- ." if (myParentNode){\n"
- ." var div = document.createElement('div');\n"
- ." div.setAttribute('id', 'D' + i);\n"
- ." div.setAttribute('class', 'CardStyle');\n"
- ." div.setAttribute('onmousedown', 'beginDrag(event, ' + i + ')');\n"
- ." myParentNode.appendChild(div);\n"
- ." } else {\n"
- ." document.write('".'<div id="'."D' + i + '".'" class="CardStyle" onmousedown="'."beginDrag(event, ' + i + ')".'"'."></div>');\n"
- ." }\n"
- ."}\n"
- ."m = div = myParentNode = null;"
- ;
- $this->bodycontent = preg_replace($search, $replace, $this->bodycontent, 1);
- }
- /**
- * get_js_functionnames
- *
- * @return xxx
- */
- function get_js_functionnames() {
- // start list of function names
- $names = parent::get_js_functionnames();
- $names .= ($names ? ',' : '').'CheckAnswer,TimesUp';
- return $names;
- }
- /**
- * fix_js_TimesUp
- *
- * @param xxx $str (passed by reference)
- * @param xxx $start
- * @param xxx $length
- */
- function fix_js_TimesUp(&$str, $start, $length) {
- $substr = substr($str, $start, $length);
- $search = "/\s*document\.getElementById\('Timer'\)\.innerHTML = '([^']*)';/s";
- if (preg_match($search, $substr, $matches, PREG_OFFSET_CAPTURE)) {
- $msg = $matches[1][0];
- $substr = substr_replace($substr, '', $matches[0][1], strlen($matches[0][0]));
- } else {
- $msg = 'Your time is over!';
- }
- if ($pos = strrpos($substr, '}')) {
- if ($this->hotpot->delay3==hotpot::TIME_AFTEROK) {
- $flag = 1; // set form values only
- } else {
- $flag = 0; // set form values and send form
- }
- $insert = ''
- ." Finished = true;\n"
- ." HP.onunload(".hotpot::STATUS_TIMEDOUT.",$flag);\n"
- ." ShowMessage('$msg');\n"
- ;
- $substr = substr_replace($substr, $insert, $pos, 0);
- }
- $str = substr_replace($str, $substr, $start, $length);
- }
- /**
- * fix_js_CheckAnswer
- *
- * @param xxx $str (passed by reference)
- * @param xxx $start
- * @param xxx $length
- * @return xxx
- */
- function fix_js_CheckAnswer(&$str, $start, $length) {
- $substr = substr($str, $start, $length);
- // remove the premature "return" if there is no guesses, because this function
- // is also called for the "Give Up" button and the onbeforeunload() event handler
- // and in those cases we need to continue and return the results to Moodle
- $search = ''
- .'/(if \(GuessSequence\.length < 1\)\{)' // $1
- .'(.*?)' // $2
- .'\s*return;'
- .'(\s*\})' // $3
- .'/s'
- ;
- $substr = preg_replace($search, '\\1\\2\\3', $substr, 1);
- // encapsulate the main body of the function code in an "if" block
- $search = ''
- .'/(?<=var AllDone = false;)' // look behind
- .'(.*?)'
- .'(\s*)'
- .'(?=if \(\(AllDone == true\)\|\|\(TimeOver == true\)\)\{)' // look ahead
- .'/s'
- ;
- if (preg_match($search, $substr, $matches, PREG_OFFSET_CAPTURE)) {
- $replace = "\n"
- .' if (GuessSequence.length){'
- .preg_replace('/[\\n\\r]+/', '\\0 ', $matches[1][0])."\n"
- ." }\n"
- ;
- $substr = substr_replace($substr, $replace, $matches[1][1], strlen($matches[1][0]));
- }
- // add other changes as per CheckAnswers in other type of HP quiz
- $this->fix_js_CheckAnswers($substr, 0, strlen($substr));
- $str = substr_replace($str, $substr, $start, $length);
- }
- /**
- * fix_js_StartUp_DragAndDrop
- *
- * @param xxx $substr (passed by reference)
- */
- function fix_js_StartUp_DragAndDrop(&$substr) {
- // fix top and left of drag area
- $this->fix_js_StartUp_DragAndDrop_DragArea($substr);
- // restrict width of drop lines
- $search = "L[i] = new Card('Drop' + i, 0);";
- if ($pos = strpos($substr, $search)) {
- $insert = "\n\t\t"."L[i].SetW(pg.W * 0.8);";
- $substr = substr_replace($substr, $insert, $pos + strlen($search), 0);
- }
- // stretch the canvas vertically down
- if ($pos = strrpos($substr, '}')) {
- $insert = ''
- ." var b = 0;\n"
- ." var objParentNode = null;\n"
- ." if (window.Segments) {\n"
- ." var obj = document.getElementById('D'+(Segments.length-1));\n"
- ." if (obj) {\n"
- ." b = Math.max(b, getOffset(obj,'Bottom'));\n"
- ." objParentNode = objParentNode || obj.parentNode;\n"
- ." }\n"
- ." }\n"
- ." if (b) {\n"
- ." // stretch parentNodes down vertically, if necessary\n"
- ." var canvas = document.getElementById('$this->themecontainer');\n"
- ." while (objParentNode) {\n"
- ." var more_height = Math.max(0, b - getOffset(objParentNode, 'Bottom'));\n"
- ." if (more_height) {\n"
- ." setOffset(objParentNode, 'Height', getOffset(objParentNode, 'Height') + more_height + 4);\n"
- ." }\n"
- ." if (canvas && objParentNode==canvas) {\n"
- ." objParentNode = null;\n"
- ." } else {\n"
- ." objParentNode = objParentNode.parentNode;\n"
- ." }\n"
- ." }\n"
- ." }\n"
- ;
- $substr = substr_replace($substr, $insert, $pos, 0);
- }
- }
- /**
- * get_stop_function_name
- *
- * @return xxx
- */
- function get_stop_function_name() {
- return 'CheckAnswer';
- }
- /**
- * get_stop_function_args
- *
- * @return xxx
- */
- function get_stop_function_args() {
- return '0,'.hotpot::STATUS_ABANDONED;
- }
- /**
- * get_stop_function_intercept
- *
- * @return xxx
- */
- function get_stop_function_intercept() {
- return "\n"
- ." if (CheckType==0) HP.onclickCheck(); // intercept Checks\n"
- ." if (CheckType==1) HP.onclickHint(0); // intercept Hints\n"
- ;
- }
- }