浏览代码

Merge pull request #690 from AngelFQC/7612

Add the type of question Draggable - refs #7612
Angel Fernando Quiroz Campos 10 年之前
父节点
当前提交
4ff3eceda0

+ 27 - 0
main/css/base.css

@@ -5903,3 +5903,30 @@ ul.holder li.bit-box{
     height: auto !important;
     max-width: 100%;
 }
+
+/***    Draggable answer    ***/
+.question_options ul.exercise-draggable-answer{
+    float: left;
+    margin-bottom: 20px;
+    min-height: 2em;
+    min-width: 100%;
+}
+ul.exercise-draggable-answer li {
+    cursor: move;
+    float: left;
+    margin: 0 20px 20px 0;
+    padding: 5px;
+    text-align: center;
+    width: 200px;
+}
+
+.question_options .droppable {
+    float: left;
+    margin: 0 20px 20px 0;
+    padding: 20px;
+    text-align: center;
+    width: 240px
+}
+.question_options .droppable .gallery .exercise-draggable-answer-option {
+    margin-bottom: 15px;
+}

+ 224 - 0
main/exercice/Draggable.php

@@ -0,0 +1,224 @@
+<?php
+
+/* For licensing terms, see /license.txt */
+
+/**
+ * Draggable
+ *
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ */
+class Draggable extends Question
+{
+
+    static $typePicture = 'matching.png';
+    static $explanationLangVar = 'Draggable';
+
+    /**
+     * Class constructor
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->type = DRAGGABLE;
+        $this->isContent = $this->getIsContent();
+    }
+
+    /**
+     * Function which redefines Question::createAnswersForm
+     * @param FormValidator $form
+     */
+    public function createAnswersForm($form)
+    {
+        $defaults = array();
+        $nb_matches = $nb_options = 2;
+        $matches = array();
+
+        $answer = null;
+
+        if ($form->isSubmitted()) {
+            $nb_matches = $form->getSubmitValue('nb_matches');
+            $nb_options = $form->getSubmitValue('nb_options');
+
+            if (isset($_POST['lessMatches'])) {
+                $nb_matches--;
+            }
+
+            if (isset($_POST['moreMatches'])) {
+                $nb_matches++;
+            }
+
+            if (isset($_POST['lessOptions'])) {
+                $nb_options--;
+            }
+
+            if (isset($_POST['moreOptions'])) {
+                $nb_options++;
+            }
+        } else if (!empty($this->id)) {
+            $answer = new Answer($this->id);
+            $answer->read();
+
+            if (count($answer->nbrAnswers) > 0) {
+                $nb_matches = $nb_options = 0;
+                
+                for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
+                    if ($answer->isCorrect($i)) {
+                        $nb_matches++;
+                        $defaults['answer[' . $nb_matches . ']'] = $answer->selectAnswer($i);
+                        $defaults['weighting[' . $nb_matches . ']'] = float_format($answer->selectWeighting($i), 1);
+                        $defaults['matches[' . $nb_matches . ']'] = $answer->correct[$i];
+                    } else {
+                        $nb_options++;
+                        $defaults['option[' . $nb_options . ']'] = $answer->selectAnswer($i);
+                    }
+                }
+            }
+        } else {
+            $defaults['answer[1]'] = get_lang('DefaultMakeCorrespond1');
+            $defaults['answer[2]'] = get_lang('DefaultMakeCorrespond2');
+            $defaults['matches[2]'] = '2';
+            $defaults['option[1]'] = get_lang('DefaultMatchingOptA');
+            $defaults['option[2]'] = get_lang('DefaultMatchingOptB');
+        }
+
+        for ($i = 1; $i <= $nb_matches; ++$i) {
+            $matches[$i] = $i;
+        }
+
+        $form->addElement('hidden', 'nb_matches', $nb_matches);
+        $form->addElement('hidden', 'nb_options', $nb_options);
+
+        // DISPLAY MATCHES
+        $html = '<table class="table table-striped table-hover">
+            <thead>
+                <tr>
+                    <th width="85%">' . get_lang('Answer') . '</th>
+                    <th width="15%">' . get_lang('MatchesTo') . '</th>
+                    <th width="10">' . get_lang('Weighting') . '</th>
+                </tr>
+            </thead>
+            <tbody>';
+
+        $form->addHeader(get_lang('MakeCorrespond'));
+        $form->addHtml($html);
+
+        if ($nb_matches < 1) {
+            $nb_matches = 1;
+            Display::display_normal_message(get_lang('YouHaveToCreateAtLeastOneAnswer'));
+        }
+
+        for ($i = 1; $i <= $nb_matches; ++$i) {
+            $renderer = &$form->defaultRenderer();
+
+            $renderer->setElementTemplate(
+                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
+                "answer[$i]"
+            );
+
+            $renderer->setElementTemplate(
+                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
+                "matches[$i]"
+            );
+
+            $renderer->setElementTemplate(
+                '<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error -->{element}</td>',
+                "weighting[$i]"
+            );
+
+            $form->addHtml('<tr>');
+            $form->addText("answer[$i]", null);
+            $form->addSelect("matches[$i]", null, $matches);
+            $form->addText("weighting[$i]", null, true, ['value' => 10]);
+            $form->addHtml('</tr>');
+        }
+
+        $form->addHtml('</tbody></table>');
+        $group = array();
+
+        $renderer->setElementTemplate(
+            '<div class="form-group"><div class="col-sm-offset-2">{element}',
+            'lessMatches'
+        );
+        $renderer->setElementTemplate('{element}</div></div>', 'moreMatches');
+
+        global $text;
+
+        $group = [
+            $form->addButtonDelete(get_lang('DelElem'), 'lessMatches', true),
+            $form->addButtonCreate(get_lang('AddElem'), 'moreMatches', true),
+            $form->addButtonSave($text, 'submitQuestion', true)
+        ];
+
+        $form->addGroup($group);
+
+        if (!empty($this->id)) {
+            $form->setDefaults($defaults);
+        } else {
+            if ($this->isContent == 1) {
+                $form->setDefaults($defaults);
+            }
+        }
+
+        $form->setConstants(
+            [
+                'nb_matches' => $nb_matches,
+                'nb_options' => $nb_options
+            ]
+        );
+    }
+
+    /**
+     * Abstract function which creates the form to create / edit the answers of the question
+     * @param FormValidator $form
+     */
+    public function processAnswersCreation($form)
+    {
+        $nb_matches = $form->getSubmitValue('nb_matches');
+        $this->weighting = 0;
+        $position = 0;
+
+        $objAnswer = new Answer($this->id);
+
+        // Insert the options
+        for ($i = 1; $i <= $nb_matches; ++$i) {
+            $position++;
+
+            $objAnswer->createAnswer($position, 0, '', 0, $position);
+        }
+
+        // Insert the answers
+        for ($i = 1; $i <= $nb_matches; ++$i) {
+            $position++;
+
+            $answer = $form->getSubmitValue('answer[' . $i . ']');
+            $matches = $form->getSubmitValue('matches[' . $i . ']');
+            $weighting = $form->getSubmitValue('weighting[' . $i . ']');
+            $this->weighting += $weighting;
+            $objAnswer->createAnswer($answer, $matches, '', $weighting, $position);
+        }
+
+        $objAnswer->save();
+        $this->save();
+    }
+
+    /**
+     * Shows question title an description
+     * @param string $feedback_type
+     * @param int $counter
+     * @param float $score
+     * @return string
+     */
+    public function return_header($feedback_type = null, $counter = null, $score = null)
+    {
+        $header = parent::return_header($feedback_type, $counter, $score);
+        $header .= '<table class="' . $this->question_table_class . '">
+            <tr>
+                <th>' . get_lang('ElementList') . '</th>
+                <th>' . get_lang('Status') . '</th>
+            </tr>';
+
+        return $header;
+    }
+
+}

