Tuesday, September 24, 2013

How I managed to allow input of only 1 (one) character in a Cloze input box (Moodle 2.5)


Hi. Do you use the Cloze (also known as the multianswer) question type in Moodle 2.5? I use it a lot! 

For quite some time, I was struggling with how to limit a text box, in a Cloze question, to not more than one character of input. Well, after much searching for an answer on and almost the entire World Wide Web, I managed to do it.
INTRODUCTIONI had a quiz situation to solve. I had to create a Cloze question where the user has to type in the individual letters to complete a word. In this type of question, a box should contain at most only one letter.

I had to solve FOUR challenges/problems. 
PROBLEM ONE, each cloze input box should be small enough to look like it could only fit one letter.
PROBLEM TWO, the user should only be allowed to key in one letter inside each box. Not more than one letter. 
PROBLEM THREE, the user should be able to type continuously, the letters a, s, s, p, o, r, t and the letters should automatically be input into each successive input box.
PROBLEM FOUR, allow only letters - no spaces or punctuation symbols.
I have a nagging feeling that both problems ONE and TWO could be solved with some creative HTML/CSS and Javascript wizardary, but my desire to solve them come what may, led me to devise this core (unfortunately) code hack. Here's how I solved problems ONE and TWO:

I edited the Cloze multianswer question type file:

    Bold text indicates hacking of core code. Colors indicate how the FIRST and SECOND problems were solved.

class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_renderer_base {
   public function subquestion(question_attempt $qa, question_display_options $options,
   $index, question_graded_automatically $subq) {
   $fieldprefix = 'sub' . $index . '_';
   ... /* Lots of untouched code here! */
    if (!$matchinganswer) {
       if (is_null($response) || $response === '') {
          $matchinganswer = new question_answer(0, '', null, '', FORMAT_HTML);
       } else {
                 $matchinganswer = new question_answer(0, '', 0.0, '', FORMAT_HTML);
   // Work out a good input field size.

    /* Hack by Frankie Kam to create single character input fields */
    $AllSingleInput = true;
    foreach ($subq->answers as $ans)
         $size = strlen(trim($ans->answer));
         if($size > 1)
            $AllSingleInput = false; //I, really, should break out of the loop now!
                                                // it is, it works anyway.

    //Are all answers single character fields?

    if($AllSingleInput === true)
         //Set $size of input box to 1 initially.
         // It of course will be expanded a bit more later by the core code.
         $size = 1;

         //Set the arbitrary maximum number of characters to 1. 
         $maxlength = 1;   /* Ah, yes! This is vital to limit the */

                           /* cloze input box to just 1 length! */
       //If the logic flows here, this means that the cloze question
       // does NOT consist of ALL-single character input boxes.

       //In which case, process as usual.
         $size = max(1, textlib::strlen(trim($response)) + 1);
         foreach ($subq->answers as $ans) {
            $size = max($size, textlib::strlen(trim($ans->answer)));
         $size = min(60, round($size + rand(0, $size*0.15)));
         // The rand bit is to make guessing harder.

        //Set the arbitrary maximum number of characters to 100.
        //It it supposed to be unlimited length, but 100 characters
        //should suffice.

        $maxlength = 100;      

      $inputattributes = array(
            'type' => 'text',
            'name' => $qa->get_qt_field_name($fieldname),
            'value' => $response,
            'id' => $qa->get_qt_field_name($fieldname),
            'size' => $size,
            /* The below line was added by Frankie! On 25th September 2013 */

            /* The line below does the trick! */
            'maxlength' => $maxlength,

      if ($options->readonly) {
            $inputattributes['readonly'] = 'readonly';
      ... /* Lots of untouched code here! */
      return $output;
I am at this point of time, unable to solve the THIRD (which is very similar to what was described by Chris Liang-Vergara in his post entitled, 'Limit the number of character in a text box field?' here) and FOURTH problems. 
If anyone is able to help me out here, I would be eternally grateful to you.

Frankie Kam

P.S., you can download my /public_html/moodle/question/type/multianswer/renderer.php file from here.

P.S.2, 'CLOZED' should be spelt as 'CLOSED' in the image at the beginning of this post. I just thought that you might want to know thiz. Thankz.

If you like this post or site
a small donation would be nice but would last only a day,
otherwise leaving a comment (or a compliment) below will last me a month!

Ratings and Recommendations by outbrain