+ 61 - 20
main/exercice/exercise.class.php

@@ -1890,7 +1890,7 @@ class Exercise
                     }
 					$class .= ' question-validate-btn'; // used to select it with jquery
                     $all_button = '&nbsp;<a href="javascript://" class="'.$class.'" onclick="validate_all(); ">'.$all_label.'</a>';
-                    $all_button .= '&nbsp;<span id="save_all_reponse"></span>';
+                    $all_button .= '&nbsp;' . Display::span(null, ['id' => 'save_all_reponse']);
                     $html .= $all_button;
                 }
             }
@@ -2772,6 +2772,8 @@ class Exercise
                         }
                     }
                     break;
+                case DRAGGABLE:
+                    //no break
                 case MATCHING:
                     if ($from_database) {
                         $sql = 'SELECT id, answer, id_auto
@@ -2824,20 +2826,38 @@ class Exercise
                                 if ($s_user_answer == $i_answer_correct_answer) {
                                     $questionScore += $i_answerWeighting;
                                     $totalScore += $i_answerWeighting;
-                                    if (isset($real_list[$i_answer_id])) {
-                                        $user_answer = '<span>'.$real_list[$i_answer_id].'</span>';
+                                    if ($answerType == DRAGGABLE) {
+                                        $user_answer = Display::label(get_lang('Correct'), 'success');
+                                    } else {
+                                        if (isset($real_list[$i_answer_id])) {
+                                            $user_answer = Display::span($real_list[$i_answer_id]);
+                                        }
                                     }
                                 } else {
-                                    $user_answer = '<span style="color: #FF0000; text-decoration: line-through;">'.$real_list[$s_user_answer].'</span>';
+                                    if ($answerType == DRAGGABLE) {
+                                        $user_answer = Display::label(get_lang('NotCorrect'), 'danger');
+                                    } else {
+                                        $user_answer = Display::span(
+                                            $real_list[$s_user_answer],
+                                            ['style' => 'color: #FF0000; text-decoration: line-through;']
+                                        );
+                                    }
                                 }
+                            } elseif ($answerType == DRAGGABLE) {
+                                $user_answer = Display::label(get_lang('Incorrect'), 'danger');
                             }
 
                             if ($show_result) {
                                 echo '<tr>';
-                                echo '<td>'.$s_answer_label.'</td>';
-                                echo '<td>'.$user_answer;
-                                if (isset($real_list[$i_answer_correct_answer])) {
-                                    echo ' <b><span style="color: #008000;">'.$real_list[$i_answer_correct_answer].'</span></b> ';
+                                echo '<td>' . $s_answer_label . '</td>';
+                                echo '<td>' . $user_answer;
+                                if ($answerType == MATCHING) {
+                                    if (isset($real_list[$i_answer_correct_answer])) {
+                                        echo Display::span(
+                                            $real_list[$i_answer_correct_answer],
+                                            ['style' => 'color: #008000; font-weight: bold;']
+                                        );
+                                    }
                                 }
                                 echo '</td>';
                                 echo '</tr>';
@@ -2850,10 +2870,13 @@ class Exercise
                                 $questionScore += $answerWeighting;
                                 $totalScore += $answerWeighting;
 
-                                $user_answer = '<span>'.$answerMatching[$choice[$answerAutoId]].'</span>';
+                                $user_answer = Display::span($answerMatching[$choice[$answerAutoId]]);
                             } else {
                                 if (isset($answerMatching[$choice[$answerAutoId]])) {
-                                    $user_answer = '<span style="color: #FF0000; text-decoration: line-through;">'.$answerMatching[$choice[$answerAutoId]].'</span>';
+                                    $user_answer = Display::span(
+                                        $answerMatching[$choice[$answerAutoId]],
+                                        ['style' => 'color: #FF0000; text-decoration: line-through;']
+                                    );
                                 }
                             }
                             $matching[$answerAutoId] = $choice[$answerAutoId];
@@ -2951,7 +2974,13 @@ class Exercise
                 if ($from == 'exercise_result') {
                     if ($debug) error_log('Showing questions $from '.$from);
                     //display answers (if not matching type, or if the answer is correct)
-                    if ($answerType != MATCHING || $answerCorrect) {
+                    if (
+                        !in_array(
+                            $answerType,
+                            [MATCHING, DRAGGABLE]
+                        ) ||
+                        $answerCorrect
+                    ) {
                         if (
                             in_array(
                                 $answerType,
@@ -3218,10 +3247,15 @@ class Exercise
                             }
                         } elseif($answerType == MATCHING) {
                             echo '<tr>';
-                            echo '<td>' . $answerMatching[$answerId] . '</td>';
-                            echo '<td>' . $user_answer . ' / <b>'
-                                . '<span style="color: #008000;">' . $answerMatching[$answerCorrect] . '</span>'
-                                . '</b></td>';
+                            echo Display::tag('td', $answerMatching[$answerId]);
+                            echo Display::tag(
+                                'td',
+                                "$user_answer / " . Display::tag(
+                                    'strong',
+                                    $answerMatching[$answerCorrect],
+                                    ['style' => 'color: #008000; font-weight: bold;']
+                                )
+                            );
                             echo '</tr>';
                         }
                     }
@@ -3535,12 +3569,19 @@ class Exercise
                                 $answerComment
                             );
                             break;
+                        case DRAGGABLE:
+                            //no break
                         case MATCHING:
                             echo '<tr>';
-                            echo '<td>' . $answerMatching[$answerId] . '</td>';
-                            echo '<td>' . $user_answer . ' / <b>'
-                                . '<span style="color: #008000;">' . $answerMatching[$answerCorrect] . '</span></b>'
-                                . '</td>';
+                            echo Display::tag('td', $answerMatching[$answerId]);
+                            echo Display::tag(
+                                'td',
+                                "$user_answer / " . Display::tag(
+                                    'strong',
+                                    $answerMatching[$answerCorrect],
+                                    ['style' => 'color: #008000; font-weight: bold;']
+                                )
+                            );
                             echo '</tr>';
 
                             break;
@@ -3842,7 +3883,7 @@ class Exercise
                 } else {
                     Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id);
                 }
-            } elseif ($answerType == MATCHING) {
+            } elseif (in_array($answerType, [MATCHING, DRAGGABLE])) {
                 if (isset($matching)) {
                     foreach ($matching as $j => $val) {
                         Event::saveQuestionAttempt($questionScore, $val, $quesId, $exeId, $j, $this->id);

+ 1 - 1
main/exercice/exercise_show.php

@@ -343,7 +343,7 @@ foreach ($questionList as $questionId) {
 		$question_result = $objExercise->manage_answer($id, $questionId, $choice,'exercise_show', array(), false, true, $show_results, $objExercise->selectPropagateNeg());
 		$questionScore   = $question_result['score'];
 		$totalScore     += $question_result['score'];
-	} elseif ($answerType == MATCHING) {
+        } elseif (in_array($answerType, [MATCHING, DRAGGABLE])) {
         $question_result = $objExercise->manage_answer($id, $questionId, $choice,'exercise_show', array(), false, true, $show_results, $objExercise->selectPropagateNeg());
         $questionScore   = $question_result['score'];
         $totalScore     += $question_result['score'];

+ 2 - 0
main/exercice/exercise_submit.php

@@ -57,6 +57,8 @@ $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.dateformat.min.js');
 $htmlHeadXtra[] = api_get_js('epiclock/javascript/jquery.epiclock.min.js');
 $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');
 
+$htmlHeadXtra[] = (new Template())->fetch('default/exercise/submit.js.tpl');
+
 // General parameters passed via POST/GET
 
 $learnpath_id = isset($_REQUEST['learnpath_id']) ? intval($_REQUEST['learnpath_id']) : 0;

+ 2 - 1
main/exercice/question.class.php

@@ -49,7 +49,8 @@ abstract class Question
         ),
         GLOBAL_MULTIPLE_ANSWER => array('global_multiple_answer.class.php' , 'GlobalMultipleAnswer'),
         CALCULATED_ANSWER => array('calculated_answer.class.php' , 'CalculatedAnswer'),
-        UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage']
+        UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage'],
+        DRAGGABLE => ['Draggable.php', 'Draggable']
         //MEDIA_QUESTION => array('media_question.class.php' , 'MediaQuestion')
     );
 

+ 1 - 0
main/inc/lib/api.lib.php

@@ -473,6 +473,7 @@ define('GLOBAL_MULTIPLE_ANSWER', 14);
 define('MEDIA_QUESTION', 15);
 define('CALCULATED_ANSWER', 16);
 define('UNIQUE_ANSWER_IMAGE', 17);
+define('DRAGGABLE', 18);
 
 //Some alias used in the QTI exports
 define('MCUA', 1);

+ 2 - 2
main/inc/lib/display.lib.php

@@ -1754,8 +1754,8 @@ class Display
         if (!empty($list)) {
             $html = '<dl class="dl-horizontal">';
             foreach ($list as $item) {
-                $html .= '<dt>'.$item['title'].'</dd>';
-                $html .= '<dd>'.$item['content'].'</dt>';
+                $html .= '<dt>' . $item['title'] . '</dt>';
+                $html .= '<dd>' . $item['content'] . '</dd>';
             }
             $html .= '</dl>';
         }

+ 127 - 2
main/inc/lib/exercise.lib.php

@@ -104,8 +104,14 @@ class ExerciseLib
             // on the right side are called answers
             $num_suggestions = 0;
 
-            if ($answerType == MATCHING) {
-                $s .= '<table class="table table-hover table-striped">';
+            if (in_array($answerType, [MATCHING, DRAGGABLE])) {
+                if ($answerType == DRAGGABLE) {
+                    $s .= '<div class="ui-widget ui-helper-clearfix">
+                        <div class="clearfix">
+                        <ul class="exercise-draggable-answer ui-helper-reset ui-helper-clearfix">';
+                } else {
+                    $s .= '<table class="table table-hover table-striped">';
+                }
                 // Iterate through answers
                 $x = 1;
                 //mark letters for each answer
@@ -908,6 +914,94 @@ class ExerciseLib
                         }  // end if()
                         $matching_correct_answer++;
                     }
+                } elseif ($answerType == DRAGGABLE) {
+                    if ($answerCorrect != 0) {
+                        $parsed_answer = $answer;
+                        $windowId = $questionId . '_' . $lines_count;
+
+                        $s .= '<li class="thumbnail" id="' . $windowId . '">';
+                        $s .= Display::div(
+                            $parsed_answer,
+                            [
+                                'id' => "window_$windowId",
+                                'class' => "window{$questionId}_question_draggable exercise-draggable-answer-option"
+                            ]
+                        );
+                        $selectedValue = 0;
+                        $draggableSelectOptions = [];
+
+                        foreach ($select_items as $key => $val) {
+                            if ($debug_mark_answer) {
+                                if ($val['id'] == $answerCorrect) {
+                                    $selectedValue = $val['id'];
+                                }
+                            }
+
+                            if (
+                                isset($user_choice[$matching_correct_answer]) &&
+                                $val['id'] == $user_choice[$matching_correct_answer]['answer']
+                            ) {
+                                $selectedValue = $val['id'];
+                            }
+
+                            $draggableSelectOptions[$val['id']] = $val['letter'];
+                        }
+
+                        $s .= Display::select(
+                            "choice[$questionId][$numAnswer]",
+                            $draggableSelectOptions,
+                            $selectedValue,
+                            [
+                                'id' => "window_{$windowId}_select",
+                                'class' => 'select_option',
+                                'style' => 'display: none;'
+                            ],
+                            false
+                        );
+
+                        if (!empty($answerCorrect) && !empty($selectedValue)) {
+                            $s .= <<<JAVASCRIPT
+                                <script>
+                                    $(function() {
+                                        DraggableAnswer.deleteItem(
+                                            $('#{$questionId}_{$selectedValue}'),
+                                            $('#drop_$windowId')
+                                        );
+                                    });
+                                </script>
+JAVASCRIPT;
+                        }
+
+                        if (isset($select_items[$lines_count])) {
+                            $s .= Display::div(
+                                Display::tag(
+                                    'b',
+                                    $select_items[$lines_count]['letter']
+                                ) . $select_items[$lines_count]['answer'],
+                                [
+                                    'id' => "window_{$windowId}_answer",
+                                    'style' => 'display: none;'
+                                ]
+                            );
+                        } else {
+                            $s .= '&nbsp;';
+                        }
+
+                        $lines_count++;
+
+                        if (($lines_count - 1) == $num_suggestions) {
+                            while (isset($select_items[$lines_count])) {
+                                $s .= Display::tag('b', $select_items[$lines_count]['letter']);
+                                $s .= $select_items[$lines_count]['answer'];
+
+                                $lines_count++;
+                            }
+                        }
+
+                        $matching_correct_answer++;
+
+                        $s .= '</li>';
+                    }
                 }
             }    // end for()
 
@@ -921,6 +1015,37 @@ class ExerciseLib
                 }
             }
 
+            if ($answerType == DRAGGABLE) {
+                $s .= "</ul></div>";
+
+                $counterAnswer = 1;
+                
+                $s .= '<div class="col-xs-12"><div class="row">';
+
+                for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
+                    $answerCorrect = $objAnswerTmp->isCorrect($answerId);
+                    $windowId = $questionId . '_' . $counterAnswer;
+
+                    if ($answerCorrect) {
+                        $s .= Display::div(
+                            $counterAnswer,
+                            [
+                                'id' => "drop_$windowId",
+                                'class' => 'droppable col-sm-4 well'
+                            ]
+                        );
+
+                        $counterAnswer++;
+                    }
+                }
+
+                $s .= '</div></div>';
+            }
+
+            if ($answerType == MATCHING) {
+                $s .= '</div>';
+            }
+
             $s .= '</div>';
 
             // destruction of the Answer object

+ 95 - 0
main/template/default/exercise/submit.js.tpl

@@ -0,0 +1,95 @@
+<script>
+    var DraggableAnswer = {
+        gallery: null,
+        trash: null,
+        deleteItem: function (item, insertHere) {
+            if (insertHere.find(".exercise-draggable-answer-option").length > 0) {
+                return false;
+            }
+
+            item.fadeOut(function () {
+                var $list = $('<div class="gallery ui-helper-reset"/>').appendTo(insertHere);
+
+                item.find('a.btn').remove();
+
+                var droppedId = item.attr('id'),
+                    dropedOnId = insertHere.attr('id'),
+                    originSelectId = 'window_' + droppedId + '_select',
+                    value = dropedOnId.split('_')[2];
+
+                $('#' + originSelectId + ' option')
+                    .filter(function (index) {
+                        return index === parseInt(value);
+                    })
+                    .attr("selected", true);
+
+                var recycleButton = $('<a>')
+                        .attr('href', '#')
+                        .addClass('btn btn-default btn-xs')
+                        .append(
+                            "{{ "Undo" | get_lang }} ",
+                            $('<i>').addClass('fa fa-undo')
+                        )
+                        .on('click', function (e) {
+                            e.preventDefault();
+
+                            var liParent = $(this).parent();
+
+                            DraggableAnswer.recycleItem(liParent);
+                        });
+
+                item.append(recycleButton).appendTo($list).fadeIn();
+            });
+        },
+        recycleItem: function (item) {
+            item.fadeOut(function () {
+                item
+                    .find('a.btn')
+                    .remove()
+                    .end()
+                    .find("img")
+                    .end()
+                    .appendTo(DraggableAnswer.gallery)
+                    .fadeIn();
+            });
+
+            var droppedId = item.attr('id'),
+                originSelectId = 'window_' + droppedId + '_select';
+
+            $('#' + originSelectId + ' option:first').attr('selected', 'selected');
+        },
+        init: function (gallery, trash) {
+            this.gallery = gallery;
+            this.trash = trash;
+
+            $("li", DraggableAnswer.gallery).draggable({
+                cancel: "a.ui-icon",
+                revert: "invalid",
+                containment: "document",
+                helper: "clone",
+                cursor: "move"
+            });
+
+            DraggableAnswer.trash.droppable({
+                accept: ".exercise-draggable-answer > li",
+                hoverClass: "ui-state-active",
+                drop: function (e, ui) {
+                    DraggableAnswer.deleteItem(ui.draggable, $(this));
+                }
+            });
+
+            DraggableAnswer.gallery.droppable({
+                drop: function (e, ui) {
+                    DraggableAnswer.recycleItem(ui.draggable, $(this));
+                }
+            });
+        }
+    };
+
+    $(document).on('ready', function () {
+        DraggableAnswer.init(
+            $(".exercise-draggable-answer"),
+            $(".droppable")
+        );
+    });
+</script>